318 lines
13 KiB
Markdown
318 lines
13 KiB
Markdown
# MoFin Cron 架构深度审查与重构设计
|
||
|
||
> 创建:2026-08-11 | 审查人:小小莫 | 状态:✅ 审查完成 + P0/P1 已执行
|
||
> 背景:新策略(预测超跌反弹 p_oversold)引入前,必须清理 cron 架构的
|
||
> 重复调度、代码分叉、职责混乱问题,让架构清晰可维护。
|
||
|
||
---
|
||
|
||
## 执行记录(2026-08-11)
|
||
|
||
### ✅ P0 已执行(消除代码多版本)
|
||
| 动作 | commit |
|
||
|------|--------|
|
||
| 根目录 market_watch.py(旧版分叉)→ archive/20260811-cron-cleanup/ | refactor: P0清理 |
|
||
| deploy/get_realtime_prices.py(死代码)→ archive | 同上 |
|
||
| promote_candidates.py 备份残留删除 | 同上 |
|
||
| 硬链接同步(110 scripts)| 已验证 |
|
||
|
||
### ✅ P1 已执行(策略扫描器独立调度)
|
||
| 动作 | 结果 |
|
||
|------|------|
|
||
| market_watch.py 移除 mr/s2 嵌入(-42 行)| ✅ 已 push + 246 pull,守卫不再回滚 |
|
||
| mr_scanner 独立 job(v_weak扫描-独立,9:35 交易日)| ✅ hermes cron list 确认 |
|
||
| s2_scanner 独立 job(S2恐慌买扫描-独立,9:35 交易日)| ✅ hermes cron list 确认 |
|
||
| market_watch 验证(90 板块 + regime,无 mr/s2 输出)| ✅ snapshot_id=1548 |
|
||
|
||
### ✅ 顶层 jobs 残留处理
|
||
- 16 个 default profile job(调度器 7/23 已死)→ 全部停用
|
||
- 备份:`~/.hermes/cron/jobs.json.bak_20260811_top_level_disabled`
|
||
- position-analyst(65 jobs)/ mohe(2 jobs)未受影响
|
||
|
||
### ✅ P2 已执行(午间重复采集判断)
|
||
| job | 判断 | 处理 |
|
||
|-----|------|------|
|
||
| 行业富集-cninfo-午间 | 只补缺失行业映射(幂等去重,早间已补全)→ **冗余** | ✅ 已停用(备份 jobs.json.bak_20260811_sector_noon)|
|
||
| 基本面刷新-午间 | 拉实时 PE/PB(随价格变动)→ **有意义** | 保留 |
|
||
|
||
### ✅ 嵌入调用全面扫描
|
||
- 11 个脚本有 subprocess 嵌入调用
|
||
- **仅 market_watch→mr/s2 是架构问题**(已修复);其余均为合理工具/流程调用
|
||
- 确认:generate_report(按需触发重评)/ sync_dashboard(包装工具)均职责清晰
|
||
|
||
### ✅ 工具函数抽取(import 级解耦,2026-08-11)
|
||
**问题**:s2_scanner import mr_scanner 的工具函数(fetch_tx_klines/calc_ma/calc_rsi/get_stock_pool)
|
||
——策略扫描器互相 import 是坏味道,新策略会越引越乱。
|
||
|
||
**重构**:
|
||
| 新模块 | 内容 | 来源 |
|
||
|--------|------|------|
|
||
| `indicators.py` | calc_ma/calc_rsi/calc_atr/calc_obv | mr_scanner 抽取 |
|
||
| `market_data.py` | fetch_tx_klines/get_stock_pool | mr_scanner 抽取 |
|
||
|
||
**验证**:mr/s2 均改为从公共模块 import,语法 OK,运行正常(trend_up/非恐慌日正确跳过),s2 不再 import mr_scanner(0 处)。
|
||
**收益**:p_oversold 扫描器直接 import indicators/market_data,不依赖任何策略扫描器。
|
||
|
||
### 守卫教训(重要)
|
||
- deploy_guard 每 15 分钟回滚 CODE_PATHS 未提交改动(07:00 实测回滚 market_watch)
|
||
- **正确流程**:本地改 → commit+push → 246 pull(守卫看到 git 干净 → 不回滚)
|
||
|
||
---
|
||
|
||
## 一、现状全景
|
||
|
||
### 1.1 调度系统
|
||
|
||
| 调度系统 | 任务数 | 说明 |
|
||
|---------|--------|------|
|
||
| hermes 顶层 jobs.json | 16 | ⚠️ 7/23 起调度器停摆(残留)|
|
||
| hermes position-analyst | 63 | ✅ 主调度(活跃)|
|
||
| hermes mohe | 2 | ✅ 少量 |
|
||
| 系统 crontab | ~33 | ⚠️ 部分与 hermes 重复 |
|
||
|
||
### 1.2 脚本总数
|
||
|
||
- deploy/profile-scripts/:~100 个 py
|
||
- hermes scripts/:硬链接(sync_profile_scripts.sh 维护)
|
||
- MoFin 根目录:库文件 + 残留
|
||
|
||
---
|
||
|
||
## 二、核心架构问题
|
||
|
||
### 问题 1:策略扫描器嵌入数据采集器(违反单一职责)
|
||
|
||
**现状**:
|
||
```
|
||
market_watch.py(行业板块采集,*/10)
|
||
├─ 1. 板块数据采集(EM→THS)→ market_snapshots
|
||
├─ 2. market_regime 计算 → market_regime 表
|
||
├─ 3. subprocess 调 mr_scanner.py(v_weak,timeout=1500s)
|
||
└─ 4. subprocess 调 s2_scanner.py(S2 恐慌买,timeout=1500s)
|
||
```
|
||
|
||
**问题**:
|
||
- market_watch 职责 = 数据采集 + 市场阶段 + 2 个策略扫描,四合一
|
||
- mr_scanner/s2_scanner **无独立调度**,只能被 market_watch 触发
|
||
- timeout=1500s(25分钟)嵌入采集器,若超时影响采集
|
||
- 新策略 p_oversold 替换时无处安放(要改 market_watch 还是新建?)
|
||
|
||
**重构方案**:策略扫描器独立调度
|
||
```
|
||
market_watch.py(纯板块采集,*/10)
|
||
mr_scanner.py(v_weak,独立 cron 0 9 * * 1-5 或并入扫描调度)
|
||
s2_scanner.py(S2 恐慌买,独立 cron)
|
||
predictive_oversold_scanner.py(新策略,独立 cron)
|
||
```
|
||
- 每个扫描器独立 job、独立日志、独立幂等
|
||
- market_watch 只做采集(单一职责)
|
||
|
||
### 问题 2:同一脚本多个调度入口
|
||
|
||
| 脚本 | 入口 | 建议 |
|
||
|------|------|------|
|
||
| market_watch.py | 顶层(0,30 9-16) + position(*/10) | 停顶层(调度器已死)|
|
||
| stale_detector.py | 策略评估-每日(21:00) + 周末重评(30 10 0,6) | 保留(两用途不同)|
|
||
| memory_guardian.py | 顶层 + position | 停顶层 |
|
||
| cron_to_xmpp.py | 顶层(* 9-16) + position(*/5) | 停顶层(已停 crontab)|
|
||
| divergence_detector.py | 工作日(*/30 8-15) + 周末(30 8-16/2) | 保留(两用途合理)|
|
||
|
||
### 问题 3:一份代码多版本(分叉)
|
||
|
||
| 文件 | 副本 | 状态 |
|
||
|------|------|------|
|
||
| market_watch.py | MoFin根(旧) vs deploy(新) | ❌ 分叉,根目录残留 |
|
||
| promote_candidates.py | docs/backup 残留 | ❌ 备份未清理 |
|
||
| self_todo_executor.py | deploy vs hermes vs AgentsMeeting | ⚠️ 新旧版并存 |
|
||
| agents_health_check.py | MoFin/AgentsMeeting/self-growing | ⚠️ 三项目各自维护 |
|
||
|
||
**原则(红线)**:
|
||
- 一份代码只存在于一个 canonical 位置(MoFin git 仓库)
|
||
- deploy/profile-scripts ↔ hermes scripts 用硬链接(已规范)
|
||
- 其他位置(根目录/backup/其他项目)不得有副本
|
||
|
||
### 问题 4:健康检查体系过度层级化
|
||
|
||
**现状 8 个健康类脚本**:
|
||
```
|
||
L0: agents_health_check(Tier1,5min)
|
||
L1: morning_health_check(8:00 体检)+ intraday_health_check(15min)
|
||
L1: functional_health_check(L1 功能检查,15min)
|
||
L1: mofin_health(dashboard 数据,15min)
|
||
L2: system_hygiene_audit(卫生审计)
|
||
L3: self_repair(LLM 修复)
|
||
L4: meta_watchdog(检查检查的检查)
|
||
+ system_audit(全局审计 17:30)
|
||
```
|
||
|
||
**问题**:8 个脚本职责重叠,互相引用,排查复杂
|
||
**建议**:保留核心 4 层(Tier1/morning+intraday/functional/self_repair),合并冗余
|
||
|
||
---
|
||
|
||
## 三、逐任务设计文档(分类)
|
||
|
||
### 3.1 候选管道(核心链路)
|
||
|
||
```
|
||
accumulation_scanner(*/10)→ candidates(sector=accumulation)
|
||
→ candidate_filter(*/30,6阶段评分)
|
||
→ promote_candidates(*/30,RR>=2 + 容量60)
|
||
→ per_stock_reassess(12维重评)→ holding_strategies
|
||
盘前: premarket_full_review(8:10)→ regenerate_all
|
||
```
|
||
|
||
| 脚本 | 职责 | 调度 | 数据流 | 问题 |
|
||
|------|------|------|--------|------|
|
||
| accumulation_scanner | 主力建仓扫描 | */10 | 行情→candidates | 与新策略无关,保留 |
|
||
| candidate_filter | 6阶段过滤 | */30 | candidates→评分 | 耦合 accumulation 设计 |
|
||
| promote_candidates | 候选提拔 | */30 | candidates→自选 | RR>=2 门槛需适配 |
|
||
| premarket_full_review | 盘前重评 | 8:10 | 全量重评 | 依赖缓存预热 |
|
||
|
||
### 3.2 策略扫描器(问题 1 核心)
|
||
|
||
| 脚本 | 职责 | 当前入口 | 重构后 |
|
||
|------|------|---------|--------|
|
||
| mr_scanner.py | v_weak 弱市扫描 | 嵌入 market_watch | 独立 cron |
|
||
| s2_scanner.py | S2 恐慌买 | 嵌入 market_watch | 独立 cron |
|
||
| **predictive_oversold_scanner** | **新策略(待建)** | 无 | 独立 cron |
|
||
|
||
### 3.3 数据采集
|
||
|
||
| 脚本 | 职责 | 调度 | 问题 |
|
||
|------|------|------|------|
|
||
| price_monitor | 价格(A+港股)| hermes */2 9-16 | ✅ 已统一 |
|
||
| market_watch | 板块 | hermes */10 | ⚠️ 待拆策略扫描 |
|
||
| capital_flow_collector | 资金流 | 1,31 9-15 | ✅ 已修锁 |
|
||
| refresh_mtf_cache | 多周期缓存 | 50 7,11,14 | ✅ 已修 flush |
|
||
| fundamentals_refresh | 基本面 | 早/午两次 | ⚠️ 午间可停?|
|
||
| sector_enrich_cninfo | 行业富集 | 早/午两次 | ⚠️ 午间可停?|
|
||
| macro_context_collector | 宏观新闻 | */30 | ✅ |
|
||
| refresh_macro_context | 宏观上下文 | */30 | ✅ |
|
||
| news_collector | 新闻 | crontab 30 9,13,17 | ✅ |
|
||
| divergence_detector | 跨市场背离 | */30+周末 | ✅ |
|
||
|
||
### 3.4 健康自检(问题 4)
|
||
|
||
| 脚本 | 职责 | 调度 | 保留 |
|
||
|------|------|------|------|
|
||
| agents_health_check | Tier1 4服务 | */5 | ✅ |
|
||
| morning_health_check | 每日体检 8类40项 | 8:00 | ✅ |
|
||
| intraday_health_check | 盘中自检 | */15 | ✅ |
|
||
| functional_health_check | L1 功能 | */15 | ✅ |
|
||
| mofin_health | dashboard 数据 | */15 | ✅ |
|
||
| self_repair | L3 LLM 修复 | */30 | ✅ |
|
||
| meta_watchdog | L4 元监控 | 5min | ✅ |
|
||
| system_hygiene_audit | 卫生审计 | 8:20 | ⚠️ 与 system_audit 重叠 |
|
||
| system_audit | 全局审计 | 17:30 | ⚠️ 与 hygiene 重叠 |
|
||
| system_health_check | 传统检查 | 已停 | ❌ 可归档 |
|
||
|
||
### 3.5 报告简报
|
||
|
||
| 脚本 | 职责 | 调度 | 备注 |
|
||
|------|------|------|------|
|
||
| opening_brief/closing_brief | 开/收盘简报 | 9:35/16:10 | ✅ |
|
||
| market_insight | 知微洞察 | 15:35 | ✅ |
|
||
| strategy_review | 策略复盘 | 20:00 | ✅ |
|
||
| strategy_evaluator | 策略评估 | 每周/每日 | ⚠️ 每日版可停 |
|
||
| collect_evaluation_data | 评估数据 | 20:30 | ✅ |
|
||
| prepare_report_data | 报告数据 | 周四 | ✅ |
|
||
|
||
### 3.6 自成长
|
||
|
||
| 脚本 | 职责 | 调度 | 备注 |
|
||
|------|------|------|------|
|
||
| branch_scanner | 分支自成长 | 15min | ✅ |
|
||
| prune_branches | 分支剪枝 | 21:00 | ✅ |
|
||
| meta_growth | 元自成长 | 0:45/12:45 | ✅ |
|
||
| hardcode_scanner | 硬编码扫描 | 17:25 | ✅ |
|
||
|
||
### 3.7 系统维护
|
||
|
||
| 脚本 | 职责 | 调度 | 备注 |
|
||
|------|------|------|------|
|
||
| deploy_guard | 部署守卫 | */15 | ✅ 核心 |
|
||
| fix_gateway_port | gateway 看门狗 | 10min | ✅ 核心 |
|
||
| agent_spiral_watchdog | 螺旋监控 | */10 | ✅ |
|
||
| db_daily_backup | DB 备份 | 7:50 | ✅ |
|
||
| vacuum_state_db | state.db 整理 | 周六 | ✅ |
|
||
| system_audit | 全局审计 | 17:30 | ✅ |
|
||
|
||
---
|
||
|
||
## 四、重构方案(待老莫批准)
|
||
|
||
### 4.1 立即执行(低风险)
|
||
1. **停顶层 jobs.json 残留**(16个 job 调度器已死)——enabled=False 或确认清理
|
||
2. **清理 market_watch.py 根目录分叉**(旧版移 archive)
|
||
3. **清理 promote_candidates.py backup 残留**
|
||
4. **统一 agents_health_check**(确认三项目各自维护是否必要)
|
||
|
||
### 4.2 重构(中等风险,需测试)
|
||
5. **拆 market_watch 策略扫描**:mr_scanner/s2_scanner 独立调度
|
||
6. **fundamentals/sector_enrich 午间版停用**(早间足够)
|
||
7. **评估每日版停用**(每周版足够)
|
||
|
||
### 4.3 为 p_oversold 准备
|
||
8. **新建 predictive_oversold_scanner.py**(独立 cron,对齐 accumulation_scanner 模式)
|
||
9. **候选管道适配**(p_oversold 走专属评估,绕过 RR>=2)
|
||
|
||
### 4.4 红线(杜绝多版本)
|
||
- 一份代码一个 canonical 位置(MoFin git)
|
||
- deploy↔hermes 硬链接(已规范)
|
||
- 根目录不留脚本副本(库文件除外,且必须与 deploy 硬链)
|
||
- 备份不进仓库
|
||
|
||
---
|
||
|
||
## 五、执行优先级
|
||
|
||
| 优先级 | 动作 | 风险 |
|
||
|--------|------|------|
|
||
| P0 | 停顶层 jobs 残留 + 清 market_watch 分叉 | 低 |
|
||
| P1 | 拆策略扫描器独立调度 | 中 |
|
||
| P2 | 停午间重复采集 | 低 |
|
||
| P3 | 建 p_oversold 扫描器 | 中 |
|
||
|
||
> 待老莫确认后分批执行。
|
||
---
|
||
|
||
## 六、补充发现(第二轮审查 2026-08-11)
|
||
|
||
### 6.1 JSON 引用问题
|
||
- ✅ 20 个脚本引用 decisions.json/portfolio.json/watchlist.json,但**多数通过 mo_data 兼容层**(read_decisions/read_portfolio 读 DB)——docstring 是旧注释,实际正常
|
||
- 🔴 **get_realtime_prices.py 直接 open('data/decisions.json')** —— decisions.json 已删除,运行必报错。**死代码**(无调度无 import),归档
|
||
- 🔴 import_holding_xls.py 有注释掉的旧 JSON 写操作(无影响)
|
||
|
||
### 6.2 死代码/残留清单
|
||
| 文件 | 状态 |
|
||
|------|------|
|
||
| get_realtime_prices.py | 死代码(读已删JSON),归档 |
|
||
| market_watch.py(MoFin根)| 旧版分叉,归档 |
|
||
| promote_candidates.py(docs/backup)| 备份残留,清理 |
|
||
| system_health_check.py | 已暂停,被替代,归档 |
|
||
| session_to_cron_bridge.py | 已停 crontab(顶层cron停摆)|
|
||
| cron_to_xmpp.py crontab版 | 已停(hermes版保留)|
|
||
|
||
### 6.3 自成长类确认
|
||
| 脚本 | 职责 | 状态 |
|
||
|------|------|------|
|
||
| branch_scanner | 分支数据采集 | ✅ 活跃(15min)|
|
||
| branch_evaluator | 分支适用性评估 | ✅ 读 DB(mo_data)|
|
||
| prune_branches | 剪枝 | ✅ 活跃(21:00)|
|
||
| meta_growth | 元层自成长 | ✅ 活跃(0:45/12:45)|
|
||
| hardcode_scanner | 硬编码扫描 | ✅ 活跃(17:25)|
|
||
|
||
### 6.4 报告简报类确认
|
||
| 脚本 | 职责 | 状态 |
|
||
|------|------|------|
|
||
| opening/closing_brief | 开/收盘简报 wrapper | ✅ |
|
||
| generate_report | 模板报告生成器 | ✅ |
|
||
| market_insight | 知微洞察 | ✅ |
|
||
| strategy_review | 三层复盘 | ✅ |
|
||
| strategy_evaluator | 双维度评估 | ⚠️ 每日版可停 |
|
||
| collect_evaluation_data | 评估数据采集 | ✅ |
|
||
| prepare_report_data | 报告参数 | ✅ |
|
||
| advice_reconciliation | 建议对账 | ✅ 读DB |
|
||
|