Skip to content

Broker / Portfolio / Reports 实施方案

本文档用于明确 zelqor 下一条主线能力的落地顺序:先做真实 portfolio,再做真实 broker,最后做完整 reports

这三层不应该并行发散设计,而应按“账户真相源 -> 成交真相源 -> 结果汇总”的顺序推进。

当前落地状态:

  • portfolio 第一阶段已开始落地
  • engine.py 已改为通过 portfolio 更新账户状态
  • summary 已开始基于 portfolio 真实状态输出
  • broker 第一阶段已开始落地,买卖成交与拒单已具备结构化执行结果
  • reports 仍处于下一阶段

1. 为什么现在做这条线

当前仓库已经具备:

  • 策略加载与统一运行入口
  • selectorstateful step 两类策略接线
  • run_backtest(...) / CLI / safe API / task envelope
  • request / result / runtime / metadata 的基础宿主契约

但回测执行内核仍然偏“最小可运行”:

  • 成交逻辑主要写在 engine.py
  • Position 还是最小模型
  • reports 仍以基础 summary 为主

这意味着当前系统已经能“结构化地跑”,但还没有形成真正可扩展的:

  • 账户状态模型
  • 成交流程模型
  • 绩效分析模型

如果要继续向更真实的回测和未来模拟盘靠拢,收益最大的路径就是把这三层真正立起来。

2. 总体实施顺序

推荐顺序:

  1. portfolio
  2. broker
  3. reports

不要反过来先做 reports,因为报表只是消费前两层结果。如果先做报表,后面 brokerportfolio 一旦调整,报表语义也要被迫重做。

3. 第一阶段:Portfolio 真实化

3.1 目标

把当前“cash + positions 的最小状态”升级成真正的组合状态中心。

3.2 当前问题

当前回测状态的核心问题是:

  • 持仓对象过薄
  • 已实现盈亏没有标准归属位置
  • 未实现盈亏主要靠日末估值临时计算
  • 现金、权益、持仓市值与交易结果之间还没有形成统一账户语义
  • 后续如果要支持更复杂 broker 规则,会缺少稳定账户边界

3.3 推荐新增模型

建议至少补这些对象:

  • HoldingLot
  • PortfolioState
  • PortfolioSnapshot
  • ClosedPositionRecord

建议职责如下:

  • HoldingLot
  • 表示一笔打开中的持仓批次
  • 持有:

    • code
    • entry_date
    • planned_exit_date
    • quantity
    • entry_price
    • entry_fee
    • cost_basis
  • PortfolioState

  • 作为账户真相源
  • 持有:

    • cash
    • holdings
    • realized_pnl
    • unrealized_pnl
    • market_value
    • equity
  • PortfolioSnapshot

  • 表示某一交易日收盘后的账户快照
  • 用于结果输出和报表计算

  • ClosedPositionRecord

  • 表示已完整平仓的一笔交易生命周期
  • 记录:
    • 买入日期
    • 卖出日期
    • 买入金额
    • 卖出金额
    • 总费用
    • realized pnl
    • 持有天数

3.4 Portfolio 阶段验收标准

完成这一阶段后,应满足:

  • 账户资金与持仓价值有明确单一真相源
  • 买入、卖出、日末估值都通过 portfolio 更新
  • BacktestResult 可稳定拿到逐日账户快照
  • 报表层可以不直接读引擎内部临时变量

4. 第二阶段:Broker 真实化

4.1 目标

把“从池子直接变成交”的逻辑从 engine.py 中拆出来,形成独立执行层。

4.2 当前问题

当前成交逻辑虽然能跑,但还属于最小实现:

  • 下单与撮合没有独立建模
  • 成交失败原因没有统一表达
  • 费用、滑点、可成交约束仍是过程式散落逻辑
  • 未来如果支持更复杂规则,会继续堆在 engine.py

4.3 推荐新增模型

建议补这些对象:

  • OrderRequest
  • OrderFill
  • RejectedOrder
  • BrokerExecutionResult
  • BrokerConfig

建议职责如下:

  • OrderRequest
  • 表示策略或引擎发出的买卖请求
  • 持有:

    • trade_date
    • code
    • side
    • target_budgetrequested_quantity
    • timing
    • reason
  • OrderFill

  • 表示实际成交
  • 持有:

    • 成交价格
    • 成交数量
    • 金额
    • 手续费
    • 印花税
    • 成交原因 / 成交路径
  • RejectedOrder

  • 表示未成交
  • 原因例如:

    • 现金不足
    • 缺失 bar
    • 数量不足一手
    • 无法解析卖出日
    • 不可成交约束
  • BrokerExecutionResult

  • 汇总某一交易日 broker 输出
  • 包含:

    • fills
    • rejects
    • warnings
  • BrokerConfig

  • 承载 broker 层执行规则
  • 包括:
    • timing
    • slippage
    • taxes
    • board lot 规则
    • limit up / limit down 可成交约束

4.4 优先支持的 broker 规则

第一版不需要追求完整撮合,但建议至少明确:

  • 买入 / 卖出执行时点
  • 滑点
  • 手续费
  • 印花税
  • A 股按手取整
  • 现金不足拒单
  • 缺失 bar 拒单
  • 涨跌停约束的最小版本

4.5 Broker 阶段验收标准

完成这一阶段后,应满足:

  • engine.py 不再直接写大段成交细节
  • 每笔成交或拒单都有结构化结果
  • portfolio 只接受 broker 的标准执行结果做账户更新
  • future 模拟盘可以复用同一层 broker 语义

5. 第三阶段:Reports 完整化

5.1 目标

让报表从“最小 summary”升级成基于真实账户与交易生命周期的分析层。

5.2 推荐输出层次

建议分三层:

  • summary
  • 面向宿主和 CLI 的快速摘要

  • trade analytics

  • 面向单笔交易和已平仓交易的统计

  • daily analytics

  • 面向逐日权益与风险指标

5.3 推荐补充指标

建议优先补这些:

  • 总收益率
  • 最大回撤
  • 胜率
  • 盈亏比
  • 平均单笔盈亏
  • 平均持有天数
  • 已实现收益
  • 未实现收益
  • 手续费总额
  • 印花税总额
  • 交易次数
  • 买入次数
  • 卖出次数

5.4 推荐新增结果对象

可以逐步新增:

  • TradeAnalytics
  • DailyAnalytics
  • ReportBundle

第一版不一定都要暴露到公共 schema,但内部要先有明确 builder。

5.5 Reports 阶段验收标准

完成这一阶段后,应满足:

  • summary 不再只依赖“equity curve + trades 粗算”
  • 交易统计来自标准 closed positions / fills
  • 宿主与 CLI 可以稳定消费更完整的绩效指标

6. 推荐实施拆分

建议拆成三个连续迭代,而不是一次性重写:

6.1 Iteration A:Portfolio 重构

目标:

  • 把账户状态抽出来
  • 保持现有外部 API 尽量不变

范围:

  • backtest/portfolio.py
  • backtest/scheduler.py
  • backtest/engine.py
  • 相关模型与测试

6.2 Iteration B:Broker 重构

目标:

  • 把执行过程从引擎里拆出来
  • 给成交和拒单建立结构化结果

范围:

  • backtest/broker.py
  • backtest/engine.py
  • 相关模型与测试

6.3 Iteration C:Reports 升级

目标:

  • 补更完整 summary 与 analytics
  • 让结果基于 portfolio / broker 真实对象计算

范围:

  • backtest/reports.py
  • models.py
  • 文档与 CLI 展示

7. 设计原则

推进这条线时,建议坚持:

  • 先收口账户真相源,再扩执行层
  • 先做结构化对象,再扩公开字段
  • 保持 direct API / CLI / task envelope 的结果契约稳定
  • 允许内部对象演进,但谨慎修改公共 schema
  • 每一轮只推进一层主责任,不要三层一起重写

8. 风险与边界

主要风险:

  • 过早把 broker 做得过于复杂,拖慢整体演进
  • 在 portfolio 未稳定前就暴露太多新结果字段
  • 直接重写 engine.py 导致已有 selector / stateful step 链路回归

本阶段不建议立即做:

  • 日内撮合
  • 多资产支持
  • 保证金 / 融资融券
  • 公司行为复权重算
  • 多账户并行

9. 推荐的第一步

真正开始写代码时,推荐从 portfolio 开始,先完成:

  1. 扩充持仓模型
  2. 建立账户级快照
  3. 把日末权益计算收敛到 portfolio
  4. 再让 engine.py 改成通过 portfolio 更新状态

一句话总结:

portfolio 是账户真相源,broker 是成交真相源,reports 是结果汇总层。
下一阶段应按这个顺序推进,而不是从报表或更复杂撮合开始。