3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
你好!欢迎来到量化交易的世界。针对你在JoinQuant(聚宽)平台上写商品期货30分钟周期策略遇到的问题,主要原因通常出在回测频率设置和期货参考标的设置上。下面为你详细解答如何解决这个问题并获取30分钟数据。
every_bar 只在9:30交易?run_daily(func, time='every_bar') 的执行频率取决于你在回测界面右上角选择的“运行频率”。如果你选择了“天”,那么它每天只会在开盘(通常是9:30)执行一次。必须在回测界面将频率选择为“分钟”。run_daily 的时间参照是A股(000001.XSHG),交易时间是9:30-15:00。商品期货有夜盘(如21:00开盘),如果不修改参考标的,引擎会按照A股的时间来跑,导致时间错乱。对于期货策略,必须将 reference_security 设置为对应的期货主力合约。要实现30分钟周期的日内交易,推荐的做法是:按分钟频率回测,并在代码中通过时间判断或直接使用 get_bars 获取30分钟K线数据。
在 initialize 中,设置期货账户,并正确注册定时运行函数。
# 导入聚宽函数库
import jqdata
def initialize(context):
# 设定基准(期货策略可以不设或设为0)
set_benchmark({'000001.XSHG': 0})
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 设置期货账户
init_cash = context.portfolio.starting_cash
set_subportfolios([SubPortfolioConfig(cash=init_cash, type='futures')])
# 定义要交易的期货品种主力合约,例如螺纹钢
g.security = 'RB9999.XSGE'
# 注册运行函数,注意 reference_security 必须设置为期货合约!
# 这样才能兼容期货的夜盘时间
run_daily(market_open, time='every_bar', reference_security=g.security)
在 market_open(每分钟执行一次)中,你可以使用 get_bars 函数直接获取30分钟级别的K线数据。为了确保只在每30分钟的节点触发交易逻辑,可以通过判断当前分钟数来实现。
def market_open(context):
# 获取当前时间
current_dt = context.current_dt
# 控制交易频率:每30分钟执行一次逻辑(例如 00分 和 30分)
# 注意:期货开盘时间可能是 09:00 或 21:00,具体视品种而定
if current_dt.minute % 30 != 0:
return
# 获取具体的交易合约(将主力合约映射为实际合约,如 RB1910.XSGE)
real_contract = get_dominant_future(g.security, current_dt)
if not real_contract:
return
# 获取过去5根30分钟K线数据
# unit='30m' 表示30分钟周期,include_now=False 表示不包含当前未走完的这根Bar
bars = get_bars(real_contract, count=5, unit='30m',
fields=['date', 'open', 'close', 'high', 'low', 'volume'],
include_now=False, df=True)
if len(bars) < 5:
return
# 计算指标,例如简单的均线
close_prices = bars['close']
ma5 = close_prices.mean()
current_price = close_prices.iloc[-1]
# 获取当前持仓
long_position = context.portfolio.long_positions.get(real_contract)
short_position = context.portfolio.short_positions.get(real_contract)
# 简单的交易逻辑示例:价格突破均线做多
if current_price > ma5 and not long_position:
# 如果有空单,先平空
if short_position:
order_target(real_contract, 0, side='short')
# 开多单 1 手
order(real_contract, 1, side='long')
log.info(f"买入开多 {real_contract}")
elif current_price < ma5 and not short_position:
# 如果有多单,先平多
if long_position:
order_target(real_contract, 0, side='long')
# 开空单 1 手
order(real_contract, 1, side='short')
log.info(f"卖出开空 {real_contract}")
run_daily 必须带上 reference_security='你的期货代码',否则夜盘不会执行。get_bars(..., unit='30m') 是获取分钟以上级别(如30m, 60m)最标准的方法,它会自动按照主流软件的切分方式为你合成30分钟K线。get_dominant_future 将 8888 或 9999 映射为真实的合约代码(如 RB2310.XSGE),因为直接对 9999 下单会报错。祝你在量化交易的道路上越走越远,双节快乐!