- qlib_adapter/provider.py:SQLite 行情按 qlib 0.9.8 二进制格式落盘(起始索引头 + 逐日 float32、instruments 3 列、小写 instrument、晚上市 offset)
- qlib_adapter/dataset.py:qlib.init 幂等({'day': uri})+ D.features 读取 close 面板
- qlib_adapter/engine.py:QlibEngine(QuantEngine)v1 —— Qlib 数据管线回测与 LocalEngine 同记账规则(无未来函数/成本/涨跌停标注),factor_test 复用共享实现;Alpha158+LightGBM 为 TODO
- 真实 20 股验证:qlib 落盘 142 文件→读取→回测(-12.81%,Local 对照 -12.97%,差异为 qlib float32 存储)
- tests/test_qlib_engine.py 5 项(格式/roundtrip/晚上市 offset/回测/因子测试)→ pytest 86 passed / ruff clean
48 lines
1.3 KiB
Python
48 lines
1.3 KiB
Python
"""Qlib 数据读取(dataset):qlib.init 幂等 + 从 provider_uri 读行情面板。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from datetime import date
|
||
from pathlib import Path
|
||
|
||
import pandas as pd
|
||
|
||
_init_state: dict = {"uri": None}
|
||
|
||
|
||
def ensure_qlib_init(provider_uri: Path) -> None:
|
||
"""初始化 qlib(进程内同 uri 幂等;不同 uri 会重新 init)。"""
|
||
if _init_state["uri"] == str(provider_uri):
|
||
return
|
||
import qlib
|
||
from qlib.config import REG_CN
|
||
|
||
qlib.init(provider_uri={"day": str(provider_uri)}, region=REG_CN)
|
||
_init_state["uri"] = str(provider_uri)
|
||
|
||
|
||
def load_close_panel(
|
||
provider_uri: Path,
|
||
symbols: list[str],
|
||
start: date,
|
||
end: date,
|
||
) -> pd.DataFrame:
|
||
"""经 qlib D.features 读取 $close,返回 date×symbol 面板(index datetime)。"""
|
||
ensure_qlib_init(provider_uri)
|
||
from qlib.data import D
|
||
|
||
lower = [s.lower() for s in symbols]
|
||
df = D.features(
|
||
lower,
|
||
["$close"],
|
||
start_time=start.strftime("%Y-%m-%d"),
|
||
end_time=end.strftime("%Y-%m-%d"),
|
||
freq="day",
|
||
)
|
||
if df.empty:
|
||
return pd.DataFrame()
|
||
close = df["$close"].unstack(level="instrument")
|
||
close.index = pd.to_datetime(close.index)
|
||
close.columns = [c.upper() for c in close.columns]
|
||
return close.sort_index()
|