- 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
57 lines
1.9 KiB
Python
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()
|
|
]
|