【期货量化实战】跨期套利策略:价差交易完整指南(TqSdk源码详解)

一、前言

跨期套利是期货市场中最经典的套利策略之一,通过同时买卖同一品种不同月份的合约,利用价差回归获利。相比单边趋势交易,套利策略风险更低、收益更稳定。

本文将介绍:

  • 跨期套利的基本原理
  • 价差计算与监控
  • 套利信号判断
  • TqSdk完整实现代码

二、为什么选择天勤量化(TqSdk)

在众多期货量化工具中,**天勤量化(TqSdk)**是目前国内最受欢迎的开源期货量化框架之一:

特点 说明
完全免费 开源免费,无需付费即可获取实时行情
数据全面 支持国内所有期货交易所的实时行情和历史数据
上手简单 几行Python代码即可获取数据
文档完善 官方文档详细,示例代码丰富

安装方法

bash 复制代码
pip install tqsdk

三、跨期套利基础

3.1 什么是跨期套利

跨期套利(Calendar Spread)是指在同一期货品种的不同交割月份合约上建立数量相等、方向相反的头寸。

类型 操作 预期
正套 买近月卖远月 价差扩大
反套 卖近月买远月 价差缩小

3.2 价差类型

价差形态 说明 常见品种
正价差(Contango) 远月价格 > 近月价格 仓储成本品种
负价差(Backwardation) 近月价格 > 远月价格 供需紧张品种

3.3 套利优势

优势 说明
风险较低 对冲了大部分方向性风险
保证金优惠 交易所通常有套利保证金优惠
收益稳定 价差波动相对可预测
适合大资金 容量大、冲击成本低

四、完整代码实现

4.1 价差监控工具

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:跨期价差实时监控
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth

# ============ 合约配置 ============
SYMBOL_NEAR = "SHFE.rb2505"   # 近月合约
SYMBOL_FAR = "SHFE.rb2510"    # 远月合约

# ============ 初始化 ============
api = TqApi(auth=TqAuth("快期账户", "快期密码"))

quote_near = api.get_quote(SYMBOL_NEAR)
quote_far = api.get_quote(SYMBOL_FAR)

print("=" * 60)
print("跨期价差监控")
print("=" * 60)
print(f"近月合约: {SYMBOL_NEAR}")
print(f"远月合约: {SYMBOL_FAR}")
print("-" * 60)

# 价差历史
spread_history = []

while True:
    api.wait_update()
    
    # 获取最新价格
    price_near = quote_near.last_price
    price_far = quote_far.last_price
    
    # 计算价差(远月 - 近月)
    spread = price_far - price_near
    spread_history.append(spread)
    
    # 保留最近100个数据计算统计值
    if len(spread_history) > 100:
        spread_history = spread_history[-100:]
    
    # 计算统计指标
    avg_spread = sum(spread_history) / len(spread_history)
    max_spread = max(spread_history)
    min_spread = min(spread_history)
    
    print(f"\r近月={price_near:.0f} 远月={price_far:.0f} "
          f"价差={spread:.0f} 均值={avg_spread:.0f} "
          f"区间=[{min_spread:.0f}, {max_spread:.0f}]", end="")

4.2 完整套利策略

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:跨期套利策略
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth, TqSim
from tqsdk.lib import TargetPosTask
import numpy as np

# ============ 合约配置 ============
SYMBOL_NEAR = "SHFE.rb2505"   # 近月合约
SYMBOL_FAR = "SHFE.rb2510"    # 远月合约
LOTS = 1                      # 每腿手数

# ============ 策略参数 ============
LOOKBACK = 60                 # 回看周期
ENTRY_THRESHOLD = 2.0        # 开仓阈值(标准差倍数)
EXIT_THRESHOLD = 0.5         # 平仓阈值
MAX_HOLD_BARS = 100          # 最大持仓K线数

# ============ 初始化 ============
api = TqApi(TqSim(init_balance=500000), auth=TqAuth("快期账户", "快期密码"))

quote_near = api.get_quote(SYMBOL_NEAR)
quote_far = api.get_quote(SYMBOL_FAR)
kline_near = api.get_kline_serial(SYMBOL_NEAR, 300, LOOKBACK + 20)
kline_far = api.get_kline_serial(SYMBOL_FAR, 300, LOOKBACK + 20)

# 持仓管理
target_pos_near = TargetPosTask(api, SYMBOL_NEAR)
target_pos_far = TargetPosTask(api, SYMBOL_FAR)

account = api.get_account()

print("=" * 60)
print("跨期套利策略")
print("=" * 60)
print(f"近月: {SYMBOL_NEAR}")
print(f"远月: {SYMBOL_FAR}")
print(f"开仓阈值: {ENTRY_THRESHOLD}倍标准差")
print(f"平仓阈值: {EXIT_THRESHOLD}倍标准差")
print("-" * 60)

# 状态变量
position = 0       # 1=正套(买近卖远), -1=反套(卖近买远), 0=空仓
hold_bars = 0      # 持仓K线数

while True:
    api.wait_update()
    
    if api.is_changing(kline_near.iloc[-1], "datetime"):
        # 获取收盘价序列
        close_near = kline_near["close"].values[-LOOKBACK:]
        close_far = kline_far["close"].values[-LOOKBACK:]
        
        # 计算价差序列
        spread = close_far - close_near
        
        # 统计指标
        spread_mean = np.mean(spread)
        spread_std = np.std(spread)
        
        # 当前价差
        current_spread = close_far[-1] - close_near[-1]
        
        # 计算z-score
        z_score = (current_spread - spread_mean) / spread_std if spread_std > 0 else 0
        
        print(f"\n价差={current_spread:.0f} 均值={spread_mean:.0f} "
              f"标准差={spread_std:.0f} Z值={z_score:.2f}")
        
        # ============ 交易逻辑 ============
        if position == 0:
            # 无持仓,判断开仓
            if z_score > ENTRY_THRESHOLD:
                # 价差过大,做反套(卖近买远)
                target_pos_near.set_target_volume(-LOTS)
                target_pos_far.set_target_volume(LOTS)
                position = -1
                hold_bars = 0
                print(f"[开仓] 反套:卖{SYMBOL_NEAR} 买{SYMBOL_FAR}")
                
            elif z_score < -ENTRY_THRESHOLD:
                # 价差过小,做正套(买近卖远)
                target_pos_near.set_target_volume(LOTS)
                target_pos_far.set_target_volume(-LOTS)
                position = 1
                hold_bars = 0
                print(f"[开仓] 正套:买{SYMBOL_NEAR} 卖{SYMBOL_FAR}")
        
        else:
            # 有持仓,判断平仓
            hold_bars += 1
            
            should_close = False
            close_reason = ""
            
            # 条件1:价差回归
            if position == 1 and z_score > -EXIT_THRESHOLD:
                should_close = True
                close_reason = "价差回归"
            elif position == -1 and z_score < EXIT_THRESHOLD:
                should_close = True
                close_reason = "价差回归"
            
            # 条件2:超时平仓
            if hold_bars >= MAX_HOLD_BARS:
                should_close = True
                close_reason = "持仓超时"
            
            if should_close:
                target_pos_near.set_target_volume(0)
                target_pos_far.set_target_volume(0)
                print(f"[平仓] {close_reason},持仓{hold_bars}根K线")
                position = 0
                hold_bars = 0
        
        # 显示账户状态
        print(f"  账户权益: {account.balance:.0f} 浮盈: {account.float_profit:.0f}")

4.3 代码解析

代码 说明
spread = far - near 计算价差
z_score = (spread - mean) / std 标准化价差
z_score > 2.0 价差偏大,做反套
z_score < -2.0 价差偏小,做正套
abs(z_score) < 0.5 价差回归,平仓

五、价差分析工具

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:价差统计分析
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
import numpy as np

# ============ 合约配置 ============
SYMBOL_NEAR = "SHFE.rb2505"
SYMBOL_FAR = "SHFE.rb2510"

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

# 获取日K线
kline_near = api.get_kline_serial(SYMBOL_NEAR, 86400, 60)
kline_far = api.get_kline_serial(SYMBOL_FAR, 86400, 60)

api.wait_update()

# 计算价差
close_near = kline_near["close"].values
close_far = kline_far["close"].values
spread = close_far - close_near

# 统计分析
print("=" * 50)
print("价差统计分析")
print("=" * 50)
print(f"数据天数: {len(spread)}")
print("-" * 50)

# 基础统计
print(f"均值: {np.mean(spread):.2f}")
print(f"标准差: {np.std(spread):.2f}")
print(f"最大值: {np.max(spread):.2f}")
print(f"最小值: {np.min(spread):.2f}")
print(f"当前值: {spread[-1]:.2f}")

# 分位数
print(f"\n分位数:")
for p in [10, 25, 50, 75, 90]:
    print(f"  {p}%分位: {np.percentile(spread, p):.2f}")

# Z-Score
current_z = (spread[-1] - np.mean(spread)) / np.std(spread)
print(f"\n当前Z-Score: {current_z:.2f}")

if current_z > 2:
    print("建议: 价差偏大,可考虑反套")
elif current_z < -2:
    print("建议: 价差偏小,可考虑正套")
else:
    print("建议: 价差正常,观望")

api.close()

六、套利注意事项

6.1 合约选择

要点 说明
流动性 选择成交量大的合约
月份间隔 通常选3-6个月间隔
避免临近交割 近月合约避免进入交割月

6.2 风险提示

风险 说明 应对
价差不回归 价差持续扩大或缩小 设置止损
流动性风险 无法同时成交 选流动性好的合约
保证金风险 极端行情追保 控制仓位
交割风险 近月合约进入交割 提前移仓

七、进阶技巧

7.1 动态阈值

python 复制代码
# 根据波动率动态调整开仓阈值
def get_dynamic_threshold(spread_std, base_threshold=2.0):
    """
    波动率大时提高阈值,波动率小时降低阈值
    """
    # 假设历史标准差为50
    NORMAL_STD = 50
    ratio = spread_std / NORMAL_STD
    
    # 限制调整范围
    ratio = max(0.5, min(ratio, 2.0))
    
    return base_threshold * ratio

7.2 价差比率

python 复制代码
# 使用价差比率而非绝对价差
spread_ratio = close_far / close_near - 1

# 适用于不同价位品种的横向比较

八、总结

要点 内容
策略原理 利用价差回归获利
核心指标 Z-Score标准化价差
开仓条件 Z值超过±2倍标准差
平仓条件 Z值回归到±0.5以内
风险控制 设置止损和持仓时间限制

免责声明:本文仅供学习交流使用,不构成任何投资建议。期货交易有风险,入市需谨慎。

更多资源

相关推荐
weixin_4617694015 小时前
15. 三数之和
c++·算法·leetcode·三数之和
NAGNIP15 小时前
一文搞懂机器学习中的学习理论!
算法·面试
Evand J15 小时前
【MATLAB代码介绍】基于累积概率的三维轨迹匹配与定位,由轨迹匹配和卡尔曼滤波形成算法,带测试结果演示
算法·matlab·滤波·定位·导航·轨迹匹配
l1t15 小时前
NineData第三届数据库编程大赛:用一条 SQL 解数独问题我的参赛程序
数据库·人工智能·sql·算法·postgresql·oracle·数独
大、男人15 小时前
python之contextmanager
android·python·adb
千金裘换酒15 小时前
LeetCode 链表两数相加
算法·leetcode·链表
NAGNIP15 小时前
一文搞懂机器学习中的优化方法!
算法
毕设源码-钟学长15 小时前
【开题答辩全过程】以 基于Python的车辆管理系统为例,包含答辩的问题和答案
开发语言·python
Sammyyyyy15 小时前
Rust 1.92.0 发布:Never Type 进一步稳定
java·算法·rust