Files
qlib/backend/app/domain/repositories/market.py
T
Simon ef09d5b419 feat(quant): M7.3 研究行情口径显式化(默认不复权 none,可切 qfq)
- DailyBarRepository.get_range_many / stream_range_many_columns 增加 adjust 参数
  (默认 'none')→ SQL 层过滤口径,消除 stock_daily 混 source/adjust 污染因子的风险
- ResearchSpec / SelectionQuery 增加 price_adjustment(none|qfq),随 config_snapshot
  落库可溯源;ResearchService._load_daily 与 SelectionService 装配按口径取数
- tests/test_price_adjustment.py:repo 读取按 adjust 过滤(none/qfq 各自命中)、
  spec 默认与字段记录;全量 pytest 通过
2026-09-09 00:32:55 +08:00

112 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Repository Protocol(Phase 1 数据层)。
业务层只依赖这些 Protocol;具体实现位于 infrastructure/persistence。
实体一律以 domain.entities 类型进出,禁止把 ORM Model 泄漏到上层。
"""
from __future__ import annotations
from collections.abc import Iterator, Sequence
from datetime import date
from typing import Protocol
from app.domain.entities.market import (
AdjustFactor,
DailyBar,
FinancialIndicator,
Stock,
SyncLog,
TradingCalendar,
)
class StockRepository(Protocol):
def get_by_symbol(self, symbol: str) -> Stock | None: ...
def list(self) -> list[Stock]: ...
def upsert_many(self, stocks: Sequence[Stock]) -> int:
"""批量写入,以 symbol 为幂等键,返回写入/更新的行数。"""
class TradingCalendarRepository(Protocol):
def upsert_many(self, days: Sequence[TradingCalendar]) -> int: ...
def list_range(self, start: date, end: date) -> list[TradingCalendar]: ...
def is_open(self, day: date) -> bool: ...
class DailyBarRepository(Protocol):
def upsert_many(self, bars: Sequence[DailyBar]) -> int: ...
def get_range(self, symbol: str, start: date, end: date) -> list[DailyBar]: ...
def get_range_many(
self,
symbols: Sequence[str],
start: date,
end: date,
adjust: str = "none",
) -> list[DailyBar]:
"""批量区间查询(研究装配面板用);adjust 指定行情口径(none 不复权 / qfq)。"""
def stream_range_many_columns(
self,
symbols: Sequence[str],
start: date,
end: date,
columns: Sequence[str],
adjust: str = "none",
) -> Iterator[tuple]:
"""流式(分批 yield)返回 symbol, trade_date(iso str), 数值列(float) 元组。
研究装配大数据面板专用:只 SELECT 所需列并在 SQL 侧转 REAL,
避免 ORM 对象 / Decimal 全量物化(内存大头,见内存优化专项)。
实现可选——ResearchService 会对缺失该方法的老实现回退到 get_range_many。
"""
def latest_date(self, symbol: str) -> date | None:
"""断点续传用:该股票本地已有数据的最新交易日。"""
class AdjustFactorRepository(Protocol):
def upsert_many(self, factors: Sequence[AdjustFactor]) -> int: ...
def get_range(self, symbol: str, start: date, end: date) -> list[AdjustFactor]: ...
class FinancialRepository(Protocol):
def upsert_many(self, rows: Sequence[FinancialIndicator]) -> int: ...
def list_symbol(self, symbol: str) -> list[FinancialIndicator]:
"""该股票本地全部财务行(增量判断 / 新浪校验重叠用,量级小)。"""
def has_report_period(self, symbol: str, report_date: date) -> bool:
"""本地是否已含该报告期(最新应披露报告期是否已入库)。"""
def list_announced(
self,
symbol: str,
as_of_date: date,
report_start: date | None = None,
) -> list[FinancialIndicator]:
"""只返回 announce_date <= as_of_date 的记录 —— 未来函数红线。"""
def list_announced_many(
self,
symbols: Sequence[str],
as_of_date: date,
) -> list[FinancialIndicator]:
"""批量版:返回这些股票 announce_date <= as_of_date 的全部记录。
供选股/截面研究一次性取财务字段(调用方按需取每 symbol 最新一版)。
实现可选 —— 未提供时 SelectionService 回退逐只 list_announced。
"""
class SyncLogRepository(Protocol):
def add(self, log: SyncLog) -> SyncLog: ...
def recent(self, source: str | None = None, limit: int = 20) -> list[SyncLog]: ...