股指期货跨期套利策略
一、交易策略解释
核心思想
股指期货跨期套利策略基于价差均值回归原理,通过统计分析不同到期月份合约之间的价差变动规律,在价差偏离合理范围时建立套利头寸,待价差回归时获利了结。 这是一种相对低风险的统计套利方法,不依赖市场单边方向,专注于捕捉合约间价差的波动机会。
理论基础
- 均值回归理论:同一品种不同月份合约的价差在长期内会围绕一个均值上下波动,当价差偏离均值过大时,存在回归的趋势
- 正态分布假设:价差的波动通常符合或接近正态分布,通过计算标准差可以确定价差偏离程度
- 基差收敛原理:随着合约临近交割,远月与近月合约的价差会逐渐收敛,提供了价差回归的内在驱动力
策略适用场景
- 最佳适用:
- 震荡整理市场,价差波动规律性强
- 主力合约与次主力合约交易组合
- 非交割月的常规交易期
- 流动性充足的股指期货品种
- 不宜使用:
- 极端单边市场,尤其是市场恐慌或剧烈上涨时期
- 交割月最后一周
- 重大政策或经济数据发布前后
- 合约流动性严重不足的情况
二、天勤介绍
天勤平台概述
天勤(TqSdk)是一个由信易科技开发的开源量化交易系统,为期货、期权等衍生品交易提供专业的量化交易解决方案。平台具有以下特 点:
- 丰富的行情数据: 提供所有可交易合约的全部Tick和K线数据,基于内存数据库实现零延迟访问。
- 一站式的解决方案: 从历史数据分析到实盘交易的完整工具链,打通开发、回测、模拟到实盘的全流程。
- 专业的技术支持: 近百个技术指标源码,深度集成pandas和numpy,采用单线程异步模型保证性能。
策略开发流程
- 环境准备
- 安装Python环境(推荐Python 3.6或以上版本)
- 安装tqsdk包:pip install tqsdk
- 注册天勤账户获取访问密钥
- 数据准备
- 订阅近月与远月合约行情
- 获取历史K线或者Tick数据(用于分析与行情推进)
- 策略编写
- 设计信号生成逻辑(基于价差、均值和标准差)
- 编写交易执行模块(开仓、平仓逻辑)
- 实现风险控制措施(止损、资金管理)
- 回测验证
- 设置回测时间区间和初始资金
- 运行策略获取回测结果
- 分析绩效指标(胜率、收益率、夏普率等)
- 策略优化
- 调整参数(标准差倍数、窗口大小等)
- 添加过滤条件(成交量、波动率等)
- 完善风险控制机制
三、天勤实现策略
策略原理
本策略通过统计方法计算近月合约与远月合约价差的均值和标准差,设定价差的合理波动区间(均值±K倍标准差)。 当价差突破上边界时,做空价差(卖近买远);当价差突破下边界时,做多价差(买近卖远);当价差回归至均值时平仓获利。
交易逻辑
- 开仓信号:
- 价差 > 均值 + k * 标准差: 做空价差(卖近买远)
- 价差 < 均值 - k * 标准差: 做多价差(买近卖远)
- 平仓信号:
- 多价差持仓: 当价差回升至均值时平仓获利
- 空价差持仓: 当价差下降至均值时平仓获利
- 止损机制:
- 当亏损超过2倍标准差时触发止损
- 可以根据风险偏好调整止损倍数
回测
回测初始设置
- 测试周期: 2020 年 12 月 21 日至 2021 年 1 月 15 日
- 交易品种: CFFEX.IH2101(上证50指数期货2101合约)与CFFEX.IH2102(2102合约)的跨期套利
- 初始资金: 1000万元
- 交易手数: 每次开仓20手
- 策略参数: k=2(标准差倍数), window=80(计算窗口)
回测结果
上述回测累计收益走势图
完整代码示例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Chaos"
from datetime import date
import numpy as np
from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask, BacktestFinished
# 参数设置
NEAR_CONTRACT = "CFFEX.IH2101" # 近月合约
FAR_CONTRACT = "CFFEX.IH2102" # 远月合约
K = 2 # 标准差倍数
WINDOW = 80 # 计算窗口
LOTS = 20 # 交易手数
START_DATE = date(2020, 12, 21) # 回测开始日期
END_DATE = date(2021, 1, 15) # 回测结束日期
# 创建API实例
api = TqApi(backtest=TqBacktest(start_dt=START_DATE, end_dt=END_DATE),
auth=TqAuth("快期账号", "快期密码"))
# 订阅行情
near_quote = api.get_quote(NEAR_CONTRACT)
far_quote = api.get_quote(FAR_CONTRACT)
near_klines = api.get_kline_serial(NEAR_CONTRACT, 15 * 60, WINDOW * 2) # 15分钟K线
far_klines = api.get_kline_serial(FAR_CONTRACT, 15 * 60, WINDOW * 2)
# 创建目标持仓任务
near_pos = TargetPosTask(api, NEAR_CONTRACT)
far_pos = TargetPosTask(api, FAR_CONTRACT)
# 持仓状态: 0-无持仓, 1-多价差(买近卖远), -1-空价差(卖近买远)
position_state = 0
print(f"策略启动: {NEAR_CONTRACT}-{FAR_CONTRACT} 跨期套利")
print(f"参数设置: K={K}倍标准差, 窗口={WINDOW}, 交易手数={LOTS}手")
try:
while True:
api.wait_update()
# 检查K线是否更新
if api.is_changing(near_klines) or api.is_changing(far_klines):
# 确保有足够的数据
if len(near_klines) < WINDOW or len(far_klines) < WINDOW:
continue
# 计算价差指标
near_close = near_klines.close.iloc[-WINDOW:]
far_close = far_klines.close.iloc[-WINDOW:]
spread = near_close - far_close
# 计算均值和标准差
mean = np.mean(spread)
std = np.std(spread)
current_spread = near_quote.last_price - far_quote.last_price
# 计算上下边界
upper_bound = mean + K * std
lower_bound = mean - K * std
print(f"价差: {current_spread:.2f}, 均值: {mean:.2f}, "
f"上界: {upper_bound:.2f}, 下界: {lower_bound:.2f}")
# 交易逻辑
if position_state == 0: # 无持仓状态
if current_spread > upper_bound: # 做空价差(卖近买远)
near_pos.set_target_volume(-LOTS)
far_pos.set_target_volume(LOTS)
position_state = -1
print(f"开仓: 卖出{LOTS}手{NEAR_CONTRACT}, 买入{LOTS}手{FAR_CONTRACT}")
elif current_spread < lower_bound: # 做多价差(买近卖远)
near_pos.set_target_volume(LOTS)
far_pos.set_target_volume(-LOTS)
position_state = 1
print(f"开仓: 买入{LOTS}手{NEAR_CONTRACT}, 卖出{LOTS}手{FAR_CONTRACT}")
elif position_state == 1: # 持有多价差
if current_spread >= mean: # 平仓获利
near_pos.set_target_volume(0)
far_pos.set_target_volume(0)
position_state = 0
print("平仓: 价差回到均值,平仓获利")
elif position_state == -1: # 持有空价差
if current_spread <= mean: # 平仓获利
near_pos.set_target_volume(0)
far_pos.set_target_volume(0)
position_state = 0
print("平仓: 价差回到均值,平仓获利")
except BacktestFinished as e:
api.close()
print("回测结束")
参考:华创期货