Files
2026-08-09 12:34:02 +08:00

5.8 KiB

知行 B1 选股策略实施计划

实施原则

  • 只修改 zhixing-system;旧项目只读,不回写、不重命名、不提交旧项目数据。
  • 先写行为测试,再补最小实现;每一步保持 uv run pytest 可定位失败范围。
  • zhixing_b1 是新策略身份;不要把 xg_composite 作为新模块的对外名称。
  • 公式语义优先于旧 Python 的偶然行为;每个有意差异都要在 fixture 或测试名中 留下证据。
  • 不启动 HTTP、前端、信号持久化或全市场批次编排;它们属于后续任务。

1. 依赖与模块骨架

  • 在 zhixing-server/pyproject.toml 声明直接依赖 pandas 和 numpy,执行 uv lock,确认锁文件与 Python 3.12 环境一致。
  • 创建 modules/selection/{domain,application,infrastructure,presentation} 包和上下文 README,保持 domain 不导入 FastAPI/Psycopg。
  • 先新增领域模型、端口和评估状态类型,再接入基础设施。

验证:

cd zhixing-server
uv lock --check
uv run python -c "import numpy, pandas; print(numpy.__version__, pandas.__version__)"

回滚点:依赖或包骨架若无法通过 Ruff/Pyright,先撤销骨架,不触碰 modules/market_data。

2. 迁移公式原语

  • 从旧项目 shared/indicators.py、kdj.py、rsi.py、zhixing.py 和 market_type.py 提取必要实现到 selection/domain/indicators.py。
  • 先覆盖 MA/EMA/LLV/HHV/SMA/REF/EXIST/EVERY/COUNT/HHVBARS/BARSLAST/CROSS, 再实现 KDJ、RSI、知行线和板块幅度参数。
  • 每个公共函数增加完整类型、参数/返回值/边界说明;NaN、除零和不足窗口行为 用测试锁定。
  • 不引入 Numba、SciPy 或其他旧项目专用依赖;首期 Pandas/NumPy 足够保持公式 计算的向量化和数值接近。

验证:

cd zhixing-server
uv run pytest tests/unit/selection/test_indicators.py

3. 实现 ZhixingB1Strategy

  • 将旧 prepare_xg_indicators() 拆成可读的领域计算步骤:基础线、振幅、KDJ/RSI、 缩量、大绿棒、异动、趋势、距离/回踩、7 个子信号。
  • 策略类固定 name = "zhixing_b1",公开入口显式接收 StockHistory 和 target_trade_date。
  • 对目标交易日定位使用日期索引,不使用 DataFrame 最后一行猜测目标日期。
  • 保留 7 个 mask 的全部命中,按公式顺序产生多个 SelectionSignal,不可使用 旧代码中的 break。
  • 详情只写可序列化、与目标行相关的关键指标;不要保存整张 DataFrame。
  • 对目标日缺失、历史不足、无信号分别返回评估状态;公式计算异常向上暴露, 不静默转换为空结果。

验证:

cd zhixing-server
uv run pytest tests/unit/selection/test_zhixing_b1.py

回滚点:若结果数量明显偏离 golden,保留公式原语测试和差异报告,回滚策略 编排层,不回退到旧 xg_composite 命名。

4. 建立市场数据读取端口与 PostgreSQL 适配器

  • 在 selection/domain/ports.py 定义只读 MarketDataReader。
  • 在 selection/infrastructure/postgres_reader.py 实现参数化查询,读取 qfq market_daily_bar,左连接同日 market_daily_basic,按日期升序映射为 StockHistory。
  • 从 Settings 注入连接串;不直接读取环境变量,不调用 Tushare,不回退 CSV。
  • 使用数据库事实表的 source_adj = 'qfq' 过滤,拒绝目标日之后的行。
  • 连接失败转换为带股票和目标日上下文的基础设施错误;目标日无 bar 属于可识别 的业务状态。

验证:

cd zhixing-server
uv run pytest tests/unit/selection/test_postgres_reader.py

若增加 PostgreSQL 集成覆盖:

cd zhixing-server
uv run pytest -m integration tests/integration/test_selection_reader.py

回滚点:只读适配器失败时删除 selection 适配器即可;不得修改已有市场数据表、 同步事务或 Alembic migration。

5. 应用用例与 Fake reader

  • 实现 EvaluateZhixingB1,输入 ts_code、target_trade_date 和 reader,输出 SelectionEvaluation。
  • 用例只负责读取、调用领域策略和映射错误;不负责全市场循环、保存信号或 HTTP 响应。
  • 提供 Fake reader 测试目标日期截断、缺失目标行、历史不足、无信号、选中多分类 和基础设施错误。

验证:

cd zhixing-server
uv run pytest tests/unit/selection/test_evaluate.py

6. 固定 fixture 与 golden 对比

  • 从旧项目现有 data/raw 中选取少量股票和目标日期,抽取最小 OHLCV CSV,放入 zhixing-server/tests/fixtures/selection/zhixing_b1/。
  • 将旧实现或人工确认结果固化为 JSON,包含目标日期、命中分类集合和关键详情的 容差范围;测试运行时不导入旧项目。
  • 至少包含普通代码和宽幅代码,并加入一个人工构造的同日多信号样本。
  • 明确记录旧实现“只保留第一个分类”与新实现“保留全部分类”的差异。

验证:

cd zhixing-server
uv run pytest tests/integration/test_zhixing_b1_golden.py

7. 完整质量检查与规划复核

实现结束后运行:

cd zhixing-server
uv run ruff format --check .
uv run ruff check .
uv run pyright
uv run pytest

并检查:

  • rg -n "xg_composite|zgnb\." src/zhixing_server/modules/selection tests 只在 迁移说明或兼容性测试中出现,不成为新领域运行时依赖;
  • 旧项目工作区没有被修改;
  • 没有新增 HTTP 路由、前端文件、信号表 migration 或调度入口;
  • golden、单元测试和端口测试都能在无网络、无生产数据库条件下运行。

完成 planning 后,先向用户展示 prd.md、design.md 和本文件摘要;只有用户 明确批准最新 planning summary,才能执行 task.py start 并进入实现阶段。