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

154 lines
5.8 KiB
Markdown
Raw Permalink 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.
# 知行 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。
- 先新增领域模型、端口和评估状态类型,再接入基础设施。
验证:
```bash
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 足够保持公式
计算的向量化和数值接近。
验证:
```bash
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。
- 对目标日缺失、历史不足、无信号分别返回评估状态;公式计算异常向上暴露,
不静默转换为空结果。
验证:
```bash
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 属于可识别
的业务状态。
验证:
```bash
cd zhixing-server
uv run pytest tests/unit/selection/test_postgres_reader.py
```
若增加 PostgreSQL 集成覆盖:
```bash
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 测试目标日期截断、缺失目标行、历史不足、无信号、选中多分类
和基础设施错误。
验证:
```bash
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,包含目标日期、命中分类集合和关键详情的
容差范围;测试运行时不导入旧项目。
- 至少包含普通代码和宽幅代码,并加入一个人工构造的同日多信号样本。
- 明确记录旧实现“只保留第一个分类”与新实现“保留全部分类”的差异。
验证:
```bash
cd zhixing-server
uv run pytest tests/integration/test_zhixing_b1_golden.py
```
## 7. 完整质量检查与规划复核
实现结束后运行:
```bash
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` 并进入实现阶段。