第四章:库存模型基础——AVCO、FIFO、LIFO

做市商的库存管理,说白了就是一门「怎么管货」的学问。你手里有多少资产、以什么成本拿到的、先卖哪一批——这些细节直接决定了你的盈亏。我个人习惯把库存模型比作记账方式,不同的记账法,算出来的利润天差地别。

今天咱们就聊聊三种最基础的库存模型:AVCO(平均成本法)FIFO(先进先出)LIFO(后进先出)。嗯,别被这些英文缩写吓到,其实逻辑都很朴素。

4.1 为什么做市商需要库存模型?

先问一个问题:你同时买入了两批BTC,第一批价格30000,第二批价格40000。现在你卖出一枚,成本该算30000还是40000?

不同的答案,会直接影响你的已实现盈亏、未实现盈亏,甚至税务计算。我在早期做市的时候,就因为没统一库存模型,导致回测结果和实盘对不上——那叫一个头疼。

库存模型的核心作用有三个:

  • 成本核算:明确每笔卖出对应的买入成本
  • 盈亏计算:区分已实现和未实现损益
  • 风险管理:了解当前持仓的真实成本基础

核心观点:库存模型不是会计游戏,它直接影响你的交易决策。选错了模型,你可能会误判自己的风险敞口。

4.2 AVCO模型(平均成本法)

AVCO,全称Average Cost,平均成本法。这是我最常用的模型,没有之一。为什么?因为它简单、平滑,不会因为某笔极端成交而扭曲整体成本。

算法其实就一句话:总成本 ÷ 总数量 = 平均成本。每次新买入,重新计算一次平均价。

举个例子:

操作 价格 数量 总成本 平均成本
买入 100 10 1000 100
买入 120 10 2200 110
卖出5个 115 -5 110(不变)

看到没?卖出时平均成本不变。已实现盈亏 = (115 - 110) × 5 = 25。就这么简单。

我的经验:AVCO特别适合做高频做市。因为你的买卖频率极高,用FIFO或LIFO会导致成本频繁跳动,干扰判断。AVCO就像给库存打了个「平滑滤镜」。

代码实现也很直接:

class AVCOInventory:
    def __init__(self):
        self.avg_cost = 0.0
        self.quantity = 0.0
    
    def buy(self, price, qty):
        total_cost = self.avg_cost * self.quantity + price * qty
        self.quantity += qty
        self.avg_cost = total_cost / self.quantity
    
    def sell(self, price, qty):
        if qty > self.quantity:
            raise ValueError("库存不足")
        realized_pnl = (price - self.avg_cost) * qty
        self.quantity -= qty
        return realized_pnl

4.3 FIFO模型(先进先出)

FIFO,First In First Out。字面意思:先买的货,先卖出去。这其实最符合物理世界的直觉——你仓库里的东西,总得先把旧的卖掉吧?

但在做市商的世界里,FIFO有个大问题:它会放大已实现盈亏的波动

为什么?你想想看,如果市场在上涨,你早期低价买入的库存会先被卖出,产生大量已实现盈利。反过来,市场下跌时,早期高价库存先出,亏损会集中爆发。

我曾经在一个波动率极高的币对上用过FIFO,结果每天已实现盈亏像过山车一样。风控部门天天找我喝茶……后来我学乖了,改用AVCO。

FIFO的实现需要维护一个队列:

from collections import deque

class FIFOInventory:
    def __init__(self):
        self.lots = deque()  # 每个元素是 (price, qty)
    
    def buy(self, price, qty):
        self.lots.append((price, qty))
    
    def sell(self, price, qty):
        realized_pnl = 0.0
        while qty > 0 and self.lots:
            lot_price, lot_qty = self.lots[0]
            if lot_qty <= qty:
                # 整个批次卖完
                realized_pnl += (price - lot_price) * lot_qty
                qty -= lot_qty
                self.lots.popleft()
            else:
                # 部分卖出
                realized_pnl += (price - lot_price) * qty
                self.lots[0] = (lot_price, lot_qty - qty)
                qty = 0
        return realized_pnl

避坑指南:我曾经在回测中用了FIFO,结果发现夏普比率被严重高估。因为早期低价库存带来的巨额盈利,掩盖了后期策略失效的风险。如果你用FIFO做回测,一定要看滚动收益曲线,别只看总收益。

4.4 LIFO模型(后进先出)

LIFO,Last In First Out。后买的货先卖。这在传统行业里不太常见,但在做市商领域,LIFO其实有它独特的价值。

为什么?因为做市商最关心的是当前市场价和最新成本的关系。LIFO能让你更敏感地反映近期市场变化。

举个例子:你刚以110的价格买入一批货,市场突然跌到105。用LIFO的话,你下一笔卖出就会优先用110的成本去算,亏损立刻体现。而用FIFO的话,可能还在用100的老成本,账面看着还是盈利的——这就有点自欺欺人了。

LIFO的实现和FIFO很像,只不过队列变成了栈:

class LIFOInventory:
    def __init__(self):
        self.lots = []  # 用列表模拟栈
    
    def buy(self, price, qty):
        self.lots.append((price, qty))
    
    def sell(self, price, qty):
        realized_pnl = 0.0
        while qty > 0 and self.lots:
            lot_price, lot_qty = self.lots[-1]  # 取最后一个
            if lot_qty <= qty:
                realized_pnl += (price - lot_price) * lot_qty
                qty -= lot_qty
                self.lots.pop()
            else:
                realized_pnl += (price - lot_price) * qty
                self.lots[-1] = (lot_price, lot_qty - qty)
                qty = 0
        return realized_pnl

个人建议:LIFO适合做短线做市,尤其是日内交易。它能让你更早地「认亏」,避免死扛。但要注意,LIFO在税务上可能不太友好(某些地区不允许用LIFO报税),实盘前一定要确认合规性。

4.5 三种模型的对比与选择

好了,三种模型都讲完了。咱们来做个横向对比:

维度 AVCO FIFO LIFO
实现复杂度
已实现盈亏波动 平滑 中高
对市场敏感度 低(依赖早期成本) 高(依赖近期成本)
适用场景 高频做市、长期持仓 传统金融、税务优化 短线交易、风险敏感型

我个人习惯是:回测用AVCO,实盘也用AVCO。只有在特定策略需要监控近期成本时,我才会切换到LIFO。至于FIFO……嗯,除非客户指定,否则我基本不用。

一个小技巧:你可以在系统中同时维护三种模型的成本数据。AVCO用于日常风控,FIFO用于税务报告,LIFO用于短线决策。互不冲突,各取所需。

4.6 本章小结

库存模型看似是个小问题,但它会渗透到你交易系统的每一个角落。选错了模型,轻则盈亏计算失真,重则风控指标失效。

记住三点:

  • AVCO最平滑,适合大多数做市场景
  • FIFO最直观,但波动大,小心被误导
  • LIFO最敏感,适合需要快速反应的市场

下一章,我们会深入讨论库存风险的量化方法。到时候你会看到,库存模型的选择如何影响VaR和压力测试的结果。嗯,那才是真正有意思的部分。