自定义任意分钟期货回测
由bqi2tg8b创建,最终由qxiao 被浏览 3 用户
一、简介
在期货分钟策略研究中,常见的回测周期包括 1 分钟、5 分钟、15 分钟和 30 分钟。但在实际研究中,我们也可能希望使用 3 分钟、7 分钟、13 分钟等自定义周期运行策略。
例如,5 分钟周期可能过于敏感,而 15 分钟周期又可能反应较慢,此时可以选择 7 分钟、10 分钟或 13 分钟等更符合研究需求的时间周期。
BigTrader 是 BigQuant 提供的量化交易引擎。设置回测频率后,交易引擎会按照对应的 K 线周期推进历史行情,并在相应时间执行策略中的 handle_data 函数。
本文以焦煤期货为例,使用一个布林带策略演示如何完成自定义 13 分钟期货回测。
需要说明的是,本文的重点不是研究布林带策略,而是说明:
- 如何设置任意分钟回测频率;
- 自定义分钟频率如何传入 BigTrader;
- 1 分钟数据和 13 分钟回测频率有什么区别;
- BigTrader 如何按照 13 分钟周期运行;
- 如何通过实际运行日志确认自定义频率已经生效;
- 如何将 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.run 的 frequency 参数。
整个过程为:
设置13min
↓
转换为13m
↓
传入bigtrader.run
↓
BigTrader按照13分钟频率运行
因此,决定自定义回测频率的关键,是传入 bigtrader.run 的 frequency 参数。
六、通过运行日志验证 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 分钟。
因此,可以从两个方面确认自定义频率已经生效:
- 回测启动日志显示
frequency=13m; - 同一段连续日志中的相邻时间相差 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 分钟回测已经生效。
需要重点掌握的是:
13min是代码中便于阅读的频率设置;13m是实际传入 BigTrader 的频率格式;- 1 分钟指标数据和 13 分钟回测频率作用不同;
- 不同交易日的第一个回调时间可能不同;
- 验证频率时,应观察同一段连续时间中的相邻间隔;
- 日志中可能同时包含时间、交易信息和系统信息。
本文中的布林带策略只负责提供可以运行的示例。将频率修改为 3 分钟、7 分钟、20 分钟或其他周期后,可以使用相同方法运行并验证自定义分钟期货回测。