fix(datareader): read_index_daily 切 dbbardata(治 benchmark 读陈旧 vnpy DbBarData)
cta_engine benchmark 经 read_index_daily 读 vnpy DbBarData(方案A前陈旧源)。 切 dbbardata(指数点位已由 sina_index_eod 灌 exchange=SSE)。 - 数据源:vnpy get_database.load_bar_data → sqlite3 直连 dbbardata - 消除覆写 vnpy SETTINGS 副作用(cta_engine.py:73/199) - 回归坑1(000300读空):CODES 已加 000300 → dbbardata 有数据(本轮修复) - 回归坑2(sz000905):默认 benchmark sh000300 不触发;中证指数用 sh 前缀 - 复用 provider 模式:substr(datetime,1,10) 比日期规避混合格式 - 测试:mock vnpy → 真实 tmp sqlite 库测 SQL 路径(2测重写) - 验证:Mac 4+5 passed + VPS 真实库 sh000300 7月23行 close4588.197
This commit is contained in:
+39
-40
@@ -110,61 +110,60 @@ def read_parquet_15min(symbol: str, start: str, end: str, cfg, dir_key: str = "m
|
||||
|
||||
def read_index_daily(code: str, start, end, cfg) -> pd.DataFrame:
|
||||
"""
|
||||
读指数日线数据(sh000300/sz399001 等),从 vnpy DB 读取(统一数据源)。
|
||||
parquet 仅作原始备份,不再读取。返回类型保持 pd.DataFrame(cta_engine 消费不变)。
|
||||
读指数日线数据(sh000300/sz399001 等),从 dbbardata 读取(2026-08-01 切自 vnpy DbBarData)。
|
||||
|
||||
指数点位已由 sina_index_eod 灌入 dbbardata exchange=SSE(16 个中证指数含 000300 沪深300)。
|
||||
中证指数须用 sh 前缀(点位在 SSE);深证指数 sz 前缀。cta_engine benchmark 用 sh000300。
|
||||
切 dbbardata 后不再调 get_database() → 消除覆写 vnpy SETTINGS 副作用(cta_engine.py:73/199)。
|
||||
|
||||
Args:
|
||||
code: 指数代码,带交易所前缀,如 "sh000300"(沪深300)、"sz399001"(深证成指)
|
||||
start: 起始日期(str "YYYY-MM-DD" / date / datetime)
|
||||
end: 结束日期(str "YYYY-MM-DD" / date / datetime)
|
||||
cfg: 数据配置对象
|
||||
start/end: 日期(str "YYYY-MM-DD" / date / datetime)
|
||||
cfg: 数据配置对象(data_paths.vnpy_db 指向含 dbbardata 表的 quant_trading.db)
|
||||
|
||||
Returns:
|
||||
pd.DataFrame: date/open/high/low/close/volume 列;无数据返回空 DataFrame。
|
||||
pd.DataFrame: date/open/high/low/close/volume 列(date 为 Timestamp);无数据返回空 DataFrame。
|
||||
"""
|
||||
from vnpy.trader.database import get_database # lazy:避免模块 import 依赖数据库驱动
|
||||
import sqlite3
|
||||
|
||||
# 前缀解析交易所(指数不能用 guess_exchange:000300 以 0 开头会被误判成 SZSE,
|
||||
# 但 000300 实际属于 SSE)。sh → SSE,sz → SZSE。
|
||||
# 前缀解析交易所(指数不能用 guess_exchange:000300 以 0 开头会误判 SZSE,但属 SSE)。
|
||||
symbol = code[2:]
|
||||
exchange = Exchange.SSE if code.startswith("sh") else Exchange.SZSE
|
||||
exchange = "SSE" if code.startswith("sh") else "SZSE"
|
||||
|
||||
# 日期归一化:str → parse, date → combine, datetime → as-is
|
||||
def _to_dt(s, is_start: bool) -> datetime:
|
||||
# 日期归一化 -> 'YYYY-MM-DD'
|
||||
def _to_str(s) -> str:
|
||||
if isinstance(s, datetime):
|
||||
return s
|
||||
return s.strftime("%Y-%m-%d")
|
||||
if isinstance(s, date):
|
||||
return datetime.combine(s, datetime.min.time() if is_start else datetime.max.time())
|
||||
return datetime.strptime(s, "%Y-%m-%d")
|
||||
return s.strftime("%Y-%m-%d")
|
||||
return str(s)[:10]
|
||||
|
||||
start_dt = _to_dt(start, True)
|
||||
end_dt = _to_dt(end, False)
|
||||
start_str = _to_str(start)
|
||||
end_str = _to_str(end)
|
||||
|
||||
# 配置 vnpy DB(与 read_db_daily 同模式)
|
||||
SETTINGS["database.name"] = "sqlite"
|
||||
vnpy_db = getattr(cfg, "data_paths", {}).get("vnpy_db")
|
||||
if not vnpy_db:
|
||||
db_path = getattr(cfg, "data_paths", {}).get("vnpy_db")
|
||||
if not db_path:
|
||||
raise RuntimeError("config 缺 data_paths.vnpy_db — 检查 backtest.yaml 初始化")
|
||||
SETTINGS["database.database"] = vnpy_db
|
||||
|
||||
db = get_database()
|
||||
bars = db.load_bar_data(
|
||||
symbol=symbol,
|
||||
exchange=exchange,
|
||||
interval=Interval.DAILY,
|
||||
start=start_dt,
|
||||
end=end_dt,
|
||||
)
|
||||
conn = sqlite3.connect(db_path, timeout=30)
|
||||
conn.execute("PRAGMA busy_timeout = 30000")
|
||||
try:
|
||||
# substr(datetime,1,10) 比日期规避混合格式(有纯日期有带时间,同 provider 模式)
|
||||
df = pd.read_sql(
|
||||
"SELECT datetime, open_price, high_price, low_price, close_price, volume "
|
||||
"FROM dbbardata WHERE symbol=? AND exchange=? AND interval='d' "
|
||||
"AND substr(datetime,1,10)>=? AND substr(datetime,1,10)<=? ORDER BY datetime",
|
||||
conn, params=(symbol, exchange, start_str, end_str),
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
if not bars:
|
||||
if df.empty:
|
||||
return pd.DataFrame(columns=["date", "open", "high", "low", "close", "volume"])
|
||||
|
||||
df = pd.DataFrame([{
|
||||
"date": b.datetime,
|
||||
"open": b.open_price,
|
||||
"high": b.high_price,
|
||||
"low": b.low_price,
|
||||
"close": b.close_price,
|
||||
"volume": b.volume,
|
||||
} for b in bars])
|
||||
return df.sort_values("date").reset_index(drop=True)
|
||||
df = df.rename(columns={
|
||||
"datetime": "date", "open_price": "open", "high_price": "high",
|
||||
"low_price": "low", "close_price": "close",
|
||||
})
|
||||
df["date"] = pd.to_datetime(df["date"], format="mixed")
|
||||
return df[["date", "open", "high", "low", "close", "volume"]].reset_index(drop=True)
|
||||
|
||||
Reference in New Issue
Block a user