跨交易所价差套利匹配算法
给出的数据结构:
bids = {
'ex1-0.00024': [0.95, 10],
'ex2-0.0005': [0.98, 10],
'ex3-0.0002': [1.00, 5],
'ex4-0.00025': [1.02, 4],
'ex5-0': [0.94, 11]
}
asks = {
'ex1-0.00024': [0.96, 50],
'ex2-0.0005': [1.03, 8],
'ex3-0.0002': [1.01, 2],
'ex4-0.00025': [1.04, 5],
'ex5-0': [0.96, 3]
}
key = 交易所名称-手续费,value = [价格, 数量]。
bids= 买单一档报价(该交易所上有人愿意出最高价买入)asks= 卖单一档报价(该交易所上有人愿意出最低价卖出)
以上为两个字典,分别代表当前买单一档报价和卖单一档报价,其中key为:交易所名称-手续费,value为:[价格,数量]
需求:
1.计算有价差套利机会的两个交易所,扣掉手续费后有利润
2.某一交易所套利完成后,减少挂单量,继续匹配下一个交易所,直到挂单量清0
一、套利逻辑与条件
跨所套利的经典做法:在"卖出价(ask)最低"的交易所买,在"买入价(bid)最高"的交易所卖。
- 在交易所 B 以
ask_B买入 1 单位,实际成本 =ask_B + fee_B(买入付本方手续费); - 在交易所 A 以
bid_A卖出 1 单位,实际所得 =bid_A - fee_A(卖出付本方手续费);
- 套利单位利润:
profit=(bidA−feeA)−(askB+feeB)\text{profit} = (\text{bid}_A - fee_A) - (\text{ask}_B + fee_B)profit=(bidA−feeA)−(askB+feeB)
- 只有当 text{profit} 0\\text\{profit\} \> 0text{profit}0 时才存在扣费后有利润的套利机会(且必须跨交易所,同一交易所自我对冲无意义)。
说明:key 中的手续费(如
0.00024)为费率,套利单边各付一次,故买方加费、卖方扣费。
二、核心算法
Step 1:找出所有"扣费后仍有利润"的跨所机会
遍历所有 (bid 交易所, ask 交易所) 组合,排除同所,计算扣费后单位利润,取利润 > 0 的,并按单位利润降序排列。
Step 2:贪心按量匹配,每完成一笔扣减挂单,直到挂单清 0
反复执行:
- 取当前单位利润最高的机会;
- 成交数量 = min(买方挂单量, 卖方挂单量);
- 分别扣减两侧挂单量,挂单量减为 0 的报价从盘中移除;
- 若无利润为正的机会或任一侧挂单清 0,则停止。
伪代码
def parse(m, sign):
# m 是 bids 或 asks dict
# sign=+1 卖出方扣费, sign=-1 买入方加费(便于统一)
def find_profitable(bids, asks):
opps = []
for A in bids: # A 是卖出方(以 bid 卖)
for B in asks: # B 是买入方(以 ask 买)
if A.ex == B.ex: continue
sell_net = A.price - A.fee
buy_cost = B.price + B.fee
if sell_net - buy_cost > 0:
opps.append(
(buy=B, sell=A, unit_profit=sell_net-buy_cost,
qty=min(A.qty, B.qty)))
return sortby(opps, -unit_profit)
def match_all(bids, asks):
trades = []
while True:
opps = find_profitable(bids, asks)
if not opps: break
best = opps[0]
qty = best.qty
# 扣减买卖双方挂单
asks[best.buy].qty -= qty
bids[best.sell].qty -= qty
# 挂单清0则移除对应报价
if asks[best.buy].qty == 0: del asks[best.buy]
if bids[best.sell].qty == 0: del bids[best.sell]
trades.append(best.with(qty) )
return trades
三、运行结果(已在本机实际运行验证)
第一步:所有扣费后有利润的跨所套利机会(按利润降序)

注:ex1 既出现在 bids 又出现在 asks,但跨所套利要求"买、卖在不同交易所",故本表只列出净值严格为正、(买,卖)跨所的配对。
第二步:贪心按量匹配(每笔扣减挂单,直到无法套利/挂单清 0)
| 笔序 | 买入所 | 卖出所 | 数量 | 单位利润 | 该笔总利润 |
|---|---|---|---|---|---|
| 1 | ex5 (买) | ex4 (卖) | 3 | 0.059750 | 0.179250 |
| 2 | ex1 (买) | ex4 (卖) | 1 | 0.059510 | 0.059510 |
| 3 | ex1 (买) | ex3 (卖) | 5 | 0.039560 | 0.197800 |
| 4 | ex1 (买) | ex2 (卖) | 10 | 0.019260 | 0.192600 |
共成交 4 笔,总套利利润 = 0.629160
执行细节解释:
- ex4 的卖出端(bid=1.02)只有 4 手,先被利润最高的 ex5(3手)吃掉,剩 1 手被 ex1 吃掉 → ex4 卖单清 0 出局;
- 之后 ex3(bid=1.00)吃掉 ex1 的 5 手 → ex3 卖单清 0 出局;
- 最后 ex2(bid=0.98)吃掉 ex1 剩余的 10 手 → ex1 买单清 0;
- 到此所有"盈利配对"都做满,剩余报价(ex1 asks、ex5 剩余 bids、ex4/ex3/ex2 已清 0 或买不到便宜货)已无正利润跨所组合,算法停止。

325

被折叠的 条评论
为什么被折叠?



