3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
要将您的策略从“每天判断一次”改造为“每分钟判断一次”,在 JoinQuant 平台上非常容易实现。核心思路是将回测频率设置为“分钟”,并使用每分钟都会触发的函数来执行您的逻辑。
以下是具体的改造步骤和代码示例:
run_daily(..., time='9:15') 替换为 run_daily(..., time='every_bar'),或者直接使用 handle_data(context, data) 函数。这两个函数在分钟频率下,都会在交易时间的每一分钟被调用一次。history 或 attribute_history 时,将时间单位参数从 '1d'(天)改为 '1m'(分钟)。假设您要比较的两个 ETF 是沪深300ETF(510300.XSHG)和中证500ETF(510500.XSHG),比较它们过去20分钟的涨幅,并在每分钟进行调仓:
# 导入聚宽函数库
import jqdata
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 定义要操作的两个ETF
g.etf1 = '510300.XSHG'
g.etf2 = '510500.XSHG'
# 核心修改:设置每分钟运行一次交易函数
run_daily(market_trade, time='every_bar')
# 每分钟都会被调用一次的函数
def market_trade(context):
# 获取过去20分钟的收盘价数据
# 注意:'1m'代表分钟线,获取的数据不包含当前正在运行的这一分钟(避免未来函数)
hist1 = attribute_history(g.etf1, 20, '1m', ['close'])
hist2 = attribute_history(g.etf2, 20, '1m', ['close'])
# 确保有足够的数据(例如刚上市的标的可能数据不足)
if len(hist1) < 20 or len(hist2) < 20:
return
# 计算过去20分钟的涨幅
# 涨幅 = (最新一分钟的收盘价 - 20分钟前的收盘价) / 20分钟前的收盘价
ret1 = (hist1['close'][-1] - hist1['close'][0]) / hist1['close'][0]
ret2 = (hist2['close'][-1] - hist2['close'][0]) / hist2['close'][0]
# 获取当前账户持仓
positions = context.portfolio.positions
# 比较涨幅并进行交易判断
if ret1 > ret2:
# 如果 ETF1 涨幅大,且当前持有 ETF2,则卖出 ETF2
if g.etf2 in positions and positions[g.etf2].closeable_amount > 0:
order_target(g.etf2, 0)
log.info("卖出 %s" % g.etf2)
# 全仓买入 ETF1
if g.etf1 not in positions or positions[g.etf1].closeable_amount == 0:
order_target_value(g.etf1, context.portfolio.total_value)
log.info("买入 %s" % g.etf1)
elif ret2 > ret1:
# 如果 ETF2 涨幅大,且当前持有 ETF1,则卖出 ETF1
if g.etf1 in positions and positions[g.etf1].closeable_amount > 0:
order_target(g.etf1, 0)
log.info("卖出 %s" % g.etf1)
# 全仓买入 ETF2
if g.etf2 not in positions or positions[g.etf2].closeable_amount == 0:
order_target_value(g.etf2, context.portfolio.total_value)
log.info("买入 %s" % g.etf2)
time='every_bar' 的含义:在 run_daily 中使用 every_bar,意味着该函数会与您设置的回测频率保持一致。如果您在界面上选择了“按分钟回测”,它就会在每天的 9:30, 9:31... 一直到 15:00 每分钟执行一次。attribute_history(security, 20, '1m', ['close']) 获取的是前20个已经走完的分钟K线。例如,在 10:05 分执行时,获取的是 09:45 到 10:04 这20根分钟K线的收盘价。这完全符合实盘逻辑,不会引入未来函数。closeable_amount > 0 判断就是为了确保只卖出可用的(非今天买入的)持仓。