掘金社区
跨期套利策略简介
什么是跨期套利?
跨期套利是套利交易中最普遍的一种,是股指期货的跨期套利(Calendar Spread Arbitrage)即为在同一交易所进行同一指数、但不同交割月份的套利活动。
跨期套利是利用同一商品但不同交割月份之间正常价格差距出现异常变化时进行对冲而获利的,又可分为牛市套利(bull spread)和熊市套利(bear spread)两种形式。例如在进行金属牛市套利时,交易所买入近期交割月份的金属合约,同时卖出远期交割月份的金属合约,希望近期合约价格上涨幅度大于远期合约价格的上帐幅度;而熊市套利则相反,即卖出近期交割月份合约,买入远期交割月份合约,并期望远期合约价格下跌幅度小于近期合约的价格下跌幅度。
什么是价差套利?
价差套利的前提是做出商品期货品种间同一月份的价格之间的价差,并且画出价差的时间序列图,分析价差,寻找合理的价差范围,超出合理的价差变动范围时如何进行操作。
协整性检验
下图为两个时间序列(“RB1701”,“RB1705”)。
可以看出,两只股票具有同涨同跌的规律,长期以来两只股票的价差比较平稳,当价差变大或变小时,会有某种“力量”使它回归均值,我们的策略也正基于此。但仅凭肉眼观测,肯定是不严谨的,这就需要协整性检验。如果两个股票具有强协整性,那么无论它们中途怎么走的,它们前进的方向总是一样的。
什么是平稳性?
提到协整性,就不得不提平稳性。在数学中,平稳随机过程(Stationary random process)或者严平稳随机过程(Strictly-sense stationary random process),又称狭义平稳过程,是在固定时间和位置的概率分布与所有时间和位置的概率分布相同的随机过程:即随机过程的统计特性不随时间的推移而变化。这样,数学期望和方差这些参数也不随时间和位置变化。平稳在理论上有严平稳和宽平稳两种,在实际应用上宽平稳使用较多。宽平稳的数学定义为:对于时间序列 $Y_t$,若对任意的$t,k,mt$,满足:
$$E(Y_t)=E(Y_{t+m})$$
$$cov(Y_t,Y_{t+k})=cov(Y_{t+k},Y_{t+k+m})$$
则称时间序列$ Y_t$ 是宽平稳的。
平稳性(stationarity)是一个序列在时间推移中保持稳定不变的性质,或许您对于上图的“价差平稳”不认可,我们将价差做了一阶差分,可以看出,它始终是围绕着一个长期均值(0)在波动。
什么是整性?
如果某一非平稳序列$X_t$能够经过$d$次差分后变成平稳序列,就称该序列为$d$阶整性,也成为单整,记为$X_t \sim I(d)$。
什么是协整性?
协整性是指若两个或多个非平稳的变量序列,其某个线性组合后的序列呈平稳性。
假设两个非平稳时间序列$Yt,Xt$,且有$Yt \sim I(d) $和 $X(t)\sim I(b)$。如果存在某一参数向量$(1-\beta)$,使得:
$$[Y_t-\beta X_t]\sim I(d-b)$$
其中,$b$为正整数,$(1-\beta)$为协整向量,$\beta$为协整系数。
那么$Y_t,X_t$之间存在协整,记为:
$$Y_t,X_t \sim CI(d,b)$$
如果$d-b=0$,那么:
$$Y_t,X_t \sim CI(d,d)$$
有:
$$\mu(Y_t-\beta X_t)\sim I(0)$$
意味着回归方程
$$Y_t=\beta X_t +\mu_t$$
有意义,因为这时$\beta$惟一存在。同时,时间序列$Y_t,X_t$在时间上的实际变动与长期均衡轨道的偏差$\mu_t$是收敛的。就是说,即使在某一时点上,$Y_t,X_t$的运动方向相互背离,当它们之间存在的长期规律或内在力量迫使它们趋向一致。即$\mu_t$服从均值为0,方差为1的正态分布。因而判定$Y_t$和$X_t$之间存在长期均衡关系。
协整概念是一个强有力的概念。因为协整允许我们刻画两个或多个序列之间的平衡或平稳关系。对于每一个序列单独来说可能是非平稳的,这些序列的矩,如均值、方差或协方差随时间而变化,而这些时间序列的线性组合序列却可能有不随时间变化的性质。
什么是单位根检验?
常用的时间序列数据单整和协整阶数的检验,是所谓的单位根检验。
DF(Dickey-Fuller)检验
考虑时间序列$Y_t$,有一阶自回归:
$$Y_t=\rho Y_{t-1}+ε_t$$
其中,$\rho $为代估参数,$ε_t$为白噪声。
如果$\rho =1$,则Y_t为随机游走过程;如果$\left | \rho \right |<1$,则$Y_t$为0阶平稳过程。基于此,1979年迪基和富勒提出检验$\rho$ 检验。称DF检验,其回归方程为:
$$DY_t=\delta Y_{t-1}+ε_t$$
其中,$\delta$为待估参数,$DY_t=Y_{t-1}-Y_{t}$
具体做法是用最小二乘法求出上式中的$\delta$,并检验其负性:
$$H_0:\delta=0$$
$$H_1:\delta<0$$
如果接受$H_0$,意味着$Yt \sim I(d) $,$d\geq1$。如果拒绝$H_0$,接受$H_1$,则$Yt \sim I(0) $
ADF(Augmented Dickey-Fuller)检验
如果$DY_t$存在自回归,考虑截距$\delta_0$,趋势项$\theta_t$,则有ADF检验方程:
$$DY_t=\delta Y_{t-1}+\delta_0+\theta_t+\sum_{i=1}^{k} \delta_i \times DY_{t-i}+ε_t$$
为什么需要检验协整性?
如果我们不经检验而求得$Y_t$,$X_t$之间的某种关系,如$Y_t=\lambda X_t \cdot \mu_t$。由于这种关系本身可能不存在,得到这样的关系纯属偶然。因而用此关系式所得到的分析,判断和预测结果会不真实乃至荒谬。
怎样检验协整性?
本策略采用“Engle-Granger两步协整检验法”,
Engle-Granger两步协整检验法用普通最小二乘法估计这些变量之间的平稳关系系数,然后用单位根检验来检验残差,如果序列是平稳的,则不存在单位根, 否则就会存在单位根。ADF检验的原假设是存在单位根,因此如果得到的统计量显著小于3个置信度(1%,5%,10%)的临界统计值时,说明是拒绝原假设的。
我们以两个序列$Y_t$和$X_t$为例,在检验协整性之前,首先要对序列的单整性进行检验,只有当两个序列单整阶数相同时,才有可能存在协整关系。
在$Y_t$和$X_t$具有相同单整阶数,通过单整性检验之后,我们用最小二乘法估计模型:
$$Y_t = β_0 + β_1X_t + ε_t $$
并计算相应的残差序列:
$$e_t =Y_t- \bar{β_0} -\bar{β_1}X_t $$
然后,检验残差序列的平稳性:
$$ De_t=\delta e_{t-1}+\delta_0+\theta_t+\sum_{i=1}^{k} \delta_i \times De_{t-i}+ε_t$$
利用ADF检验法,检验在上述估计下得到的回归方程的残差$e_t$是否平稳(如果$Y_t$和$X_t$不是协整的,则他们的任意组合都是非平稳的,因此残差$e_t$将是非平稳的)。也就是说,我们检验残差$e_t$的非平稳的假设,就是检验$Y_t$和$X_t$不是协整的假设。
跨期套利策略实现(基于掘金量化平台)
策略思想
- 首先获取套利(RB1801,RB1805)标的价格序列。
- 根据$EG$两步法(1、序列同阶单整 2、$OLS$残差平稳)判断序列具有协整关系之后(若无协整关系则全平仓位不进行操作)。
- 通过计算两个真实价格序列回归残差的1.5个标准差上下轨,并在价差突破上轨的时候做空价差,价差突破下轨的时候做多价差并在回归至标准差水平内的时候平仓。
策略主要步骤实现
订阅数据
subscribe(symbols=symbols, frequency='1d', count=31, wait_group=True)
订阅数据需要在定义init
函数里面设置,并调用subscribe
函数,这里注意,我们需要通过计算前三十根bars来作为开平仓的标准,并在当前bar上做出开平仓操作,所以需要获取31根bar:
symbols
需要设置订阅的标的代码。frequency
需设置订阅数据的周期级别,这里设置1d
表示以一天为周期。count
需要设置获取的bar的数量
数据获取
data_rb = context.data(symbol=symbol, frequency='1d', count=31, fields='close')
订阅数据之后,需要获取已经订阅的数据来进行操作,这时需调用context.data
函数:
symbols
需要设置订阅的标的代码。frequency
需设置订阅数据的周期级别,这里设置1d
表示以一天为周期。count
需要设置获取的bar的数量fields
需要设置返回值的种类
协整性检验
def cointegration_test(series01, series02):
urt_rb1801 = ts.adfuller(np.array(series01), 1)[1]
urt_rb1805 = ts.adfuller(np.array(series02), 1)[1]
print (ts.adfuller(np.array(series01), 1))
# 同时平稳或不平稳则差分再次检验
if (urt_rb1801 > 0.1 and urt_rb1805 > 0.1) or (urt_rb1801 < 0.1 and urt_rb1805 < 0.1):
urt_diff_rb1801 = ts.adfuller(np.diff(np.array(series01)), 1)[1]
urt_diff_rb1805 = ts.adfuller(np.diff(np.array(series02), 1))[1]
# 同时差分平稳进行OLS回归的残差平稳检验
if urt_diff_rb1801 < 0.1 and urt_diff_rb1805 < 0.1:
matrix = np.vstack([series02, np.ones(len(series02))]).T
beta, c = np.linalg.lstsq(matrix, series01)[0]
resid = series01 - beta * series02 - c
if ts.adfuller(np.array(resid), 1)[1] > 0.1:
result = 0.0
else:
result = 1.0
return beta, c, resid, result
else:
result = 0.0
return 0.0, 0.0, 0.0, result
else:
result = 0.0
return 0.0, 0.0, 0.0, result
协整性检验需要我们自己定义函数(如以上代码),此函数需要输入两个序列,返回值为回归方程中的各项参数及两序列是否具有协整性的结果。
策略回测分析
回测报告
分析
我们选取了2017年7月至2017年10月作为回测周期,“RB1801”与“RB1805”作为标的合约,价差均值周期设为30,可以看出:
- 胜率(具有盈利的平仓次数与总平仓次数之比)达到了50%。
- 卡玛比率(年化收益率与历史最大回撤之比)是使用最大回撤率来衡量风险。**采用最大回撤率来衡量风险,关注的是最极端的情况。**卡玛比率越高表示策略承受每单位最大损失获得的报酬越高。在这里卡玛比率超过了16.02。
- 夏普比率(年化收益率减无风险收益率的差收益波动率之比)超过2.76,也即承受1单位的风险,会有超过2.5个单位的收益回报
- 策略收益曲线相当稳定,适合稳定型投资者,最大回撤极小,缺点是交易次数少,很长时间无交易。
策略源码
taoli pic.py
源码
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
import talib
import matplotlib as plt
from pylab import *
import numpy as np
import datetime
from sklearn import preprocessing
#from matplotlib.dates import AutoDateLocator, DateFormatter
set_token('your token')
data1 = history(symbol='SHFE.rb1701', frequency='1d', start_time='2016-04-01', end_time='2016-10-31', fields='close,eob',df='True')
data2 = history(symbol='SHFE.hc1701', frequency='1d', start_time='2016-04-01', end_time='2016-10-31', fields='close,eob',df='True')
d1=data1.index
close1=[]
close2=[]
for i in data1.close:
close1.append(i)
for i in data2.close:
close2.append(i)
print (len(close1),len(close2))
print (np.corrcoef(close1,close2))
spread=[]
for i in range(len(d1)):
spread.append(close2[i]-close1[i])
mean1=[np.average(spread)]*len(d1)
up=[mean1[0]+2*np.std(spread)]*len(d1)
down=[mean1[0]-2*np.std(spread)]*len(d1)
#print (up,down)
plt.figure(1)
plt.subplot(211)
plt.plot(d1,close1,'r-',label="RB1701")
plt.plot(d1,close2,'b-',label='HC1701')
plt.xlabel('Date Number')
plt.ylabel('Price')
plt.legend()
plt.subplot(212)
plt.plot(d1,spread,'r-',label="Delt")
plt.plot(d1,mean1,'k:',label="mean")
plt.xlabel('Date Number')
plt.ylabel('Delt Price')
plt.plot(d1,up,'g:',label="up")
plt.plot(d1,down,'b:',label="down")
plt.legend()
b=np.arange(0,(len(d1)-1))
c=[0]*b
a=np.diff(np.array(spread),1)
plt.figure(2)
plt.plot(b,a,'b-')
plt.plot(b,c,'r:')
plt.show()
-
想问下为什么回测交易明细中看开仓是信号出的当日开,平仓却是出了信号后次日才平?
-
@th666-シ 您好,如有问题请前往掘金QQ群或微信群@掘金技术支持寻求帮助。