3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在商品期货量化交易中,由于期货合约具有生命周期(到期交割),长期持仓的策略必须进行移仓换月操作。聚宽(JoinQuant)平台提供了主力连续合约的拼接,但主力合约本身(如 RB9999.XSGE)是不可直接下单交易的。我们需要通过 get_dominant_future 获取当前实际的主力具体合约,并在主力合约发生切换时,自动平掉旧合约持仓,同时等量开仓新的主力合约。
get_dominant_future(underlying_symbol, date=None)underlying_symbol: 期货品种代码,如 'RB'(螺纹钢)、'CU'(阴极铜)。date: 查询日期。在回测/模拟盘中默认不填,自动获取当前逻辑日期。'RB2310.XSGE'。set_subportfolios'futures',否则无法下单。RB)。get_dominant_future 获取最新的主力合约。以下是基于 JoinQuant API 编写的完整自动移仓换月策略模板:
# 导入聚宽函数库
import jqdata
from kuanke.user_space_api import *
def initialize(context):
# 1. 开启真实价格模式(Tick/期货策略必须开启)
set_option('use_real_price', True)
# 2. 设置初始资金并初始化期货账户
init_cash = context.portfolio.starting_cash
set_subportfolios([SubPortfolioConfig(cash=init_cash, type='futures')])
# 3. 定义需要交易和监控的期货品种(以螺纹钢 RB 为例)
g.underlying = 'RB'
# 4. 记录当前持有的具体主力合约代码
g.current_dominant = None
# 5. 设定每日运行函数
# 每天 09:00 开盘前检查主力合约并进行移仓监控
run_daily(check_and_switch_dominant, time='09:00', reference_security='RB9999.XSGE')
# 每天 09:30 开盘时执行常规交易逻辑
run_daily(market_open, time='09:30', reference_security='RB9999.XSGE')
def check_and_switch_dominant(context):
"""每日开盘前检查主力合约是否切换,若切换则执行移仓"""
log.info("--- 开始检查主力合约 ---")
# 获取最新主力合约
new_dominant = get_dominant_future(g.underlying)
log.info(f"当前最新主力合约为: {new_dominant}")
# 如果是第一次运行,先记录当前主力
if g.current_dominant is None:
g.current_dominant = new_dominant
return
# 如果主力合约发生切换
if new_dominant != g.current_dominant:
log.info(f"检测到主力合约切换!旧主力: {g.current_dominant} -> 新主力: {new_dominant}")
# 获取旧合约的持仓情况
portfolio = context.portfolio
# 检查多头持仓并移仓
if g.current_dominant in portfolio.long_positions:
old_long_amount = portfolio.long_positions[g.current_dominant].total_amount
if old_long_amount > 0:
log.info(f"正在移仓多头:平仓旧主力 {g.current_dominant} 共 {old_long_amount} 手")
# 平旧合约多仓(卖出)
order(g.current_dominant, -old_long_amount, side='long')
# 开新合约多仓(买入)
order(new_dominant, old_long_amount, side='long')
# 检查空头持仓并移仓
if g.current_dominant in portfolio.short_positions:
old_short_amount = portfolio.short_positions[g.current_dominant].total_amount
if old_short_amount > 0:
log.info(f"正在移仓空头:平仓旧主力 {g.current_dominant} 共 {old_short_amount} 手")
# 平旧合约空仓(买入平仓)
order(g.current_dominant, -old_short_amount, side='short')
# 开新合约空仓(卖出开仓)
order(new_dominant, old_short_amount, side='short')
# 更新全局变量
g.current_dominant = new_dominant
else:
log.info("主力合约未发生变化,无需移仓。")
def market_open(context):
"""常规交易逻辑(示例:若无持仓,则买入开仓一手最新主力合约)"""
dominant_contract = g.current_dominant
portfolio = context.portfolio
# 如果当前没有任何持仓,买入一手主力合约
has_position = False
if (dominant_contract in portfolio.long_positions and portfolio.long_positions[dominant_contract].total_amount > 0) or \
(dominant_contract in portfolio.short_positions and portfolio.short_positions[dominant_contract].total_amount > 0):
has_position = True
if not has_position:
log.info(f"当前无持仓,开仓买入一手最新主力合约: {dominant_contract}")
order(dominant_contract, 1, side='long')
set_slippage 设置合理的滑点以贴近实盘。09:00 盘前进行逻辑判断,若有移仓需求,订单会以挂单形式进入引擎,并在 09:30 开盘时自动撮合成交。