127 lines
8.5 KiB
Markdown
127 lines
8.5 KiB
Markdown
# fidc-backtest-engine
|
||
|
||
面向中国 A 股和期货策略的 Rust 回测核心。仓库目标是提供平台自有的策略 DSL、执行模型、撮合模型和结果分析能力,最终由 `fidc-backtest-service` 对外提供策略运行服务。
|
||
|
||
## Runtime position exposure schedule
|
||
|
||
`strategy_spec.runtimeExpressions.risk.positionExposureSchedule` accepts dated
|
||
`effectiveDate` plus `targetExposureBps` points. The platform expression strategy
|
||
uses the latest point whose date is not later than the current execution date and
|
||
otherwise keeps the strategy's normal `exposureExpr`. This contract is intended for
|
||
audited runtime controls replayed by paper/live shadow reconciliation; it is not a
|
||
market-data signal and does not change selection, pricing, fees, or execution-day
|
||
risk checks.
|
||
|
||
## 当前能力
|
||
|
||
- 日频和分钟执行价策略生命周期与确定性回放。
|
||
- A 股行情、估值、因子、基准、候选资格、涨跌停触达、停牌和 ST 标记。
|
||
- 平台策略 DSL 与 `StrategyContext` 数据 API,不暴露非平台脚本语法。
|
||
- `BacktestConfig` 支持起止日期、初始资金、决策滞后、执行价格字段、基准代码。
|
||
- `DailyMarketSnapshot` 支持 `open/close/last/day_open/prev_close/upper_limit/lower_limit`。
|
||
- Universe 选择器支持动态市值带、排序、Top-N、动态订阅和策略内更新。
|
||
- A 股规则钩子支持 T+1、停牌、涨停不可买、跌停不可卖、整手和最小下单量。
|
||
- Broker 支持目标权重、显式金额、目标股数、限价、VWAP/TWAP、挂单、撤单和订单查询。
|
||
- 期货账户支持多空持仓、开平仓、今昨仓、保证金、手续费、结算和到期处理。
|
||
- 报告输出支持权益曲线、成交、持仓、月度收益、风险指标、基准序列和 JSON 分析包。
|
||
- 账户出入金以独立外部现金流记录保存;权益曲线同时输出 `externalCashFlow` 和现金流中性 `unitNav`,收益指标不把入金/出金计入交易收益。延迟出金在结算前做整批资金校验,不能把账户现金变成负数。
|
||
- 内置 `OmniMicroCapStrategy`,覆盖动态市值带、均线过滤、止损止盈、固定频率再平衡和盘中执行近似。
|
||
|
||
## Workspace 布局
|
||
|
||
```text
|
||
.
|
||
├── Cargo.toml
|
||
├── crates
|
||
│ └── fidc-core
|
||
│ └── src
|
||
│ ├── broker.rs
|
||
│ ├── calendar.rs
|
||
│ ├── cost.rs
|
||
│ ├── data.rs
|
||
│ ├── engine.rs
|
||
│ ├── futures.rs
|
||
│ ├── platform_expr_strategy.rs
|
||
│ ├── portfolio.rs
|
||
│ ├── rules.rs
|
||
│ ├── scheduler.rs
|
||
│ ├── strategy.rs
|
||
│ └── strategy_ai.rs
|
||
└── docs
|
||
```
|
||
|
||
## 核心模块
|
||
|
||
- `calendar`: 交易日历、交易日滚动和调度日期工具。
|
||
- `instrument`: 证券和合约静态定义。
|
||
- `data`: 行情、因子、基准、候选资格、公司行为、盘口和期货交易参数数据模型。
|
||
- `universe`: 动态市值带和预排序候选集。
|
||
- `portfolio`: 股票账户现金、持仓、可卖数量、盈亏、分红应收和资金流水。
|
||
- `futures`: 期货账户、合约参数、保证金、手续费和多空持仓。
|
||
- `rules`: 中国市场交易规则和风控校验。
|
||
- `broker`: 股票撮合、订单簿、滑点、成交量约束、限价和显式订单执行。
|
||
- `scheduler`: 日、周、月和分钟调度规则。
|
||
- `platform_expr_strategy`: 平台 DSL 解析后的表达式策略执行模型。
|
||
- `strategy`: 策略 trait、内置策略和运行时视图。
|
||
- `strategy_ai`: 策略 AI 手册、提示词生成和数据库字段目录合并。
|
||
- `engine`: 回测主循环、事件发布、报告和指标汇总。
|
||
|
||
## 平台策略模型
|
||
|
||
策略代码不直接运行 Python 或非平台 API,而是被解析为平台自有的策略 spec。执行链路是:
|
||
|
||
1. 页面编辑平台 DSL。
|
||
2. spec 生成器解析变量、函数、选股、排序、风控、资金分配和显式订单。
|
||
3. 回测引擎按交易日和调度事件构造 `StrategyContext`。
|
||
4. 策略返回 `StrategyDecision` 或显式订单动作。
|
||
5. Broker、规则钩子和账户模型完成撮合、费用、持仓和权益更新。
|
||
6. Analyzer 输出标准化结果供服务和前端展示。
|
||
|
||
平台 DSL 支持:
|
||
|
||
- `strategy("name") { ... }` 策略入口。
|
||
- `let` 自定义参数和 `fn` 自定义函数。
|
||
- `when / unless / else` 条件块。
|
||
- `selection.market_cap_band(...)` 动态市值带。
|
||
- `filter.stock_expr(...)` 任意指标、因子和组合选股。
|
||
- `ordering.rank_by(...)` 与 `ordering.rank_expr(...)` 排序。
|
||
- `allocation.buy_scale(...)` 相对等权槽位的个股资金倍率;显式权重可以大于 `1.0`,组合总仓位仍由 `risk.index_exposure(...)` 和严格资金预算控制。
|
||
- `risk.stop_loss(...)`、`risk.take_profit(...)` 多条件止盈止损。
|
||
- `order.*`、`cancel.*`、`update_universe(...)`、`subscribe(...)` 显式交易动作。
|
||
|
||
任意数据库指标和自定义因子通过 `factor("field")`、`factor_value("field", lookback)`、`rolling_mean("field", n)`、`sma("close", n)` 等函数读取。未预计算的均线窗口可在回测中按已有历史数据实时计算。
|
||
|
||
Source Lake 日线成交量保留原始可用性合同:源 `volume=null` 与真实 `volume=0` 含义不同。依赖成交量的 rolling 窗口只要包含源空值就返回缺失,不得把空值补成 0;停牌日明确提供的 0 成交量仍是合法观测。该合同随 runner 快照版本冻结,旧快照不能跨版本复用。
|
||
|
||
盘后固定价格不是策略类型,也不是 `matchingType`。自 2026-07-06 起,只有实际同日提交时间落在 15:00–15:30 的普通委托才由 broker 进入盘后固定价格执行阶段;15:00–15:04 的委托等待到 15:05,15:05–15:30 按官方收盘价和真实盘后成交量撮合,不叠加滑点,未成交余量不跨日。窗口外委托继续沿用连续竞价、当前收盘或下一交易日开盘合同;`next_bar_open` 策略即使在 15:00 生成信号,也不得被改写为同日盘后委托。缺失盘后行情时必须明确不成交,禁止回退全天成交量或 15:00 前分钟行情。
|
||
|
||
分钟回放使用行情时间戳与策略定时事件的有序合并时钟。`OnDay`、`Bar` 或 `Minute` 阶段只要声明显式 `physical_time`,就必须在各自真实分钟进入同一时间轴,即使该分钟没有预加载行情也必须触发,并由执行层按需查询该时点或之前最新有效价格;同一时间戳只形成一个事件,scheduler 回调先于 `on_minute`。日线 `current_bar_close` 无显式时间时使用官方日收盘,有显式时间时使用该触发点的 `Last` 行情,禁止读取下一分钟;多个时间点分别执行,禁止压成最后一个时间、把早盘单改成盘后单或依赖已有 BAR 才触发。`next_bar_open` 的 T 日信号时钟继续留在粗粒度决策阶段,不能延迟到 T+1 的同名分钟。
|
||
|
||
`holdUntilExit=true` 与 `stopTakeReferencePriceMode=signal_day_post_adjusted_close` 组合表示持久模型组合语义:股票进入模型目标后即记录信号日和后复权参考价,不以买单是否成交为前提。涨停、停牌或其他执行风控导致买单未成交时,模型成员仍占用目标槽位、每天累计模型持有日并继续生成目标仓位;达到止盈、止损或最大模型持有期后才从模型组合移除。实际订单仍由成交日风控独立决定,不得用实际持仓集合覆盖模型目标集合。
|
||
|
||
## 内置微盘策略
|
||
|
||
`OmniMicroCapStrategy` 是平台内置的微盘轮动策略,用于 demo、性能验证和策略迁移基线:
|
||
|
||
1. 使用 `benchmark_signal_symbol` 的同日决策价格计算指数信号。
|
||
2. 按 `(index_level - base_index_level) * xs + base_cap_floor` 计算动态市值带。
|
||
3. 在预排序 eligible universe 中按市值区间截取候选。
|
||
4. 过滤停牌、ST、退市、科创板、一元股、涨停、跌停和不可买卖标记。
|
||
5. 使用个股短中长均线过滤。
|
||
6. 支持止损、止盈、定期再平衡和替补买入。
|
||
7. 默认按 10:18 附近的平台调度快照近似盘中决策,并使用 `last_price` 或配置的盘口价格执行。
|
||
|
||
## 运行方式
|
||
|
||
`fidc-backtest-engine` 不再维护本地 CSV demo、partitioned snapshot 目录或导出融合表作为运行入口。生产和集成回测由 `fidc-backtest-service` runner 创建 `DataSet`,数据来自 Strategy Factory Source Lake 的 Arrow/Parquet、manifest/data_epoch 缓存和运行时逻辑视图。
|
||
|
||
本仓库只保留核心库构建和测试入口:
|
||
|
||
## 测试与构建
|
||
|
||
```bash
|
||
cargo fmt
|
||
cargo test
|
||
cargo build
|
||
```
|