市场有风险,投资需谨慎,回测结果不代表未来表现。本策略示例旨在学习交流,实盘前务必充分理解并进行严格测试。以下代码均基于天勤量化test编写,仅作参考,不为交易结果负责!!!
一、交易策略解释
核心思想
白糖-玉米淀粉替代套利的核心在于监控和交易两者之间的“相对价值价差”。白糖(SR)和淀粉糖(主要由玉米淀粉CS经深加工转化而来)在食品、饮料等多个行业中存在一定的消费替代关系。当两者价差出现显著偏离时,下游用户可能会调整其在配方中白糖和淀粉糖的使用比例。
- 白糖-玉米淀粉相对价值价差 (Sugar-Corn Starch Relative Value Spread):
- 由于期货市场上没有直接的淀粉糖合约,本策略使用玉米淀粉(CS)期货价格作为淀粉糖成本或其价格变动趋势的一个重要参考指标。该价差旨在模拟白糖与以玉米淀粉为基础的甜味剂之间的价格对比关系。
- 价差 = (白糖期货价格 × 白糖合约乘数 × 白糖手数因子) - (玉米淀粉期货价格 × 玉米淀粉合约乘数 × 玉米淀粉手数因子)。其中,手数因子用于调整不同合约的价值规模,使其在价差计算中具有可比性或代表一定的替代比例。
核心思想是:
- 这个相对价值价差会受到白糖、玉米(进而影响玉米淀粉)各自供需基本面、生产成本、替代品之间的比价关系以及相关产业政策的影响。策略通过计算该价差的标准化得分(Z-score)来衡量其偏离历史均值的程度。
- 预期价差扩大: 当该价差的Z-score显著为正(例如,高于一个设定的正阈值),表明当前白糖相对于玉米淀粉(代表的淀粉糖成本/价格)的价格远高于其历史平均关系。
- 预期价差缩小/转负: 当该价差的Z-score显著为负(例如,低于一个设定的负阈值),表明当前白糖相对于玉米淀粉的价格远低于其历史平均关系。
- 该策略的平仓逻辑则基于价差(或其Z-score)向其历史均值区域回归。即入场后,当价差的偏离程度减小,Z-score的绝对值回落到某个较小的阈值内时,头寸会被平掉。
理论基础
- 消费替代性: 在饮料、糖果、焙烤食品等领域,白糖和高果糖玉米糖浆(一种主要的淀粉糖)可以相互替代。其替代程度主要受价格差异、产品特性要求、消费者偏好以及转换成本等因素影响。当白糖价格显著高于淀粉糖时,生产商有动力增加淀粉糖的使用比例。
- 供需基本面驱动:
- 白糖端 (SR): 主要受国内甘蔗、甜菜的种植面积、天气、单产影响,以及国际糖价、进口政策(配额、关税)、国家抛储/收储政策、走私情况和下游消费季节性等因素影响。
- 玉米淀粉端 (CS): 其价格与上游玉米的供需和价格密切相关(受玉米种植面积、产量、天气、进口、临储拍卖等影响)。同时,淀粉行业的开工率、环保政策、下游需求(淀粉糖、造纸、发酵、食品等)以及其他玉米深加工产品的景气度也会影响玉米淀粉的价格。
- 均值回归特性 (Mean Reversion of Relative Value): 尽管白糖和玉米淀粉(及淀粉糖)各自拥有独立的供需逻辑,但由于它们之间的替代关系,其相对价值(价差)在一定程度上可能表现出围绕某个历史均值波动的特性。当价差偏离过大时,市场替代机制或各自基本面的调整可能促使其向历史关系回归。策略的平仓逻辑部分依赖于此特性。
- 政策影响: 农业补贴政策(如对玉米、甘蔗的补贴)、食糖进口配额管理、环保政策对淀粉及糖类生产企业的影响等,都可能改变两者的供需平衡和相对价格。
策略适用场景
- 白糖-玉米淀粉相对价值价差显著偏离: 当计算出的相对价值价差的Z-score突破预设的阈值时,视为潜在的交易信号。
- 预期均值回归(主要针对平仓和整体策略有效性): 虽然开仓可能基于短期偏离趋势的持续,但策略的盈利平仓通常依赖于价差最终向其历史均值区域回归的预期。
- 基本面分析辅助: 结合对白糖和玉米(玉米淀粉)各自短期及长期基本面的分析,可以为统计信号提供额外的佐证或警示。
- 流动性充足: 策略涉及郑州商品交易所(CZCE)的白砂糖期货(CZCE.SR)和大连商品交易所(DCE)的玉米淀粉期货(DCE.CS),需要保证各合约均有良好的流动性。
二、天勤介绍
天勤平台概述
天勤(TqSdk)是一个由信易科技开发的开源量化交易系统,为期货、期权等衍生品交易提供专业的量化交易解决方案。平台具有以下特 点:
- 丰富的行情数据: 提供所有可交易合约的全部Tick和K线数据,基于内存数据库实现零延迟访问。
- 一站式的解决方案: 从历史数据分析到实盘交易的完整工具链,打通开发、回测、模拟到实盘的全流程。
- 专业的技术支持: 近百个技术指标源码,深度集成pandas和numpy,采用单线程异步模型保证性能。
策略开发流程
- 环境准备
- 安装Python环境(推荐Python 3.6或以上版本)
- 安装tqsdk包:pip install tqsdk
- 注册天勤账户获取访问密钥
- 数据准备
- 订阅近月与远月合约行情
- 获取历史K线或者Tick数据(用于分析与行情推进)
- 策略编写
- 设计信号生成逻辑(基于价差、均值和标准差)
- 编写交易执行模块(开仓、平仓逻辑)
- 实现风险控制措施(止损、资金管理)
- 回测验证
- 设置回测时间区间和初始资金
- 运行策略获取回测结果
- 分析绩效指标(胜率、收益率、夏普率等)
- 策略优化
- 调整参数(标准差倍数、窗口大小等)
- 添加过滤条件(成交量、波动率等)
- 完善风险控制机制
三、天勤实现策略
策略原理
核心价差定义与计算(白糖-玉米淀粉相对价值价差组合价值):
该策略的核心是追踪一个经过特定价值权重调整后的白糖期货价值与玉米淀粉期货价值之间的差额。这个“相对价值价差组合价值”的构建方式如下:
- 首先,为白糖和玉米淀粉期货分别设定一个“相对价值权重因子”。这些因子用于在比较时,衡量单位白糖价值对应多少单位玉米淀粉的价值(例如,脚本中设定1单位白糖价值对应2.5单位玉米淀粉价值的比例关系)。
- 随后,将每种期货的最新市场价格(通常是收盘价)与其各自合约规定的价值乘数(代表一手合约对应的标的物数量或金额)相乘,得到每手合约的当前市场价值。再将此价值与前述设定的“相对价值权重因子”相乘。
- 最终的 白糖-玉米淀粉相对价值价差组合价值 是通过从白糖期货经过权重调整后的总价值中,减去玉米淀粉期货经过权重调整后的总价值而得到。 这个计算出的差额,旨在量化在预设的价值权重下,白糖与玉米淀粉(作为淀粉糖成本/价格的代表)之间的相对价格水平。
指标构建:
策略采用一种称为标准化得分(或Z-score)的统计指标,来衡量当前计算出的“相对价值价差组合价值”与其在一段近期历史时期内的平均水平的偏离程度。
- 历史价差数据收集: 首先,获取白糖和玉米淀粉期货在过去一段固定交易周期(例如,最近30个交易日)内的每日价格数据。基于这些历史价格和上述的价差计算方法,可以得到一个每日“相对价值价差组合价值”的历史时间序列。
- 计算历史统计特性: 对这个历史价差序列,计算出其算术平均值和标准差。平均值代表了这段时期内价差的典型水平,而标准差则衡量了价差围绕这个平均值波动的幅度。
- 计算当前标准化得分: 使用最新的市场价格计算出当前的“相对价值价差组合价值”。然后,通过以下方式得到其标准化得分:即用(当前价差组合价值 减去 历史平均价差)的结果,再除以历史标准差。 这个得分的意义在于,它表示当前的价差偏离其历史均值的程度是多少个标准差。得分的绝对值越大,说明偏离越显著。
交易逻辑
开仓信号 (入场):
-
预期白糖相对价值将从高位回落:
- 触发条件: 当计算出的“标准化得分”显著高于一个预设的积极阈值(例如,得分大于2)。这通常意味着当前白糖相对于玉米淀粉的价值远高于其历史平均关系。
- 交易动作: 策略预期这种极端的高价差状况难以持续,价差更可能向其历史均值区域回落(即价差缩小)。因此,会建立一个旨在从价差缩小中获利的头寸:卖出预定数量的白糖期货,同时买入按比例调整后的玉米淀粉期货。
-
预期白糖相对价值将从低位回升:
- 触发条件: 当计算出的“标准化得分”显著低于一个预设的消极阈值(例如,得分小于负2)。这通常意味着当前白糖相对于玉米淀粉的价值远低于其历史平均关系。
- 交易动作: 策略预期这种极端的低价差状况难以持续,价差更可能向其历史均值区域回升(即价差扩大)。因此,会建立一个旨在从价差扩大中获利的头寸:买入预定数量的白糖期货,同时卖出按比例调整后的玉米淀粉期货。
平仓信号:
- 触发条件: 当“标准化得分”的绝对值回落到一个较小的、预设的接近零的中性区域内(例如,得分的绝对值小于0.5)。这表明之前显著偏离的相对价值价差,已经回归到其历史平均水平附近。
- 交易动作: 平掉所有持有的白糖和玉米淀粉期货头寸,实现潜在的套利收益。
特定条件下的平仓信号 (类似止损或极端行情退出):
- 触发条件:
- 如果最初是因预期价差回升而做多价差(即买入白糖、卖出玉米淀粉),但之后“标准化得分”不仅没有上升,反而进一步下跌并再次低于(或等于)最初入场时的那个消极阈值。
- 如果最初是因预期价差回落而做空价差(即卖出白糖、买入玉米淀粉),但之后“标准化得分”不仅没有下降,反而进一步上升并再次高于(或等于)最初入场时的那个积极阈值。
- 交易动作: 立即平掉所有持有的期货头寸,以控制潜在的进一步亏损。
回测
回测初始设置
- 测试周期: 2024 年 3 月 20 日 - 2024 年 5 月 15 日
- 交易品种: CZCE.SR409 / DCE.cs2409
- 初始资金: 1000万元
回测结果

上述回测累计收益走势图

完整代码示例
#!/usr/bin/env python
# coding=utf-8
__author__ = "Chaos"
from tqsdk import TqApi, TqAuth, TargetPosTask, TqBacktest, BacktestFinished
import numpy as np
from datetime import date
# === 用户参数 ===
# 合约参数
SR = "CZCE.SR409" # 白糖期货合约
CS = "DCE.cs2409" # 玉米淀粉期货合约
START_DATE = date(2024, 3, 20) # 回测开始日期
END_DATE = date(2024, 5, 15) # 回测结束日期
# 套利参数
LOOKBACK_DAYS = 30 # 计算历史价差的回溯天数
STD_THRESHOLD = 2.0 # 标准差阈值,超过此阈值视为套利机会
ORDER_VOLUME = 200 # 白糖的下单手数
CLOSE_THRESHOLD = 0.5 # 平仓阈值(标准差)
# 替代比例参数(可根据实际需要调整)
SR_RATIO = 1 # 1手白糖
CS_RATIO = 2.5 # 2.5手玉米淀粉
# === 初始化API ===
api = TqApi(backtest=TqBacktest(start_dt=START_DATE, end_dt=END_DATE),
auth=TqAuth("快期账号", "快期密码"))
# 获取合约行情和K线
sr_quote = api.get_quote(SR)
cs_quote = api.get_quote(CS)
sr_klines = api.get_kline_serial(SR, 60*60*24, LOOKBACK_DAYS)
cs_klines = api.get_kline_serial(CS, 60*60*24, LOOKBACK_DAYS)
# 创建目标持仓任务
sr_pos = TargetPosTask(api, SR)
cs_pos = TargetPosTask(api, CS)
# 获取合约乘数
sr_volume_multiple = sr_quote.volume_multiple
cs_volume_multiple = cs_quote.volume_multiple
# 初始化状态变量
in_position = False # 是否有持仓
mean_spread = 0 # 历史价差均值
std_spread = 0 # 历史价差标准差
print(f"策略启动,监控合约: {SR}, {CS}")
print(f"参数: 标准差阈值={STD_THRESHOLD}, 平仓阈值={CLOSE_THRESHOLD}, 白糖:{CS}替代比例={SR_RATIO}:{CS_RATIO}")
# === 主循环 ===
try:
# 初始计算历史统计值
spreads = []
for i in range(len(sr_klines) - 1):
sr_value = sr_klines.close.iloc[i] * sr_volume_multiple * SR_RATIO
cs_value = cs_klines.close.iloc[i] * cs_volume_multiple * CS_RATIO
spread = sr_value - cs_value
spreads.append(spread)
mean_spread = np.mean(spreads)
std_spread = np.std(spreads)
print(f"历史白糖-玉米淀粉价差均值: {mean_spread:.2f}, 标准差: {std_spread:.2f}")
# 主循环
while True:
api.wait_update()
# 当K线数据有变化时进行计算
if api.is_changing(sr_klines) or api.is_changing(cs_klines):
# 重新计算历史价差统计
spreads = []
for i in range(len(sr_klines) - 1):
sr_value = sr_klines.close.iloc[i] * sr_volume_multiple * SR_RATIO
cs_value = cs_klines.close.iloc[i] * cs_volume_multiple * CS_RATIO
spread = sr_value - cs_value
spreads.append(spread)
mean_spread = np.mean(spreads)
std_spread = np.std(spreads)
# 计算当前白糖-玉米淀粉价差
sr_value = sr_klines.close.iloc[-1] * sr_volume_multiple * SR_RATIO
cs_value = cs_klines.close.iloc[-1] * cs_volume_multiple * CS_RATIO
current_spread = sr_value - cs_value
# 计算z-score (标准化的价差)
z_score = (current_spread - mean_spread) / std_spread
print(f"当前白糖-玉米淀粉相对价值价差: {current_spread:.2f}, Z-score: {z_score:.2f}")
# 获取当前持仓
sr_position = api.get_position(SR)
cs_position = api.get_position(CS)
current_sr_pos = sr_position.pos_long - sr_position.pos_short
current_cs_pos = cs_position.pos_long - cs_position.pos_short
# 计算玉米淀粉实际下单手数(根据替代比例)
cs_volume = int(ORDER_VOLUME * CS_RATIO / SR_RATIO)
if cs_volume < 1:
cs_volume = 1 # 保证至少1手
# === 交易信号判断 ===
if not in_position: # 如果没有持仓
if z_score > STD_THRESHOLD: # 白糖相对价值显著高于玉米淀粉
# 反向:做空白糖,做多玉米淀粉
print(f"白糖相对价值偏高: 卖出白糖{ORDER_VOLUME}手,买入玉米淀粉{cs_volume}手")
sr_pos.set_target_volume(-ORDER_VOLUME)
cs_pos.set_target_volume(cs_volume)
in_position = True
elif z_score < -STD_THRESHOLD: # 白糖相对价值显著低于玉米淀粉
# 反向:做多白糖,做空玉米淀粉
print(f"白糖相对价值偏低: 买入白糖{ORDER_VOLUME}手,卖出玉米淀粉{cs_volume}手")
sr_pos.set_target_volume(ORDER_VOLUME)
cs_pos.set_target_volume(-cs_volume)
in_position = True
else: # 已有持仓
# 平仓条件1: 价差回归至均值区域
if abs(z_score) < CLOSE_THRESHOLD:
print("价差回归至均值区域,平仓所有头寸")
sr_pos.set_target_volume(0)
cs_pos.set_target_volume(0)
in_position = False
# 平仓条件2: 止损 - 如果价差向不利方向继续扩大
if (current_sr_pos > 0 and z_score < -STD_THRESHOLD) or \
(current_sr_pos < 0 and z_score > STD_THRESHOLD):
print("止损:价差向不利方向扩大,平仓所有头寸")
sr_pos.set_target_volume(0)
cs_pos.set_target_volume(0)
in_position = False
except BacktestFinished as e:
print("回测结束")
api.close()

&spm=1001.2101.3001.5002&articleId=155302236&d=1&t=3&u=c44da3a56e1446db9a5baab9f331bfd1)
820

被折叠的 条评论
为什么被折叠?



