b2c5d8fd79
- datareader: +read_parquet_15min(sh/sz前缀+15min.parquet), get_database lazy(去tzlocal等依赖)
- data_source: iter_bars cross-section yield(date,{symbol:Bar}), raw首版fallback qfq+warning(spec§17)
- 本机 mock _read_fn 测调度逻辑, read_parquet_15min 容器冒烟 4 tests passed.
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""模拟盘行情统一接口(qfq/raw 双源,spec §3.3 / §5)。
|
||
|
||
_read_fn 内 lazy import datareader,避免模块级依赖 vnpy 链(tzlocal 等),
|
||
本机无 vnpy 完整依赖时仍可 import + 单测(mock _read_fn)。
|
||
"""
|
||
import logging
|
||
from collections.abc import Iterator
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _read_fn(interval: str):
|
||
"""按 interval 返回读取函数(lazy import)。"""
|
||
if interval == "d":
|
||
from sanguo_data.datareader import read_parquet_daily
|
||
return read_parquet_daily
|
||
if interval == "15m":
|
||
from sanguo_data.datareader import read_parquet_15min
|
||
return read_parquet_15min
|
||
raise ValueError(f"不支持的 interval: {interval}(首版仅 d / 15m)")
|
||
|
||
|
||
def iter_bars(
|
||
symbols: list[str],
|
||
start: str,
|
||
end: str,
|
||
interval: str,
|
||
adjust: str = "qfq",
|
||
cfg=None,
|
||
) -> Iterator[tuple]:
|
||
"""按日期 cross-section yield (date, {symbol: BarData})。
|
||
|
||
raw 首版 fallback qfq + warning(NAS 暂无 raw parquet,spec §17 开放项)。
|
||
"""
|
||
if adjust == "raw":
|
||
logger.warning(
|
||
"raw 模式首版 fallback qfq(NAS 暂无 raw parquet,spec §17 开放项)"
|
||
)
|
||
read_fn = _read_fn(interval)
|
||
by_date: dict = {}
|
||
for sym in symbols:
|
||
for bar in read_fn(sym, start, end, cfg):
|
||
dt = bar.datetime
|
||
key = dt.date() if hasattr(dt, "date") else dt
|
||
by_date.setdefault(key, {})[sym] = bar
|
||
for date in sorted(by_date.keys()):
|
||
yield date, by_date[date]
|
||
|
||
|
||
def fetch_day(symbol: str, date: str, interval: str,
|
||
adjust: str = "qfq", cfg=None):
|
||
"""实走模式拉当日 bar(C-S3 用)。"""
|
||
if adjust == "raw":
|
||
logger.warning("raw fallback qfq(spec §17)")
|
||
read_fn = _read_fn(interval)
|
||
bars = read_fn(symbol, date, date, cfg)
|
||
return bars[-1] if bars else None
|