10 KiB
10 KiB
MoFin 架构改革 — 变更日志
日期:2026-06-29 ~ 2026-06-30 执行:Sisyphus (小小莫) 背景:total_assets 频繁计算错误(遗漏 frozen_cash)、币种混淆(CNY/HKD)、港股 15 分钟延迟
新增文件
| 文件 | 用途 |
|---|---|
mo_models.py |
统一数据模型 —— calc_total_assets(), is_hk_stock(), get_hk_rate(), to_cny(), validate_portfolio() |
mo_provider.py |
DSA 数据源适配器 —— 包装 daily_stock_analysis 的 16 个 Fetcher,TDX 优先、DSA 自动 fallback |
mo_config.py |
配置单例 —— 替代散落在 10+ 文件中的硬编码路径 |
mo_bridge.py |
DSA 集成桥 —— 从 DSA 获取大盘复盘/新闻,注入 MoFin 分析 prompt |
scripts/data_validate.py |
数据自检脚本(知微创建) |
scripts/holdings_reconciliation.py |
持仓一致性校验(知微创建) |
scripts/process_trade.py |
成交处理脚本(知微创建) |
docs/portfolio-data-model.md |
数据模型文档(知微创建) |
data_freshness.py |
数据新鲜度校验(知微创建) |
修改文件
| 文件 | 变更 |
|---|---|
price_monitor.py |
① 合并两处重复 total_assets 计算 → 统一调用 mo_models.calc_total_assets() ② is_hk_stock 检测切换为 mo_models.is_hk_stock() ③ HK_RATE 获取切换为 mo_models.get_hk_rate() ④ 港股行情来源从腾讯 gtimg(15分钟延迟)切到东方财富 push2.eastmoney.com(实时) |
server.py:960 |
total_assets 公式补上 frozen_cash |
strategy_lifecycle.py:428 |
currency_utils(不存在)→ mo_models |
scripts/stale_push_wlin.py |
① is_hk_stock 统一走 mo_models ② lot_cost 去掉硬编码 0.866 ③ fallback total_assets 改为 mo_models |
scripts/stock_scorer.py |
len(code)<=5 误判 → mo_models.is_hk_stock() |
scripts/holdings_reconciliation.py:98 |
total_assets 公式补上 frozen_cash |
scripts/import_holding_xls.py:93 |
total_assets 公式补上 frozen_cash |
mo_bridge.py |
DSA 路径自动检测(服务器 /home/hmo/daily-stock-analysis) |
mo_provider.py |
DSA 路径自动检测 + Tencent API 集成 |
服务器部署
| 操作 | 状态 |
|---|---|
git pull 拉取最新代码 |
✅ |
DSA 源码上传到 /home/hmo/daily-stock-analysis/ |
✅ |
| DSA .env 配置(opencode-go 三 Key:新Key → 旧Key → Key3) | ✅ |
pip install 安装 DSA 依赖(litellm, sqlalchemy, pandas, akshare 等) |
✅ |
| Python 语法检查(37 个文件) | ✅ |
| 实盘数据验证(total_assets=967712.85 零误差) | ✅ |
| 港股实时行情测试(8/8 全成功) | ✅ |
| DSA Web 服务启动(FastAPI + Swagger) | ✅ |
DSA Web 访问
- 地址:
http://192.168.1.246:8001 - API 文档:
http://192.168.1.246:8001/docs(Swagger 交互界面) - 触发分析:
POST /api/v1/analysis/analyze - 开机自启:已加入 crontab
@reboot
注意:React 前端未构建(apps/dsa-web/ 未上传,需要 Node.js),目前只提供 API 服务和 Swagger 文档界面。 |
架构变化总结
之前:
total_assets 在 6+ 个文件中各自计算,3 个漏了 frozen_cash
is_hk_stock 有 3 种不同实现,len(code)<=5 会误判深市A股
hk_rate 硬编码 4 个不同值(0.866/0.87/0.8664/0.8700)
30+ 文件绕过 mofin_db 直接读写 JSON
港股走腾讯 gtimg.cn — 15分钟延迟
data_dir 在 10+ 个文件中各自硬编码
之后:
total_assets → 唯一入口 mo_models.calc_total_assets(pf)
is_hk_stock → 唯一入口 mo_models.is_hk_stock(code)
hk_rate → 唯一入口 mo_models.get_hk_rate()(API → 缓存 → 0.87 fallback)
港股行情 → 东方财富 push2.eastmoney.com(实时,免费)
→ fallback: 腾讯 gtimg.cn(15分钟延迟兜底)
DSA 数据源 → mo_provider(16 Fetcher 自动 fallback)
DSA 情报 → mo_bridge(大盘复盘注入 MoFin 分析)
配置路径 → mo_config(单例,不再散落)
待办(服务器端)
# 知微需要确认的:
# 1. 明天开盘后验证港股价格是实时的(不再滞后15分钟)
# 2. migrate_all.py 需要跑一次(补齐 stock_sector_map/watchlist/market_context 表)
cd /home/hmo/MoFin && python3 migrate_all.py
测试记录
- 语法检查:37/37 文件通过
- 导入链路:16/17 核心模块通过
- mo_models 自检:is_hk_stock 7 用例全通过、calc_total_assets 零误差
- 实盘验证:total_assets=967712.85 = stored 967712.85
- 港股实时:8/8 港股东方财富拉取成功
- DSA 集成:DataFetcherManager 加载成功(6 Fetcher)
2026-06-30 — DSA Web + 选股链路 + 小果EasyTier
DSA Web 界面上线
- DSA 完整源码上传到
/home/hmo/daily-stock-analysis/ - React 前端构建并部署(40个静态文件)
- FastAPI 服务运行在
http://192.168.1.246:8001 - Swagger API 文档:
http://192.168.1.246:8001/docs - 开机自启已加入 crontab
- 防火墙 8001 端口已开放
DSA 三项功能对接 MoFin
| 功能 | 文件 | 说明 |
|---|---|---|
| 新闻搜索 | mo_bridge.get_stock_news() |
DSA SearchService → akshare 东方财富 fallback |
| 大盘复盘 | mo_bridge.get_market_review() |
缓存优先(24h),cron 不阻塞 |
| 策略参考 | mo_bridge.get_stock_analysis() |
独立调用,mo_dsa_opinion.py 00700 腾讯控股 |
| 策略注入 | strategy_lifecycle.reassess_with_context() |
DSA 上下文自动追加到 MoFin 分析 prompt |
DSA 策略注入
strategy_lifecycle.py 的 reassess_with_context() 中增加了 DSA 上下文注入:
- 自动识别港股/A股 → 选择对应区域大盘复盘
enrich_analysis_context()追加到macro_desc- DSA 不可用时静默跳过,不影响 MoFin
AlphaSift 选股(默认关闭)
- AlphaSift 已安装(
pip install alphasift) - 8 种策略可用
mo_alphasift_bridge.py支持多策略并行选股- 默认关闭(
ALPHASIFT_ENABLED=false) - 启用:
ALPHASIFT_ENABLED=true python3 mo_alphasift_bridge.py - 每条自选股记录包含:来源策略、评分、日期、因子得分、选股理由
原有选股链路修复
问题:market_watch.py 和 market_screener.py 从未加入 cron,导致零产出。
修复:
market_watch.py→market.json(90个板块,每30分钟更新)market_screener.py→ 小果 LLM →candidate_pool.json(每30分钟)- 已加入 crontab:
*/30 9-15 * * 1-5
小果连接统一(EasyTier 兼容)
问题:5个文件硬编码 192.168.1.122,小果离开局域网后无法连接。
修复:
- 全部改为
node122(机器名) /etc/hosts配置:- LAN:
192.168.1.122 node122 - EasyTier VPN:
10.144.144.2 node122
- LAN:
- 涉及文件:
market_screener.py,xiaoguo_scanner.py,xiaoguo_news_processor.py,intraday_health_check.py,ocr_client.py mo_config.py统一管理:xiaoguo_host="node122",xiaoguo_port=18003
待办
# 知微需要确认:
# 1. 明天开盘验证 market_screener 产出有效候选股
# 2. 如需启用 AlphaSift: ALPHASIFT_ENABLED=true python3 mo_alphasift_bridge.py
- LLM 连通:opencode-go 三 Key 正常
2026-07-01 — DB 迁移 + 唯一价格源 + 保活机制
JSON → DB 完整迁移(币种约束)
4 张核心表加 currency 列(NOT NULL DEFAULT 'CNY'):
holdings— 新增 price, market_value, change_pct, currencyholding_strategies— 新增 15 列(currency, action, trigger_json, changelog_json 等)portfolio_summary— 新增 total_mv, frozen_cash, currencywatchlist_stocks— 新增 10 列(price, entry_low/high, stop_loss, currency, source 等)
写入保护:所有 write_* 函数校验币种,写入 USD 直接拒绝。
所有高危写入者已迁移到 DB:
price_monitor.py— holdings + portfolio_summary + watchliststrategy_lifecycle.py— regenerate_all → holdings + strategies + watchlist + summaryholdings_reconciliation.py— holdings + strategies + summaryprocess_trade.py— holdings + strategiesimport_holding_xls.py— holdings + summary- JSON 保留作为冷备(DB 写失败不影响 JSON 写入)
唯一价格源(消除多入口拉价)
问题:17 个文件各自调用腾讯 qt.gtimg.cn 拉价,互不通信,币种转换不一致。
修复:所有价格读取改为 DB 优先,腾讯 API 仅作 fallback。
| 文件 | 改动 |
|---|---|
mofin_db.py |
新增 get_price_from_db() / get_prices_batch_from_db() 通用工具 |
strategy_lifecycle.py |
batch_fetch_prices() + get_price_tencent() DB 优先 |
stale_push_wlin.py |
fetch_trend_data() + 移除硬编码 0.87 fallback |
per_stock_reassess.py |
价格从 DB 读,不再自拉腾讯 |
stale_detector.py |
fetch_prices() DB 优先 |
server.py |
/api/portfolio DB 优先 |
strategy_evaluator.py |
fetch_prices() DB 优先 |
technical_analysis.py |
get_quote() DB 优先,移除 60s 缓存 |
stock_profile.py |
get_quote() DB 优先 |
collect_evaluation_data.py |
fetch_tencent_data() DB 优先 |
branch_scanner.py (×2) |
get_price() DB 优先 |
strategy_review.py |
fetch_price() DB 优先 |
xiaoguo_signal_consumer.py |
fetch_quote() DB 优先 |
price_monitor 保活
- cron:交易日 9:00-16:00 每 2 分钟
price_monitor.py - 健康检查:每 10 分钟检查进程 + DB 新鲜度
- 健康检查脚本:
scripts/check_price_monitor.py
NEAR_SL 误报修复
stale_detector.py:距止损 <5% 时加浮盈判断- 浮盈 >5% →
[PROFIT_PROTECT](利润保护,不报警) - 浮盈 ≤5% →
[NEAR_SL](真正危险)
小果连接统一
- 全部改为
node122(机器名),/etc/hosts自动解析 LAN/EasyTier - 涉及 5 个文件:market_screener, xiaoguo_scanner, xiaoguo_news_processor, intraday_health_check, ocr_client
待办(知微)
- 明天开盘验证 price_monitor 正常更新 DB
- 验证
[PROFIT_PROTECT]标记取代[NEAR_SL]误报 - DB 表新增了列,旧
migrate_all.py可能需要重新跑一次 refactor-for-xiaoxiao.md中的 Phase 2 待讨论- 如果启用 AlphaSift:
ALPHASIFT_ENABLED=true python3 mo_alphasift_bridge.py