abctrader 发表于 2019-8-11 15:40:51

【宽客策略源码】跨期套利策略


本策略根据EG两步法(1.序列同阶单整2.OLS残差平稳)判断序列具有协整关系之后(若无协整关系则全平仓位不进行操作),通过计算两个真实价格序列回归残差的0.9个标准差上下轨,并在价差突破上轨的时候做空价差,价差突破下轨的时候做多价差,并在回归至标准差水平内的时候平仓

回测数据为:SHFE.rb1801和SHFE.rb1805的1min数据
回测时间为:2017-09-25 08:00:00到2017-10-01 15:00:00


# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import numpy as np
from gm.api import *
try:
    import statsmodels.tsa.stattools as ts
except:
    print('请安装statsmodels库')

# 协整检验的函数
def cointegration_test(series01, series02):
    urt_rb1801 = ts.adfuller(np.array(series01), 1)
    urt_rb1805 = 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)
      urt_diff_rb1805 = ts.adfuller(np.diff(np.array(series01), 1))
      # 同时差分平稳进行OLS回归的残差平稳检验
      if urt_diff_rb1801 < 0.1 and urt_diff_rb1805 < 0.1:
            matrix = np.vstack().T
            beta, c = np.linalg.lstsq(matrix, series01)
            resid = series01 - beta * series02 - c
            if ts.adfuller(np.array(resid), 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
def init(context):
    context.goods = ['SHFE.rb1801', 'SHFE.rb1805']
    # 订阅品种
    subscribe(symbols=context.goods, frequency='60s', count=801, wait_group=True)
def on_bar(context, bars):
    # 获取过去800个60s的收盘价数据
    close_01 = context.data(symbol=context.goods, frequency='60s', count=801, fields='close')['close'].values
    close_02 = context.data(symbol=context.goods, frequency='60s', count=801, fields='close')['close'].values
    # 展示两个价格序列的协整检验的结果
    beta, c, resid, result = cointegration_test(close_01, close_02)
    # 如果返回协整检验不通过的结果则全平仓位等待
    if not result:
      print('协整检验不通过,全平所有仓位')
      order_close_all()
      return
    # 计算残差的标准差上下轨
    mean = np.mean(resid)
    up = mean + 0.9 * np.std(resid)
    down = mean - 0.9 * np.std(resid)
    # 计算新残差
    resid_new = close_01[-1] - beta * close_02[-1] - c
    # 获取rb1801的多空仓位
    position_01_long = context.account().position(symbol=context.goods, side=PositionSide_Long)
    position_01_short = context.account().position(symbol=context.goods, side=PositionSide_Short)
    if not position_01_long and not position_01_short:
      # 上穿上轨时做空新残差
      if resid_new > up:
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Short)
            print(context.goods + '以市价单开空仓1手')
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Long)
            print(context.goods + '以市价单开多仓1手')
      # 下穿下轨时做多新残差
      if resid_new < down:
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Long)
            print(context.goods, '以市价单开多仓1手')
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Short)
            print(context.goods, '以市价单开空仓1手')
    # 新残差回归时平仓
    elif position_01_short:
      if resid_new <= up:
            order_close_all()
            print('价格回归,平掉所有仓位')
      # 突破下轨反向开仓
      if resid_new < down:
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Long)
            print(context.goods, '以市价单开多仓1手')
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Short)
            print(context.goods, '以市价单开空仓1手')
    elif position_01_long:
      if resid_new >= down:
            order_close_all()
            print('价格回归,平所有仓位')
      # 突破上轨反向开仓
      if resid_new > up:
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Short)
            print(context.goods, '以市价单开空仓1手')
            order_target_volume(symbol=context.goods, volume=1, order_type=OrderType_Market,
                              position_side=PositionSide_Long)
            print(context.goods, '以市价单开多仓1手')
if __name__ == '__main__':
    '''
    strategy_id策略ID,由系统生成
    filename文件名,请与本文件名保持一致
    mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    token绑定计算机的ID,可在系统设置-密钥管理中生成
    backtest_start_time回测开始时间
    backtest_end_time回测结束时间
    backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    backtest_initial_cash回测初始资金
    backtest_commission_ratio回测佣金比例
    backtest_slippage_ratio回测滑点比例
    '''
    run(strategy_id='strategy_id',
      filename='main.py',
      mode=MODE_BACKTEST,
      token='token_id',
      backtest_start_time='2017-09-25 08:00:00',
      backtest_end_time='2017-10-01 16:00:00',
      backtest_adjust=ADJUST_PREV,
      backtest_initial_cash=500000,
      backtest_commission_ratio=0.0001,
      backtest_slippage_ratio=0.0001)



页: [1]
查看完整版本: 【宽客策略源码】跨期套利策略