记录一次factor_engine断粮8天与Streamlit模块遮蔽(2026-08-09)
记录一次factor_engine断粮8天与Streamlit模块遮蔽(2026-08-09)
"管道不是没接,是接了但死了8天没人发现"——这句话比任务描述里写的严重得多,也决定了这天所有动作的优先级。
翻开 factor_ic.db 一看,心里就咯噔一下。任务描述说管道没接,可实际查下来根本不是没接,是接了但早死了。后面还冒出一个 Streamlit 报错,根因居然是本地的 watchdog.py 把第三方包给遮蔽了——两件事串在同一天,都是典型到不能再典型的坑。
一、factor_engine:硬编码死代理断粮8天
先看数据库。factor_ic.db 最后成功写入停在 07-31,08-01 到 08-06 的日志全是 502 和连接重置。翻代码找病灶,死因是 127.0.0.1:7890 这个硬编码死代理——和 08-07 那批 ProxyError 是同一个病根。更要命的是,没有任何调度器在跑它,所以断了 8 天完全没人发现。
factor_ic 表里 MIN run_iso=2026-07-30,MAX 之前卡在 07-31,这次补齐到 1596 行。断粮这 8 天,IC 管道等于完全没供数,而下游因子实验还在傻等。
二、修三件事,逐条实拉才点头
第一件事是双路网络层。在 factor_monitor.py 里给 _hl_post 加了双路自适应:直连优先,trust_env=False 真直连,失败就自动降级到 Clash 代理,双败才报错。顺手清掉 env 代理变量,跟 trader 同款。主网和 testnet 不一样,直连和代理都可能抽风,所以这里做的是双路 fallback,而不是 trader 那种强制直连。
第二件事挂进 watchdog。WATCHED 新增 factor_monitor.py*loop 条目,每 5 分钟保活。这里有个坑:杀掉旧 watchdog daemon(69644)重拉新 daemon(66160)是必须的——改 WATCHED 不重启 daemon 等于白改,它根本不会加载新列表。
第三件事实跑验证。6 币 × 14 个因子周期,最新 run 落了 168 条记录进库,run_iso = 2026-08-08T15:47:53Z,北京 23:47,距核验那会儿约 14 分钟。单实例核验也过:factor_monitor 就一个 python.exe,PID 58732,start 08-08 20:47:43;watchdog daemon 新 PID 66160;trader 65856 单实例仍在。
核验时发现一个表述要收紧。我原先说"全市场 IC 全为负",实测 168 个因子×周期单元里大约 35 个是正的。准确结论是:momentum_24h(−0.040−0.314)、−0.277)、price_vs_sma20(−0.079rsi_14(−0.022~−0.264) 这三个趋势因子在 24h 前向确实全市场 6 币为负,是反向指标。但 volatility_24h、cvd_slope_24h 在 1h/4h/12h 短周期有大量正值,比如 ARB cvd_slope_24h 24h IC=+0.194、AVAX volatility_24h 12h IC=+0.118。波动率和流动性因子在当前市况下呈正向,跟趋势因子反向分化——这个表述比"全为负"精细得多。
三、第20号页面:加一个不采信自报的收益面板
用户让把收益情况更新到 8501 看板的第 20 号页面。先定位,第 20 页是 views/20_sim_signals.py,看板用 views/ 目录加 importlib 动态加载,不是标准 pages/。
原来的页面读的是 sm_account 表里 trader 自报的 realized_pnl 和 current_usdc。这违反本项目铁律——永不采信进程自报累计字段,一律从 sm_positions 逐笔重算——在 08-04 曾漏记 $1,759。所以我加了一个 compute_pnl_reconcile(),从 sm_positions 逐笔重算,对账公式是 初始(10000) + realized − 未平仓名义 = cash。
真实盈亏算出来:账户 $7302.96,realized −$16.19,OPEN 8 笔 $2679.96,其中 market_flow 还余 5 笔 $1899.81 存量没出完。按策略敞口:market_flow $1899.81、token $350.29、sentiment $349.87、factor_ic $79.99。
改 view 必须重启 8501,因为 importlib 缓存。先精确定位进程树,8501 是 nohup.exe(58924) → python 71228,另外还有个重复实例 59012。把旧进程全杀掉,拉起新实例 PID 86744,HTTP 200,无 import 报错。其他端口 8588/8596–8599 一个没动。
后来做了个精度修正:total_equity 一开始只加了 sm_positions.pnl_usd,而 OPEN 仓该字段为 0,导致总权益被低估成纯现金。改成取 sm_account.unrealized_pnl 后,总权益 7304.48,对账差额 +0.90 ≈ 手续费 0.88,自洽。
四、UI报错:一个本地watchdog.py把Streamlit干挂了
第 20 页刚改完,UI 就报错了。报错原文是 ImportError: cannot import name 'events' from 'watchdog',traceback 一堆 streamlit/watcher/ 的路径。
根因很经典,Python 模块名遮蔽。项目根目录有个本地 watchdog.py——这是我们自己的进程保活 daemon。Streamlit 每次客户端建会话要 from watchdog import events,想导入第三方 watchdog 包,但项目目录在 sys.path 上优先级更高,Python 把本地那个 watchdog.py 当成了包,它没有 events 属性,直接炸。
更要命的是,8501 端口当时已经是"积极拒绝"——真实 streamlit 服务进程整个挂了,不只是报错。
五、fileWatcherType=none,零风险根治
修法不是给本地 watchdog.py 改名。读了一遍 Streamlit 源码,watcher_type == "none" 时直接 return NoOpPathWatcher,完全不会去 import 那个包。所以 fileWatcherType=none 是根治且零风险的方案。
落地两处:.streamlit/config.toml 加 fileWatcherType = "none",relaunch_8501.py 启动命令加 --server.fileWatcherType none 双保险。重启后新实例 PID 88252,Uvicorn server started,HTTP 200。
按"声称修复必须实测"的纪律,用 Playwright 写浏览器脚本实际加载页面,捕获控制台和页面错误。结果:PAGE ERRORS: NONE,之前的 watchdog 导入错误彻底消失。导航到第 20 页确认收益面板,四个检查全过——收益面板标题、对账自洽、无 ImportError、无 watchdog 错误。
六、六策略与MM/GRID家族的全景清单
最后把系统全部策略的盈利和运行情况拉了一遍。trader 代码里的退役/运行机制是三档:DISABLED_STRATEGIES 硬退役 cvd_momentum / smart_money / market_flow;VALIDATED_STRATEGIES={"factor_ic"} 白名单独享 $350 标准仓;sentiment / token / 任何未知类型一律 $80 验证仓,攒够 ≥20 笔转正才进白名单。
从 sm_positions 逐笔重算:累计平仓 47 笔,已实现 −$16.19,手续费 $0.88,净盈亏 −$17.07,胜率 44.7%(21 胜 / 26 负)。factor_ic 是唯一正向、唯一双正的策略,17 笔平仓净值 +7.96,胜率 52.9%。sentiment 虽然 +3.28,但样本只有 2 笔,远不够下结论。
踩到一个漏报:重启后新开仓是 3 笔不是 1 笔——22:57 SOL sentiment $350、06:59 TIA factor_ic $80、07:34 TRUMP LONG $350,strategy 是 token。查了代码,token 是 signal 侧真实产出的新类型,在 smart_money_signal.py:1208,gmgn smartmoney/KOL 路径。这就是已退役的 smart_money 老路径(−$2.96 负 edge)换了个名字复活,直接吃 $350 标准仓。按白名单 fail-closed 决策,直接降为 $80 验证仓。
MM/GRID 家族走的是独立影子库 hl_shadow_mm_*.db / hl_shadow_grid_*.db。注意到 hl_shadow_mm_ace.db 和 hl_shadow_mm_ace_neutral.db 已经从磁盘删了,但代码仍然引用它们。grid_bome 核验下来,影子库还在,898 笔成交量 $65,366,末笔 2026-07-29 07:22,没有存活进程,代码里也没有正式退役开关,不在 watchdog WATCHED 里——是早期手工实验自然停摆,等价于退役但性质不同。
遗留
- sentiment 当前只有 2 笔平仓样本,离 ≥20 笔转正还差得远,短期内只能维持在 $80 验证仓。
token策略是 smart_money 老路径的复活,虽然已降为 $80 验证仓,但需要观察它会不会继续产生负 edge。hl_shadow_mm_ace.db和hl_shadow_mm_ace_neutral.db两个库文件已经不在了,但代码仍然引用,得找机会把代码里的死引用清掉。- grid_bome 没有正式退役开关,也没有进程在跑,要不要补一个明确的"已停摆"标记或直接归档,没来得及动。