核心概念¶
QTrade 体量不大,但理清各组件之间的关系会让 API 和源码都好读得多。本页提供整体的心智模型。
组件构成¶
┌─────────────────────────────────────────────────┐
│ Backtest │
│ (orchestrates a full run; iterates the bars) │
└────────────────────┬────────────────────────────┘
│ owns
▼
┌─────────────────────────────────────────────────┐
│ Strategy │
│ user code: prepare(), on_bar_close() │
│ reads market data, places Orders via the Broker│
└────────────────────┬────────────────────────────┘
│ places orders on
▼
┌─────────────────────────────────────────────────┐
│ Broker │
│ fills Orders into Trades, tracks cash, equity, │
│ margin, SL/TP, equity history │
└──────────┬──────────────────────────┬───────────┘
│ holds │ records
▼ ▼
┌──────────────────┐ ┌─────────────────────┐
│ Position │ │ Order / Trade │
│ active + closed │ │ filled / closed │
│ Trade objects │ │ queues │
└──────────────────┘ └─────────────────────┘
做强化学习时,把 Backtest 换成 TradingEnv —— 底层是相同的 Broker,只是驱动方式从 Python for 循环换成了 Gymnasium 的 step()。
每个组件做什么¶
Broker¶
模拟核心。你通常不会直接实例化它 —— Backtest 和 TradingEnv 都会自动创建。
Broker 负责:
保存 OHLCV 数据(单资产或多资产的
dict[str, DataFrame])跟踪
cash,计算equity、unrealized_pnl、available_margin维护 pending / executing / filled / closed 几个订单队列
每个 bar 检查止损 / 止盈触发
每个资产持有一个
Position记录组合级别的
equity_historySeries
Order¶
交易 意图 —— 你想做什么。用带符号的 size 创建(正 = 买,负 = 卖),可选 limit / stop / sl / tp / tag 以及 asset 资产代码。订单进入 broker 的队列后,要么成交,要么被拒(通常是保证金不足)。
Trade¶
A filled position. Each Order that fills opens (or partially closes)
a Trade. While open, the Trade has entry_price, entry_date, size,
optional sl / tp (modifiable mid-trade — see Stops),
and optional trailing-stop state. When the Trade is closed (by an
opposite-side order, an SL/TP trigger, or end-of-backtest), it gets
exit_price, exit_date, profit, and an exit_reason.
Position¶
某个资产上 trades 的容器。active_trades 是开仓中的,closed_trades 是已平仓的。position.size 是该资产所有 active trades 的净有符号 size。
多资产模式下,Broker 持有 positions: dict[str, Position] —— 每个资产一个。broker.position(单数)是单资产模式专用的便捷访问器。
Strategy¶
你需要自己写的那部分。继承 qtrade.backtest.Strategy 并实现:
prepare()—— 在 bar 循环开始前调用一次。在这里加指标。on_bar_close()—— 每根 bar 调用一次。下单和管理仓位的地方。
在 on_bar_close() 内部你可以使用:
self.data(单资产)/self.data_by_asset[asset](多资产)—— 从开始到当前 bar 的 OHLCV 切片。self.position/self.positions[asset]—— 当前持仓。self.equity、self.unrealized_pnl—— 组合级快照。self.buy(...)、self.sell(...)、self.close(...)—— 下单辅助方法。
Backtest¶
驱动器。给定 data、Strategy 类、现金、佣金、保证金设置后,它会:
构造一个
Broker和一个Strategy实例。调用
strategy.prepare()。逐根 bar 循环,依次调用
broker.process_bar(ts)和strategy.on_bar_close()。结束时关闭所有未平仓位。
以及工具方法:optimize、walk_forward_optimize、show_stats、get_trade_history、plot。
TradingEnv(强化学习)¶
一个包装相同 Broker 的 Gymnasium 环境。由三个可插拔的 scheme 组合而成:
Scheme |
决定 |
|---|---|
|
动作空间 + 一个动作如何转换为 Orders |
|
观测空间 + 智能体每步看到什么 |
|
每步返回的标量奖励 |
完整内容见自定义交易环境。
回测的生命周期¶
对于一根典型的 bar,按以下顺序执行:
Backtest.run推进到第 i 根 bar。Broker.process_bar(ts)触发:从 pending 队列中清除已取消 / 已拒绝的订单。
处理 executing 队列订单(排队等下一根 bar 开盘成交)。
对每笔 active trade 检查 SL / TP —— 触发的就平仓。
处理 pending 队列里的 stop / limit 订单。
用新 bar 的 equity 更新
equity_history。
Strategy.on_bar_close()运行 —— 你可以读self.data(截到 i)并下新单。如果trade_on_close=True,新单立即成交;否则进入队列等下一根 bar 开盘。
最后一根 bar 之后,Broker.close_all_positions() 用最后一根 bar 的 close 价清掉所有未平仓位。
关键设计选择(以及原因)¶
事件循环,而非向量化。策略代码读起来就是真实的交易逻辑(
if x then buy)。更好写、更好调试。在大规模参数扫描场景比 vectorbt 慢 —— 参见 COMPARISON.md。结构上杜绝未来函数。
self.data被切片到[:current_time],你在on_bar_close()里根本读不到未来 bar。一个现金池 + 各资产独立持仓。多资产回测获得真实的组合行为(保证金跨资产共享),不必管理 N 个独立的 broker。
Strategy 和 RL 共用一个 Broker。相同的账户逻辑、相同的 SL/TP 行为、相同的成交语义。
TradingEnv里的 RL 智能体和Backtest里的Strategy受完全一样的规则约束。
下一步读什么¶
快速开始 —— 单资产的标准 Strategy / Backtest 工作流。
多资产 / 投资组合回测 —— 传入 dict 数据并使用多资产 Strategy API。
Walk-forward 优化 —— 样本外参数选择。
统计指标词汇表 —— 每个指标的含义。
交易环境 —— 强化学习工作流。
FAQ —— 常见坑。