docs: document auditable execution workflow

This commit is contained in:
ao gong
2026-08-21 21:38:08 +08:00
parent da2ca51ff7
commit b2af2a10a6
2 changed files with 31 additions and 11 deletions
+18 -2
View File
@@ -19,7 +19,7 @@
## 模块
- `alpha_factors` — 158 alpha 公式 + 24 基础算子(移植自 qlib alpha158)
- `execution` — 执行仿真(成本/滑点/T+1/涨跌停/部分成交/价差)+ 多日 NAV + PnL 拆解(借鉴 hikyuu 部件化思想)
- `execution` — A 股长仓执行仿真(成本/滑点/现金约束)+ 逐日成交/拒绝/持仓/NAV 审计;T+1、涨跌停、成交量与价差提供独立约束函数
- `indicators` — 50+ 技术指标(MACD / KDJ / 布林 / ATR / ADX / 等)
- `data_adapter` — 桥接 qtdb_pro 长表与新模块(rename / long-wide / 复权 / vwap 代理)
- `backtest` — weight-based 多日仿真(rebalance_table / compute_nav / compare_to_benchmark)
@@ -59,7 +59,7 @@ ruff check src/ tests/ # lint
```python
from quant_engine.alpha_factors import alpha_001, alpha_005, ALPHA158_REGISTRY
from quant_engine.execution import (
ExecutionConfig, simulate_with_daily_data, compute_realized_pnl,
ExecutionConfig, simulate_multi_day_with_audit, simulate_with_daily_data,
)
from quant_engine.backtest import run_weight_backtest
from quant_engine.portfolio_construction import scores_to_weight_table
@@ -76,6 +76,22 @@ df = load_qtdb_daily(["000001.SZ"], "2024-01-01", with_adj=True)
prices, volumes = prepare_execution_inputs(df)
result = simulate_with_daily_data(prices, initial_cash=1_000_000.0)
# 已正确滞后的目标权重 → 现金约束执行 → 唯一来源的成交/拒绝/日末持仓/NAV
execution = simulate_multi_day_with_audit(
target_weights_history=[
("2024-01-02", {"000001.SZ": 1.0}),
("2024-01-03", {"000001.SZ": 1.0}),
],
price_history=[
("2024-01-02", {"000001.SZ": 10.0}),
("2024-01-03", {"000001.SZ": 10.5}),
],
initial_cash=1_000_000.0,
config=ExecutionConfig(),
)
print(execution.nav_series)
print(execution.daily_executions)
# 多期因子分数 → Top-K 等权组合 → 稳定回测结果
rebalance_weights = scores_to_weight_table(
factor_scores,
+13 -9
View File
@@ -344,15 +344,11 @@ def test_simulate_multi_day_first_day_value_equals_initial():
def test_simulate_multi_day_holdings_evolution():
"""调仓后 holdings 演化。
注意:positions[i] 是第 i 天 rebalance 之前的快照。
所以要看 d2 rebalance 后的 holdings,需要看 positions[2](d3 的快照)。
"""
"""日末快照应反映当天调仓后的 holdings。"""
signals = [
("d1", {"A": 0.5, "B": 0.5}),
("d2", {"A": 1.0, "B": 0.0}), # 全仓 A
("d3", {"A": 1.0, "B": 0.0}), # 第三天的快照才能看到 d2 rebalance 后的 holdings
("d3", {"A": 1.0, "B": 0.0}),
]
prices = [
("d1", {"A": 10.0, "B": 20.0}),
@@ -360,9 +356,8 @@ def test_simulate_multi_day_holdings_evolution():
("d3", {"A": 12.0, "B": 22.0}),
]
positions = simulate_multi_day(signals, prices, 1_000_000.0)
# d3 的 PRE-trade snapshot 应该只有 A(B 在 d2 被平仓)
assert "B" not in positions[2].holdings
assert "A" in positions[2].holdings
assert "B" not in positions[1].holdings
assert "A" in positions[1].holdings
def test_simulate_multi_day_with_audit_rebalances_target_weights_by_delta():
@@ -567,6 +562,15 @@ def test_run_end_to_end_poc_costs_recorded():
result = run_end_to_end_poc(signals, prices, 1_000_000.0)
assert result["total_costs"] > 0
assert result["total_turnover"] > 0
executions = [
execution
for daily in result["daily_executions"]
for execution in daily.executions
]
assert result["total_costs"] == pytest.approx(sum(item.total_cost for item in executions))
assert result["total_turnover"] == pytest.approx(
sum(item.executed_value for item in executions)
)
# ── v1.2.0 Phase 2: T+1 / 涨跌停 / 部分成交 / 买卖价差 ─────