"""MarketDataProvider(数据源抽象)。 业务层只依赖本 Protocol(AGENT.md §6),禁止在业务代码中 import tushare / 新浪实现。数据源一律返回 domain.entities 中的归一化实体。 """ from __future__ import annotations from datetime import date from typing import Protocol from app.domain.entities.index import IndexWeight from app.domain.entities.market import ( AdjustFactor, DailyBar, DailyBasic, FinancialIndicator, Stock, StockNameHistory, TradingCalendar, ) class MarketDataProvider(Protocol): """统一市场数据源接口。 实现约定: - get_daily 返回**不复权**行情(复权经 AdjustFactor 显式计算,禁止静默改口径) - get_financial 返回带 announce_date 的指标,供上层按 as_of 过滤 - 实现不得抛出裸连接异常以外的噪音;业务错误应转为 DataSourceError """ name: str def get_stock_basic(self, list_status: str = "L") -> list[Stock]: """股票基础信息。list_status: L=上市 / D=退市 / P=暂停上市(tushare 口径)。 默认 "L" 保持既有行为不变;研究侧的**幸存者偏差**修正依赖 "D"(已退市) ——退市股的历史行情与 delist_date 缺失会让回测系统性高估收益。 """ ... def get_trade_cal(self, start: date, end: date) -> list[TradingCalendar]: ... def get_daily(self, symbol: str, start: date, end: date) -> list[DailyBar]: ... def get_adjust_factor(self, symbol: str, start: date, end: date) -> list[AdjustFactor]: ... def get_financial( self, symbol: str, start: date | None = None, end: date | None = None, ) -> list[FinancialIndicator]: """财务指标快照。 start/end 为**报告期**窗口(对应 Tushare fina_indicator 的 start_date/end_date 参数,按报告期过滤);不传表示全量历史。 新浪接口不支持按窗口拉取,提供方会忽略窗口后由调用方自行过滤。 """ def get_index_weight(self, index_code: str) -> list[IndexWeight]: """指数历史成分(含权重):每期成分快照 → IndexWeight(index_code, trade_date, symbol)。 供 index_weight 同步与历史成分 Universe(v3 §9)。""" def get_name_changes(self, start: date, end: date) -> list[StockNameHistory]: """区间内全市场股票名称变更(时点 ST / 风险警示判定依据)。 仅 Tushare 提供;备用源应抛 `DataSourceNotSupported`(不得静默返回空列表, 否则名称历史会「看起来同步成功但一条没有」,导致时点 ST 静默降级)。 """ ... def get_daily_basic(self, trade_date: date) -> list[DailyBasic]: """单交易日全市场每日指标(估值 / 股息率 / 市值)。 按**交易日**整表拉取(Tushare daily_basic 支持 trade_date 参数一次返回全市场), 幂等键 (symbol, trade_date)。 实现约定: - 只能返回该 trade_date 当天已可得的值(dv_ratio 为时点值,天然无未来函数); - 不支持本接口的数据源(如新浪)必须抛 DataSourceNotSupported, 禁止返回空列表冒充成功(AGENT.md §7:禁止静默切换)。 """