【期货量化实战】跨期套利策略:价差交易完整指南(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以内
风险控制 设置止损和持仓时间限制

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

更多资源

相关推荐
yijianace5 小时前
Python线程与多线程完全总结(从入门到理解并发本质)
开发语言·python
三十..5 小时前
Redis 核心原理与高可用架构实践
运维·数据库·redis
这个DBA有点耶5 小时前
索引优化深潜(下):索引合并、ICP 与索引设计的实战法则
数据库·mysql·架构
努力努力再努力wz5 小时前
【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解
linux·c语言·数据结构·数据库·c++·qt·链表
八解毒剂6 小时前
数据结构-平衡二叉树——对二叉搜索树的优化
数据结构·c++·算法
JdSnE27zv6 小时前
Qt 操作SQLite数据库
数据库·qt·sqlite
会Tk矩阵群控的小木6 小时前
基于Python的iMessage短信群发与社媒多账号统一管理系统实现
开发语言·windows·python·新媒体运营·开源软件·个人开发
tedcloud1236 小时前
HyperFrames部署教程:用HTML生成MP4视频
前端·数据库·人工智能·html·音视频
布朗克1686 小时前
25 IO流高级操作——序列化、NIO与Files工具类
java·数据库·io·nio
阿演6 小时前
DataDjinn 新版本更新:新增 Oracle 支持,查询窗口、表预览和连接树继续打磨
数据库·oracle·ai编程·数据库连接工具