博客

量化套利入门 03|三个交易对绕一圈,多出来的钱从哪来?

一笔钱换三次又回到原币种,结果比出发时多。多出来的钱确实有人付,只是轮得到谁拿,取决于手续费、盘口厚度和最后那一笔能不能成交。

约 12 分钟量化套利入门系列

匈牙利央行编过一本外汇市场教材,里面有个三行就能算完的例子。1 美元换 1.25 瑞郎,1 英镑换 1.80 美元。按这两个价格,1 英镑应该值 1.80 × 1.25 = 2.25 瑞郎。现在假设市场上有人报出 1 英镑换 2.30 瑞郎。

拿 1 英镑去找他,换回 2.30 瑞郎。2.30 瑞郎按 1.25 换成美元,得到 1.84 美元。1.84 美元按 1.80 换回英镑,得到约 1.0222 英镑。钱从英镑出发,又回到英镑,三次兑换以后多了 2.22%。

这就是三角套利。整个过程没有赌英镑涨跌,起点和终点是同一种货币。多出来的钱来自三个报价互相对不上,而那个对不上的报价背后有人买单。报 2.30 的人愿意为每一英镑多付 0.05 瑞郎,你从他那里换走多少,他就多付多少。

只是教材里的 2.22% 在今天几乎见不到。一项研究翻查了币安从 2017 年 11 月到 2019 年 8 月的近 20 亿笔成交,能认出来的完整三角套利只占全部成交的 0.24%,扣掉手续费后平均每笔赚 9.3 个基点。1 个基点是 0.01%,也就是一万块钱赚九块多。这篇要讲清楚两件事。三个价格为什么会对不上,以及屏幕上看到的环,为什么大多变不成账户里的钱。

复古金融终端风插画:三座兑换柜台组成闭合环路,资产绕行一圈回到起点
三次兑换以后回到原币种。终点的钱比起点多,环才真正闭上。

三个报价为什么会对不上

英镑换瑞郎有两条路。一条是直接换,另一条是先换成美元,再用美元换瑞郎。两条路最后拿到的瑞郎应该差不多,否则大家都会去走划算的那条。绕路算出来的价格叫交叉汇率。例子里绕路价是 2.25,直达价是 2.30,同一英镑在两条路上差了 0.05 瑞郎。

环有两个方向,只有一个方向赚钱。假如直达价反过来报成 2.20,就要倒着走。1 英镑先换成 1.80 美元,再换成 2.25 瑞郎,最后按 2.20 换回英镑,得到约 1.0227 英镑。规则其实很朴素,在哪条路上英镑卖得贵,就从哪条路卖出英镑,再从便宜的路买回来。

可以把三个报价想成三个兑换柜台,柜员各看各的屏幕。美元柜台刚改了牌价,瑞郎柜台的柜员还没反应过来,牌子上挂的还是旧价格。这个类比说中了一件事,三个价格由不同的人在不同时刻更新,彼此之间天然有时差。它不像的地方也要说清楚。真实市场里没有固定的柜员,报价是许多挂单叠出来的,而且没反应过来的时间常常按毫秒计算。柜台类比容易让人以为可以慢慢走过去换钱,现实里等你走到,牌子早换了。

所以付钱的人通常就是挂着旧价格的一方。他挂单时价格可能是合理的,市场动了,他还没来得及撤单,被人按过时的价格成交。这笔亏损不大,但很确定。套利者赚到的,就是他慢的那一下。

完整算例可以在匈牙利央行的外汇市场手册里找到。数字货币市场把货币换成了交易对,道理不变。USDT 买 BTC,BTC 换 ETH,ETH 再卖回 USDT。三条实际成交汇率相乘大于 1,扣完费用还有剩余,环才成立。

换成真实盘口,先把方向和费用算对

教材只给一个汇率,真实报价至少有两个。兑换店的牌子上,每种货币都写着买入价和卖出价。交易所也一样,买一是此刻出价最高的买单,卖一是要价最低的卖单。你主动买,只能接卖一。你主动卖,只能接买一。三条腿各吃一次买卖价差,纸面上的利润还没开始算手续费,就已经被咬掉一块。

方向也容易弄反。交易所通常只挂 ETH/BTC,不挂 BTC/ETH。报价 0.05 的意思是 1 ETH 值 0.05 BTC。你手里拿着 BTC 想换 ETH,要用 BTC 数量除以价格。手里拿着 ETH 想换 BTC,才是乘以价格。三条边里有一条乘除用反,纸面利润可能从正数瞬间变成负数。

我习惯先拿一小笔虚拟本金顺着路径走一遍,每个数字后面都写上单位。下面用一组假设的报价算一次,数字是为了演示,不对应任何真实时刻。

从 10,000 USDT 出发。BTC/USDT 的卖一是 60,000,买到 0.166667 BTC。ETH/BTC 的卖一是 0.05000,用 BTC 买 ETH 要除以价格,得到 3.33333 ETH。ETH/USDT 的买一是 3,012,卖掉以后拿回 10,040 USDT。一圈毛利 40 USDT,也就是 0.40%。

再扣手续费。假设每条腿收 0.1%,三条腿就是三次乘以 0.999,合起来约等于乘以 0.997。10,040 USDT 扣完以后剩约 10,009.9 USDT,净利润不到 10 USDT。手续费吃掉了四分之三。前面那项币安研究假设套利者处在最低费率档,吃单手续费只有 0.024%,三条腿合计约 0.072%。同样这一圈,净利润能剩下约 0.33%。同一个环,费率档位不同,可能是一门生意,也可能只够给交易所打工。

这 0.40% 本身也有前提。它默认三个报价在同一瞬间都有效,而且每一档挂单都够你吃。这两条,后面几节会一条条拆开。

程序眼里,这是一张找环的图

把每种资产当成一个点,把能交易的方向当成一条带箭头的边。BTC/USDT 在图上是两条边。用 USDT 买 BTC 是一个方向,按卖一算。把 BTC 卖成 USDT 是另一个方向,按买一算。边上记的是扣完手续费后,1 个单位能换到多少。

程序要做的,就是找从某个点出发、沿箭头走回原点、一路乘下来大于 1 的环。规模其实不吓人。那项研究统计过,数据期间币安有 204 个币、704 个交易对,能组成的三角环一共 6,534 个。每次行情变化,把这几千个三角形重新乘一遍,对计算机来说很轻松。

你在资料里还会看到负对数和 Bellman-Ford 这类说法。它们解决的是同一个问题,只是换了个算法。对数有个性质,几个数相乘取对数,等于各自取对数后相加。一圈乘积大于 1,取对数后总和就大于 0。再加个负号,就变成一圈的总长度小于 0。图算法里把这种环叫负权环,Bellman-Ford 是寻找它的经典方法。这样做的好处是能顺带找四条、五条边的长环,路径一多,逐个枚举就吃力了。它的局限也要知道,算法找到的是某一个负权环,未必是利润最大的那个,更不知道这个环能做多大。在单一交易所里只找三角形时,直接枚举往往更简单,也更容易排查。

搜索只负责提出候选,下单前还要过第二遍验算。三条行情是不是同一时刻的,有没有一条已经超过允许的延迟,交易对是否暂停,最小下单量和数量精度能不能满足,都是门槛。公式算出来大于 1,不代表交易所愿意接下那三张订单。

利润率会随着下单量缩水

假设按最优报价走一圈能赚 0.3%。第一条腿的卖一只挂着价值 500 美元的单子,第二条腿能吃 3,000 美元,第三条腿有 1 万美元。这个环能按最好价格做完的规模只有 500 美元。再往上做,第一条腿就要吃到第二档、第三档,价格一档比一档差。

所以程序不只问有没有环,还要问这个环做多大最划算。做得太小,利润还不够覆盖系统和资金的占用。做得太大,滑点把利润吃光。滑点就是你实际成交的平均价,比下单时看到的价格更差的那部分。最合适的规模,通常卡在订单簿某一档台阶的前面。

更稳的算法是从最薄的那条边倒推。先确定那条边在可接受的价格内最多能成交多少,再换算出前后两条腿各需要多少数量,逐档检查盘口。这样不会出现第一条腿买了一大堆,走到第二条腿才发现门太窄。

数量在三条腿之间传递时,还会被精度规则切掉零头。研究里举过币安 ETH/BTC 的例子,这个交易对的数量最小步长是 0.001 ETH。卖出 0.153 ETH,按 0.018876 成交,扣掉 2.4 个基点的手续费,得到 0.002887334873 BTC。下一步只能用掉 0.00288733 BTC,剩下的零头留在账户里。单笔看不值一提,做上万次以后,账户里会积起一堆换不出去的碎币。回测若默认每一步都能无限精确,这些碎币也会被算成利润。

复古金融终端风插画:三角兑换环路缺少最后一段,交易者被留在中间资产上
少成交一条腿,这个环路就会变成一笔你原本没打算持有的仓位。

最危险的是最后一条腿

在中心化交易所里,三条腿没法保证一起成交。程序可以把指令发得很快,交易所却是一笔一笔撮合的。前两笔成交、第三笔失败,账户里就留下一个本来没想持有的币。它的价格接下来往哪走,跟你算好的那个环已经没有关系。

顺序本身也是问题。那项研究提到,币安在研究期间不支持把多笔订单打包成一个请求发出去。第二条腿要卖的是第一条腿换来的币,如果第二笔订单比第一笔先到交易所,账户里还没有这个币,订单直接失败。

更常见的麻烦来自同行。研究里观察到,有时两个甚至更多机器人同时拿到同一个中间币,再同时去抢下一步的最好价格。先到的人把那一档吃光,后到的人只能按更差的价格卖,或者把手里的币拆开换成别的几种币止损。按资金加权算,拆成几种币退出的平均亏 23.8 个基点,一次全换成一种币的平均亏 27.4 个基点。而经中间币绕路换币成功一次,同样口径下平均只比直接换好 14.4 个基点。粗算下来,失败一次,要成功将近两次才补得回来。

常见的处理是先做最薄、最容易消失的那条腿,再做流动性更深的两条。也有人三笔同时发出,接受部分成交,再立刻对冲剩下的敞口。先做最薄的一条也不总是对的。最薄的币若拿到手以后很难卖,先成交反而把最危险的仓位留给了自己。排序要同时看三件事,这条腿消失的概率,失败以后对冲有多难,以及失败会亏多少。系统可以给每种失败情形估一个损失,再选预期损失最小的顺序。

链上的情况换了一套规则。三次兑换如果写进同一笔合约交易,要么全部成功,要么整笔回滚,只成交两条腿的问题没有了。可是从你发出交易到它进入区块,池子里的价格可能已经变了。合约一般会设置最低输出,结果不够就整笔回滚。本金没丢,gas 费照样花掉。gas 是付给区块链网络的执行费,失败的交易也要付。利润若很醒目,其他机器人还会出更高的费用插到你前面,或者照抄你的路径。链上三角套利把只成交一半的风险,换成了抢区块排序的竞争。

机会越来越短,钱也越来越薄

外汇市场很早就有三角套利。EBS 是银行之间交易主要货币的一个电子撮合平台,研究者拿它的高频成交数据做过一项研究,发表在 2014 年的 Journal of Finance。他们的结论是,算法交易让三角套利机会出现的频率明显下降,而且主要靠电脑主动去吃别人挂出的报价。这正好对上前面那个问题。钱由挂着旧价格的人付,电脑把他挂错价的时间压得越来越短。机器没有发明这个环,只是比人更快按完三次计算器。

加密市场交易对多、场所分散、小币种盘口薄,看起来机会更多。币安那项研究给出的图景要冷静得多。已经完整做完三条腿的套利里,约 95% 是赚钱的,扣费后平均 9.3 个基点。这是在假设套利者处于最低费率档、几乎全部用吃单的前提下算的。作者的判断是,对大多数参与者来说,交易所的费率结构让完整的三角套利做不出利润。

研究里更有意思的发现是,很多机器人干脆不走第三条腿。它们只做前两步,把 A 币经中间币换成 C 币,拿到比直接换更好的价格。这种两步换币占全部成交的 2.71%,是完整三角套利的 11 倍,平均比直接换好 14.4 个基点。作者认为,参与者是把它当成调仓的便宜通道来用。环里最难走的那一步,很多人选择不走。

这些数字也有边界。研究用的盘口快照 60 秒才有一份,大多数时候买一和卖一是用成交均价估出来的。它统计的是已经发生的成交,看不到那些算出来有利、最后没敢下单或没抢到的候选。所以它能说明完整三角套利有多稀薄,却说不准一个新入场的程序今天还能分到多少。

回到那 2.22%

教材里那一圈能多出 2.22%,是因为有人挂着一个过时的 2.30。今天的市场里,这样的报价仍会出现,只是存在的时间很短,金额很小,而且一出现就有许多程序同时扑上去。你能拿到多少,取决于费率比别人低多少,速度比别人快多少,以及三条腿出事时能不能体面地退出。

判断一条环,可以按这个顺序走。先确定每条边的交易方向,别把买价和卖价用反。再按目标数量沿订单簿算出三条腿的平均成交价。之后扣掉三次手续费,以及链上的 gas 或借币成本。最后模拟某条腿只成交一部分时,系统怎样退出,要亏多少。

如果一条环只有在三笔都按最优报价瞬间成交时才赚钱,它更像屏幕保护程序,不像交易策略。

上线以后,每个候选环都要留快照。三条行情的时间戳、计划数量、预期利润、实际成交和失败原因都要记下来。否则日报只会写着今天发现八千次机会,账户却一分钱没多。比起机会总数,我更想看八千个候选里有多少走到下单、多少全部成交、最后剩多少净利润,每一层又是为什么掉下去的。