栏目:量化工具研究 · 最小样例已跑通
测试日期:2026-10-29。AKQuant 0.3.75,macOS arm64,Python 3.12.2。本文使用人工合成价格,不是真实行情,也不是策略收益评测。
先说结论:在这次小实验中,费用配置改变了实际扣款,T+1 改变了卖单能否成交;不传撮合配置时,订单按下一根 K 线开盘价成交。三件事都可以从逐笔记录中核对,而不必猜测一条收益曲线为什么变化。
为什么先测这个
AKQuant 是一个 Rust 引擎配合 Python 接口的量化框架。对准备上手的人来说,先确认一笔交易怎样发生,比马上做一个复杂策略更有帮助。
官方快速开始已经提醒:没有指定相关配置时,回测不计成本、不开 T+1。这不是发现了一个隐藏缺陷,而是要验证:文档里的设置,在实际运行时怎样影响订单。项目说明
这次只做一个可以手算的小例子,不比较速度,不训练模型,也不接券商账户。
实验:两天、八根人工 K 线、四组配置
样本只有两个日期,每天四根盘中 K 线,不是完整交易日行情。虚构标的名为 SYNTH,起始资金 10,000,买卖数量都是 100。显式指定时区、两日交易日历和每手 100 的设置;未单独验证手数限制。
所有组使用同一段逻辑:
- 第一天 09:31 提交买入 100 的市价单。
- 第一天 09:33 若仍持仓,提交卖出 100 的市价单。
- 第二天 09:31 若仍持仓,再提交一张新的卖单。
这里的“第二天再提交”很重要:被拒的订单不是自动等到次日成交,而是脚本主动重新发单。
为了容易核算,费用组只设置双边佣金 0.1%,最低佣金、印花税与过户费都设为零。这是实验参数,不是实际券商报价或现行税费说明。其他组不传费用参数,也不使用券商配置模板。
| 组别 | 费用设置 | T+1 | 本例累计费用 | 结束时资金(已无持仓) |
|---|---|---|---|---|
| A | 不传,沿用默认 | 不传,沿用默认 | 0.00 | 10,100.00 |
| B | 双边佣金 0.1% | 不传,沿用默认 | 2.10 | 10,097.90 |
| C | 不传,沿用默认 | 显式开启 | 0.00 | 9,950.00 |
| D | 双边佣金 0.1% | 显式开启 | 1.95 | 9,948.05 |
“默认”只指本次留空的费用、T+1 与撮合配置,不表示整次运行没有显式设置其他参数。
逐笔看,比只看最后的数字清楚
以下时间均为 Asia/Shanghai;原始记录同时保存 UTC 时间。
| 订单 | 提交时间 | A/B 组处理结果 | C/D 组处理结果 |
|---|---|---|---|
| 买入 100 | 10 月 26 日 09:31 | 09:32,以 10.00 成交 | 同左 |
| 当日卖出 100 | 10 月 26 日 09:33 | 09:34,以 11.00 成交 | 09:34,被拒,成交量为零 |
| 次日新卖单 | 10 月 27 日 09:31 | 已无持仓,不提交 | 09:32,以 9.50 成交 |
开启 T+1 的两组,当日卖单留下的状态是 rejected。原因原文为:
Risk: Insufficient available position for SYNTH at execution. Available: 0, Required: 100
当时账户仍有 100 的持仓,但可用于这笔卖单的数量为零。隔日重新提交后卖出成功。这个结果支持的是“本例的同日新增持仓卖出限制有效”,并不覆盖完整市场规则。
费用也能手算:
- B 组:买入扣
100 × 10 × 0.001 = 1.00,卖出扣100 × 11 × 0.001 = 1.10,合计 2.10。 - D 组:买入扣 1.00,次日卖出扣
100 × 9.5 × 0.001 = 0.95,合计 1.95。被拒的那笔单没有成交,也没有扣佣金。
本例特意设置了次日下跌,所以延后卖出降低了余额。它说明交易约束会改变交易路径,不能据此得出“T+1 总会让结果变差”的结论。
另一个重要细节:信号时间不等于成交时间
09:31 的买单没有按该根 K 线的收盘价成交,而是在 09:32 以其开盘价成交。卖单也遵循相同规律。
测试脚本把每笔成交的价格和时间,与下一根样本 K 线逐项比对;安装包中的默认撮合定义也是 NextOpen。这个机制值得先弄清楚,否则一套策略即使逻辑没变,只因对成交时点理解不同,也会出现无法解释的结果。
不过,“下一根开盘撮合”并不会自动消除所有未来信息问题。数据如何生成、因子是否提前读到未来,仍是策略代码自己的责任。
对 AKQuant 的第一轮评价
值得继续研究。此次在 macOS arm64 独立环境使用基础发行包的预编译 wheel 即可运行,没有额外编译 Rust;短脚本就能拿到订单、成交和费用记录。对于入门研究,容易定位“交易究竟怎么发生”是实用优点。
暂时不能评价的部分也很明确:这次没有验证大数据性能、机器学习功能、实盘接入、不同资产类型,也没有测试停牌、涨跌停、节假日、部分成交、最低佣金和卖出税费。八根合成 K 线能验证几个配置分支,不能证明整个框架在复杂市场环境中可靠。
运行中出现了 pandas 3.1.0 的弃用警告,来自依赖包的结果排序代码;本次七项测试仍然通过。它不是这次计算失败,但说明升级依赖时应重新测试,不能只锁主框架版本。
怎样复现
下载完整复现包(不含运行环境),或逐个查看以下文件。压缩包包含完整脚本、人工样本、依赖版本锁和原始输出:
在包含上述文件的实验目录,新建隔离环境后运行:
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python --only-binary :all: -r requirements.lock.txt
.venv/bin/python experiment.py
.venv/bin/python test_experiment.py
实验只使用本地合成数据,不需要行情接口或模型密钥。安装依赖需要联网;上述命令只在本次 macOS arm64 环境验证,Linux 和 Windows 未实测。订单和成交 ID 每次随机生成,因此不能要求整份结果文件哈希每次相同;重复测试比较的是去掉这些 ID 后的完整业务记录。
如果只带走一条经验:先用能手算的样本核对一笔交易,再把更多数据、因子和模型加进来。这样得到的不是一张更漂亮的图,而是对工具行为更明确的认识。
相关阅读:首批 18 个项目短评 · 专题总览