问题描述
解决方案
在 QMT 量化交易平台中,获取期货品种当前主力合约代码主要使用 ContextInfo.get_main_contract() 接口。
该接口可以根据传入的“品种代码.市场后缀”格式,自动返回当前的主力合约代码(例如传入 'IF.IF' 返回 'IF2206.IF')。
以下是具体的实现代码和详细说明。
策略代码示例
# -*- coding: gbk -*-
def init(ContextInfo):
print("策略初始化,开始获取主力合约...")
# 1. 获取中金所 - 沪深300股指期货(IF)的主力合约
# 格式:'品种.市场',中金所后缀为 .IF
if_main = ContextInfo.get_main_contract('IF.IF')
print(f"沪深300(IF) 主力合约: {if_main}")
# 2. 获取上期所 - 螺纹钢(rb)的主力合约
# 上期所后缀为 .SF
rb_main = ContextInfo.get_main_contract('rb.SF')
print(f"螺纹钢(rb) 主力合约: {rb_main}")
# 3. 获取大商所 - 铁矿石(i)的主力合约
# 大商所后缀为 .DF
i_main = ContextInfo.get_main_contract('i.DF')
print(f"铁矿石(i) 主力合约: {i_main}")
# 4. 获取郑商所 - 白糖(SR)的主力合约
# 郑商所后缀为 .ZF
sr_main = ContextInfo.get_main_contract('SR.ZF')
print(f"白糖(SR) 主力合约: {sr_main}")
# 5. 获取能源中心 - 原油(sc)的主力合约
# 能源中心后缀为 .INE
sc_main = ContextInfo.get_main_contract('sc.INE')
print(f"原油(sc) 主力合约: {sc_main}")
def handlebar(ContextInfo):
# 在盘中运行时,也可以在 handlebar 中实时获取
# 注意:主力合约通常不会频繁变动,建议在 init 或定时任务中获取,避免每个 tick 都调用
pass
函数说明
ContextInfo.get_main_contract(codemarket)
- 参数:
codemarket(string): 格式为 "品种代码.市场代码"。
- 返回值:
- (string): 返回具体的主力合约代码(如
'rb2310.SF')。
- (string): 返回具体的主力合约代码(如
- 市场代码后缀对照表(参考 QMT 文档附录):
- 中金所 (CFFEX):
.IF(例如IF.IF,IC.IF) - 上期所 (SHFE):
.SF(例如rb.SF,au.SF) - 大商所 (DCE):
.DF(例如m.DF,i.DF) - 郑商所 (CZCE):
.ZF(例如SR.ZF,TA.ZF) - 能源中心 (INE):
.INE(例如sc.INE)
- 中金所 (CFFEX):
注意事项
- 品种代码大小写:通常建议与行情软件中显示的品种代码大小写保持一致(如螺纹钢通常用小写
rb,股指期货用大写IF),但在 QMT 内部通常不区分大小写,建议以实际测试为准。 - 主力切换:该函数返回的是当前时刻系统认定的主力合约。在回测模式下,它会根据历史时间点返回当时的主力合约,从而实现“主力连续”回测的效果。
- 数据订阅:获取到主力合约代码后,如果需要获取该合约的行情数据(如 K 线或 Tick),需要使用
ContextInfo.subscribe_quote()或ContextInfo.get_market_data_ex()对返回的具体合约代码进行操作。
Q&A
Q: get_main_contract 在回测模式下有效吗?
A: 有效。在回测模式下,该函数会根据回测当前运行到的时间点(ContextInfo.barpos 对应的时间),返回历史上那个时间点的主力合约代码,非常适合编写基于主力合约的连续回测策略。
Q: 如果传入了不存在的品种代码会发生什么?
A: 函数通常会返回空字符串或抛出异常(取决于具体版本),建议在代码中增加判断,例如 if main_contract: 来确保获取到了有效的代码。
Q: 如何获取次主力合约?
A: QMT 的标准 API get_main_contract 仅直接支持获取主力合约。如果需要获取次主力,通常需要获取该品种所有活跃合约的持仓量(Open Interest),通过比较持仓量大小自行逻辑判断(持仓量第二大的即为次主力)。