Files
qlib/backend/tests/conftest_quant.py
T
Simon e9f59d3cf8 feat(backend): Phase 2 研究引擎 — ResearchSpec / 因子 / 评估 / 低频回测 / 引擎抽象
- domain:ResearchSpec(universe/factors/selection/rebalance/costs 校验)+ 标准化 BacktestResult / FactorTestReport
- 因子引擎:注册表 + 元数据,内置 9 个行情因子(momentum/volatility/量比/乖离/反转),支持自定义注册;只用行情字段规避未来函数
- 评估:横截面 IC / RankIC(rank+pearson 免 scipy)/ ICIR / 分层收益
- 回测:TopK 等权低频,无未来函数记账(t 收盘成交、自 t+1 计收益),成本/涨跌停/停牌约束,未建模项显式写入 unimplemented(AGENT §24)
- 引擎抽象 QuantEngine + LocalEngine(pandas 默认实现);qlib_adapter 桥接占位 —— pyqlib 无 aarch64+cp312 wheel(ROADMAP 已备注)
- 真实链路冒烟:600519 2024 月度动量回测闭环产出标准结果
- 测试 60 passed / ruff clean
2026-09-06 17:08:00 +08:00

57 lines
1.9 KiB
Python

"""共享测试装置:合成确定性 A 股行情(含涨跌趋势与噪声,无外部依赖)。"""
from __future__ import annotations
from decimal import Decimal
import numpy as np
import pandas as pd
def synthetic_daily(drifts: dict[str, float], n: int = 320, base: float = 100.0) -> pd.DataFrame:
"""生成多股票日线长表。
每股价格:p[j] = p[j-1] * (1 + drift + 0.012 * sin((j + i) * 0.8)) —— 确定性、
趋势 + 微幅周期噪声;含 high/low/volume/amount 供各因子使用。
"""
dates = pd.bdate_range("2024-01-01", periods=n)
rows: list[dict] = []
for i, (sym, drift) in enumerate(drifts.items()):
price = float(base)
for j, d in enumerate(dates):
ret = drift + 0.012 * np.sin((j + i) * 0.8)
prev = price
price = price * (1 + ret)
rows.append(
{
"symbol": sym,
"trade_date": d.date(),
"open": float(prev),
"high": float(price * 1.008),
"low": float(min(prev, price) * 0.992),
"close": float(price),
"volume": float(1_000_000 + j * 1000 + i * 3000),
"amount": float(price * (1_000_000 + j * 1000 + i * 3000)),
}
)
return pd.DataFrame(rows)
def bars_dataframe_to_daily_bars(daily: pd.DataFrame) -> list:
"""测试辅助:DataFrame → domain DailyBar 实体(供 service/仓储层路径测试)。"""
from app.domain.entities.market import DailyBar
return [
DailyBar(
symbol=r.symbol,
trade_date=r.trade_date,
open=Decimal(str(r.open)),
high=Decimal(str(r.high)),
low=Decimal(str(r.low)),
close=Decimal(str(r.close)),
volume=Decimal(str(r.volume)),
amount=Decimal(str(r.amount)),
)
for r in daily.itertuples()
]