跨期套利组合构建
与跨品种套利不同,跨期套利是对同一市场,同一品种,不同到期月份的合约之间进行套利,这其中涉及到非主力合约的问题。非主力合约成交量比较小,有的甚至低到几十数百手,很容易被几手交易量将价格拉至异常。这种异常实际较难捕捉,只会放大回测结果。我们以沪镍为例,其主力合约主要在1,5,9月交割,其余月份成交量很低。而1月交割合约活跃期为7月至12月,5月交割合约活跃期11月到来年4月,所以在构建1月交割合约和5月交割合约的套利组合时,我们选择11、12月作为套利策略实施的时间进行测试,12月底若有持仓强行平仓。这个时间内,1月交割合约为主力合约,5月交割合约为次主力合约。
镍跨期套利
在套利时,我们需要计算均衡价差,一般来说有两种算法:
模拟交割法:通过模拟交割过程各项费用,来计算套利过程中的各项成本,从而得出均衡价差。优点:容易计算,价差变化下;缺点:实际中价差很少恢复到这一水平
历史滞后均值法:通过历史的价差,选择时间窗口长度,得到均衡价差。优点:容易计算,价差动态;缺点:不能保证样本外价差恢复到这一水平
我们以选定套利组合的开盘价差为对象,使用历史滞后均值法,取N日价差均值为中线,中线加上N日价差M倍均值为上轨,中线减去N日价差M倍均值为下轨来构造布林带通道,当价差突破上轨,做空价差。我们选择1,5,9这三个月份交割合约,滚动的进行测试,其中1-5合约测试的时间为11月和12月,5-9合约测试的时间为3月和4月,9-1合约测试的时间为7月和8月,所以全年有半年时间不进行操作。
相关参数及设定
成交价设置为当日开盘价。这里,考虑到次主力合约成交量可能较少,我们设置为3个滑点。
开仓信号为价差超过上轨或者突破下轨,信号触发当天即按所设定的成交价进行成交。平仓信号达到中线附近或者,所设定的套利期现结束强行平仓。
手续费设为6元一手
回测时间为5月至4月
暂不考虑止损。
universe = ‘NIM0’ # 策略期货合约
start = ‘-05-18’ # 回测开始时间
end = ‘-04-31’ # 回测结束时间
capital_base = 1000000 # 初试可用资金
refresh_rate = 1 # 调仓周期
freq = ‘d’ # 调仓频率:m-> 分钟;d-> 日
margin_rate = 0.09
commission = {‘NI’: (6, ‘perShare’)}
slippage = Slippage(3, ‘perShare’)
months = [‘07’, ‘08’, ‘11’, ‘12’, ‘03’, ‘04’]
mid, up, low = [], [], []
def initialize(futures_account): # 初始化虚拟期货账户,一般用于设置计数器,回测辅助变量等。
futures_account.mean = deque([], maxlen=10)
futures_account.std = deque([], maxlen=10)
futures_account.M0 = ''futures_account.M1 = ''
def handle_data(futures_account): # 回测调仓逻辑,每个调仓周期运行一次,可在此函数内实现信号生产,生成调仓指令。
if futures_account.current_date[5:7] in [‘11’, ‘12’]:
M0 = universe[:2] + str(int(futures_account.current_date[2:4])+1) + ‘01’
M1 = universe[:2] + str(int(M0[2:4])+(int(M0[4:])+4)/12)+’0’+str((int(M0[4:])+4)%12)
elif futures_account.current_date[5:7] in [‘07’, ‘08’]:
M0 = universe[:2] + str(int(futures_account.current_date[2:4])) + ‘09’
M1 = universe[:2] + str(int(M0[2:4])+(int(M0[4:])+4)/12)+’0’+str((int(M0[4:])+4)%12)
elif futures_account.current_date[5:7] in [‘03’, ‘04’]:
M0 = universe[:2] + str(int(futures_account.current_date[2:4])) + ‘05’
M1 = universe[:2] + str(int(M0[2:4])+(int(M0[4:])+4)/12)+’0’+str((int(M0[4:])+4)%12)
long_position = futures_account.position.get(futures_account.M0, dict()).get('long_position', 0)short_position = futures_account.position.get(futures_account.M1, dict()).get('short_position', 0)if futures_account.current_date[5:7] not in months:if long_position != 0:order(futures_account.M0, -20, 'close')order(futures_account.M1, 20, 'close')returnM0_open_price = get_symbol_history(symbol=M0, field='openPrice', time_range=11)[M0]['openPrice']M1_open_price = get_symbol_history(symbol=M1, field='openPrice', time_range=11)[M1]['openPrice']diff = np.array(M0_open_price - M1_open_price, dtype=float)futures_account.mean.append(ta.MA(diff, 10)[-1])futures_account.std.append(ta.STDDEV(diff, 10)[-1])if diff[-1] < futures_account.mean[-1] - 1 * futures_account.std[-1] and long_position == 0:order(M1, -20, 'open')order(M0, 20, 'open')if diff[-1] > futures_account.mean[-1] - 0.2 * futures_account.std[-1] and long_position != 0:order(M1, 20, 'close')order(M0, -20, 'close')futures_account.M0 = M0futures_account.M1 = M1
如果觉得《跨期套利》对你有帮助,请点赞、收藏,并留下你的观点哦!