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:
@@ -131,55 +131,73 @@ def test_download_index_clears_proxy(tmp_path):
|
||||
assert "https_proxy" not in os.environ
|
||||
|
||||
|
||||
def test_read_index_daily_reads_from_vnpy_db(tmp_path):
|
||||
"""read_index_daily 经 vnpy get_database.load_bar_data 读指数日线,返回 DataFrame。
|
||||
def test_read_index_daily_reads_from_dbbardata(tmp_path):
|
||||
"""read_index_daily 从 dbbardata 表读指数日线(2026-08-01 切自 vnpy DbBarData)。
|
||||
|
||||
注:read_index_daily 数据源是 vnpy DbBarData 表(非 parquet);D2 根治拟切 dbbardata,
|
||||
届时 mock 数据源随之更新。当前测 vnpy 路径(与 read_db_daily 同 mock 模式)。
|
||||
建 tmp sqlite 库 + dbbardata 表插指数行,测真实 SQL 路径(非 mock)。
|
||||
中证指数用 sh 前缀 → exchange=SSE(点位由 sina_index_eod 灌入)。
|
||||
"""
|
||||
from types import SimpleNamespace
|
||||
from datetime import datetime
|
||||
import sqlite3
|
||||
from sanguo_data.datareader import read_index_daily
|
||||
|
||||
db = tmp_path / "q.db"
|
||||
conn = sqlite3.connect(db)
|
||||
conn.execute(
|
||||
"CREATE TABLE dbbardata (symbol TEXT, exchange TEXT, datetime TEXT, interval TEXT, "
|
||||
"volume REAL, turnover REAL, open_interest REAL, open_price REAL, "
|
||||
"high_price REAL, low_price REAL, close_price REAL)"
|
||||
)
|
||||
conn.executemany(
|
||||
"INSERT INTO dbbardata (symbol,exchange,datetime,interval,volume,turnover,"
|
||||
"open_interest,open_price,high_price,low_price,close_price) VALUES (?,?,?,?,?,?,?,?,?,?,?)",
|
||||
[
|
||||
("000300", "SSE", "2024-01-02", "d", 100000, 0, 0, 3495.0, 3505.0, 3490.0, 3500.0),
|
||||
("000300", "SSE", "2024-01-03", "d", 120000, 0, 0, 3505.0, 3515.0, 3500.0, 3510.0),
|
||||
("000300", "SSE", "2024-01-04", "d", 110000, 0, 0, 3515.0, 3525.0, 3510.0, 3520.0),
|
||||
],
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
cfg = DataConfig(
|
||||
data_paths={"vnpy_db": str(tmp_path / "q.db")},
|
||||
data_paths={"vnpy_db": str(db)},
|
||||
data_sources={}, validation={}, performance={},
|
||||
)
|
||||
# vnpy load_bar_data 返回类 BarData 对象(有 datetime/open_price/... 属性)
|
||||
bars = [
|
||||
SimpleNamespace(datetime=datetime(2024, 1, 2), open_price=3495.0,
|
||||
high_price=3505.0, low_price=3490.0, close_price=3500.0, volume=100000),
|
||||
SimpleNamespace(datetime=datetime(2024, 1, 3), open_price=3505.0,
|
||||
high_price=3515.0, low_price=3500.0, close_price=3510.0, volume=120000),
|
||||
SimpleNamespace(datetime=datetime(2024, 1, 4), open_price=3515.0,
|
||||
high_price=3525.0, low_price=3510.0, close_price=3520.0, volume=110000),
|
||||
]
|
||||
mock_db = MagicMock()
|
||||
mock_db.load_bar_data.return_value = bars
|
||||
# read_index_daily 内 lazy import,patch 源模块属性(同 test_datareader)
|
||||
with patch("vnpy.trader.database.get_database", return_value=mock_db):
|
||||
result = read_index_daily("sh000300", date(2024, 1, 1), date(2024, 12, 31), cfg)
|
||||
result = read_index_daily("sh000300", date(2024, 1, 1), date(2024, 12, 31), cfg)
|
||||
|
||||
assert len(result) == 3
|
||||
assert "close" in result.columns
|
||||
assert list(result.columns) == ["date", "open", "high", "low", "close", "volume"]
|
||||
assert result["close"].iloc[0] == 3500.0
|
||||
|
||||
|
||||
def test_read_index_daily_passes_date_range_to_vnpy(tmp_path):
|
||||
"""read_index_daily 把 start/end 传给 vnpy load_bar_data(日期过滤在 vnpy 层)。"""
|
||||
from datetime import datetime
|
||||
def test_read_index_daily_filters_date_range(tmp_path):
|
||||
"""read_index_daily 用 substr(datetime,1,10) 比日期,正确过滤 start/end 范围。"""
|
||||
import sqlite3
|
||||
from sanguo_data.datareader import read_index_daily
|
||||
|
||||
db = tmp_path / "q.db"
|
||||
conn = sqlite3.connect(db)
|
||||
conn.execute(
|
||||
"CREATE TABLE dbbardata (symbol TEXT, exchange TEXT, datetime TEXT, interval TEXT, "
|
||||
"volume REAL, turnover REAL, open_interest REAL, open_price REAL, "
|
||||
"high_price REAL, low_price REAL, close_price REAL)"
|
||||
)
|
||||
conn.executemany(
|
||||
"INSERT INTO dbbardata (symbol,exchange,datetime,interval,volume,turnover,"
|
||||
"open_interest,open_price,high_price,low_price,close_price) VALUES (?,?,?,?,?,?,?,?,?,?,?)",
|
||||
[
|
||||
("000300", "SSE", "2024-01-02", "d", 100, 0, 0, 1, 1, 1, 3500.0),
|
||||
("000300", "SSE", "2024-06-15", "d", 100, 0, 0, 1, 1, 1, 3600.0),
|
||||
("000300", "SSE", "2025-01-10", "d", 100, 0, 0, 1, 1, 1, 3700.0), # 范围外
|
||||
],
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
cfg = DataConfig(
|
||||
data_paths={"vnpy_db": str(tmp_path / "q.db")},
|
||||
data_paths={"vnpy_db": str(db)},
|
||||
data_sources={}, validation={}, performance={},
|
||||
)
|
||||
mock_db = MagicMock()
|
||||
mock_db.load_bar_data.return_value = []
|
||||
with patch("vnpy.trader.database.get_database", return_value=mock_db):
|
||||
read_index_daily("sh000300", date(2024, 1, 1), date(2024, 6, 30), cfg)
|
||||
|
||||
# start=date→combine 00:00:00; end=date→combine datetime.max.time()(23:59:59.999999)
|
||||
call = mock_db.load_bar_data.call_args
|
||||
assert call.kwargs["start"] == datetime(2024, 1, 1, 0, 0, 0)
|
||||
assert call.kwargs["end"] == datetime(2024, 6, 30, 23, 59, 59, 999999)
|
||||
result = read_index_daily("sh000300", "2024-01-01", "2024-12-31", cfg)
|
||||
assert len(result) == 2 # 只 2024 两行, 2025 范围外排除
|
||||
assert result["close"].iloc[1] == 3600.0
|
||||
|
||||
Reference in New Issue
Block a user