feat(backtest): M9-2 回测补 selection_history/signal_history/fills(Signal↔Fill 区分)
- BacktestResult 新增:RankedPick(调仓意图,与 select(as_of) 同源排序)、 ActionRecord(BUY/SELL 意图 + filled + reject_reason/price)字段 selection_history / signal_history / fills(fills=signal_history 中 filled 子集)(v3 §20.3/§22.3) - TopKBacktestRunner:调仓记录卖出/买入逐动作与是否成交;涨停/停牌导致的 「BUY 信号未成交」保留原因;意图 picks 与执行 targets 分离(不因涨停悄悄改选股视图) - ChartService.backtest_stock_chart 改用 history 生成三类标记(selection/signal/fill), 未成交意图在图上可见(v3 §20.4) - tests/test_backtest_history.py:意图=select 一致、fills 推导、涨停拒绝可见(构造 +10% 涨停日)、序列化 roundtrip;相关回归(quant/consistency/charts)全过;全量 pytest 通过
This commit is contained in:
@@ -153,6 +153,30 @@ class Position(BaseModel):
|
||||
weight: float
|
||||
|
||||
|
||||
class RankedPick(BaseModel):
|
||||
"""调仓日选股意图候选(与 select(as_of) 同源;v3 §22.3 selection_history)。"""
|
||||
|
||||
date: date
|
||||
symbol: str
|
||||
rank: int
|
||||
score: float
|
||||
|
||||
|
||||
class ActionRecord(BaseModel):
|
||||
"""一次交易意图(Signal)及其成交结果(Fill)—— v3 §20.3 Signal↔Fill 区分。
|
||||
|
||||
signal=BUY/SELL(策略意图);filled=是否实际成交;reject_reason 给出未成交原因
|
||||
(涨停/跌停/无价/现金不足等)。fills = [a for a in signal_history if a.filled]。
|
||||
"""
|
||||
|
||||
date: date
|
||||
symbol: str
|
||||
signal: str = Field(pattern="^(BUY|SELL)$")
|
||||
filled: bool
|
||||
reject_reason: str | None = None
|
||||
price: float | None = Field(default=None, description="成交价(fill)或意图参考价")
|
||||
|
||||
|
||||
class BacktestResult(BaseModel):
|
||||
"""标准化回测结果(ARCHITECTURE §14)。前端只依赖该结构。"""
|
||||
|
||||
@@ -163,6 +187,15 @@ class BacktestResult(BaseModel):
|
||||
yearly_returns: list[YearlyReturn]
|
||||
positions: list[Position]
|
||||
trades: list[Trade]
|
||||
selection_history: list[RankedPick] = Field(
|
||||
default_factory=list, description="各调仓日选股意图候选(同 select(as_of))"
|
||||
)
|
||||
signal_history: list[ActionRecord] = Field(
|
||||
default_factory=list, description="交易意图与是否成交(v3 §20.3)"
|
||||
)
|
||||
fills: list[ActionRecord] = Field(
|
||||
default_factory=list, description="实际成交(signal_history 中 filled=True 的子集)"
|
||||
)
|
||||
turnover_pct: float
|
||||
unimplemented: list[str] = Field(
|
||||
default_factory=list,
|
||||
|
||||
Reference in New Issue
Block a user