自定义任意分钟期货回测

由bqi2tg8b创建,最终由qxiao 被浏览 5 用户

一、简介

在期货分钟策略研究中,常见的回测周期包括 1 分钟、5 分钟、15 分钟和 30 分钟。但在实际研究中,我们也可能希望使用 3 分钟、7 分钟、13 分钟等自定义周期运行策略。

例如,5 分钟周期可能过于敏感,而 15 分钟周期又可能反应较慢,此时可以选择 7 分钟、10 分钟或 13 分钟等更符合研究需求的时间周期。

BigTrader 是 BigQuant 提供的量化交易引擎。设置回测频率后,交易引擎会按照对应的 K 线周期推进历史行情,并在相应时间执行策略中的 handle_data 函数。

本文以焦煤期货为例,使用一个布林带策略演示如何完成自定义 13 分钟期货回测。

需要说明的是,本文的重点不是研究布林带策略,而是说明:

  1. 如何设置任意分钟回测频率;
  2. 自定义分钟频率如何传入 BigTrader;
  3. 1 分钟数据和 13 分钟回测频率有什么区别;
  4. BigTrader 如何按照 13 分钟周期运行;
  5. 如何通过实际运行日志确认自定义频率已经生效;
  6. 如何将 13 分钟修改为其他分钟周期。

布林带、ATR、仓位管理、止损和移仓换月只用于提供一个完整的运行示例,本文不展开讨论这些策略模块。


二、示例代码

本文后续说明基于一个完整的焦煤期货布林带策略。

该策略使用期货 1 分钟行情计算指标,并通过 BigTrader 按照自定义 13 分钟周期运行交易逻辑。

完整策略代码

https://bigquant.com/codesharev3/c6a93c70-cb3c-4f56-b8f6-63b6ac39efd0

后续内容只说明与自定义分钟频率直接相关的部分,不再重复展示完整代码,也不展开分析布林带信号和具体交易逻辑。


三、什么是自定义 13 分钟回测

1. 什么是 K 线

一根 K 线可以理解为:

将一段固定时间内的市场行情整理成一条记录。

例如:

  • 1 分钟 K 线记录 1 分钟内的行情;
  • 5 分钟 K 线记录 5 分钟内的行情;
  • 13 分钟 K 线记录 13 分钟内的行情。

每根 K 线通常包含开盘价、最高价、最低价、收盘价和成交量等信息。

2. 什么是 13 分钟回测

13 分钟回测表示 BigTrader 使用 13 分钟频率推进历史行情。

在同一个连续交易时段内,交易引擎按照相应的分钟周期调用策略中的 handle_data 函数。

可以将其理解为:

BigTrader 按照 13 分钟频率运行策略,并在相应的回调时点检查数据和执行交易逻辑。

需要注意,不同交易日和不同交易时段的第一个回调时间不一定完全相同,应以 BigTrader 实际生成的日志为准。

3. 13 分钟控制的是策略运行频率

自定义分钟频率控制的是:

策略按照什么时间间隔运行。

它并不直接决定:

  • 什么时候开仓;
  • 什么时候平仓;
  • 买入还是卖出;
  • 使用什么技术指标;
  • 每次交易多少手。

这些内容由具体的策略规则决定。

因此,示例中的布林带策略可以替换为其他策略,而自定义分钟回测框架仍然可以继续使用。

4. 自定义分钟回测的基本过程

设置13分钟频率
        ↓
将频率传入BigTrader
        ↓
BigTrader推进历史行情
        ↓
在相应时点执行handle_data
        ↓
策略判断是否需要交易
        ↓
继续处理后续行情

四、1 分钟数据和 13 分钟回测有什么区别

示例中同时出现了:

  • 1 分钟行情数据;
  • 13 分钟回测频率。

两者作用不同,需要区分。

1. 1 分钟数据用于计算指标

示例策略从 cn_future_bar1m 读取行情。

其中:

  • cn_future 表示中国期货市场;
  • bar 表示 K 线数据;
  • 1m 表示 1 分钟频率。

因此,cn_future_bar1m 是中国期货 1 分钟行情数据表。

示例中的均线、标准差、布林带和 ATR,均根据 1 分钟行情计算。

例如,代码中的:

length = 70

表示使用 70 根 1 分钟 K 线计算指标,并不是使用 70 根 13 分钟 K 线。

2. 13 分钟频率用于控制策略运行节奏

代码中设置:

frequency = '13min'

启动回测时,再将其转换为 BigTrader 使用的频率格式。

该参数控制的是 BigTrader 的回测运行频率,而不是 SQL 中指标数据的频率。

因此,当前示例的实际含义是:

使用 1 分钟行情计算指标,以 13 分钟频率运行交易逻辑。

3. 当前示例不是严格的 13 分钟指标策略

当前示例采用的是:

1 分钟指标数据 + 13 分钟回测频率。

它并不是直接在 13 分钟 K 线上计算布林带。

两种方式的区别如下:

回测方式 指标计算频率 BigTrader运行频率
当前示例 1分钟 13分钟
13分钟指标策略 13分钟 13分钟

如果希望指标本身也基于 13 分钟 K 线,需要先将 1 分钟行情合成为 13 分钟行情,再在合成后的数据上计算指标。

本文重点介绍自定义回测频率,因此不展开讨论指标数据的重新合成。


五、BigTrader 如何按照 13 分钟运行

BigTrader 的基本运行顺序可以概括为:

启动回测
    ↓
执行initialize
    ↓
每日执行before_trading_start
    ↓
按照设定频率执行handle_data
    ↓
直至回测结束

三个主要函数的作用如下:

函数 执行时间 主要作用
initialize 回测启动时执行一次 加载数据、计算指标和设置参数
before_trading_start 每个交易日开始前执行 完成每日准备和行情订阅
handle_data 回测运行过程中重复执行 读取当前数据并运行交易逻辑

1. initialize

initialize 是回测启动时的准备函数。

在本文示例中,它主要负责读取历史行情、计算示例指标并保存回测所需的数据。

该函数在整个回测开始时只执行一次,不会每隔 13 分钟重复执行。

2. before_trading_start

before_trading_start 是每日盘前准备函数。

它通常用于确定当天需要处理的合约,并订阅相应行情。

该函数一般每个交易日执行一次,也不受 13 分钟频率控制。

3. handle_data

handle_data 是与自定义分钟频率直接相关的函数。

原代码在 handle_data 中使用:

today = data.current_dt.strftime('%Y-%m-%d %H:%M:%S')
print(today)

因此,每次 handle_data 执行时,Notebook 都会直接打印当前回测时间。

日志中不会自动添加“触发时间”或“设置频率”等说明文字,只会输出时间字符串。

4. bigtrader.run

bigtrader.run 用于正式启动回测。

本文首先定义:

frequency = '13min'

启动回测时,通过:

frequency=frequency.replace('min', 'm')

将其转换为:

13min → 13m

随后将 13m 传入 bigtrader.runfrequency 参数。

整个过程为:

设置13min
    ↓
转换为13m
    ↓
传入bigtrader.run
    ↓
BigTrader按照13分钟频率运行

因此,决定自定义回测频率的关键,是传入 bigtrader.runfrequency 参数。


六、通过运行日志验证 13 分钟回测

回测启动后,实际日志中出现:

bigtrader.run start: market=cn_future, frequency=13m, mode=backtest

其中的:

frequency=13m

说明 13 分钟频率已经传入 BigTrader。

随后,Notebook 直接打印 handle_data 中的当前时间。例如:

2026-01-05 09:13:00
2026-01-05 09:26:00
2026-01-05 09:39:00
2026-01-05 09:52:00

这一段连续日志中的相邻时间均相差 13 分钟。

其他交易日也可以看到类似结果。例如,2026 年 1 月 6 日的部分日志为:

2026-01-06 09:10:00
2026-01-06 09:23:00
2026-01-06 09:36:00
2026-01-06 09:49:00
2026-01-06 10:02:00
2026-01-06 10:15:00

这一段相邻时间同样相差 13 分钟。

因此,可以从两个方面确认自定义频率已经生效:

  1. 回测启动日志显示 frequency=13m
  2. 同一段连续日志中的相邻时间相差 13 分钟。

运行日志截图

回测启动日志显示 frequency=13m。在连续运行区间内,Notebook 输出的相邻回调时间相差 13 分钟,说明自定义 13 分钟频率已经生效。


七、如何理解日志中的时间变化

实际日志并不是全天按照自然时间连续输出。

例如,日志中出现:

2026-01-05 10:05:00
2026-01-05 10:33:00

也出现:

2026-01-05 11:25:00
2026-01-05 13:38:00

这说明日志中存在较长的时间间隔。

验证 13 分钟频率时,不应跨越这些较长间隔进行比较,而应选择同一段连续输出的时间。

例如:

2026-01-05 09:13:00
2026-01-05 09:26:00
2026-01-05 09:39:00
2026-01-05 09:52:00

或者:

2026-01-06 13:35:00
2026-01-06 13:48:00
2026-01-06 14:01:00
2026-01-06 14:14:00
2026-01-06 14:27:00
2026-01-06 14:40:00
2026-01-06 14:53:00

这些连续输出中的相邻时间均相差 13 分钟。

因此,判断自定义频率是否正确时,应重点观察:

同一段连续日志中,相邻回调时间是否符合设定的分钟间隔。


八、为什么日志中还会出现交易信息

除了时间以外,实际日志中还会出现策略产生的交易信息。

例如:

-------- 2026-01-06 09:10:00 直接开空 jm2605.DCE

以及:

====== 2026-01-06 13:35:00 空换多 jm2605.DCE

这些内容来自原策略中的 print 语句,用于显示开仓、反手等交易行为。

因此,实际日志中可能同时包含:

  • BigTrader 启动信息;
  • handle_data 打印的时间;
  • 策略交易信息;
  • 回测结束信息;
  • Notebook 输出截断提示;
  • 运行环境警告。

这些交易信息不会改变自定义分钟频率的验证方法。判断频率时,仍然主要查看时间行。


九、日志输出过长时的情况

实际运行中,Notebook 可能显示:

Output is truncated. View as a scrollable element or open in a text editor.

这表示当前单元格输出内容较多,Notebook 对显示结果进行了截断。

它不表示回测提前停止,也不表示日志缺失。

在截图底部还可以看到:

bigtrader run done.

说明本次回测已经运行结束。

如果需要查看完整日志,可以使用 Notebook 提供的滚动显示或文本查看功能。


十、如何修改为其他任意分钟周期

本文示例使用 13 分钟频率。

需要修改为其他周期时,只需要调整代码顶部的频率变量。

目标周期 代码中的设置 传入BigTrader的结果
3分钟 3min 3m
5分钟 5min 5m
7分钟 7min 7m
13分钟 13min 13m
20分钟 20min 20m
30分钟 30min 30m

程序通过字符串替换,将 min 转换为 m

例如:

7min → 7m
13min → 13m
20min → 20m

修改频率后,建议先使用较短的回测区间运行,再通过日志检查实际时间是否符合预期。


十一、如何验证其他自定义周期

假设将回测频率修改为 7 分钟,可以按照以下步骤验证。

第一步:修改频率

将原来的 13 分钟改为 7 分钟。

第二步:运行较短的回测区间

第一次测试时,可以先选择几个交易日,减少运行和排查时间。

第三步:查看启动日志

确认启动日志中出现:

frequency=7m

这说明新的频率已经传入 BigTrader。

第四步:检查实际时间

在同一段连续输出中,比较相邻时间是否相差 7 分钟。

验证时不要直接使用跨越较长间隔的两个时间计算差值。


十二、常见问题

1. 只修改 frequency 就能完成其他分钟周期的回测吗?

如果只是修改策略的运行频率,通常只需要调整 frequency

例如,将 13 分钟改为 7 分钟后,BigTrader 会按照 7 分钟频率运行。

但需要注意,这只改变策略的运行节奏,不会自动改变指标的计算频率。

如果指标仍然来自 1 分钟行情,那么修改后的策略仍然是:

使用 1 分钟数据计算指标,以 7 分钟频率运行交易逻辑。

2. 当前示例是否等同于 13 分钟布林带策略?

不等同。

当前示例中的布林带由 1 分钟行情计算,只是 BigTrader 使用 13 分钟回测频率运行策略。

真正的 13 分钟布林带策略,应先形成 13 分钟 K 线,再根据 13 分钟 K 线计算均线、标准差和布林带。

3. 为什么不同交易日的第一个时间不一样?

实际日志中,2026 年 1 月 5 日首先出现:

2026-01-05 09:13:00

而 2026 年 1 月 6 日首先出现:

2026-01-06 09:10:00

因此,不能假设每天的第一个回调时间都固定为 09:13。

判断频率时,应观察同一段连续日志中的相邻时间差,而不是只看每天的第一个时间。

4. 修改回测频率会改变策略结果吗?

会。

即使指标计算方式保持不变,不同回测频率也可能改变:

  • 信号检查时间;
  • 下单时间;
  • 交易次数;
  • 持仓持续时间;
  • 实际成交价格;
  • 最终回测收益。

因此,每次修改频率后,都应重新运行并单独评估回测结果。

5. 回测频率越短越好吗?

不一定。

较短的频率会更频繁地运行策略,但也可能带来:

  • 更多交易次数;
  • 更高的手续费和滑点影响;
  • 更多短期价格噪声;
  • 更长的回测运行时间。

较长的频率通常交易次数较少,但也可能错过较短时间内的价格变化。

自定义频率应根据策略目的选择,不能简单认为周期越短越好。

6. 为什么日志中既有时间,又有“直接开空”等文字?

时间来自:

print(today)

“直接开空”“空换多”等文字来自策略下单部分的其他 print 语句。

二者可能出现在同一段输出中,属于正常情况。

7. 如何确认修改后的分钟频率已经生效?

需要同时检查两个方面。

第一,启动日志中的频率参数,例如:

frequency=13m

第二,同一段连续时间中的相邻间隔,例如:

2026-01-06 09:10:00
2026-01-06 09:23:00
2026-01-06 09:36:00
2026-01-06 09:49:00

如果参数日志和连续时间间隔都符合预期,就可以确认自定义分钟频率已经生效。


十三、总结

在 BigQuant 中完成自定义任意分钟期货回测,核心过程可以概括为:

设置自定义分钟周期
        ↓
转换为BigTrader频率格式
        ↓
启动bigtrader.run
        ↓
BigTrader按照设定频率运行
        ↓
handle_data输出当前时间
        ↓
通过日志检查连续时间间隔

本文使用的是:

13min → 13m

实际启动日志中出现:

frequency=13m

实际时间日志中出现:

2026-01-06 09:10:00
2026-01-06 09:23:00
2026-01-06 09:36:00
2026-01-06 09:49:00

这一段连续时间的相邻间隔均为 13 分钟,因此可以确认自定义 13 分钟回测已经生效。

需要重点掌握的是:

  1. 13min 是代码中便于阅读的频率设置;
  2. 13m 是实际传入 BigTrader 的频率格式;
  3. 1 分钟指标数据和 13 分钟回测频率作用不同;
  4. 不同交易日的第一个回调时间可能不同;
  5. 验证频率时,应观察同一段连续时间中的相邻间隔;
  6. 日志中可能同时包含时间、交易信息和系统信息。

本文中的布林带策略只负责提供可以运行的示例。将频率修改为 3 分钟、7 分钟、20 分钟或其他周期后,可以使用相同方法运行并验证自定义分钟期货回测。

{link}