LumiBot / 回测与实盘一致性
LumiBot 的「同一份代码从回测到实盘」到底同一在哪、差在哪
官方对 LumiBot 的核心承诺是 Same code for backtest and live trading:回测、模拟盘(paper)与实盘共用同一个 Strategy 子类,共用同一套生命周期钩子、同一套 create_order / submit_order 接口。这句话在策略层是真的。
但「策略类复用」不等于「结果一致」。真正决定差异的是三处:① 订单最终由谁执行、按什么规则撮合;② 现金与持仓怎么记账、什么时候计息;③ 行情从哪个数据源来、除权与分红怎么处理。官方为这三处各写了一份文档,而不是用一句口号盖掉。
官方在券商行为文档里把原则写成了两条:执行正确性由数据决定、「券商会怎么做」是券商与品种特定的。同一份文档还明确列出一条待办——Required follow-up: turn documentation into truth,也就是说那张按券商分节的行为表还没有被自动化 smoke test 覆盖。这一句是本站写这一页的出发点。
同码三阶段
同一份 Strategy 在回测 / 模拟 / 实盘里的复用点与差异点(依据LumiBot 官方文档推导的示意)
docs/BROKER_ORDER_SEMANTICS.md、docs/CASH_ACCOUNTING_AND_CASH_EVENTS.md,2026-09-22 采集)。官方在券商行为表中自述该表仍需 smoke test 才能从「文档」变成「事实」,本示意图不替官方扩大结论。回测、模拟盘、实盘:同一份 Strategy,三套外部世界
把「阶段」当成同一条流水线的三个开关是常见误解。实际上订单落到谁手里、行情从哪来、成交怎么发生,三个阶段完全不同;LumiBot 复用掉的只是策略层的写法。
| 维度 | 回测(backtest) | 模拟盘(paper) | 实盘(live) | 注意点 |
|---|---|---|---|---|
| 订单最终由谁执行 | 框架内的回测撮合逻辑 | 券商接口,但账户是模拟的 | 券商的真实撮合系统 | 回测的撮合规则是框架实现的,与券商真实规则不可能完全同构 |
| 行情从哪来 | 由 BACKTESTING_DATA_SOURCE 指定的历史数据源(Yahoo / ThetaData / Polygon 等) | 券商或数据源接口的实时/延时行情 | 券商行情与账户状态 | 换一个数据源,分红与除权处理就变,同一策略可能跑出两条曲线 |
| 成交假设 | 按历史 bar 与框架的成交规则推定 | 按券商的模拟撮合结果 | 真实成交、部分成交、拒单都会发生 | 回测里「价格到了就成交」的直觉,在实盘里会遇到流动性、涨跌幅与最小变动单位 |
| 现金与持仓 | 框架内的回测账本 | 券商返回的模拟账户状态 | 券商返回的真实账户状态 | 实盘的现金事件与订单事件是分开记录的,不能只对订单账单 |
| 时间如何推进 | 由历史 bar 驱动,指标必须按策略时间取 | 由真实时钟驱动 | 由真实时钟驱动,且受交易时段与假期约束 | 回测里用 datetime.now() 会直接引入未来信息,官方在代码规则里明令禁止 |
| 复用的是哪一层 | 同一个 Strategy 子类、同一套生命周期钩子、同一套 create_order / submit_order / 组合查询接口 | 「复用策略代码」与「复现结果」是两件事,中间隔着券商行为与数据口径 | ||
| 出错代价 | 时间与算力,可以重跑 | 几乎为零,但会发现接口与权限问题 | 真实资金损失,且部分动作不可撤销 | 本站建议:任何策略先在 paper 跑通订单生命周期,再考虑真实资金 |
| 是否必须有券商账号 | 不需要(Yahoo 免费日线即可) | 需要(券商提供 paper 环境) | 需要,且要开通对应资产类别的交易权限 | 期权、期货、加密各自有额外的权限与合规门槛 |
哪些环节真的复用,哪些必须按券商另行处理
把这张表当成迁移清单:左列是策略里的环节,右两列告诉你它在回测与实盘分别靠什么支撑,最后一列是你必须自己确认的东西。
| 环节 | 回测 | 实盘 | 是否同一份代码 | 注意点 |
|---|---|---|---|---|
| 策略类与参数 | Strategy 子类 + parameters | 同一个类、同一份参数 | 是 | 这是官方 same-code 承诺的主体,也是本页唯一「完全复用」的部分 |
| 生命周期钩子 | initialize / on_trading_iteration / before_market_opens 等 | 同一组钩子 | 是 | 钩子被调用的频率与时刻由真实时钟或历史 bar 决定,两者节奏不同 |
| 下单 API | create_order + submit_order | 同样的调用 | 是 | 调用方式相同不代表结果相同:实盘可能拒单、部分成交、延迟很久 |
| 订单状态与成交确认 | 由回测撮合逻辑写状态 | 由券商回报写状态 | 接口是,语义要核 | 官方反复强调:除非 is_filled 为真,否则不要说成交 |
| 现金与持仓账本 | 框架内的回测账本 | 券商账户的真实状态 | 部分 | 实盘现金事件与订单事件分开记录,专门讨论过去重与体积问题 |
| 手续费与滑点 | 回测参数 | 券商实际收取与真实成交价 | 否 | 回测里没设的成本假设,会在实盘里以「莫名其妙的亏损」出现 |
| 期权到期与指派 | 需按框架的处理规则 | 由券商实际执行 | 否 | 官方有专文 OPTIONS_EXPIRATION_ASSIGNMENT_POLICY.md;到期日附近是最容易对不上的时点 |
| 期货移仓 | 需按框架的移仓规则 | 由你的操作与券商合约决定 | 否 | 官方有专文 FUTURES_ROLL_POLICY.md;连续合约与具体合约不是一回事 |
| 限价单与高级订单 | 按历史数据推定 | 按券商订单类型与交易所规则 | 否 | 官方有 SMART_LIMIT_LIVE_TESTING.md;限价单的成交概率在回测里天然被高估 |
| 调度、监控与止损开关 | 你自己跑脚本 | 要么自己运维,要么用托管平台 | 否 | 官方托管 BotSpot 承担调度、监控、告警与 kill switch,属商业服务而非开源代码自带能力 |
docs/ 目录中的专项文档标题整理,各规则细节以对应文档为准。LumiBot 的券商行为表,为什么官方自己说「这张表还没变成事实」
docs/BROKER_ORDER_SEMANTICS.md 是本站认为最值得一读的一份文档:它没有声称回测与实盘等价,而是先把「不知道的部分」列出来。
原则 A:执行正确性由数据决定
订单在什么价位、什么时点算成交,取决于你喂进去的数据与撮合规则,而不是取决于你用哪个券商。这条原则决定了回测的可复现性来自数据,而不是来自平台。
原则 B:「券商会怎么做」是券商与品种特定的
同一笔市价单,在股票、期权、期货、加密上的处理完全不同;不同券商的委托类型、拒单条件、部分成交规则也各不相同。这条原则直接否定了「一套撮合规则通吃所有券商」的想法。
append-only 行为表 + 一句待办
文档维护一张只追加的「已核验行为表」,按券商与资产类别分节。同时写明 Required follow-up: turn documentation into truth——即需要 smoke test 才能把文档变成事实。这句话是官方自己写的,不是本站的推测。
| 分节 | 覆盖的资产类别 | 行为表是否已有内容 | 你能拿它做什么 | 注意点 |
|---|---|---|---|---|
| Alpaca | 股票 | 有 | 核对下单与回报的预期形态 | 股票之外的资产类别不适用 |
| Schwab | 股票 | 有 | 核对委托受理与回报 | 另有一份 SCHWAB_BROKER_RESILIENCE.md 讲容错,说明该通道有过稳定性问题 |
| Tradier | 股票 / 期权 | 有 | 期权与股票的委托差异可查 | 期权行权与被指派要另看专文 |
| Interactive Brokers | 股票 / 期权 | 有 | 核对股票期权通道行为 | IBKR 有 REST 变体与网关依赖,接入形态与其它券商不同 |
| Interactive Brokers | 期货 | 有 | 核对期货通道行为 | 期货另有 IBKR_FUTURES_BACKTESTING.md 与移仓规则 |
| Tradovate | 期货 | 有 | 核对期货委托受理 | 仅期货,不覆盖股票期权 |
| ProjectX(TopstepX) | 期货 | 有 | 核对期货通道行为 | 对应 README 里的 TopstepX 期货产品条目 |
| Crypto(Coinbase 为例) | 加密 | 有 | 核对 24/7 市场的收盘不变量 | 文档另有 crypto-futures close invariant 与 live crypto history completeness invariant 两条不变量,说明加密侧的历史完整性本身是待验证项 |
LumiBot 为什么把现金事件和订单事件分开记
回测里的「现金」是一个数字,实盘里的「现金」是一串事件流。docs/CASH_ACCOUNTING_AND_CASH_EVENTS.md 专门解释了为什么不合并这两本账。
| 项 | 回测侧 | 实盘侧 | 注意点 |
|---|---|---|---|
| 记录对象 | 现金分录与回测产物 | 券商回报的 broker cash events | 实盘侧与订单事件是两个独立流,不能靠订单账单还原现金 |
| 语义定义 | 文档给出明确的会计分录语义 | 按券商回报归一化成统一事件结构 | 归一化意味着「字段对齐」是官方做的,但「券商是否如实上报」仍需你自己核对 |
| 计息时点 | 文档单列 accrual timing 一节 | 由券商实际结算决定 | 利息、股息、费用的入账时点差异,会让「同一天的现金」两边不等 |
| 收益计算 | 文档给出 return calculation 口径 | 由账户实际净值决定 | 口径不同会导致「我的回测收益率」与「账户显示的收益率」不是同一个数 |
| 去重与体积 | 回测产物按固定结构输出 | 文档专门讨论 dedupe 与 payload 体量 | 需要去重说明真实环境中存在重复回报,不能假设一条事件只来一次 |
| 券商覆盖范围 | 覆盖所有回测数据源 | 文档带 Broker support in this release 一节 | 「本版支持哪些券商」是被显式限定的,不是「全部券商都支持」 |
| 测试覆盖 | 文档说明回测侧计算方式 | 文档带 Current test coverage 与 Known validation constraints | 官方主动列出「已知的验证限制」,读这两节比看示例代码更能判断可信度 |
| 自定义报表指标 | TEARSHEET_METRICS.md 给出 hook 契约与单位语义 | 同上(同一套 hook) | 自定义指标的单位必须与官方语义一致,否则报表会给出看似合理但方向错误的数字 |
docs/CASH_ACCOUNTING_AND_CASH_EVENTS.md 的章节结构与本机读取的文档内容,具体字段以LumiBot 官方文档为准。同一份 LumiBot 策略、同一只票,为什么两条曲线不一样
回测的不一致往往不出在策略上,而出在你换了数据源。官方 README 的数据源对照表直接标出了各源的除权与分红能力差异。
| 数据源 | OHLCV | 除权调整 | 分红 | 分红调整收益 | 对判断的影响 | 注意点 |
|---|---|---|---|---|---|---|
| Yahoo | 有 | 有 | 有 | 有 | 免费日线的默认选择,也适合先跑通一条最小链路 | 官方对照表里同时具备分红与分红调整收益的一条;仍与部分付费源口径不同 |
| Alpaca | 有 | 有 | 无 | 无 | 做股息策略或长周期持有回测时,收益会被系统性低估 | 官方标注为无分红;换源后必须重跑基线再比较 |
| Polygon | 有 | 有 | 无 | 无 | 换源后同一策略的净值曲线会与 Yahoo 口径不同 | 差异通常集中在分红除权日附近,可据此定位是否为口径问题 |
| Tradier | 有 | 有 | 无 | 无 | 同 Alpaca 与 Polygon,缺分红列 | 若你的策略依赖分红再投资,这条口径会直接改变结论 |
| Polymarket | 有 | N/A | N/A | N/A | 预测合约没有除权分红概念 | 不要把它与股票口径直接放在同一条收益曲线上比较 |
| Pandas / CSV(Yahoo dataframe 格式) | 有 | 有 | 取决于文件 | 取决于文件 | 自有数据的复权与分红由你自己保证 | 文件里没有分红列,回测就不知道有分红;列名须符合该格式要求 |
| ThetaData(可选 extras) | 有 | — | — | — | 官方推荐用于更深的股票、期权、期货与指数历史 | 属可选 extras;是否必需本机 Java 运行时本站未实测 |
把 LumiBot 回测从「能跑」变成「敢上 paper」的 8 个问题
下面这组问题按「答不上来就先别往下走」的顺序排列。它们全部来自官方文档里被单独成文的那些点——也就是官方自己认为最容易出错的地方。
| 问题 | 合格答案长什么样 | 答不上来会怎样 | 注意点 |
|---|---|---|---|
| 我的回测数据来自哪个源? | 能说出具体数据源,并知道它有没有分红列 | 分红口径被静默影响,却把差异当成策略效果 | Yahoo 有分红调整;Alpaca / Polygon / Tradier 没有 |
| 指标有没有用到未来数据? | 知道框架已改成「按策略时间截前缀」,且自己没用 datetime.now() | 回测虚高,且这种虚高在实盘里必然消失 | 官方列出的「仍未证明」部分要一起看,详见未来函数与时间安全 |
| 手续费与滑点怎么假设的? | 有明确参数,且能解释为什么取这个值 | 高频策略的「盈利」会被真实成本吃掉 | 回测的成交假设天然比真实市场乐观 |
| 成交是怎么判定的? | 知道要看 is_filled,而不是看「已提交」 | 把未成交当成已成交,仓位与预期不符 | 详见下单与成交 |
| 现金事件和订单事件对得上吗? | 能说出对账方式与频率 | 账户净值与自己的账本长期偏离却找不到原因 | 官方为 cash events 专门做了去重与体积讨论 |
| 期权到期、期货移仓谁负责? | 知道官方有专门文档,并看过处理规则 | 到期日与移仓日出现非预期持仓变动 | OPTIONS_EXPIRATION_ASSIGNMENT_POLICY.md 与 FUTURES_ROLL_POLICY.md |
| 策略挂掉时谁来兜底? | 自托管方案里明确写了进程守护与告警;或明确使用托管平台 | 半夜掉线无人知晓,持仓处于无管理状态 | 调度、监控、告警、kill switch 属托管商业服务能力,不是开源代码自带 |
| 我的券商属于行为表哪一节? | 能指出「券商 + 资产类别」对应的那一行 | 拿其它资产类别的经验套用,遇到拒单或部分成交时误判为框架 bug | 行为表按券商与资产类别分节,且官方自述仍需 smoke test |
关于回测与实盘的常见问题
以下回答依据 2026-09-22 采集的官方 README、docs/ 目录中的专项文档与仓库结构;涉及代码行为的部分以官方实现为准。本站未实盘下单,不做收益声明。
「同一份代码」到底是同一到什么程度?
同一到策略层:同一个 Strategy 子类、同一组生命周期钩子、同一套 create_order / submit_order 调用,回测与实盘都跑这一份。但订单最终由谁执行、现金怎么记账、行情从哪来,这三处取决于券商与数据源。官方为此单独写了券商行为、现金会计与数据源对照三份文档——如果三者真的等价,就不需要这些文档了。以官方文档为准。
回测赚钱、实盘亏钱,是框架的问题吗?
不能这样归因。官方自己列出的差异来源至少有四类:券商撮合规则(原则 B:券商会怎么做是券商与品种特定的)、数据源的分红与除权口径、手续费与滑点假设、以及订单成交与否的判定。本站的建议是先逐项排除这四类差异,再看策略本身。本站不做收益声明,也不评价任何策略的有效性;具体行为以官方文档和你自己的实盘记录为准。
券商行为表能当成规则手册用吗?
可以当差异清单用,但不能当保证。它是 append-only 的,按 Alpaca / Schwab / Tradier / IBKR(股票期权与期货两节)/ Tradovate / ProjectX / Crypto 分节记录已核验行为;官方在同一份文档里写着 Required follow-up: turn documentation into truth,明确表示还需要 smoke test 才能把这些描述变成事实。也就是说:表里有的你可以参考,表里没有的不要假设。
为什么现金也要单独记一份?订单记录不够吗?
不够。官方的做法是把实盘的 broker cash events 与 order events 分成两个流,并为现金流单独处理去重与传输体积问题。原因很实际:利息、股息、费用这些现金变动不一定由某笔订单产生;反过来,一笔订单也可能分裂出多条回报。官方文档还带 Broker support in this release、Current test coverage 与 Known validation constraints 三节,等于主动告诉你哪些地方还没验证。以官方文档为准。
我应该先在 paper 上跑多久?
本站不给时间建议,只给验收标准:在 paper 上你要能观察到完整的订单生命周期——就绪检查通过、订单被受理、拿到标识符、状态推进到终态、并且能用 is_filled 判定成交;同时账户里的现金事件能与你的账本对上。这四件事在 paper 上没跑通之前,实盘只会把问题放大,而不是让你先「试试看」。这段验收标准的依据是官方工具文档中关于订单状态与成交判定的描述。
托管平台和自建,差别只是省不省事吗?
不是。自建意味着调度、进程守护、日志轮转、告警、密钥保管与 kill switch 都由你自己解决;官方托管的 BotSpot 把这些一并承担,并提供并行回测与监控。这是商业服务,与开源代码是两件事:你付的是运维与基础设施的钱,代码仍然是同一份。本站不替官方评价性价比,也不复制其推广链接;请以官方页面为准。
本页的结论有多少是实测的?
如实说明:本页没有实盘实测,也没有在本机跑通完整的回测—paper—实盘链路。本页所有结论的来源是官方 README、docs/ 目录中可读取的专项文档(BROKER_ORDER_SEMANTICS.md、CASH_ACCOUNTING_AND_CASH_EVENTS.md、TEARSHEET_METRICS.md 等)与仓库结构。凡属「官方自述」的内容,本页都明确标注为官方说法;凡本站未验证的,都写成未验证。