Files
MoFin/CHANGELOG.md
T

378 lines
21 KiB
Markdown
Raw 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.
## 2026-08-12 — Cron 架构梳理(3+1 环节×3+1 层 + cron 体系统一 hermes
### 背景
按老莫"3+6+12 核心=3+1 环节(选股/买入/卖出/每日重评)× 3+1 层(采集/加工/使用/监控运维)"原则,全面梳理 cron 架构:保证运行(环节产出)、功能不重复、性能稳定、cron 统一 hermes(禁止系统 crontab)。
### cron 体系统一(禁止系统 crontab)
- **迁移到 hermes**watchlist_auto_exit(环节3卖出核心 50 8/ kanban_xmpp_bridge*/2/ parallel_batch10 8/ live_data_collector5 15
- **停系统 crontab 重复**news_collector(旧版58只,与 hermes news_collector_full 全市场重复)/ agents_health_checkMoFin,与 mofin_health/functional_health_check 重复)
- **结果**:系统 crontab 只剩 main_dsa.py(独立 DSA 服务 :8001,非定时任务);所有定时自动任务统一 hermes。备份 `.backups/crontab_backup_20260812_1505.txt`
- **F 健康 cron 来源标记**pipelines 加 source 字段,系统 cron 红色"⚠️系统cron(违规)",顶部横幅"🚫 自动任务必须部署在 hermes,严禁系统 crontab"
### 停冗余(功能不重复)
- 策略评估-每日(stale_detector,与策略评估-每周重复 + error)
- 市场精选推荐-每日(PROMPT,与专属扫描器重叠 + LLM 故障)
- 宏观风险扫描-周末(与 8:30 主版重复)
- 跨市场背离检测-周末(与工作日同脚本重复)
- 基本面刷新-午间(与早间 + 全市场 fundamentals_full_refresh 重复)
- 行业富集-cninfo-午间(已暂停,确认删除——早间已覆盖)
### 修 error(保证运行)
- **premarket_full_review**(环节4每日重评核心):修 `from scripts.watchlist_auto_exit``from watchlist_auto_exit`(同目录模块,修 ModuleNotFoundError
- capital_flow_collector / divergence_detector:瞬时 error 已自动恢复 ok
- self_repairLLM 端点故障(等 LLM 恢复,非脚本问题)
### 恢复环节产出(保证运行)
- **环节2买入**:注册 stale_push_wlin(自选买入区提醒+触发重评,`*/30 9-15 * * 1-5` 盘中)——此前未注册 cron,买入推荐缺失
- **环节4每日重评**:恢复 per_stock_reassess(自选买入区提醒-盘前午间尾盘 resume)
- **环节3卖出**watchlist_auto_exit 迁移到 hermes(自选退出 50 8 盘前)
### 3+1 环节 cron 覆盖(梳理后)
| 环节 | 核心 cron | 状态 |
|------|-----------|------|
| 选股 | p_oversold / v_weak / accumulation → candidate_filter → promote_candidates | ✅ |
| 买入 | stale_push_wlin*/30 盘中买入区提醒+触发重评) | ✅ 恢复 |
| 卖出 | watchlist_auto_exit50 8 盘前退出)/ clean_watchlist5 9 清理) | ✅ 已迁移 |
| 每日重评 | premarket_full_review10 8 盘前,已修)/ per_stock_reassess0 12,15 已恢复)/ stale_detector(周末) | ✅ |
> 执行:Sisyphus(小小莫)
> 架构文档:docs/SYSTEM_ARCHITECTURE.md3+1 层次 + 3+1 环节 + cron 统一 hermes + 开发原则)
---
## 2026-08-12 — 超跌策略回测框架全面扩展(v_weak/v_oversold 回测支持)
### 背景
v_weak(实盘)+ p_oversold(新策略)需研究 Tab 展示真实回测数据。原 run_backtest 用 compute_single_score 逐窗口评分,单股 161 秒(全市场 4000 股不可行);超跌策略研发时用的是 run_mr_backtestO(N) 门槛过滤)+ step27-49 pandas 管道(年化 18.57%)。
### 修改
1. **strategy_lab.py 性能修复**
- `prepare_sector_context` ADX 计算 O(N²)→O(N)calc_trend_strength 移到板块外层循环,296板块×490天卡死→0.95秒)
- `_get_external_factors` 改预加载模式(prepare_external_context 一次载入基本面分位/行业动量/新闻,消除循环内逐日查库——403万行 news 全表扫是卡死根因)
2. **calc_factors 加超跌因子**bias60/dist_lo20/r5f/vol_shrink/close_upma60 已在 bars 里)
3. **pass_filters 加因子检查**bias60/dist_lo20/r5f/vol_shrink/mkt_rsi/mkt_dd60/mcap_q/pe_q/news3/sec_ret20
4. **_load_index_ctx 加大盘 RSI/DD60**mkt_rsi/mkt_dd60p_oversold 门控)
5. **run_mr_backtest 扩展**:支持外部因子过滤 + tp_pct=None 兜底 + 外部因子记录
6. **注册**v_weakv_mr 研发参数:bias_max=-10单边/rsi_max=42/ret_max=-15/mom20_max=5/amount_max=15/rsi_delta_min=2/mkt_mode=any)、v_oversold12维因子 mr config
7. **scripts/research/step49_save_to_research.py**:复现 v5 定稿(年化 18.57%)并保存 strategy_research(支持 10y/5y/2y
8. **evolution/evolution_api.py**baseline 改 v_weak/v_oversold;组合 Tab members 查询兼容 v_oversold(研究名)
### 回测结果(2026-08-12 复现)
| 策略 | 10y | 5y | 2y |
|------|-----|-----|-----|
| v_weak | 21697笔/53.6%/cagr11.7%/dd25.4% | 5297笔/49.6%/cagr7.7%/dd24.7% | 1872笔/42.0%/cagr4.3%/dd18.0% |
| v_oversold | 200笔/53.5%/cagr18.6%/dd32.4% ✅复现 | 122笔/59.8%/cagr27.4%/dd32.4% | 34笔/76.5%/cagr37.9%/dd17.7% |
> v_oversold 10y 完全复现研发 v5 定稿(年化18.57%/回撤-32.4%/873信号/分年净值一致)。
### 效果
- 研究 Tabv_weak/v_oversold 标记 current,展示真实回测数据 ✅
- 组合 Tabp_oversold 显示 10y cagr 18.6%(不再"待回测")✅
- 进化模块 baselinev_weak/v_oversold ✅
- 性能:10y 全市场回测 280-420 秒(可接受)
> 执行:Sisyphus (小小莫)
> 待办:部署步骤 2-6(dry-run/管道验证/全链路/健康监控/观察期)待老莫批准
---
## 2026-07-19 — XMPP bot 递归重连修复
### 根因
XMPP bot 断线后 `on_disconnect` 调用 `self.reconnect()`,但 slixmpp 在重连失败时再次触发 disconnect 事件,导致 `on_disconnect → reconnect → disconnect` 无限递归,最终 `maximum recursion depth exceeded`
### 修改
- **文件:** `MoFin/deploy/bot/xmpp_agent_core.py`
- **变更:** 在 `XmppAgent.__init__` 中增加 `_reconnecting` 标志位,重连开始前设为 True、结束后(finally)恢复 False。重入时直接 return。
- **效果预期:** 断线重连失败后最多尝试一次,不会爆栈;bot 保持在 service 管理下等待 systemd 自动重启。
> 日期:2026-06-29 ~ 2026-07-03
> 执行:Sisyphus (小小莫) + Zhiwei (知微)
---
## 2026-07-09 — 信号堆积修复
### 根因
xiaoguo_signal_consumer 仅处理今日信号(`date(created_at)=today`),之前日期的信号永远不被消费 → 33条堆积。SIGNAL_MAX_AGE_HOURS=4 已定义但未被使用。
### 修复清单
1. **xiaoguo_signal_consumer**: `date(today)``created_at > -4h` 年龄过滤
2. **xiaoguo_signal_consumer**: 无时效内信号时自动标记过期信号为已处理
3. **xiaoguo_signal_consumer**: 移除 `mo_data.get_price` 导入(import path 冲突,root mo_data.py 无 get_price),改用腾讯 API 直连 fallback
4. **intraday_health_check**: 信号堆积检查限定 4h 内,避免过期信号误报
5. **system_audit**: 同上
### 效果
- 已清理 20 条过期信号(>4h),剩余 0 条未处理
- 盘中健康检查不会再因过期信号误报堆积
- 信号管道只监控时效内的处理速度
### [2026-07-09 跟进] 监控盲区修复 + 信号积压根治
- **发现**: intraday_health_check 和 system_audit 仅监控 source LIKE 'xiaoguo%',完全忽略 divergence_watch(80条)、trend(46条) 等来源信号积压
- **修复① (当日监控层)**: 两端都增加全量未处理查询(total_unproc),区分 xiaoguo 和其他来源分别报告
- **修复② (同天根治)**: divergence_detector.py 写入 signal_news 时标记 processed=1(已有macro_divergence_state.json自用,signal_news只做归档);trend 46条空summary死数据标记已处理
- **效果**: signal_news 1077条全量已处理,健康检查 PASS,后续不会再次积压
## 2026-07-03 — 代码重构
### 删除重复文件
- `scripts/strategy_lifecycle.py` — 旧版本,缺少 quality gateroot 版本是规范
- `scripts/price_monitor.py` — 旧版本,root 版本是规范
### 清理 JSON 路径常量
- 移除 scripts/ 中 12 个文件的 DECISIONS_PATH / PORTFOLIO_PATH / WATCHLIST_PATH 声明
- 移除 root level 中无用的 JSON 路径常量
### 文档更新
- `docs/SYSTEM_ARCHITECTURE.md` — 完整重写(v5.0
- `CHANGELOG.md` — 补充重构记录
---
## 2026-07-03 — JSON 彻底移除 + 币种架构修正
### JSON→DB 全面迁移 (32+ 文件)
**数据层**
- `mo_data.py`:删除所有 JSON fallback,纯 SQLite 读取
- `mofin_db.py`
- `write_holding_strategy` 改为 DELETE+INSERT(旧 ON CONFLICT 静默失败)
- `holding_strategies` 新增 10 列:avg_price, decision_timestamp, note, quality_check, quality_checked_at, quality_issues_json, position_advice, signal_factors_json, time_horizon, decision_type
- 新增 `live_prices` / `mtf_cache` / `capital_flow_cache` 三张表 + 读写函数
- 已有 `market_snapshots` 表接替 market.json
**server.py**
- 新增 `_save_portfolio` / `_save_decision` / `_save_watchlist` 写函数
- 所有 13 个 API 写端点切到 DB,读端点删除 JSON fallback
**脚本层**
- 15 个文件 `json.load → mo_data.read_*()`
- 12 个文件 `json.dump → mofin_db.write_*()` 或直接删除
- strategy_lifecycle JSON 冷备行全部删除
- branch_scanner / prune_branches 切到 DB
- system_audit / stale_push_wlin / refresh_mtf_cache JSON→DB
**LLM Prompt**
- evaluation-daily v2`evaluation.json` → DB 表
- knowledge-extraction v1`decisions.json` → DB 表
- analytics.py:删除 JSON 路径常量
**已移除的 JSON 文件**(不再被任何代码读写)
- portfolio.json / decisions.json / watchlist.json
- live_prices.json / multi_tf_cache.json / market.json / capital_flow_cache.json
### 币种架构
**港股** — 个股 price/cost/stop_loss 存 **HKD**`currency='HKD'`
**A股** — 个股 price/cost/stop_loss 存 **CNY**`currency='CNY'`
**总资产**`calc_total_assets()` 汇总时港股 HKD×汇率→CNY
| 场景 | 港股 | A股 |
|------|------|-----|
| 个股显示(股软对照) | HKD | CNY |
| 技术位(止损/止盈/买入区) | HKD | CNY |
| 总资产 / 总市值 / P&L | CNY(汇总时转换) | CNY |
### 关键修复
-`price_monitor.py``scripts/price_monitor.py` 不一致(前者存 HKD,后者转 CNY)→ 统一:存 HKD,不转换
- `s.get('price', 0)` 在 price 为 None 时返回 None 导致 TypeError → 改为 `s.get('price') or 0`
- 东财 API 限流(之前 0.1s 间隔疯狂刷被封)→ 第一只失败立刻切腾讯兜底
### 验证
```
holdings: 19 (8 HKD + 11 CNY)
decisions: 19 (8 HKD + 11 CNY)
total_assets: stored = calculated ✅
```
---
## 2026-07-01 — 统一读取层 + 现金日志
### 新增
- `mo_data.py``read_portfolio()` / `read_decisions()` / `read_watchlist()`
- `mofin_db.py``cash_log` 表 + `write_cash_log` / `query_cash_log`
### 修改
- 16 个文件 `json.load → mo_data.read_*()`
- HK 股成本 HKD→CNY 修复(import_holding_xls 导入时转换)
---
## 2026-06-30 — 初始架构重构
### 新增
- `mo_models.py``calc_total_assets()`, `is_hk_stock()`, `get_hk_rate()`, `to_cny()`, `validate_portfolio()`
- `mo_config.py` — 配置单例
- `mo_bridge.py` — DSA 集成桥
- `mo_provider.py` — DSA 数据源适配器
- `scripts/data_validate.py`, `holdings_reconciliation.py`, `process_trade.py`(知微)
- DSA Web UI: `http://192.168.1.246:8001`
### 修改
- `price_monitor.py`:港股腾讯→东方财富 + 统一 total_assets
- 8 个文件散落 `is_hk_stock` / `total_assets` 统一到 mo_models
---
## 2026-07-06 — 全面系统修复(知微)
### 1. XMPP Bot 稳定性修复
- **去自ping心跳**:之前bot每15秒给自己(zhiwei@yoin.fun)发XEP-0199 ping检测连接。gateway阻塞时自ping也超时,导致bot误判连接断开→断线重连→死循环。改为纯TCP 30秒检查。
- **永续重试**:gateway超时消息最多重试3次就丢弃 → 永不丢弃+指数退避(1s→2s→4s→...→120s),5次失败日志报警。
- **跨重连引用**:消息队列中 `bot_ref` 在重连后指向旧bot实例(已断开)→ 加 `_current_bot` 模块级变量,处理消息时优先用当前活跃bot实例。
### 2. Cron Delivery 修复(10个job
- 宏观风险扫描 ×3(早/午/周末):`deliver=all``local`
- 小果信号消费-盘中、策略复盘-每日、数据治理-每周、记忆守卫-每日、盘中自检-高频、系统常规体检-开盘前、自愈执行器:`deliver=origin``local`
- 根因:cron job没有上游渠道可推送,`origin/all`解析失败
### 3. 脚本Bug修复
- **refresh_mtf_cache.py**:导入 `strategy_lifecycle.PORTFOLIO_PATH` 报错(DB-only重构后常量已删除)。改为从 `mofin.db` 的holdings/watchlist_stocks表直接读股票代码列表,走腾讯API拉K线。
- **clean_watchlist.py**`mo_data.read_portfolio()` 调用名错误(`mo_data`前缀有多余)+ 硬编码JSON路径。修复为纯DB读取。
### 4. 脚本目录同步
- MoFin/scripts/git仓库)与~/.hermes/profiles/position-analyst/scripts/cron运行版本)双向补全
- 57个文件从profile→MoFin同步,全部md5校验一致
### 5. Git提交
- `66962ae` 全面系统修复:包含以上所有变更
- `e055485``.gitignore`(取自code_only分支,排除`__pycache__/ *.pyc data/reports/`
- 已推送到origin master
### 6. 数据
- watchlist新增 000850 华茂股份(金融股权低估逻辑,PB 0.83破净,2026-07-03公告分红3675万)
### 已知未解决
- ejabberd容器重启46次(exit code 0+无日志,系统负载高峰时被外部信号杀死)
## 2026-07-09
**stale_push_wlin 推送流程重构**
- 加4小时重评冷却:查DB `holding_strategies.updated_at`,冷却期内跳过 per_stock_reassess
- Zone notes冷却30分→4小时,匹配重评冷却
- 修早退bug`if not actionable: return 0``if not actionable and not zone_notes`
- 标题自适应:有推荐→"自选买入提醒" | 仅区间→"操作区间提醒"
- 操作建议标题只在有可操作项时显示
- 区间说明格式改为 Dad 确认的"进入操作区间,但重评结果: xxx"
---
### 修正的活代码路径(唯一真正在读写 JSON 的路径)
- `price_monitor.py` — 每2分钟读 decisions.json 改为 mo_data.read_decisions()DB
- 其他18处代码注释写"写入 portfolio.json/decisions.json"但代码已实际写 DB,只修了注释
### 健康检查脚本
- `system_health_check.py`(主+scripts/两个版本)— 数据条目标签从"portfolio.json DB记录"改为"DB持仓记录"
- 消除 LLM cron 误读标签后 stat JSON 文件大小的问题
### 配置层标记废弃
- `mo_config.py`(主+scripts/两个版本)— 所有 JSON 路径 property 加 ⚠️ 已废弃 docstring
### 磁盘残留 JSON 文件
- portfolio.json / decisions.json / watchlist.json → 全部改为废弃 stub
- 保留空文件防导入报错,内容仅含废弃声明
### 变更总结
- 核心数据(持仓/自选/策略)的读和写已 100% 走 DB
- 唯一仍用 JSON 的非核心文件:reports/*.json(报告缓存)、stocks/*.json(个股详情缓存)、market.json(大盘数据缓存)、accuracy_stats.json(统计缓存)
## 2026-07-08 — BUGFIX: per_stock_reassess.py holding_strategies DB 写回 + JSON 最终移除
### 发现
Dad 反馈我的 v4 手动分析(买入区3.62~3.72)与 13:01 cron 报告(买入区3.78~3.87)不一致。经审计发现两个问题:
1. **per_stock_reassess.py** 调用 reassess_with_context() 后不写 holding_strategies 表(只写 watchlist_stocks 表)。而 read_decisions() 从 holding_strategies 读 → 新策略数据不可见
2. **decisions.json** 仍有残余依赖,2条旧数据的文件被当作权威源
### 修改
- `per_stock_reassess.py`:策略更新后追加 `write_holding_strategy()` 写入 DB,持仓/自选全部写回 holding_strategies 表
- `per_stock_reassess.py`:移除 DECISIONS_PATH 常量 + 清理 JSON 死代码注释
- 同步修复 profile 副本(`~/.hermes/profiles/position-analyst/scripts/per_stock_reassess.py`
- `sync_db_to_json.py`:删除(DB→JSON 反向同步,无调用者)
- `decisions.json`(两处):删除,备份为 .bak
### 审计确认
- MoFin/scripts/ + web-dashboard/ + profile/scripts/ 三个目录下的 active python 代码 **均不再直接读写 decisions.json**
- 所有策略数据通过 `mo_data.read_decisions()` → DB holding_strategies 表 读取
- 所有策略写入通过 `mofin_db.write_holding_strategy()` → DB holding_strategies 表
### 验证
- `per_stock_reassess 688981` → 输出 `[DB] holding_strategies 已更新: 688981`
- DB holding_strategies 从 1 条 → 17 条
- web-dashboard PID 4003859 正常运行,API 通过 DB 读取
## 2026-07-10 — 知微XMPP Bot离线修复
### 根因
Bot被bash包装器手动启动(非systemd),形成孤儿进程。systemd因PID文件冲突僵在`activating (auto-restart)`循环无法接管。孤儿bot在11:40:48断线后卡在重连循环中。
### 修复
1. 杀死孤儿进程 PID 422464
2. 清理 `/home/hmo/.hermes/zhiwei_bot.pid``/tmp/xmpp_zhiwei_bot.pid`
3. systemd RestartSec=10s 自动重启接管
4. 验证:加入coregroup、XMPP就绪、presence available、bridge:5805正常、gateway正常
### 预防
自愈系统新增检查项:systemd状态优先于进程检查——发现进程存在但非systemd管理时自动清理孤儿。
## 2026-07-13 — XMPP Bot非阻塞 + 深套规则重构 + 换股规划
### XMPP Bot修复
- gateway调用改为 45s短超时 → "处理中"预回复 → 后台300s轮询,不再阻塞事件循环
- 远程XMPP服务器不通,改为连本地 127.0.0.1:5222 代理
- 注册 xep_0045 修复MUC崩溃
- **涉及文件**: /home/hmo/xmpp_agent_core.py
### price_monitor推送冷却持久化
- _push_cooldown 从内存dict改为文件持久化,解决每2分钟重复推操作区间通知
- **涉及文件**: scripts/price_monitor.py
### 深套股规则重构
- 删除全部 `is_deep_loss` 特殊处理(止损/止盈/买入区/质量检查6处guard + action_note覆盖)
- 回归客观判断,该加就加该割就割
- **涉及文件**: scripts/strategy_lifecycle.py
### 换股规划功能
- `python3 strategy_lifecycle.py swap-plan [--need 金额]`
- 五维评分排序,自动计算释放资金方案
- **涉及文件**: scripts/strategy_lifecycle.py
### 技术分析增强
- 周线/月线趋势/MA/支撑阻力注入mtf_context传递到LLM
- 健康Tab写无读警告 3→0
- 每日汇总只发一次(16:35)
- 健康监控新增数据实体检查
- **涉及文件**: technical_analysis.py, mofin_health.py, cron_to_xmpp.py, cron_health_monitor.py
## 2026-07-14 — price_monitor DB写锁死锁根治
### 根因
多 cron 脚本(price_monitor、mofin_health 等)同时 BEGIN IMMEDIATE 写 mofin.dbWAL 文件膨胀到 2.7MB 未 checkpoint,进程卡在 D 状态,后续全部超时。原代码的 3 次重试 + 2s 退避不足,且 write_portfolio_summary / write_live_prices 返回值未检查。
### 修复
1. **统一 BEGIN IMMEDIATE + 内联 SQL**(替代调用 write_holdings_batch/write_portfolio_summary/write_live_prices):一个事务包裹所有写操作,任一失败立即 rollback + 重试
2. **5 次重试 + 指数退避**1s → 2s → 4s → 8s → 16s,共 ~31s),原 3 次 + 固定 2s
3. **Emergency WAL checkpoint**:所有重试耗尽后自动执行 PRAGMA wal_checkpoint(TRUNCATE) 释放死锁
4. **try/except 确保连接始终释放**rollback + close),修复原代码异常时 conn 泄漏
5. **三副本同步**profile/scripts + MoFin/scripts + MoFin/root
- **涉及文件**: scripts/price_monitor.py, /home/hmo/MoFin/scripts/price_monitor.py, /home/hmo/MoFin/price_monitor.py
## 2026-07-14 — intraday_health_check XMPP Bot误报修复
### 根因
check_bots() 使用 `systemctl is-active xmpp-zhiwei.service` 检查bot状态。但 xmpp-zhiwei.service 已于2026-07-14因与gateway管理冲突被主动停止(gateway watchdog管理bot生命周期),systemctl返回inactive→每次盘中自检报「知微XMPP Bot离线」。
同时:`ss -tnp` 非root用户看不到root进程(小果bot)的PID列,导致PID匹配失效。
### 修复
1. **check_bots() → check_bot_process()**: 彻底移除systemctl依赖
2. 改用双重检测:`/proc/{pid}/net/tcp`(检查ESTABLISHED+远端:5222+ 进程存在性(pid file/pgrep
3. 小果bot同理——读/proc/PID/net/tcp不受用户限制
4. 关闭历史误报TODOcancelled+解释说明)
### 涉及文件
- /home/hmo/.hermes/profiles/position-analyst/scripts/intraday_health_check.py