migration: preserve screener and tracking slice
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# 切片 06:智能选股、自定义选股与策略持续跟踪
|
||||
|
||||
> 基线:`cf2aad2`(切片 05)
|
||||
> 回档标签:`xiaobai-preservation-slice-06-20260731`
|
||||
> 结论:源码、API、数据库、真实页面和全量回归通过;最终视觉仍等待全站人工验收
|
||||
|
||||
## 1. 原实现归位
|
||||
|
||||
本切片只机械移动原版选股实现,没有从`next/`取用代码,也没有改写策略、因子、权重、排序、
|
||||
盘后候选或跟踪逻辑。
|
||||
|
||||
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|
||||
|---|---|---|
|
||||
| `app/screener.py` | `app/backend/features/screener/engine.py` | 根级模块指向同一模块对象 |
|
||||
| `app/advanced_strategies.py` | `app/backend/features/screener/strategies.py` | 根级模块指向同一模块对象 |
|
||||
| `app/llm_strategy.py` | `app/backend/features/screener/compiler.py` | 根级模块指向同一模块对象 |
|
||||
| `DashboardService`选股入口 | `app/backend/features/screener/service.py` | `ScreenerServiceMixin` |
|
||||
| `ReviewDatabase`选股持久化方法 | `app/backend/features/screener/repository.py` | `ScreenerRepositoryMixin` |
|
||||
| 原策略持续跟踪服务 | `app/backend/features/screener/tracking.py` | 容器直接导入唯一实现 |
|
||||
|
||||
四个同时服务公共行情与选股的方法归入`MarketRepositoryMixin`,没有复制第二套实现:
|
||||
`upsert_stock_master`、`list_stock_master`、`upsert_daily_bars`、`daily_bars_for_date`。
|
||||
|
||||
## 2. 源码与接口等价
|
||||
|
||||
- `test_preservation_slice_screener.py`逐项验证选股引擎、29套策略定义、自然语言策略编译器、
|
||||
13个服务方法、25个选股持久化方法和跟踪服务与原版等价。
|
||||
- 三个根级兼容模块与正式模块暴露同一模块及类对象;原类不再重复保留已移动方法。
|
||||
- 原版与迁移版的`/api/screener/setup`、`/api/screener/tracking`和`/api/screener/run`
|
||||
状态码及业务JSON一致。
|
||||
- 差分仅规范化策略启动刷新和顺序执行必然变化的数组顺序与`updated_at`;其他字段仍逐项比较。
|
||||
- 请求与差分结果见`api-requests.json`和`api-diff.json`。
|
||||
|
||||
## 3. 数据库差分
|
||||
|
||||
- 两个临时副本均为62个schema对象,结构完全一致。
|
||||
- 13张关键表逐行一致,覆盖约143万条日线、77万条技术指标和51万条竞价因子。
|
||||
- `screener_runs`两边均为251行;会话和运行时间戳只在临时副本内规范化。
|
||||
- 正式`data/review.db`和`app/data/review.db`未写入测试策略、测试会话或差分时间戳。
|
||||
- 完整表计数与哈希见`database-diff.json`。
|
||||
|
||||
## 4. 真实浏览器检查
|
||||
|
||||
- 已登录迁移版真实服务,分别检查阶段选股、策略选股、自定义选股和策略持续跟踪。
|
||||
- 阶段选股显示退潮、置信度92%、匹配策略和262日因子就绪状态;策略选股载入29套策略。
|
||||
- 自定义选股保留因子权重、过滤条件、公式入口、手动执行和独立候选结果。
|
||||
- 跟踪页只展示手动加入的候选,批次、标的、T+1/T+3进度、胜率和移除操作均正常。
|
||||
- 各检查状态无横向溢出、无加载遮罩残留,浏览器控制台无错误。
|
||||
- 截图SHA-256:
|
||||
- `curated-screener.jpg`:`529ecd0947b34b42eb63d166c6804b0041e26fa362a171e4d0d7b584e073c05e`
|
||||
- `custom-screener.jpg`:`7f31f50d44bc63a488277be0a74232e2ac256779d0accda42b96cc1eef88cc6e`
|
||||
- `tracking.jpg`:`b19b1bc0cd4a98c29500917676bdcc4cc9a430a0c72dea8aff1110ad911db6e3`
|
||||
|
||||
## 5. 自动验证与保留边界
|
||||
|
||||
| 验证 | 结果 |
|
||||
|---|---:|
|
||||
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
|
||||
| 迁移版`python -m unittest discover -s tests -q` | 265项通过 |
|
||||
| `python -m unittest tests.test_preservation_slice_screener -q` | 7项通过 |
|
||||
| `npx.cmd playwright test --reporter=dot` | 45项通过 |
|
||||
| `git diff --check` | 通过 |
|
||||
|
||||
- Windows下由Playwright自行创建静态服务器时存在子进程不退出的测试基线问题;复用独立的8876
|
||||
测试服务器后45项用例在2.1分钟内通过并正常返回退出码0。
|
||||
- 选股引擎保留原版数据客户端依赖,边界测试将其与普通页面Service区分;后续只可在不改变行为且有
|
||||
独立差分证据时治理该依赖。
|
||||
- 前端资产保持原位置,切片10再按页面职责归档;本切片没有改DOM、CSS、动画或交互。
|
||||
- 没有删除待定代码、没有修改正式数据库、没有切换Docker/NAS。
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"all_equal": true,
|
||||
"endpoints": [
|
||||
{
|
||||
"name": "盘后自动候选与策略库",
|
||||
"method": "GET",
|
||||
"endpoint": "/api/screener/setup?trade_date=2026-07-30",
|
||||
"original_status": 200,
|
||||
"migrated_status": 200,
|
||||
"original_sha256": "e33a10e94accda4948c2af53887ea97736697f588ee1a92f561aa5c4bb28c2fd",
|
||||
"migrated_sha256": "e33a10e94accda4948c2af53887ea97736697f588ee1a92f561aa5c4bb28c2fd",
|
||||
"equal": true,
|
||||
"first_difference": null
|
||||
},
|
||||
{
|
||||
"name": "策略持续跟踪",
|
||||
"method": "GET",
|
||||
"endpoint": "/api/screener/tracking?limit=12",
|
||||
"original_status": 200,
|
||||
"migrated_status": 200,
|
||||
"original_sha256": "f4476f53152b6a2ce01f2918da5999246cfd0ad7d0b71e80fdea8fa59c7456c2",
|
||||
"migrated_sha256": "f4476f53152b6a2ce01f2918da5999246cfd0ad7d0b71e80fdea8fa59c7456c2",
|
||||
"equal": true,
|
||||
"first_difference": null
|
||||
},
|
||||
{
|
||||
"name": "自定义选股执行",
|
||||
"method": "POST",
|
||||
"endpoint": "/api/screener/run",
|
||||
"original_status": 200,
|
||||
"migrated_status": 200,
|
||||
"original_sha256": "b3866e7d270aa222bd2bad0c0276b7e81ccd48e5f3a75941a32ef8e559a92c7b",
|
||||
"migrated_sha256": "b3866e7d270aa222bd2bad0c0276b7e81ccd48e5f3a75941a32ef8e559a92c7b",
|
||||
"equal": true,
|
||||
"first_difference": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
[
|
||||
{
|
||||
"name": "盘后自动候选与策略库",
|
||||
"method": "GET",
|
||||
"endpoint": "/api/screener/setup?trade_date=2026-07-30",
|
||||
"sort_lists": {
|
||||
"$.strategies": "id"
|
||||
},
|
||||
"exclude_paths": [
|
||||
"$.strategies[].updated_at"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "策略持续跟踪",
|
||||
"method": "GET",
|
||||
"endpoint": "/api/screener/tracking?limit=12"
|
||||
},
|
||||
{
|
||||
"name": "自定义选股执行",
|
||||
"method": "POST",
|
||||
"endpoint": "/api/screener/run",
|
||||
"exclude_paths": [
|
||||
"$.result.meta.updated_at"
|
||||
],
|
||||
"payload": {
|
||||
"trade_date": "2026-07-30",
|
||||
"regime": "retreat",
|
||||
"strategy_name": "保真迁移差分策略",
|
||||
"mode": "quant",
|
||||
"run_backtest": false,
|
||||
"formula": {
|
||||
"meta": {
|
||||
"library": "quant",
|
||||
"category": "量化公式"
|
||||
},
|
||||
"universe": {
|
||||
"exclude_st": true,
|
||||
"listed_days_min": 120
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"field": "pct_chg",
|
||||
"op": "between",
|
||||
"value": [-2, 2]
|
||||
}
|
||||
],
|
||||
"score": [
|
||||
{
|
||||
"field": "amount_billion",
|
||||
"weight": 1,
|
||||
"direction": "desc"
|
||||
}
|
||||
],
|
||||
"limit": 5,
|
||||
"min_score": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"all_equal": true,
|
||||
"schema": {
|
||||
"object_count": 62,
|
||||
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
|
||||
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
|
||||
"equal": true
|
||||
},
|
||||
"tables": [
|
||||
{
|
||||
"table": "stock_master",
|
||||
"original_count": 5535,
|
||||
"migrated_count": 5535,
|
||||
"original_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
|
||||
"migrated_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "daily_bars",
|
||||
"original_count": 1430501,
|
||||
"migrated_count": 1430501,
|
||||
"original_sha256": "d72a06755d92d6be95ab4f4c98a4718e973bee59d4f381b01acb963b6d7ae9e6",
|
||||
"migrated_sha256": "d72a06755d92d6be95ab4f4c98a4718e973bee59d4f381b01acb963b6d7ae9e6",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "benchmark_bars",
|
||||
"original_count": 261,
|
||||
"migrated_count": 261,
|
||||
"original_sha256": "691f7666dddcfdf7ebe8ba1d3e1ddd8f2d9670d1d7a06e740a929f3ef32ec1c9",
|
||||
"migrated_sha256": "691f7666dddcfdf7ebe8ba1d3e1ddd8f2d9670d1d7a06e740a929f3ef32ec1c9",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "daily_indicators",
|
||||
"original_count": 770238,
|
||||
"migrated_count": 770238,
|
||||
"original_sha256": "cd5a71c7d8de201ff2e3e58c64e2617a31d247911732fbddf81acb025d31fde9",
|
||||
"migrated_sha256": "cd5a71c7d8de201ff2e3e58c64e2617a31d247911732fbddf81acb025d31fde9",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "fundamental_indicators",
|
||||
"original_count": 49490,
|
||||
"migrated_count": 49490,
|
||||
"original_sha256": "4b6859256063d3a0238ba3cbbbe2842f1278cf88d44b0f6114f1af978b8bfa7d",
|
||||
"migrated_sha256": "4b6859256063d3a0238ba3cbbbe2842f1278cf88d44b0f6114f1af978b8bfa7d",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "moneyflow_daily",
|
||||
"original_count": 36368,
|
||||
"migrated_count": 36368,
|
||||
"original_sha256": "f7591dec150c7e0094568e3c46d77fc54e14a803223e15940dc54af1017bd83d",
|
||||
"migrated_sha256": "f7591dec150c7e0094568e3c46d77fc54e14a803223e15940dc54af1017bd83d",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "earnings_events",
|
||||
"original_count": 580,
|
||||
"migrated_count": 580,
|
||||
"original_sha256": "ebac03fe9ef491a6d6d2b5bc8f5ee08b609fa0ebe5992087fa067216490a6b9d",
|
||||
"migrated_sha256": "ebac03fe9ef491a6d6d2b5bc8f5ee08b609fa0ebe5992087fa067216490a6b9d",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "auction_factors",
|
||||
"original_count": 511914,
|
||||
"migrated_count": 511914,
|
||||
"original_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
|
||||
"migrated_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "popularity_factors",
|
||||
"original_count": 232,
|
||||
"migrated_count": 232,
|
||||
"original_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
|
||||
"migrated_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "lhb_institution_daily",
|
||||
"original_count": 47,
|
||||
"migrated_count": 47,
|
||||
"original_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
|
||||
"migrated_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "screener_strategies",
|
||||
"original_count": 36,
|
||||
"migrated_count": 36,
|
||||
"original_sha256": "e58859dbd478272d71bf85b6bc4ba45e609baccba74bb818b044d93bafa07312",
|
||||
"migrated_sha256": "e58859dbd478272d71bf85b6bc4ba45e609baccba74bb818b044d93bafa07312",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "screener_runs",
|
||||
"original_count": 251,
|
||||
"migrated_count": 251,
|
||||
"original_sha256": "117b0b95a362c91ddd70ca2def1e62e96e0ade2494ba4302bab5154c8d384498",
|
||||
"migrated_sha256": "117b0b95a362c91ddd70ca2def1e62e96e0ade2494ba4302bab5154c8d384498",
|
||||
"equal": true
|
||||
},
|
||||
{
|
||||
"table": "strategy_tracks",
|
||||
"original_count": 16,
|
||||
"migrated_count": 16,
|
||||
"original_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
|
||||
"migrated_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
|
||||
"equal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"updated_at": "2026-07-31T02:42:00+08:00",
|
||||
"updated_at": "2026-07-31T03:56:00+08:00",
|
||||
"status": "active",
|
||||
"migration_mode": "behavior_preserving_source_migration",
|
||||
"source_of_truth": "current_original_webapp_runtime_and_source",
|
||||
@@ -9,10 +9,10 @@
|
||||
"failed_roots": [
|
||||
"next"
|
||||
],
|
||||
"current_slice": "slice-06-screener-custom-tracking",
|
||||
"last_completed_slice": "slice-05-auction-themes-popularity-dragon-tiger",
|
||||
"last_checkpoint": "xiaobai-preservation-slice-05-20260731",
|
||||
"next_action": "capture_slice-06_screener_custom_selection_and_tracking_contracts_then_move_original_implementations",
|
||||
"current_slice": "slice-07-mentor-skills-llm-streaming",
|
||||
"last_completed_slice": "slice-06-screener-custom-tracking",
|
||||
"last_checkpoint": "xiaobai-preservation-slice-06-20260731",
|
||||
"next_action": "capture_slice-07_mentor_skill_model_pool_and_streaming_contracts_then_move_original_implementations",
|
||||
"authoritative_documents": [
|
||||
"AGENTS.md",
|
||||
"docs/migration/原版保真迁移总纲.md",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 小白复盘保真迁移账本
|
||||
|
||||
> 当前状态:正式迁移,切片05“集合竞价、题材库、人气热榜与龙虎榜”已完成
|
||||
> 当前状态:正式迁移,切片06“智能选股、自定义选股与策略持续跟踪”已完成
|
||||
|
||||
本账本是上下文恢复和人工审计的连续记录。任何迁移提交必须在同一提交中更新本文件及
|
||||
`保真迁移状态.json`。
|
||||
@@ -25,6 +25,7 @@
|
||||
| 2026-07-31 | `xiaobai-preservation-slice-03-20260731` | 情绪周期、五类股池与涨停表现原实现归位 | 自动、API与浏览器差分通过,进入切片04 |
|
||||
| 2026-07-31 | `xiaobai-preservation-slice-04-20260731` | 市场天梯与板块轮动原实现归位 | 自动、API与浏览器差分通过,进入切片05 |
|
||||
| 2026-07-31 | `xiaobai-preservation-slice-05-20260731` | 集合竞价、题材库、人气热榜与龙虎榜原实现归位 | 自动、API、数据库与浏览器差分通过,进入切片06 |
|
||||
| 2026-07-31 | `xiaobai-preservation-slice-06-20260731` | 智能选股、自定义选股与策略持续跟踪原实现归位 | 自动、API、数据库与浏览器差分通过,进入切片07 |
|
||||
|
||||
## 资产处置登记
|
||||
|
||||
@@ -48,6 +49,10 @@
|
||||
| `DashboardService`竞价、题材、人气与龙虎榜方法 | 业务服务 | 切片05四类页面与API | 按职责机械移动 | `app/backend/features/auction/`、`themes/`、`popularity/`、`dragon_tiger/` | 8个方法AST、7个真实API与原版一致 | 已移动 |
|
||||
| `ReviewDatabase`竞价、人气与龙虎榜方法 | 持久化 | 市场洞察及后续智能选股 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/auction/repository.py`、`popularity/repository.py`、`dragon_tiger/repository.py` | 7个方法AST一致;62个schema对象及5张关键表逐行一致 | 已移动 |
|
||||
| Tushare游资名录与龙虎榜实现 | 公共数据计算 | 龙虎榜与游资档案 | 原位置保持唯一实现 | `app/backend/data/providers/tushare_client.py` | 2个方法AST与原版一致 | 已归位 |
|
||||
| 选股引擎、策略库与公式编译器 | 业务计算 | 阶段、策略、自定义选股 | 整体机械移动并保留兼容别名 | `app/backend/features/screener/engine.py`、`strategies.py`、`compiler.py` | 原版AST/源码等价;根级模块为同一模块对象 | 已移动 |
|
||||
| `DashboardService`选股方法 | 业务服务 | 选股三个工作区 | 按职责机械移动 | `app/backend/features/screener/service.py` | 13个方法AST及3个真实API一致 | 已移动 |
|
||||
| `ReviewDatabase`选股方法 | 持久化 | 因子、策略运行、候选与跟踪 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/screener/repository.py` | 25个方法AST一致;62个schema对象及13张关键表逐行一致 | 已移动 |
|
||||
| `StrategyTrackingService` | 业务服务 | 手动候选持续跟踪 | 保持唯一实现并调整容器导入 | `app/backend/features/screener/tracking.py` | 类定义AST、真实API与浏览器行为一致 | 已归位 |
|
||||
|
||||
处置只允许:`原样保留`、`移动`、`合并重复`、`待定`、`确认废弃`。
|
||||
|
||||
@@ -115,6 +120,16 @@
|
||||
- 回档:标签`xiaobai-preservation-slice-05-20260731`。
|
||||
- 完整证据:`docs/migration/evidence/slice-05/README.md`。
|
||||
|
||||
已完成切片:`slice-06-screener-custom-tracking`。
|
||||
|
||||
- 原版基线:提交`cf2aad2`,即切片05回档点。
|
||||
- 迁移范围:完整选股引擎、29套高级策略、策略编译器、13个页面服务方法、25个持久化方法及持续跟踪。
|
||||
- 兼容边界:三个根级模块指向正式模块对象;选股引擎保留原版数据客户端依赖,不为通过边界测试改写算法。
|
||||
- API与数据库:3个真实API业务JSON一致;62个schema对象和13张关键表逐行一致。
|
||||
- 验收:原版231项、迁移版265项Python测试、7项切片源码等价测试、45项Playwright及四个真实工作区通过。
|
||||
- 回档:标签`xiaobai-preservation-slice-06-20260731`。
|
||||
- 完整证据:`docs/migration/evidence/slice-06/README.md`。
|
||||
|
||||
## 决策记录
|
||||
|
||||
| 日期 | 决策 | 原因 |
|
||||
|
||||
Reference in New Issue
Block a user