套利策略

套利策略系统设计

做市商视角的完整套利系统:三角套利、期现套利、期权期货套利、交易所做市返佣、割头皮统计套利策略,以及配套的风控、延迟优化与盈亏监控体系。

1. 套利系统总览

套利系统以做市商 (Market Maker) 角色运行,同时覆盖多种套利策略,通过高频交易赚取价差、交易所返佣和统计回归收益。所有策略共享统一的信号采集、订单执行和风控模块。

核心设计原则

微秒级延迟

Co-location + Kernel Bypass + 共享内存订单簿,端到端延迟 < 100μs

多策略并行

三角套利、期现套利、做市、统计套利并行运行,共享行情与执行通道

统一风控

所有策略共享持仓限制、净敞口控制、最大亏损熔断,避免策略间相互冲突

原子执行

多腿套利使用原子下单或对冲延迟 < 5ms,防止单腿风险

自适应参数

根据波动率、流动性自动调整价差、仓位和阈值

全链路监控

每笔交易归因到具体策略,实时 PnL、Sharpe、最大回撤仪表盘

2. 三角套利

三角套利利用同一交易所内三个交易对之间的价格不一致,在极短时间内完成三步交易,锁定无风险利润。做市商由于 Maker 负手续费(返佣),在三角套利中具有天然成本优势。

核心算法

// === 三角套利检测 ===
function detectTriangularArb(bookA, bookB, bookC):
    // 路径 1: USDT → BTC → ETH → USDT
    // 步骤: 买BTC/USDT(ask) → 卖ETH/BTC(bid) → 卖ETH/USDT(bid)
    rate1 = (1 / bookA.bestAsk) * bookC.bestBid * bookB.bestBid

    // 路径 2: USDT → ETH → BTC → USDT
    // 步骤: 买ETH/USDT(ask) → 买ETH/BTC(ask, 即卖BTC) → 卖BTC/USDT(bid)
    rate2 = (1 / bookB.bestAsk) * (1 / bookC.bestAsk) * bookA.bestBid

    // 扣除手续费 (3次交易)
    feeMultiplier = (1 - makerFee) ** 3  // 做市商用 maker fee (可能为负 = 返佣)
    netRate1 = rate1 * feeMultiplier
    netRate2 = rate2 * feeMultiplier

    if netRate1 > 1.0:
        return { path: "USDT→BTC→ETH→USDT", profit: (netRate1 - 1) * capital }
    if netRate2 > 1.0:
        return { path: "USDT→ETH→BTC→USDT", profit: (netRate2 - 1) * capital }
    return null

// === 执行策略 ===
function executeTriangularArb(signal):
    // 关键: 三腿必须在极短时间内完成
    // 方案 A: 并行下单 (风险: 部分成交)
    // 方案 B: 顺序下单 + 对冲 (更安全)

    orders = buildOrderLegs(signal)

    // 使用 IOC (Immediate or Cancel) 避免挂单
    for order in orders:
        order.timeInForce = "IOC"
        order.type = "LIMIT"  // 用限价+IOC, 而非市价, 避免滑点

    // 并行提交 (通过多路复用连接)
    results = await Promise.all(orders.map(submitOrder))

    // 检查是否全部成交
    if any(r.status != "FILLED" for r in results):
        hedgeRemainingLegs(results)  // 对冲未成交腿
检测频率

每次 OrderBook 更新触发重算(tick-by-tick),延迟 < 1ms。扫描所有三角组合。

利润阈值

净利润 > 最小阈值(通常 > 3倍手续费)才触发。做市商返佣可大幅降低阈值。

深度检查

不仅看最优价,还检查可用深度。只在深度足够覆盖下单量时触发。

单腿保护

使用 IOC 订单 + 毫秒级超时。任何一腿未成交立即对冲其他腿。

三角套利模拟器

调整三个交易对的价格,观察均衡偏离和套利利润。点击「制造套利机会」快速体验:

三角套利模拟器 — 调整价格发现套利机会
均衡 ETH/BTC 价格0.052381
实际 ETH/BTC 价格0.052400
价格偏离+0.0364%

3. 期现套利 (Basis Trade)

期现套利利用期货与现货之间的价差(基差 Basis)来获利。当期货溢价(正基差)超过持有成本时,买入现货 + 卖出期货,锁定年化收益。对于永续合约,利用资金费率进行类似套利。

期现套利算法

// === 期现套利 (交割合约) ===
function basisArbitrage(spot, futures, daysToExpiry):
    basis = futures - spot
    basisRate = basis / spot
    annualized = basisRate * (365 / daysToExpiry)

    // 成本计算
    tradingFee = (spot + futures) * quantity * feeRate * 2  // 开平各一次
    borrowCost = spot * quantity * (borrowRate / 365) * daysToExpiry
    totalCost = tradingFee + borrowCost

    netProfit = abs(basis) * quantity - totalCost

    if basis > 0 and netProfit > minProfit:
        // 正向套利: 买现货 + 卖期货
        execute("BUY", "SPOT", spot, quantity)
        execute("SELL", "FUTURES", futures, quantity)
        return { annualized, netProfit, action: "CASH_AND_CARRY" }

    if basis < 0 and netProfit > minProfit:
        // 反向套利: 卖现货 + 买期货
        execute("SELL", "SPOT", spot, quantity)
        execute("BUY", "FUTURES", futures, quantity)
        return { annualized, netProfit, action: "REVERSE_CASH_AND_CARRY" }

// === 永续合约资金费率套利 ===
function fundingRateArbitrage(fundingRate, spot, perpPrice):
    // 资金费率 > 0: 多头付空头 → 做空永续 + 买入现货
    // 资金费率 < 0: 空头付多头 → 做多永续 + 卖出现货

    annualizedFunding = fundingRate * 3 * 365  // 每8小时一次

    if abs(annualizedFunding) > minYield:
        if fundingRate > 0:
            execute("BUY", "SPOT", spot, qty)
            execute("SELL", "PERP", perpPrice, qty)
            // 持续收取资金费率直到不划算
        else:
            execute("SELL", "SPOT", spot, qty)
            execute("BUY", "PERP", perpPrice, qty)
正向套利

期货溢价时买现货卖期货。到期自动收敛,风险极低。年化收益率 = 基差率 * 365 / 剩余天数。

反向套利

期货折价时卖现货买期货。需要融币或已持有现货。通常在市场恐慌时出现机会。

资金费率套利

永续合约 funding rate 持续为正时,做空永续 + 买入现货。每 8 小时收取一次资金费率。

展期风险

交割合约到期需要展期。展期时基差可能变化,需重新评估。永续合约无此问题。

4. 期权期货套利

基于 Put-Call Parity(看跌看涨平价关系),通过期权构建合成期货,与实际期货价格对比。当两者出现偏差时,通过买低卖高锁定无风险利润。

期权期货套利算法

// === Put-Call Parity 套利 ===
// 理论: C - P = F * e^(-rT) - K * e^(-rT)
// 变形: F_synthetic = K + (C - P) / e^(-rT)

function optionFuturesArbitrage(call, put, strike, futuresPrice, T, r):
    discount = exp(-r * T)
    syntheticFuture = strike + (call - put) / discount
    diff = futuresPrice - syntheticFuture

    if abs(diff) < minSpread:
        return null  // 价差太小,无机会

    if diff > 0:
        // 实际期货 > 合成期货
        // 策略: 卖出实际期货 + 做多合成期货 (买Call + 卖Put)
        return {
            legs: [
                { action: "SELL", instrument: "FUTURES", price: futuresPrice },
                { action: "BUY",  instrument: "CALL",    price: call, strike },
                { action: "SELL", instrument: "PUT",     price: put,  strike },
            ],
            profit: diff,
            type: "CONVERSION"  // 转换套利
        }
    else:
        // 实际期货 < 合成期货
        // 策略: 买入实际期货 + 做空合成期货 (卖Call + 买Put)
        return {
            legs: [
                { action: "BUY",  instrument: "FUTURES", price: futuresPrice },
                { action: "SELL", instrument: "CALL",    price: call, strike },
                { action: "BUY",  instrument: "PUT",     price: put,  strike },
            ],
            profit: -diff,
            type: "REVERSAL"  // 反转套利
        }

// === Box Spread 套利 (进阶) ===
// 同时做 Bull Call Spread + Bear Put Spread
function boxSpreadArbitrage(K1, K2, calls, puts, T, r):
    // Bull Call: 买 Call(K1) + 卖 Call(K2)
    bullCallCost = calls[K1].ask - calls[K2].bid
    // Bear Put:  买 Put(K2) + 卖 Put(K1)
    bearPutCost = puts[K2].ask - puts[K1].bid

    totalCost = bullCallCost + bearPutCost
    boxValue = (K2 - K1) * exp(-r * T)  // 理论价值

    if boxValue - totalCost > minProfit:
        // 买入 Box (期望到期获得 K2-K1)
        return { profit: boxValue - totalCost, type: "LONG_BOX" }
Conversion 转换

实际期货高于合成期货时,卖期货+买Call+卖Put。到期无论涨跌均获得固定利润。

Reversal 反转

实际期货低于合成期货时,买期货+卖Call+买Put。与 Conversion 方向相反。

Box Spread

使用两个行权价构建盒式价差。收益固定,等价于买入零息债券,用于套利定价偏差。

执行难点

期权流动性通常低于期货。需要同时在 3 个市场建仓,腿间延迟是核心风险。

期现 / 期权套利模拟器

切换 Tab 体验期现基差套利和期权期货 Put-Call Parity 套利:

期现 / 期权期货套利模拟器

5. 做市商 & 交易所返佣

做市商通过在买卖两侧持续挂单提供流动性,赚取买卖价差 (Spread)。交易所为激励做市商提供负手续费(Maker Rebate),即每笔 Maker 成交不仅不收手续费,还反向支付返佣给做市商。顶级做市商月交易量超过 20 亿 USDT,单月返佣可达数十万美元。

做市策略核心

// === Avellaneda-Stoikov 做市模型 ===
// 最优报价 = 中间价 ± 调整后价差

function calculateQuotes(midPrice, inventory, volatility, T):
    // 保留价格 (考虑库存风险的理论中间价)
    gamma = riskAversion  // 风险厌恶系数, 通常 0.01 - 0.1
    reservationPrice = midPrice - inventory * gamma * volatility^2 * T

    // 最优价差
    optimalSpread = gamma * volatility^2 * T + (2/gamma) * ln(1 + gamma/kappa)
    // kappa = 订单到达率参数

    bidPrice = reservationPrice - optimalSpread / 2
    askPrice = reservationPrice + optimalSpread / 2

    return { bidPrice, askPrice }

// === 库存管理 ===
function adjustForInventory(quotes, inventory, maxInventory):
    // 库存偏移: 持仓偏多时降低 ask 吸引卖单
    skew = (inventory / maxInventory) * maxSkewBps

    quotes.bidPrice -= skew * midPrice / 10000
    quotes.askPrice -= skew * midPrice / 10000

    // 库存超限时只挂减仓方向
    if inventory >= maxInventory:
        quotes.bidQty = 0     // 不再买入
    if inventory <= -maxInventory:
        quotes.askQty = 0     // 不再卖出

    return quotes

// === 交易所返佣计算 ===
function calculateRebate(volume, tier):
    // 各交易所返佣结构 (示例)
    // Tier 0: Maker -0.010%, Taker 0.030%
    // Tier 1: Maker -0.015%, Taker 0.025%  (月交易量 > 1亿)
    // Tier 2: Maker -0.020%, Taker 0.020%  (月交易量 > 5亿)
    // Tier 3: Maker -0.025%, Taker 0.015%  (月交易量 > 20亿)

    rebateRate = REBATE_TIERS[tier].makerRebate
    monthlyRebate = volume * abs(rebateRate)

    return {
        dailyRebate: monthlyRebate / 30,
        monthlyRebate,
        annualRebate: monthlyRebate * 12
    }
双边报价

同时在买卖两侧挂限价单。Bid 和 Ask 价格围绕中间价对称分布,价差 = 利润来源之一。

库存管理

核心风险。做市商需要在做市和持仓风险间取得平衡。使用偏移 (Skew) 鼓励减少库存方向。

返佣机制

交易所对 Maker 订单返还手续费(负费率)。交易量越大,返佣比例越高。顶级做市商返佣 -0.025%。

自适应价差

低波动率时收窄价差抢成交量;高波动率时放宽价差保护库存。使用 Avellaneda-Stoikov 模型。

做市商模拟器

设置中间价、价差和做市等级,点击开始模拟做市过程,实时查看成交、返佣和 PnL:

做市商模拟器 — 双边报价 & 交易所返佣
BID (买入报价)
41,989.5
0.5 BTC
Spread
21.00
5 bps
ASK (卖出报价)
42,010.5
0.5 BTC

成交笔数
0
总成交额
0 U
总返佣
+0.0000 U
净 PnL
+0.0000 U
库存
0.0000 BTC
返佣率
-0.010%
等级月交易量Maker 返佣Taker 费率1亿月交易额返佣
普通做市< 1亿-0.010% ()0.030%+10,000 U
专业做市 T11-5亿-0.015% ()0.025%+15,000 U
专业做市 T25-20亿-0.020% ()0.020%+20,000 U
顶级做市 T320亿+-0.025% ()0.015%+25,000 U

6. 割头皮统计套利

割头皮(Scalping)统计套利结合配对交易 (Pairs Trading) 和高频割头皮策略。选取具有协整关系的两个资产,当价差偏离均值超过 Z-Score 阈值时建仓,等待均值回归获利。持仓时间极短(秒级到分钟级),单次利润微小但频率极高。

统计套利核心算法

// === 配对交易 - 协整检验 ===
function findCointegrationPairs(assets, window):
    pairs = []
    for i in range(len(assets)):
        for j in range(i+1, len(assets)):
            // Engle-Granger 两步法
            // 1. 回归: priceA = α + β * priceB + ε
            beta = OLS(assets[i].prices, assets[j].prices).slope
            residuals = assets[i].prices - beta * assets[j].prices

            // 2. ADF 检验残差平稳性
            adfStat = augmentedDickeyFuller(residuals)
            if adfStat.pValue < 0.05:
                halfLife = calcHalfLife(residuals)
                pairs.append({ assetA: i, assetB: j, beta, halfLife })

    return pairs.sortBy(halfLife)  // 半衰期越短,回归越快

// === Z-Score 信号生成 ===
function generateSignal(priceA, priceB, beta, lookback):
    spread = priceA - beta * priceB
    rollingMean = mean(spreads[-lookback:])
    rollingStd = std(spreads[-lookback:])
    zscore = (spread - rollingMean) / rollingStd
    return zscore

// === 割头皮执行 ===
function scalpingExecution(zscore, position, params):
    { entryZ, exitZ, stopZ, size } = params

    if position == NONE:
        if zscore > entryZ:
            // 价差过高 → 做空价差 (卖A买B)
            shortA(size)
            longB(size * beta)
            return SHORT_SPREAD

        if zscore < -entryZ:
            // 价差过低 → 做多价差 (买A卖B)
            longA(size)
            shortB(size * beta)
            return LONG_SPREAD

    if position == SHORT_SPREAD:
        if zscore < exitZ:     closeAll(); return NONE  // 止盈
        if zscore > stopZ:     closeAll(); return NONE  // 止损

    if position == LONG_SPREAD:
        if zscore > -exitZ:    closeAll(); return NONE  // 止盈
        if zscore < -stopZ:    closeAll(); return NONE  // 止损

// === 动态参数调整 ===
function adaptiveParams(volatility, recentPnL):
    // 高波动率 → 放宽入场阈值,缩小仓位
    entryZ = baseEntryZ * (1 + volatility / baseVolatility * 0.5)
    size = baseSize * (baseVolatility / volatility)

    // 连续亏损 → 缩减仓位 (Kelly 准则)
    if recentPnL < 0:
        size *= max(0.25, 1 + recentPnL / maxDrawdown)

    return { entryZ, size }
协整关系

不同于相关性,协整意味着价差是平稳的、会回归均值。使用 ADF 检验确认。同币种跨所最强。

Z-Score 信号

价差标准化后的 Z-Score 指示偏离程度。|Z| > 2 入场,|Z| < 0.5 平仓。简单高效。

半衰期

均值回归的速度。半衰期越短(< 50 个 tick),策略换手越快,适合割头皮。

风险管理

止损阈值 (|Z| > 4) 防止价差发散。仓位按波动率动态调整。连续亏损自动缩仓。

统计套利模拟器

模拟两个协整资产的价差变化,实时观察 Z-Score 信号触发交易。调整入场/出场阈值体验不同策略效果:

割头皮统计套利模拟器 — 配对交易 Z-Score 策略

当前仓位
空仓
当前 Z-Score
-
总 PnL
+0.0000 U
胜率
0.0% (0/0)

7. 套利风控系统

净敞口控制

所有策略合并计算净多/空仓位。净敞口不能超过限额。三角套利本身无敞口,但单腿失败会产生临时敞口。

亏损熔断

单笔亏损、日内亏损、累计亏损三级熔断。触发后暂停对应策略,不影响其他策略运行。严重时全量撤单。

单腿保护

多腿套利中,任何一腿成交后,其余腿必须在 100ms 内完成。超时立即用市价对冲,将风险转化为已知亏损。

自适应缩仓

波动率飙升或连续亏损时,自动缩减所有策略仓位到 25%-50%。使用改进版 Kelly 准则动态计算最优仓位。

8. 基础设施与延迟优化

┌──────────────────────────────────────────────────────────────┐
│                    延迟优化技术栈                              │
├──────────────┬───────────────────┬───────────────────────────┤
│     层级      │      技术         │       延迟目标             │
├──────────────┼───────────────────┼───────────────────────────┤
│ 网络层        │ Co-location       │ 物理距离 < 1km            │
│              │ FPGA NIC          │ 网络延迟 < 5μs            │
│              │ Kernel Bypass     │ 避免系统调用开销            │
├──────────────┼───────────────────┼───────────────────────────┤
│ 数据处理      │ Lock-free Queue   │ 行情解析 < 1μs            │
│              │ 共享内存 OrderBook │ 簿更新 < 2μs              │
│              │ SIMD 指令集       │ 批量价格计算 < 0.5μs       │
├──────────────┼───────────────────┼───────────────────────────┤
│ 策略层        │ 预编译决策树       │ 信号生成 < 1μs            │
│              │ 缓存行友好布局     │ L1 Cache 命中率 > 95%     │
│              │ 分支预测优化       │ 减少 CPU stall            │
├──────────────┼───────────────────┼───────────────────────────┤
│ 执行层        │ 预构建报文模板     │ 序列化 < 0.5μs           │
│              │ 多路复用连接       │ 同时多腿下单              │
│              │ 零拷贝发送        │ 数据直接从用户态到网卡      │
├──────────────┼───────────────────┼───────────────────────────┤
│ 端到端        │ 行情 → 信号 → 下单 │ < 50-100μs (目标)        │
└──────────────┴───────────────────┴───────────────────────────┘

Co-location

服务器部署在交易所机房或同城数据中心。物理距离 < 1km。网络往返 < 100μs。

Kernel Bypass

使用 DPDK/io_uring 绕过内核网络栈。减少上下文切换和拷贝开销。

共享内存

多策略共享同一份 OrderBook 数据。使用 mmap + lock-free 结构避免锁竞争。

预热优化

JIT 预热、内存预分配、CPU 亲和性绑定。减少运行时不确定性。

9. 盈亏归因与监控

// === PnL 归因 ===
function dailyPnLAttribution(trades, positions):
    attribution = {
        triangularArb: { pnl: 0, trades: 0, volume: 0 },
        basisTrade:    { pnl: 0, trades: 0, volume: 0 },
        optionArb:     { pnl: 0, trades: 0, volume: 0 },
        marketMaking:  { pnl: 0, trades: 0, volume: 0 },
        statArb:       { pnl: 0, trades: 0, volume: 0 },
    }

    for trade in trades:
        strategy = trade.strategyTag
        attribution[strategy].pnl += trade.realizedPnl
        attribution[strategy].trades += 1
        attribution[strategy].volume += trade.notional

    // 加入返佣
    for rebate in rebates:
        attribution[rebate.strategy].pnl += rebate.amount

    // 计算各策略 Sharpe
    for strat in attribution:
        returns = getDailyReturns(strat, last30Days)
        strat.sharpe = mean(returns) / std(returns) * sqrt(365)
        strat.maxDrawdown = calcMaxDrawdown(returns)

    return attribution

// === 监控指标 ===
// Sharpe Ratio > 2.0:   优秀
// Sharpe Ratio 1.0-2.0: 良好
// Sharpe Ratio < 1.0:   需要优化
// 最大回撤 < 3%:         目标
// 胜率 > 55%:            做市/统计套利
// 日换手率:              衡量资金利用效率

策略归因

每笔成交标记 strategyTag。PnL 精确归属到三角/期现/做市/统计套利各策略。

交易所归因

跨所套利需按交易所分别计算 PnL。含手续费差异、返佣差异和出入金成本。

Sharpe Ratio

风险调整后收益指标。目标 > 2.0。低于 1.0 的策略需要优化或暂停。

实时仪表盘

Grafana + Prometheus 实时展示各策略 PnL、仓位、延迟百分位。异常自动触发 Slack 告警。