fix: align ledger performance with signal window
This commit is contained in:
@@ -19,12 +19,12 @@
|
||||
## 模块
|
||||
|
||||
- `alpha_factors` — 158 alpha 公式 + 24 基础算子(移植自 qlib alpha158)
|
||||
- `execution` — A 股长仓执行仿真(成本/滑点/现金约束)+ 逐日成交/拒绝/持仓/NAV 审计;T+1、涨跌停、成交量与价差提供独立约束函数
|
||||
- `execution` — A 股长仓执行仿真(成本/滑点/现金约束)+ 稀疏调仓/完整交易日 Ledger + 可投影成交与 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)
|
||||
- `portfolio_construction` — 多期因子分数 → Top-K → 等权目标权重表
|
||||
- `research_pipeline` — 因子日 → 下一真实交易日 → 显式执行价 → 执行审计(防前视编排)
|
||||
- `research_pipeline` — 因子日 → 下一真实交易日 → 显式执行价 → 日末估值 → 成本后绩效(防前视编排)
|
||||
- `metrics` — 绩效(年化收益 / 波动率 / Sharpe / 最大回撤 / Calmar)
|
||||
- `factor_library` — 通用方法(turnover / winsorize / IC / OLS / jb_test)
|
||||
- `portfolio_decomp` — 组合分解(risk_parity / mean_variance / 因子归因)
|
||||
@@ -60,9 +60,12 @@ 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_multi_day_with_audit, simulate_with_daily_data,
|
||||
ExecutionConfig, simulate_daily_ledger_with_audit,
|
||||
simulate_multi_day_with_audit, simulate_with_daily_data,
|
||||
)
|
||||
from quant_engine.research_pipeline import (
|
||||
run_factor_backtest_research, run_factor_execution_research,
|
||||
)
|
||||
from quant_engine.research_pipeline import run_factor_execution_research
|
||||
from quant_engine.backtest import run_weight_backtest
|
||||
from quant_engine.indicators import macd, bollinger, kdj
|
||||
from quant_engine.data_adapter import (
|
||||
@@ -103,6 +106,24 @@ factor_execution = run_factor_execution_research(
|
||||
initial_cash=1_000_000.0,
|
||||
)
|
||||
|
||||
# 推荐研究入口:同一交易日历上显式区分 open 成交和 close 估值。
|
||||
# 因子日保持现金,下一交易日成交后的真实持仓才参与当日收盘收益。
|
||||
factor_backtest = run_factor_backtest_research(
|
||||
factor_scores,
|
||||
top_k=20,
|
||||
execution_prices=open_prices,
|
||||
valuation_prices=close_prices,
|
||||
execution_price_field="open",
|
||||
valuation_price_field="close",
|
||||
initial_cash=1_000_000.0,
|
||||
config=ExecutionConfig(),
|
||||
)
|
||||
print(factor_backtest.nav)
|
||||
print(factor_backtest.returns)
|
||||
print(factor_backtest.stats())
|
||||
print(factor_backtest.execution.ledger_frame)
|
||||
print(factor_backtest.execution.trades_frame)
|
||||
|
||||
# run_weight_backtest 是低层算子:只接受收益区间开始前已经生效的持仓权重。
|
||||
# 不要把 signal-date 的 factor_scores/decision_weights 直接传给它。
|
||||
backtest = run_weight_backtest(
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
借鉴 hikyuu SG/MM/CN/PG 部件化思想(不引入 hikyuu 框架):
|
||||
- ExecutionConfig:佣金 + 印花税 + 滑点 + 最小交易额 + 止损/止盈阈值
|
||||
- simulate_execution():从目标权重 → 实际成交金额(应用成本/滑点)
|
||||
- simulate_daily_ledger_with_audit():稀疏调仓 + 完整交易日收盘估值 Ledger
|
||||
- simulate_multi_day_with_audit():目标权重差额调仓(成交/拒绝/持仓/NAV)
|
||||
- simulate_multi_day():兼容的多日日末持仓快照入口
|
||||
- check_stop_loss_take_profit():止损/止盈触发判定
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""可信研究链路:因子分数经交易日历滞后后进入执行审计。
|
||||
"""可信研究链路:因子分数经交易日历滞后后进入执行与日频 Ledger。
|
||||
|
||||
本模块只编排现有组合构建与执行组件,不连接账户、券商或实盘订单。
|
||||
时间契约借鉴 Qlib 的 prediction/trade time 分离与 Backtrader 的 next-bar
|
||||
执行语义:signal_date 上形成的目标权重,默认最早在下一交易时点执行。
|
||||
完整回测链路进一步分离 execution price 与日末 valuation price,非调仓日也
|
||||
持续盯市,并从真实成交后持仓派生日收益和绩效。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -300,6 +302,13 @@ def run_factor_backtest_research(
|
||||
execution_calendar,
|
||||
lag_sessions=lag_sessions,
|
||||
)
|
||||
if decision_weights.empty:
|
||||
execution_window = execution_snapshot.iloc[:0].copy()
|
||||
valuation_window = valuation_snapshot.iloc[:0].copy()
|
||||
else:
|
||||
research_start = decision_weights.index[0]
|
||||
execution_window = execution_snapshot.loc[research_start:].copy()
|
||||
valuation_window = valuation_snapshot.loc[research_start:].copy()
|
||||
|
||||
target_history: list[tuple[str, dict[str, float]]] = []
|
||||
execution_history: list[tuple[str, dict[str, float]]] = []
|
||||
@@ -308,7 +317,7 @@ def run_factor_backtest_research(
|
||||
target_history.append(
|
||||
(date_label, {asset: float(weight) for asset, weight in weights.items()})
|
||||
)
|
||||
prices = execution_snapshot.loc[execution_date]
|
||||
prices = execution_window.loc[execution_date]
|
||||
execution_history.append(
|
||||
(date_label, {asset: float(price) for asset, price in prices.items()})
|
||||
)
|
||||
@@ -318,7 +327,7 @@ def run_factor_backtest_research(
|
||||
str(pd.Timestamp(valuation_date)),
|
||||
{asset: float(price) for asset, price in prices.items()},
|
||||
)
|
||||
for valuation_date, prices in valuation_snapshot.iterrows()
|
||||
for valuation_date, prices in valuation_window.iterrows()
|
||||
]
|
||||
execution = simulate_daily_ledger_with_audit(
|
||||
target_history,
|
||||
@@ -329,8 +338,8 @@ def run_factor_backtest_research(
|
||||
)
|
||||
return FactorBacktestResult(
|
||||
factor_scores=factor_snapshot,
|
||||
execution_prices=execution_snapshot,
|
||||
valuation_prices=valuation_snapshot,
|
||||
execution_prices=execution_window,
|
||||
valuation_prices=valuation_window,
|
||||
schedule=schedule,
|
||||
execution_price_field=execution_field,
|
||||
valuation_price_field=valuation_field,
|
||||
|
||||
Reference in New Issue
Block a user