币本位期现差价回归套利.ipynb下载
上次介绍了永续合约资金费率套利(https://www.fmz.com/digest-topic/6381 ), 通过做空永续合约期货,做多等量现货,持续的获取资金费率收益,在大的负溢价情况下,还能赚钱溢价回归收益。在8、9月份的牛市中,年化一度可达100%,是一个比较受欢迎的策略。
数字货币低风险套利中,还有一类策略没有介绍——期现基差回归套利。具体原理:
1.存在期货合约和现货的差价。交割合约的特点是到交割日才按照现货价格结算,因此在离交割日很远时,交割合约的交割非常容易收到市场情绪的影响,如果市场表现不错,更多的人会看好未来的价格,因此出现正溢价,当出现大跌时,往往会有负溢价。但总的来说交割合约的交割不会偏离现货太多,并且总会在交割日回归。
2.存在币本位交割合约,如币安有当季和次季交割合约。币本位交割合约和USDT本位永续合约区别较大,币本位使用币结算,而币价又在不断的变化,接下来将详细介绍。
本文代码可以直接运行,但由于网络原因,爬取数据部分需要科学上网,最好使用自己的电脑运行,或者使用Google的colab。
根据币安文档,收益= 交易方向×成交数量×合约倍数×(1 / 开仓价格- 1 / 平仓价格) = 持仓价值×(1 / 开仓价格- 1 / 平仓价格),做空时持仓价值为负。假如持有100张BTCUSD交割合约,每张价值100USD,开仓价格为10000USD,那么随着价格盈亏的情况如下:
通过计算分析,币本位做空或者做多的收益都是非线性的,以币收益衡量,做空最多亏一个持仓币量,赚币数量无上限,做多最多赚一个持仓币量,亏损则无上限。看起来做空更划算,但做空的收益伴随着币价的降低,按USD算其实没这么高。如果计算USD收益,情况正好相反,做空最多赚一个持仓价值,亏损则是无限的。
同时交易币本位合约,需要原本就持有币,如果考虑USD计价,此时 账户总价值 = (账户币数 + 持仓价值 ×(1 / 开仓价格- 1 / 平仓价格))×现货价格。如果持仓价值 = – 账户币数 × 开仓价格,即一倍杠杆做空,账户总价值 = 账户币数 × 开仓价格 × 平仓时现货价格 / 平仓价格, 考虑到交割合约的价格最终回归于现货价格,最终 账户总价值 = 账户币数 × 开仓价格。也就是说账户价值将以开仓价格锁定,不在随当前价格而改变,而根据分析,即使价格无限上涨,也不会爆仓。这就是套保的原理。一倍杠杆做空相当于把你现货的币以期货的价格提前卖出。
如果期货账户的币是从现货市场上购买的,那么 账户总收益 = 账户币数 × (开仓价格 – 现货购买价格),只要开仓,我们的收益就已经固定,和当前价格无关。其中的差价就是套利的收益。这就是期现套利的原理。
当然大部分情况下我们不必等待到交割日,如果差价降低可以提前平仓,这时候的 账户总收益 = 现货价值 × (开仓期现比/平仓期现比 – 1),只要开仓时期货现货价格比大于平仓时,并且能够覆盖手续费,此时就有收益。
In [15]:
import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
In [96]:
value = 100*100 #持仓价值
open_price = 10000 #开仓价格10000USD
long_profit_list = []
short_profit_list = []
long_usdt_profit_list = []
short_usdt_profit_list = []
close_range = range(1000,30000,10)
for p in close_range:
profit = value*(1/open_price-1/p)
long_profit_list.append(profit)
long_usdt_profit_list.append(profit*p)
short_profit_list.append(-profit)
short_usdt_profit_list.append(-profit*p)
In [97]:
#币本位计价收益
plt.figure(figsize=(12, 7), dpi=80)
plt.plot(close_range,long_profit_list,label=\'long\');
plt.plot(close_range,short_profit_list);
plt.plot(close_range,[1]*len(close_range),\'r--\');
plt.plot(close_range,[-1]*len(close_range),\'g--\');
plt.ylabel(\'profit\');
plt.xlabel(\'close price\');
plt.grid(True)
plt.annotate(\'Short profit\', xy=(4500, 1.5), xytext=(7000, 2.5),arrowprops=dict(facecolor=\'black\'));
plt.annotate(\'Long profit\', xy=(4500, -1.5), xytext=(7000, -2.5),arrowprops=dict(facecolor=\'black\'));
plt.annotate(\'Open price\', xy=(10000, 0), xytext=(13000, 2.5),arrowprops=dict(facecolor=\'black\'));
Out[97]:
In [101]:
#收益用USD计算
plt.figure(figsize=(12, 7), dpi=80)
plt.plot(close_range,long_usdt_profit_list,label=\'long\');
plt.plot(close_range,short_usdt_profit_list);
plt.ylabel(\'profit\');
plt.xlabel(\'close price\');
plt.annotate(\'Short profit\', xy=(5000, 5000), xytext=(7000, 10000),arrowprops=dict(facecolor=\'black\'));
plt.annotate(\'Long profit\', xy=(5000, -5000), xytext=(7000, -10000),arrowprops=dict(facecolor=\'black\'));
plt.grid(True)
Out[101]:
以币安交易所交割数据数据为例,共存在 BTCUSDT,ETHUSDT,ADAUSDT,LINKUSDT,BCHUSDT,DOTUSDT,XRPUSDT,LTCUSDT,BNBUSDT 9个交易对可以用于套利交易。这里选取ETH具体分析交割合约与现货的溢价变化。
今年以来ETH从600U起步,最高涨到5月份的4000U,然后跌倒6月、7月的2000U一下,最近又重新回到3500U,行情大起。考察到期日为210625,210924,211231的三个交割合约,其中210625溢价长期维持在8%,如果10%开始套利,6%平仓,4个月大概有4次机会,年化在50%以上。210924溢价最高15%以上,现在已经回归,还有较长时间到期的211231,最高溢价5%。可见只要耐心等待,ETH上套利机会很多。
读者可以自行更改交易对,情况基本类似,总的来说,今年1-4月份是个很好的区间。
In [103]:
## 当前交易对
Info = requests.get(\'https://dapi.binance.com/dapi/v1/exchangeInfo\')
symbols = [s[\'symbol\'] for s in Info.json()[\'symbols\']]
In [106]:
symbols_nq = list(filter(lambda x:x.split(\'_\')[-1]==\'211231\', symbols)) #次季合约
symbols_q = list(filter(lambda x:x.split(\'_\')[-1]==\'210924\', symbols)) #当季合约
symbols_s = [s.split(\'_\')[0]+\'T\' for s in symbols_nq] # 现货交易对
In [108]:
\',\'.join(symbols_s)
Out[108]:
In [109]:
def GetKlines(symbol=\'BTCUSDT\',start=\'2020-8-10\',end=\'2021-8-10\',period=\'1h\',base=\'fapi\',v = \'v1\'):
Klines = []
start_time = int(time.mktime(datetime.strptime(start, \"%Y-%m-%d\").timetuple()))*1000 + 8*60*60*1000
end_time = int(time.mktime(datetime.strptime(end, \"%Y-%m-%d\").timetuple()))*1000 + 8*60*60*1000
intervel_map = {\'m\':60*1000,\'h\':60*60*1000,\'d\':24*60*60*1000}
while start_time < end_time:
mid_time = min(start_time+1000*int(period[:-1])*intervel_map[period[-1]],end_time)
url = \'https://\'+base+\'.binance.com/\'+base+\'/\'+v+\'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000\'%(symbol,period,start_time,mid_time)
res = requests.get(url)
res_list = res.json()
if type(res_list) == list and len(res_list) > 0:
start_time = res_list[-1][0]
Klines += res_list
elif type(res_list) == list:
start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
else:
print(url)
df = pd.DataFrame(Klines,columns=[\'time\',\'open\',\'high\',\'low\',\'close\',\'amount\',\'end_time\',\'volume\',\'count\',\'buy_amount\',\'buy_volume\',\'null\']).astype(\'float\')
df.index = pd.to_datetime(df.time,unit=\'ms\')
return df
In [110]:
symbol = \'ETH\'
df_s = GetKlines(symbol=symbol+\'USDT\',start=\'2020-12-26\',end=\'2021-9-15\',period=\'1h\',base=\'api\',v=\'v3\')
df_nq = GetKlines(symbol=symbol+\'USD_211231\',start=\'2021-6-26\',end=\'2021-9-15\',period=\'1h\',base=\'dapi\')
df_q = GetKlines(symbol=symbol+\'USD_210924\',start=\'2021-3-26\',end=\'2021-9-15\',period=\'1h\',base=\'dapi\')
df_lq = GetKlines(symbol=symbol+\'USD_210625\',start=\'2020-12-26\',end=\'2021-6-24\',period=\'1h\',base=\'dapi\')
In [128]:
# 现货价格
df_s.close.dropna().plot(figsize=(16,6),grid=True);
Out[128]:
In [139]:
# 上季合约溢价
(100*(df_lq.close-df_s.close)/df_s.close).dropna().plot(figsize=(16,6),grid=True);
# 当季合约的溢价
(100*(df_q.close-df_s.close)/df_s.close).dropna().plot(figsize=(16,6),grid=True);
# 次季合约溢价
(100*(df_nq.close-df_s.close)/df_s.close).dropna().plot(figsize=(16,6),grid=True);
Out[139]:
由于210924合约即将到期,这里主要考察还有3个月到期的211231,目前基本溢价在3%附近,最高的溢价是5%,可以说机会不是特别好,但210924到期后,将产生新的次季合约,距离交割时长6个月,会有更多的机会。
In [143]:
df_all = pd.DataFrame(index=pd.date_range(start=\'2021-6-26\', end=\'2021-9-16\', freq=\'1H\'),columns=symbols_s)
for i in range(len(symbols_nq)):
symbol_nq = symbols_nq[i]
symbol_s = symbols_s[i]
df_s = GetKlines(symbol=symbol_s,start=\'2021-6-26\',end=\'2021-9-16\',period=\'1h\',base=\'api\',v=\'v3\')
df_nq = GetKlines(symbol=symbol_nq,start=\'2021-6-26\',end=\'2021-9-16\',period=\'1h\',base=\'dapi\')
df_all[symbol_s] = (100*(df_nq.close-df_s.close)/df_s.close).drop_duplicates()
In [144]:
df_all.dropna().plot(figsize=(16,10),grid=True);
Out[144]:
本文主要介绍了利用交割合约和现货之间差价的回归进行套利交易。这种套利方式是一种普遍的交易行为,有着很多优势:
主要风险:
买好币上币库:https://www.kucoin.com/r/1f7w3