之前给大家介绍了一下三角套利的原理(https://wequant.io/blog/triangular-arbitrage-1/),现在为大家奉上考虑交易成本的三角套利方法和代码。
一、考虑交易成本情况下的策略调整
我们以第一个策略(正循环套利_挣CNY策略为例)。
我们设计的套利策略是被动套利策略,具体来讲,我们在LTC/BTC,LTC/CNY,BTC/CNY三个市场上都是作为taker去吃单。
在LTC/BTC市场上下买单,就必须使用该市场的卖一价格(ltc_btc_sell1_price)加上一定的滑点(ltc_btc_slippage,以百分比表示)来作为买单价格,即:
P3 = ltc_btc_sell1_price*(1+ltc_btc_slippage)
同理,在BTC/CNY市场下买单,就必须使用该市场的卖一价格(btc_cny_sell1_price)加上一定的滑点(btc_cny_slippage,以百分比表示)来作为买单价格,即:
P1= btc_cny_sell1_price*(1+btc_cny_slippage)
同理,可以推导出在LTC/CNY市场下卖单的价格如下:
P2 = ltc_cny_buy1_price*(1-ltc_cny_slippage)
假设各个市场的费率情况如下(以百分比表示):
LTC/BTC: ltc_btc_fee
BTC/CNY: btc_cny_fee
LTC/CNY: ltc_cny_fee
在LTC/BTC市场净买入1个LTC,实际上需要买入1/(1-ltc_btc_fee)个LTC,其中的ltc_btc_fee比例部分,是被交易平台收走的手续费。买入1/(1-ltc_btc_fee)个LTC需要花费的BTC数量是:
ltc_btc_sell_1_price*(1+ltc_btc_slippage)/(1-ltc_btc_fee)
在LTC/CNY市场,卖出1个LTC,得到的CNY是:
ltc_cny_buy_1_price*(1-ltc_cny_slippage)*(1-ltc_cny_fee)
在BTC/CNY市场,净买入
ltc_btc_sell_1_price*(1+ltc_btc_slippage)/(1-ltc_btc_fee)
个BTC,实际上需要买入
ltc_btc_sell_1_price*(1+ltc_btc_slippage)/[(1-ltc_btc_fee)*(1-btc_cny_fee)]
个BTC,其中btc_cny_fee比例部分,是被平台收走的手续费,而对应需要花费的CNY是:
btc_cny_sell_1_price*(1+btc_cny_slippage)*ltc_btc_sell_1_price*(1+ltc_btc_slippage)/[(1-ltc_btc_fee)*(1-btc_cny_fee)]
套利的前提条件是:得到的CNY > 花费的CNY,即:
ltc_cny_buy_1_price*(1-ltc_cny_slippage)*(1-ltc_cny_fee)> btc_cny_sell_1_price*(1+btc_cny_slippage)*ltc_btc_sell_1_price*
(1+ltc_btc_slippage)/[(1-ltc_btc_fee)*(1-btc_cny_fee)]
调整一下,对应的套利条件就是:
ltc_cny_buy_1_price >
btc_cny_sell_1_price*ltc_btc_sell_1_price*(1+btc_cny_slippage)*(1+ltc_btc_slippage) /[(1-btc_cny_fee)*(1-ltc_btc_fee)*(1-ltc_cny_fee)*(1-ltc_cny_slippage)]
考虑到各市场费率都在千分之几的水平,做精度取舍后,该不等式可以进一步化简成:
(ltc_cny_buy_1_price/btc_cny_sell_1_price-ltc_btc_sell_1_price)/ltc_btc_sell_1_price
>btc_cny_slippage+ltc_btc_slippage+ltc_cny_slippage+btc_cny_fee+ltc_cny_fee+ltc_btc_fee
基本意思就是:只有当公允价和市场价的价差比例大于所有市场的费率总和再加上滑点总和时,做三角套利才是盈利的。
如果价差满足条件,交易数量上的计算规则如下:
先计算以下几个值:
1.LTC/BTC卖方盘口吃单数量:ltc_btc_sell1_quantity*order_ratio_ltc_btc,其中ltc_btc_sell1_quantity 代表LTC/BTC卖一档的数量,order_ratio_ltc_btc代表本策略在LTC/BTC盘口的吃单比例。
2.LTC/CNY买方盘口吃单数量:ltc_cny_buy1_quantity*order_ratio_ltc_cny,其中order_ratio_ltc_cny代表本策略在LTC/CNY盘口的吃单比例。
3.LTC/BTC账户中可以用来买LTC的BTC额度及可以置换的LTC个数:
btc_available - btc_reserve,可以置换成
(btc_available – btc_reserve)/ltc_btc_sell1_price个LTC
其中,btc_available表示该账户中可用的BTC数量,btc_reserve表示该账户中应该最少预留的BTC数量(这个数值由用户根据自己的风险偏好来设置,越高代表用户风险偏好越低)。
4.BTC/CNY账户中可以用来买BTC的CNY额度及可以置换的BTC个数和对应的LTC个数:
cny_available - cny_reserve, 可以置换成
(cny_available-cny_reserve)/btc_cny_sell1_price个BTC,
相当于
(cny_available-cny_reserve)/btc_cny_sell1_price/ltc_btc_sell1_price
个LTC
其中:cny_available表示该账户中可用的人民币数量,cny_reserve表示该账户中应该最少预留的人民币数量(这个数值由用户根据自己的风险偏好来设置,越高代表用户风险偏好越低)。
5.LTC/CNY账户中可以用来卖的LTC额度:
ltc_available – ltc_reserve
其中,ltc_available表示该账户中可用的LTC数量,ltc_reserve表示该账户中应该最少预留的LTC数量(这个数值由用户根据自己的风险偏好来设置,越高代表用户风险偏好越低)。
拿到上面5个值之后,对它们取最小值,得到LTC的数量,作为LTC/BTC市场的下单数量。然后,根据LTC/BTC成交的数量,得到需要对冲的LTC数量和BTC数量,分别在LTC/CNY和BTC/CNY市场下对冲单,所有市场先下限价单进行对冲,超时之后补市价单,确保完全对冲。
对最小交易单位的处理规则如下:
如果欲下单的LTC数量小于最小LTC交易单位(取LTC/BTC和LTC/CNY两个市场的最小LTC交易数量的最大值)的某个倍数(比如2倍),则放弃本次套利;
如果欲下单的LTC数量对应的BTC数量( LTC数量乘上系数 ltc_btc_sell1_price)小于最小BTC交易单位(取LTC/BTC和BTC/CNY两个市场的最小BTC交易数量的最大值)的某个倍数(比如2倍),则放弃本次套利。
二、三角套利策略流程
(1)初始化:
a)在BTC/CNY市场放入如下资产:
i.BTC:1个BTC, 最少预留20% (btc_reserve = 20%)
ii.CNY:2万元,最少预留20% (cny_reserve = 20%)
b)在LTC/CNY市场放入如下资产:
i.LTC:100个LTC,最少预留20% (ltc_reserve = 20%)
ii.CNY:2万元,最少预留20% (cny_reserve = 20%)