- domain/repositories/selection.py + SelectionMeta:选股 Repository Protocol
- models/selection.py + migration a6c91d4e7f20:selection_snapshot(查询/统计快照)+
selection_result(逐候选:rank/score/factor_values/filter_status/reason JSON)
- repositories/selection_impl.py:save/get/list_recent(读回重建 SelectionResult)
- api/selections.py:POST /api/selections(同步执行+落库,返回 selection_id+result)、
GET /{id}、GET 列表(as_of/method 过滤);deps 装配 SelectionService/Repo
- config._build_mysql_url:仅编码破坏 URL 结构的字符(修 Alembic configparser 遇 %21 崩)
- 迁移已在 MySQL 应用(alembic head a6c91d4e7f20);tests/test_selections_api.py 4 例
提交→读回一致/404/列表过滤/condition;全量 pytest 通过
30 lines
1.1 KiB
Python
30 lines
1.1 KiB
Python
"""选股 Repository Protocol(M6.3 落库)。
|
||
|
||
业务层只依赖本 Protocol;实现位于 infrastructure/persistence。
|
||
结果按 v2 §8:selection_snapshot(一次运行的查询与统计)+ selection_result(逐候选行),
|
||
用于回答「2023-08-15 为什么选这只股票」「某日选了什么」。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from datetime import date
|
||
from typing import Protocol
|
||
|
||
from app.domain.entities.selection import SelectionMeta, SelectionResult
|
||
|
||
|
||
class SelectionRepository(Protocol):
|
||
def save(self, selection_id: str, result: SelectionResult) -> None:
|
||
"""落库一次选股:snapshot 一行 + 候选逐行(同一事务,由调用方 commit)。"""
|
||
|
||
def get(self, selection_id: str) -> SelectionResult | None:
|
||
"""按 id 读回完整结果(重建 SelectionResult)。"""
|
||
|
||
def list_recent(
|
||
self,
|
||
as_of: date | None = None,
|
||
method: str | None = None,
|
||
limit: int = 20,
|
||
) -> list[SelectionMeta]:
|
||
"""历史选股元数据列表(按 created_at 倒序;可选 as_of/method 过滤)。"""
|