feat(selection): M6.3 选股结果落库 + /api/selections(快照 + 逐候选行)
- 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 通过
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"""选股持久化表(M6.3)。
|
||||
|
||||
selection_snapshot:一次选股运行的查询与统计快照(复现/历史查询用)
|
||||
selection_result:逐候选行(symbol/rank/score + 可解释字段 JSON),
|
||||
回答 v2 §8「某日为什么选这只股票」。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
|
||||
from sqlalchemy import BigInteger, Date, DateTime, Integer, Numeric, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.infrastructure.persistence.sqlalchemy.base import Base
|
||||
|
||||
PK_INT = BigInteger().with_variant(Integer, "sqlite")
|
||||
|
||||
|
||||
class SelectionSnapshotModel(Base):
|
||||
__tablename__ = "selection_snapshot"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(32), primary_key=True)
|
||||
as_of: Mapped[date] = mapped_column(Date, index=True)
|
||||
method: Mapped[str] = mapped_column(String(16))
|
||||
query_json: Mapped[str] = mapped_column(Text)
|
||||
statistics_json: Mapped[str] = mapped_column(Text)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, index=True)
|
||||
|
||||
|
||||
class SelectionResultModel(Base):
|
||||
__tablename__ = "selection_result"
|
||||
|
||||
id: Mapped[int] = mapped_column(PK_INT, primary_key=True, autoincrement=True)
|
||||
selection_id: Mapped[str] = mapped_column(String(32), index=True)
|
||||
symbol: Mapped[str] = mapped_column(String(12))
|
||||
rank: Mapped[int] = mapped_column(Integer)
|
||||
score: Mapped[float] = mapped_column(Numeric(14, 6))
|
||||
factor_values_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
filter_status_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
reason_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime)
|
||||
Reference in New Issue
Block a user