Files
sanguo_vnpy_v2/docs/deployment/vps-production-runbook.md
T
claude_dev 3a938ecac8
CI/CD / test (push) Successful in 40s
CI/CD / nas-deploy (push) Successful in 7s
CI/CD / nas-verify (push) Successful in 8s
fix(portfolio): 运行注册表种子缺失条目自动 merge——治挑战者双机漏登记缺口 [vps]
2026-09-27 实证: 挑战者 szneul_eq_reb63 登记 config 种子后, 双机运行副本
(ensure_runtime_registry 首触才拷贝)永不知晓——周报 job 按运行副本点名
stage+paper_account_id, 挑战者被跳过=影子 A/B 评测腿(周报/孵化梯/毕业 gate)全盲。
治本: 首触整拷语义不变, 另加 _merge_seed_entries——种子有而运行副本缺的
条目(strategies/factors 双主顾)每次 touch 自动补入, 同名条目运行态为准
(防部署回滚转移结果), 无缺条目不写盘(幂等)。
config 种子挑战者 paper_account_id null→63(周报点名非空才算, 与双机手动补行一致)。
runbook 注册表行同步更语义(档随码走)。a 方案(双机手动补行)已先行落地救急。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-27 18:35:43 +08:00

49 KiB
Raw Blame History

VPS 生产运维 Runbook(大QMT 桥栈)

sanguo 实盘交易栈生产运维手册(infra session 维护的活文档;上次全面更新 2026-09-14)。 2026-09-08 全量切桥(miniQMT → 大QMT RPC 桥)后本文为权威运维文档;旧 FastAPI bridge(:8765)+Caddy+miniQMT 直连架构已退役(文末历史节)。

相关文档:

  • 发布流程与发布关联性检查清单:../three-env-code-promote.md(唯二主文档之「发布」)
  • 提交纪律(环境标签 + 三线设计档同步闸门):promote §12/§12.1 —— 触及基建域(含本工具箱 scripts/qmt_relogin/)须同 push 更新本档或发布档,纯实现打 [no-doc];CI 强制,档随码走
  • 大QMT 无人值守登录:../qmt-headless-login-runbook.md
  • 本档=唯二主文档之「运维」。旧 vps-unified-deploy.md(web/回测/数据面)已收编进本档 §7 并归档。

安全约定:本文进 git 不含任何凭证。登录凭证=DPAPI C:\sanguo_bigqmt\creds\qmt_login.enc (进程内解密,never in argv / never on disk / never logged);redis 密码运行时读 C:\redis\redis.conf。


1. 生产栈架构(2026-09 实态)

┌────────────────────────── Windows VPS 49.232.102.198 ──────────────────────────┐
│                                                                                │
│  XtItClient.exe(大QMT 客户端 GUI,唯一)                                         │
│   └─ 模型交易实例(自动运行)= 桥 server 宿主                                     │
│        BIGQMT_REDIS_DRYRUN.py + bigqmt_signal_trader(含本地归一化补丁)           │
│              │ Redis RPC(127.0.0.1,queue=bigqmt:rpc:queue:<acc>)               │
│              ▼                                                                 │
│  C:\sanguo_bigqmt\xtquant_bridge\xtquant\(glue shim,接口兼容旧 miniQMT 语法)    │
│      ▲                    ▲                                                     │
│      │                    │                                                     │
│  12 引擎进程          21:00 xt_eod(数据腿,同一 shim)                            │
│  ├─ live_17~22 ×6    sanguo_portfolio.runner_live   ← sanguo-live-supervisor     │
│  └─ shadow_57~62 ×6  sanguo_trader.shadow --auto   ← sanguo-shadow-desk          │
│                                                                                │
│  三层防御 schtask:07:50 relogin / 30min 哨兵 / 09:15 盘前探针                      │
│  采集 schtask 群:bs-daily 18:05 / idx 18:30 / ak 19:00+ / xt-daily 21:00          │
└────────────────────────────────────────────────────────────────────────────────┘

关键事实(新接手必读):

  • XtItClient.exe = 大QMT 客户端本体 + 桥 server 宿主。它是 GUI 程序、无 headless 登录路径、 登录窗无「记住密码/自动登录」,登录会话不随柜台日切刷新 → 必须每日晨间重登(07:50 自动链)。
  • miniQMT(XtMiniQmt.exe/miniquote.exe)零生产依赖(2026-09-10 数据腿切桥后),09-18 券商停服无感。 判活指标已不含 mini 栈;旧探针里 mini 相关 WARN 属遗留口径。
  • 引擎断桥有 with_connect_retry 重试环,但 36h+ 长断桥后重试环会死(09-14 实例)→ 桥恢复后 若引擎日志无「📅 新交易日」,需收割重启(策略域工序)。
  • 基线锚点:TRADE_PROBE GREEN cash=7846164.67(恒等式基线,分毫不动即健康;变了先怀疑未对账成交)。

1.5 桥 RPC 接口与更新流程(2026-09-19 起)

查接口一律先查桥仓库的接口参考:xtquant_big_convert repo docs/RPC_API_REFERENCE.md(全量 119 只读 + 2 下单,含参数/返回/语义;桥代码与接口文档同仓,改接口必须同步改这份)。运维高频入口:

需求 RPC 方法 说明
当日成交/委托 query_stock_trades / query_stock_orders 空 strategy_name=全账户;当日会话语义,隔日查不到
历史成交/委托(任意日) get_history_trade_detail 组合入口(0.3.26 起):先终端原生函数(实盘注入)→ 模拟端/失败自动落本地 XtClient 日志扫描;返回 {source: client|local|none, rows}
柜台持仓快照对账 get_position_snapshots_local 每次登录柜台全量下发持仓表,按登录批次切快照(一日约 3 张);A(晨初)/B(盘后)/C(次日晨初) 对齐法 = 09-17 清算回滚案的破案工具:C==A 而 B!=A 即当夜清算回滚签名
桥能力探测 probe_capabilities qmt_globals 报每个终端注入函数的可用性(如模拟端 get_history_trade_detail_data: false)
热重载 reload_deployment 下个 adjust tick 重导入部署包,不重启 QMT
  • 调用模板:scripts/qmt_relogin/qmt_bridge_probe.py(redis 127.0.0.1:6379 db=5,密码运行时读 C:\redis\redis.conf;call_redis_rpc(rc, ACCOUNT, method, params);注意返回是 rpc 信封,handler 结果在 data 里)。
  • 桥代码更新流程(源码=xtquant_big_convert repo src/bigqmt_signal_trader/,部署树=C:\国金QMT交易端模拟\python\bigqmt_signal_trader\,二者无自动同步):repo 改+测试 → scp 到 VPS C:\tmp\ → 远程 python(glob 定位中文路径)落部署树(先备份 .bak_日期)→ RPC reload_deployment → ping 的 version 字段核对生效。09-19 实例:0.3.26 = commit 583e219。
  • 取证原则:柜台侧疑案(持仓/清算对不上)先拉快照对齐,再看 deal 回放——source=none 是「没证据」不是「没成交」(回放只在终端当晚重连时写入,个别日子缺)。
  • 快照留痕协议(2026-09-21 起,用户令「复发直接定罪 QMT,不再靠推断」):C:\tmp\snap_archive.py(Mac 侧母本 /tmp/snap_archive.py,滚动 3 日窗 start_date/end_date 必传、空串=空结果)经 RPC get_position_snapshots_local 拉快照,归档 C:\sanguo_vnpy_v2\logs\position_snapshots\snap_<ts>.json;节奏=盘前基线(随 09:20 例查)/盘后 B(21:05)/次晨 C(08:05,07:50 重登后),由 infra 的 claude-cron 唤醒执行;复发判定=C==B 且当日成交消失=柜台自身数据定罪,零推断(对齐表盯 002088/002415/159915/300059/510050 五票)。

2. schtask 全景表

任务 频率 动作 域
sanguo-qmt-relogin 每日 07:50 杀+拉起+物理键入登录+验桥(v2 两阶段 exe→login) infra
sanguo-qmt-sentinel 00:10 起每 30min 进程+RPC ping+日历探针+cash 留痕;RED→自动触发 relogin infra
sanguo-qmt-probe0915 工作日 09:15 盘前主动探针(510050×100@0.01 FIX 必不成交+即撤)=会话当日金标准 infra
sanguo-live-supervisor 开机/手动 run_live_bridge.ps1 → sanguo_live --supervisor → 6×runner_live 任务=infra,进程=策略域
sanguo-shadow-desk 开机/手动 run_shadow_bridge.ps1 → sanguo_trader.shadow --auto → 6×shadow 同上
sanguo-api 开机 run_api.ps1 :8000(web/回测 API) infra
sanguo-bs-daily 18:05 baostock eod→fund 串行 数据
sanguo-xt-daily 21:00 xt_eod(ETF/基金/北交 EOD,走桥 shim) 数据
sanguo-idx-* / sanguo-ak-* / sanguo-margin-ps / sanguo-dsa / sanguo-factor-full 各时段 指数/akshare 域/融资/截面/因子 数据
sanguo-ak-events-retry 周一至五 20:30 起每小时×4 发 重跑 ak-events wrapper(marker 幂等,兜 EM 当日未出数时序失败;09-25 重建=weekly 版,首版 hourly 被建成一次性跑完即死,§7.5 终态) 数据
sanguo-caddy 开机 mysanguo.online HTTPS 直 serve infra
sanguo-ui / sanguo-shot 按需 console session UI 原语/截屏通道(ssh=session 0 不可用) infra
sanguo-data-monitor-eve 每日 23:50 data_monitor_wrapper.ps1 -Shift evening(数据面监控终检:注册表 42 项四层证据链→data/monitor/health_*.json+alerts.db,spec §20.15) 数据监控
sanguo-data-monitor-morn 每日 08:05 同 wrapper -Shift morning(晨间全量+前夜自愈回看+NAS inbox 摄取;08:10 晨检 agent 首读 health_latest.json) 数据监控

监控注记(spec §20.15):监控 wrapper 恒 exit 0(红态由 alerts/health 承载,防污染调度层自检的 Last Result 判读);NAS 监控 v2 挂 sanguo-vps-mirror 16:00 班尾(/volume1/stock/monitor_nas/run_monitor_nas.sh→事件 JSON scp 至 VPS data/monitor/inbox/,VPS 两班摄取落库 host=nas);告警消费入口=前端「运维告警」页 /ops-alerts(四类 tab+ack,API GET /api/v1/alerts)。NAS 检查器语义(09-26 校准):dmsk=事件驱动域(无新披露不写盘,mtime 阈值 80h 非日频 34h);vps-mirror 完成度在 16:00 班前查昨日 DONE 行(早班查当日必空)。VPS 侧日历=确认集(dbbardata 000300)∪近 15 日工作日假定集——未确认日缺失降黄、确认日缺失才红(治 dbbardata 晚间源滞后塌期望的循环依赖,09-25 首跑实案)。事件摄取=NAS events 文件带 green_keys 回传(VPS 据此 resolve NAS 告警);过程层日志窗=26h(防旧失败每日重炒)。

3. 三层防御 + 每日节律

时点 动作 判据
07:50 relogin 自动重登 EXIT=0 + trade-probe GREEN
08:05 策略 session 晨查 引擎 12/12 日志推进+锚
09:15 盘前探针 order status=50 已报=会话当日
09:25 infra 五件套闸门 对钟/引擎/RPC+allow_order/09:15 结果/日历探针(max 入历)+锚
全天 :10/:40 哨兵 GREEN 留痕 C:\sanguo_bigqmt\gate\
15:10 恒等式(策略域) 柜台 vs 台账逐票,前置=fresh trade-probe GREEN
21:00 xt_eod DONE ok≈2303 fail=0

防御设计原则(用户 09-09 拍板,勿擅改):报警只记 log 不加通道;哨兵 30min;09:15 探针做; 失败不退避;脚本验可用性、agent 验正确性。被动查询测不出会话陈旧——主动探针是唯一金标准。

4. 非代码资产清单(promote.sh 推不到,发版/重装时人工核对)

git 不是 VPS 生产全貌。以下资产只存在 VPS(或需手动 scp),代码晋升流程管不到它们:

资产 位置 说明
桥工具箱+防御脚本 C:\sanguo_bigqmt\(源码=repo scripts/qmt_relogin/) 哨兵/探针/relogin/gate/wintree/ui_act/dsp_reset/minall/setclip 等;改 repo 后必须手动 scp 到 VPS 才生效
glue shim C:\sanguo_bigqmt\xtquant_bridge\xtquant\ 引擎+xt_eod 共用的接口兼容层;改动=双侧部署+relogin
桥 server 部署位 C:\国金QMT交易端模拟\python\bigqmt_signal_trader\ 含本地补丁(market_bigqmt.py 归一化等);⚠️ 客户端升级会重装此树=补丁丢失须重打;同名包在安装树内有多份拷贝,打补丁先确认运行时 sys.path 实际加载的那份
桥策略第三方包 ...\bin.x64\Lib\site-packages\ QMT 策略进程 sys.path 特殊,第三方包放这里(redis-py 用 3.5.3,4.x 不兼容 py3.6)
redis C:\redis\(Windows 服务) requirepass;密码运行时读 redis.conf 零落盘
frps(FRP 服务端) C:\frp\frps.exe -c C:\frp\frps.json(nssm 服务 sanguo-frps,:7000) 家里 Mac frpc-beijing 反连:13000=家Gitea 代码通道 / 13001=claude.mysanguo.online(北京 Caddy 反代)/ 18789=OpenClaw;token 看 frps.json(⚠️同目录 frps.toml 是 07-30 旧文件,勿混);nssm 崩溃放弃后不自愈,须手动 sc start sanguo-frps;验活=sc query sanguo-frps+`netstat -ano
登录凭证 C:\sanguo_bigqmt\creds\qmt_login.enc DPAPI hex blob;换机/换用户即失效
wrapper ps1 ×5 C:\sanguo_bigqmt\run_live_bridge.ps1 / run_shadow_bridge.ps1 / qmt_relogin_run.ps1 / xt_eod wrapper / C:\sanguo_vnpy_v2\run_api.ps1 必须 ASCII-only(PS5.1 无 BOM 按 GBK 解析中文注释可吃掉语句行);重定向已改追加式 *>>(保 stdout 证据)
引擎运行时状态 C:\sanguo_vnpy_v2\runtime\<inst>\live_state.json 含锚(strategy_start_date),策略域所有,重启语义敏感
gate 留痕 C:\sanguo_bigqmt\gate\ 每日 log + latest.json
schtask 注册本身 注册表 XML 定义各任务;重建任务须原样(SYSTEM/HighestAvailable/频率)

5. 运维命令速查(Mac 出发)

# 对钟(VPS 有漂移前科,任何时序排查先做)
ssh 49.232.102.198 "powershell -Command \"Get-Date -Format 'yyyy-MM-dd HH:mm:ss'\""; date '+本地: %Y-%m-%d %H:%M:%S'

# 桥健康(交易腿真数据)
ssh 49.232.102.198 "python C:\\sanguo_bigqmt\\bridge_switch_ops.py trade-probe"
# 期望: TRADE_PROBE GREEN cash=7846164.67

# 引擎/进程计数(supervisor+子进程)
ssh 49.232.102.198 "python C:\\sanguo_bigqmt\\bridge_switch_ops.py count"
# 期望: LIVE_SUP 1 + LIVE_CHILD n=6 + SHADOW_SUP 1 + SHADOW_CHILD n=6

# 哨兵最新判据
ssh 49.232.102.198 "type C:\sanguo_bigqmt\gate\qmt_gate_latest.json"

# 引擎日志推进(进程在≠活,日志推进才是活)
ssh 49.232.102.198 "powershell -Command \"Get-Content C:\sanguo_vnpy_v2\logs\live_21.log -Tail 5\""

# relogin 末轮全链日志(登录链取证)
ssh 49.232.102.198 "powershell -Command \"Get-Content C:\sanguo_bigqmt\qmt_relogin.log -Tail 30\""

引擎收割/重启工序(⚠️ 顺序错误会触发重拉赛跑杀树):

  1. 先 /end 整个 desk(sanguo-shadow-desk 或 sanguo-live-supervisor)让 supervisor 优雅退场;
  2. 再收割残留子进程(若有);
  3. /run 重新拉起。 直接 terminate auto-respawn supervisor 的子进程=触发 supervisor 立即重拉,TerminateProcess 不走清理、 锁残留可致新子 8 秒全灭(09-14 shadow 事故实证)。rc=15=psutil terminate 指纹,发现时刻≠击杀时刻。

6. 已知问题库(09-08 切桥以来 35 起提炼,2026-09-18)

6.1 五波大事故(影响/差点影响交易)

日期 事故 根因 解法/防御
09-08 pip 装桥 client 污染官方 xtquant → xt_eod 炸 wheel src/xtquant 与 site-packages 同名 force-reinstall;缺口 LOOKBACK 自愈
09-08 全舰队交易腿瘫痪全天 切档重启桥策略挤掉引擎连接;重连只在 boot 轮换重启引擎;切档前预告策略域
09-09 26 单全拒 证券交易未初始化 客户端会话不随柜台日切 07:50 每日重登(三层防御第一层)
09-11 12 引擎调度器全天停摆 桥 native 日历返字符串≠毫秒契约;四件套闸门无日历探针=盲区 server+shim 双归一化;第五探针=日历类型断言
09-12~14 崩溃循环 16+ 轮(周末) 客户端写日线缓存撕裂 7 DAT,启动重载即崩 隔离 DAT(move 不删自动重下)+WER 对话框 PostMessage;黑屏 CDS 重置;哨兵 30min 自愈实证
09-14 shadow 六实例整树死 收割波触发旧 supervisor 重拉竞态 收割前先 /end desk(§5 工序);三信号监控

6.2 长尾坑分类(同类复发先查这里)

类别 要点
A. QMT 是 GUI 不是服务(最大类) 重登后 ~30min 持仓/资产查询空窗(不报错只返空,引擎不得在此窗读仓);周日夜柜台拒登(等开门自愈勿通宵折腾);WER 对话框盖登录窗;无人接入截屏全黑(dsp_reset);FG 抢占(minall);键盘错位暂态;1x 截图坐标幻觉(只信像素扫描+wintree+UIA);UI 自动化必须 console session(ssh=session 0 死)
B. 桥契约差异 get_trading_dates 必须 int 毫秒(日历探针钉死);get_market_data 返 DataFrame;安装树同名包多拷贝(部署位陷阱);QMT 策略 py3.6+特殊 sys.path
C. 双腿架构 XtItClient=交易腿勿与 mini 栈混淆;mini 栈现为闲置,重启会拉起登录窗=噪声
D. 编排/进程生命周期 长断桥后引擎重试环会死(桥活也不重连→收割重启);supervisor 树杀顺序(§5);session-only cron 随 session 死(系统 schtask 是底座);时钟漂移先对钟;EOD 对账在 server 死时=伪干净(恒等式前置=fresh trade-probe);盘外 vps-deploy 收尾必滚动重启双树(vps_restart_resident.sh:taskkill→/end×2→sleep 30→/run×2 连发→引擎核验;盘中 09:15-15:30 自动跳过)——遇「无署名双 desk 重启」先对表 Gitea vps-deploy run 起止窗再谈悬案(09-14 23:13:13=run#1243、09-16 20:30:54/55=run#1256,两案悬三天实为授权部署的收尾步;infra 汇报部署必提此副作用;boot 时间戳可直接对表 CI run);09-13 16:16 frps OOM 饿死 5 天(Resource-Exhaustion 2004 点名 30.7GB 失控 python 吃光 commit→frps 被 nssm 拉起必崩 fatal error: out of memory→16:17 放弃 exit 1066 永不自愈→claude.mysanguo.online 502+13000 断;09-18 手动拉活)——同机失控计算会殃及交易栈,commit>90% 告警/回测内存上限待立项;09-19 真凶钉死=一周末两案两凶(2004 事件×8+文件 mtime 咬合取证):09-12(周六)18:05-18:31 六连 2004=ak 静态表周六马拉松 30.7GB(akshare_static_20260912_103200.log 10:32 写到 18:32,XtItClient 同场 980MB 侥幸未死);09-13(周日)16:11/16:16=margin TMC 回填 33GB(margin_backfill_20260913_075540.txt 07:55 跑到 16:17:59,深段翻页战争累积 8.3h)——两凶均已在代码层修根(margin=75af7f2 逐层预算+3cce22a 键集早停/翻页硬上限 90/per-stock 通道;ak-quarter=挪周六+vintage 自检),残余风险=未来任一新回填/回测类长跑再犯,防御三件 09-19 第一波已落地(用户拍板「先探着」):①哨兵第六探针+②commit>90% 告警=qmt_sentinel.py infra_probe()(frps:7000+claude 200+commit%≥90 三查,每 30min 全天候随哨兵 schtask,RED/AMBER 只记录不自愈;首跑 21:37 GREEN commit=28.8%;已部署 VPS+repo 同步);③回测/回填内存上限=第二波待统一监控设计时一并做(用户定位=现有探针是未来监控系统地基)
E. 环境/footgun PS wrapper 必须 ASCII-only;裸跑 xt_eod 无 PYTHONPATH 回落旧腿(必须 schtask 或 wrapper);中文经 ssh/GBK 必坏(匹配用 ASCII 子串)

细节与时间线:记忆 miniqmt-shutdown-migration-20260918 / qmt-ui-automation-toolchain / qmt-sentinel-gate-plan-20260909 / xt-eod-bridge-leg-switch-20260910;登录处置全流程= ../qmt-headless-login-runbook.md。

7. web/回测/数据面(2026-09-14 自 vps-unified-deploy.md 收编)

7.1 三机角色与网络入口

机器 角色 跑什么
北京 VPS 49.232.102.198 生产 sanguo_api :8000 + 前端 dist + 大QMT 桥栈(§1) + 权威 DB + 采集 schtask 群
NAS 192.168.2.154 test/备份 Docker 容器(运维见 three-env-code-promote §9/§10)
Mac mini 开发 改码/构建/部署(runner 是 Mac,睡眠时 CI 不跑)
  • 对外入口:https://vnpy.mysanguo.online(北京 Caddy :443 直 serve,BootTrigger,ICP 已备案);老 vnpy.mysanguo.top 首尔入口 502=历史残留勿用。

7.2 VPS 安装清单与 sanguo_api

  • Python C:\Python310;vnpy 4.4.0 = 源码 PYTHONPATH 引用(不 pip install);pip 走阿里镜像。
  • sanguo-api schtask → C:\sanguo_vnpy_v2\run_api.ps1:env 定死(SANGUO_DATA_ROOT/SANGUO_DB_PATH/SANGUO_FILE_DIR/SANGUO_LIVE_ENABLED/SANGUO_QMT_ACCOUNT 等)= 保 git 真相、三机共用 config;API 日志=C:\Users\Administrator\sanguo_api.log(worker traceback 看这里)。
  • 回测入口=runner_backtest 独占(VPS 不走 ProcessPool;runner≠orchestrator 的 runner 易混)。

7.3 已知坑(web/回测面,事故实锤)

坑 现象 解法
empyrical×numpy2.0 结果页垃圾值(3305%)+无图 metrics.py 导入前补回 np 别名(NINF/Inf 等)
回测静默吞异常 显示垃圾不报错 cta_engine 已加 traceback 到 warning(见 api log)
ProcessPool worker 缓存旧代码 改 .py 行为没变 重启 sanguo-api(/end+/run)
SSH 密集连接触发限连 Connection closed ... port 22 等 30-60s 冷却;长脚本 detached + 轮询文件
复杂引号 ssh 命令拆坏 PS 管道报「不是内部或外部命令」 powershell -Command - + stdin heredoc 喂脚本

7.4 NAS 同步链(03:00 root 班+周日全量;2026-09-17 定稿)

链脚本=repo scripts/nas_sync/,执行位=NAS /volume1/stock/sanguo_vnpy_v2/scripts/nas_sync/(root 班实跑这份,手动 scp 部署,CI 不覆盖;homes/admin 下同名目录=CI 仓副本非执行位,2026-09-18 实证勘误:09-17 两修只落 repo 未 scp 执行位,03:00 连跑两晚旧 13 类版,NAS margin 停 0911 而 VPS 已 0916);调度=DSM id=2 每日 03:00(root 身份执行)+周日 04:00 全量。方向=NAS 主动 ssh VPS 拉(SSH 22 出站通,光猫只拦 80/443)。 防漂移(09-18 加,两连咬后):改 scripts/nas_sync/ 任一脚本 push 后,必须 scp -O 五 .sh 全量到执行位并 diff 执行位↔repo 逐个 SAME 收口(曾发生:repo 缺 parquet/valuation 两钩子、执行位带 NAS 本地热修的反向漂移,盲目推 repo 会静默停跑日同步)。

段 脚本 内容 频率
dbbardata 增量 sync_dbbardata.sh+export/merge_increment.py 行情库增量 日
两表 sync_tables.sh constituent_unified+bs_adjust_factor REPLACE 日
per-date 18 类 sync_parquet_daily.sh 7 天窗单文件拉+gdhs/nb_hold 季度段+§20.13 三域 listing 段(09-22:pledge_ratio/research_report 周五锚+pledge_detail 月桶,skip-if-exists,滞后任意天必追上) 日
根级目录 sync_valuation_daily.sh valuation/financial_abstract+vb/fb/index_const_hist scp -r 日
周全量 sync_parquet.sh static+vb+fb 整树 6.24G/70min 周日
  • 运维规矩(09-17 实锤坑):①03:00 班以 root 跑,写的文件 root:root 644——admin 手动重跑链会撞 Permission Denied(盖不掉 root 属主文件,~60 个/晚);手动验证只用只读探针,写操作交给 03:00 班。②新增 per-date 数据域必须同步扩 sync_parquet_daily 覆盖(09-17 教训:四域+hot_rank 漏扩=NAS 周级滞后一周才实锤;形态二选一=TYPES 滚动窗[日更域]或 listing 段[周频/月桶 write-once 域,09-22 起 §20.13 三域先例——周五锚文件若首班失败次周补落,文件龄 8 天滚出 7 天窗,listing 才追得上])。

  • ak-weekly 三新域(融合 spec §20.13,2026-09-22 挂载):ak_stock_wrapper.ps1 追加两条独立命令(不带 --force,marker 幂等增量):--types pledge_ratio,pledge_detail --start 20210108 + --types research_report --start 20210701。pledge_ratio 仅枚举周五(非周五 EM result=None 必失败),未发布周五 failed 不写 marker 次周自愈;pledge_detail=RPTA_APP_ACCUMDETAILS 254 页走 fetch_em_dc_pages 节流通道(1.2s/页≈6 分钟)月桶留存;research_report=reportapi 直连周窗 anchor=周五。

  • 反向镜像链(融合 spec §20.11,2026-09-17 新增):push_vps_mirror_daily.sh+vps_mirror_lib.py(纯逻辑,宿主 python3.8 stdlib)——corpus 五子域(09-22 起 +flash_meta 快讯域)+dmsk 五域 NAS→VPS 推送(09-18 起挂 sanguo-corpus-daily DSM 任务尾部=run_corpus_standalone.sh EXIT trap 完赛即推,典型 ~10:1x/backfill 日 ~17:3x;rc 隔离=corpus rc∈0/1/3 才推[09-19 首验勘误:rc() 把「墙停+噪声 failed」报 1,旧 0/3 闸门 11 天只推 1 天,仅 rc=2 限流不推]、推送失败只记日志不进聚合 rc;admin 账号=避开 root 属主坑;原独立 16:00 DSM 方案作废),分区粒度 journal 指纹 diff 只增不删;部署位 /volume1/stock/vps-mirror/(宿主文件,改 repo 副本后 scp -O 同步,同 corpus/dmsk runner 纪律),journal/watermark_*.json/push.log 同目录;VPS 落 data\corpus+data\fundamentals\dmsk+族根 _mirror_watermark.json(消费方 get_watermark() 晨检对表);任一失败不 commit journal/不落水位线=次日 diff 自愈;--dry-run 打印将推送清单=验收收敛证明。设计与消费契约=融合 spec §20.11。09-20 增独立 static manifest lane(spec §20.11.7):data_backup/static_overlay/manifests/*.list(补洗变更清单,每行 <domain>/<file>)文件级幂等推送、整单成功归档 pushed/、失败只 WARN 不影响 corpus/dmsk 聚合——三表 per-stock 文件由此 lane 推 VPS(不进 journal 指纹体系)。

  • flash 快讯 lane+xcheck 对账 lane(融合 spec §20.12.3/§20.12.4,09-22 上线):①run_corpus_standalone.sh 第三 lane --lane flash(金十快照+东财 kuaixun 翻页 T-1 边界,秒级完赛,rc 隔离不进聚合、独立跑不 gate 于 daily/backfill)→ corpus/flash_meta/ 落盘,镜像车五子域自动携带;②run_corpus_standalone.sh 第四 lane xcheck.py --lane corpus_side(ann_em 拉取+公告披露日对照+腾讯 qt 全市场估值快照对照,rc 隔离);③run_dmsk.sh 第四 lane xcheck.py --lane fund_side(读 wash manifests 当日命中股→新浪三表近 12 期+两源 NOTICE_DATE 对照)。xcheck 域落 corpus/xcheck/ 不推 VPS(NAS 侧质检设施);findings 报告+trace 追溯=融合 spec §20.12.4;容器名 sanguo-xcheck(杀=docker stop sanguo-xcheck)。首跑锚点:corpus cron.log flash lane exit=0(隔离) 行 + xcheck corpus_side exit=0 行 + dmsk cron.log xcheck fund_side exit=0 行 + 次日 push.log 出现 flash_meta 分区计数。

  • 因子月度批评·先批后评四段链(流水线 spec §4.2 决议 H+§12.4 决议 J,09-23 上线;09-27 加 stage4 归因批 10-04 首班起):双机同评——NAS+VPS 每月第一个周日 09:30 各跑同一批评链(①②③段),JSON 对拍件({host}_{asof}.json)落各自报告目录,人工/VPS 侧 scp 汇集到 NAS 后 python -m sanguo_factor.review_compare nas_*.json vps_*.json 对拍(一致=落档进告警流程;分歧 exit 2=只开排查 issue 不出降权告警)。ⓐNAS 侧:run_factor_monthly.sh(源码=repo scripts/nas_sync/run_factor_monthly_standalone.sh,改后 scp -O 同步生效位 /volume1/stock/sanguo_vnpy_v2/)——一次性容器四段串行 monthly_batch(注册表全量 12M 窗重评批,重活)→monthly_review --host nas(判定报告,JSON append-only)→data_gap_check→attribution_batch(归因批: 15 截面增量[12 源+size_log+在位者+挑战者,daily_section 幂等 merge,as_of 撞周末模块内归一最近 bar 日]→归因双跑[#69 影子 A/B 归因侧供给,挑战者落 challenger/ 子目录]→cp 双投递生效位[在位者件→admin 家 data/attribution/ 根 glob 取最新;挑战者件带因子名;生效位目录容器挂 rw /effective-data,代码卷恒 :ro];工作区 /volume1/stock/factor_cross_section/attribution/ 留全历史);as_of=上月末脚本头自算;rc 语义=①非零停链、②③ exit 2 是有效信号按 0 聚合、④非零=真失败(截面断供/归因挂/投递缺)进 final;容器金丝雀坑=必须 -e HOME=/tmp -e MPLCONFIGDIR=/tmp/mpl(--user 1024 下 HOME=/ → vnpy import 建不了 /.vntrader)。报告目录 /volume1/stock/sanguo_vnpy_v2/reports/factor_monthly/;日志=factor_monthly_cron.log。DSM 任务 sanguo-factor-monthly=每周日 09:30 admin(UI 手建)+脚本头日号闸——DSM 计划任务月度档只有「每月几号」没有「第一个周日」原生选项,调度只能建每周日,「是不是第一个周日」由脚本头 dom>7 静默退出 兜住。ⓑVPS 侧:wrapper=scripts/factor_research/factor_monthly_wrapper.ps1(三段同链批评部分,--host vps,eval_db=C:\sanguo_vnpy_v2\data\factor_eval.db,报告/日志=C:\sanguo_vnpy_v2\reports\factor_monthly\;ASCII-only 纪律;stage4 归因批不镜像——归因双跑落 NAS 工作区+生效位,VPS 侧归因件走 infra 偏差日报链另行供给);schtask 注册=scripts/factor_research/register_factor_monthly_task.ps1(XML ScheduleByMonthDayOfWeek 原生「每月第一个周日」,无需日号闸——zh-CN schtasks 不吃星期名组合走 ak-monthly 同款 XML 路线;SYSTEM/不限时,monthly_batch 重活首班实测耗时后再定是否拆任务错时)——vps-deploy 把两文件推上 VPS 后 ssh 跑一次注册脚本即成。首班=部署后第一个周日人工盯全程。

  • static 三表事件驱动补洗(融合 spec §20.11.7,2026-09-20 上线):run_dmsk.sh 第三 lane static_overlay_wash.py(dmsk daily/backfill 后 ~07:2x 起跑,--until 15:00 墙停,rc 隔离)——dmsk NOTICE_DATE 雷达命中股逐股 F10(emweb) 近 12 期 upsert 重写 static/{income,balance,cashflow}/ per-stock 文件;pending 重试队列(F10 落库滞后/网络失败次日自愈,30 天老化);周日 sync_parquet 全量回冲=雷达窗内自愈、更深归月度全量洗兜底;变更清单→晚间镜像车 manifest lane 推 VPS。

  • 数据归属口径四原则与 14 条管线全景=融合 spec §20.10(数据面唯一权威查询入口)。

  • 数据读取口径/灌库/备份不在本档:见数据设计活文档 docs/superpowers/specs/2026-07-21-data-source-fusion-design.md 与 provider 文档。

7.5 数据源间歇断供档案(复发时判因用;2026-09-22 开档)

目的=病因留痕:断供事件证据位+未定论假说+复发判别树(下次复发照树走三探针即判因,不用重新勘测)。

事件 #1:hot_rank(东财 emappdata 人气榜)2026-09-17~21 三晚断供

  • 症状:ak-events 19:30 班 hot_rank/{date} 3/3 retry 全烧,签名=('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))=服务端掐连接(非 timeout 非 403)。09-16 及 09-22 晚均正常(0.2s/100 行)。
  • 证据位:VPS data\static\logs\akshare_static_YYYYMMDD_193*.log(grep hot_rank);数据面=data\static\hot_rank\ 文件名=最后成功日(快照型一晚一文件,断了就缺,无告警——类型级 failed 不抬 rc,巡检看目录新鲜度 vs 最后交易日)。
  • 前科:ak_events_wrapper.ps1 头部 09-04 注释「emappdata 夜间开关,19:30 失败/22:28 实测 OK」——但 09-22 19:30 成功反证非固定时段开关。
  • 病因未定论(恢复后无法回溯):假说 A=emappdata 服务端间歇故障(全国性);假说 B=针对 VPS IP(腾讯云段)的间歇风控。断供窗口内没做第二 IP 对照是本案取证缺口。
  • 缺口口径:快照型端点无 date 参数,断供晚=该日快照永久丢(fetch 永远返当前榜,补跑老日期会拿今天的榜写老文件=数据污染;wrapper --start today 无自愈窗是防污染正确设计,margin 族滚动窗自愈不适用于快照族)。
  • 复发判别树(核心,照抄执行):
    1. VPS 探针看签名:ssh 49.232.102.198 'C:\Python310\python.exe -X utf8 -c "import requests;s=requests.Session();s.trust_env=False;r=s.post(\"https://emappdata.eastmoney.com/stockrank/getAllCurrentList\",json={\"appId\":\"appId01\",\"globalId\":\"786e4c21-70dc-435a-93bb-38\",\"marketType\":\"\",\"pageNo\":1,\"pageSize\":100},timeout=15);print(r.status_code,len(r.content))"' —— RemoteDisconnected=服务端掐;timeout=IP 黑洞型;403/429=风控明示。
    2. Mac/NAS 同命令对照(第二 IP):双侧同挂→假说 A 服务端故障(等恢复+评估换源);仅 VPS 挂→假说 B IP 风控(换源或深夜错峰重试)。
    3. 当晚 22:30 同探针再打一次:恢复→间歇型(记录窗口即可);仍挂→持续性(触发换源决策)。
  • 换源/加固备选(连续≥3 晚才动,动前报用户):①wrapper 尾加 22:30 二次重试今日 unit(marker 幂等,治间歇型;改 VPS 生效位须口令)②同花顺 ths_hot_list 备份源(零鉴权)③xueqiu_hot 已每晚并行在采(语义邻近:关注热度 vs 人气榜)。

事件 #2:hot_rank 2026-09-23 晚第 4 次断供(晨检 09-24 发现,判别树已执行)

  • 签名同 #1:193003.log RemoteDisconnected 3/3(19:30:17~24),同班 sina_sector/sw_industry 全绿=仅 emappdata 域挂。
  • 判别树执行结果(09-24 08:2x):探针②Mac=200/4476 ✓、探针③VPS=200/4476 ✓——双侧已自愈,窗口已过,A/B 假说仍不可判(几小时自愈窗口略偏假说 A 服务端间歇,不定论);探针①昨晚签名档在案。
  • 序列:交易日 17断/18断/21断/22通/23断=4 断/6 交易日(频率较开档时 3/5 上升),但非连续≥3 晚,换源决策线未触发。
  • 取证缺口持续:断供总在 19:30 窗口内、晨检 08:10 才发现,Mac 对照永远迟到。根治=备选①22:30 二次重试(重试成功=记录恢复窗口;仍挂=可当场跑 Mac 对照抓现行)——频率已 4/6,是否提前上待用户拍板(改 VPS wrapper 生效位须口令)。

哨兵方案(09-24 用户拍板「下猛药」:每小时重试+双 IP 同频对照)

  • 社区调研结论(09-24):①GitHub issue 2026-01 同签名案例「服务器上总是 RemoteDisconnected、本地正常」=云服务器 IP 段被检测的社区实证 ②东财服务端静默断连机制(空闲超时15s/单连接20 次限制,超限不发 FIN 直接掐=本案签名) ③「IP 列观察名单而非硬封」解释同 IP 间歇通断 ④云 IP 段(腾讯云等)更易被限。假说 B(IP 维度灰度限制)证据加权但未定论,A/B 判定仍靠双 IP 同频对照。
  • VPS 侧(零代码改动,✅09-24 已注册生效,用户授权):每小时重试班=schtask sanguo-ak-events-retry 重跑与 19:30 主班完全相同的 wrapper(marker 幂等:已成功类型秒级 skip,只有断供的 hot_rank 真跑;时间护栏 19:00-23:59 天然覆盖)。窗口 20:30/21:30/22:30/23:30 四发(前科 22:28 恢复≈3 发内覆盖;跑通宵无增量信息且早榜漂移过大)。重试 log 行自带时刻+尝试签名=恢复窗口量化。
  • 注记(09-27 审计 🟢-8):hot_rank 已迁 NAS 采集(§7.5 本节),VPS static/hot_rank/ 内 NAS 时代推送件(0925 起)无 .akshare marker(与 VPS 自采时代不对称)——现无消费方依赖 marker,备案防未来复用时误判「未完成」重拉。注册命令(留档备用,重装/迁移用):schtasks /create /tn sanguo-ak-events-retry /tr "powershell -ExecutionPolicy Bypass -File C:\sanguo_vnpy_v2\scripts\data_platform\ak_events_wrapper.ps1" /sc hourly /mo 1 /st 20:30 /du 003:30 /f。
  • Mac 侧(✅09-24 已上线):~/bin/hot_rank_probe.py+crontab 30 19,20,21,22,23 * * *(与 VPS 同频五发:19:30 主班时刻+四个重试时刻),只读探针恒 exit 0,log=~/logs/hot_rank_probe.log 一行/发(时刻 ok/FAIL+签名)。
  • 判读法(自动出结论):断供夜两侧 log 按时间轴对齐——VPS 挂 Mac 通=假说 B(云 IP);双挂=假说 A(服务端);VPS 重试第 N 发成功=恢复窗口分布。跑 1-2 周自然分晓,无需晨检手工对照。
  • 快照语义注记:重试成功时刻≠19:30 定档时刻(人气榜盘中后仍有散户行为漂移),文件仍按当日名落盘,实际成功时刻以 log/文件 mtime 为准,消费方按需知悉。

终态定论(09-25 晚,哨兵首夜即出结论+迁移收口,本案闭档)

  • 哨兵首夜判读(09-24 夜):时间轴完美对齐——Mac 探针五发全绿(19:30~23:30 全 200)vs VPS 主班+四发重试全断(20:30:00 Mac ok / 20:30:09 VPS RemoteDisconnected 3/3,四发重试 log 实证真跑过 hot_rank 非 marker skip)。假说 A 排除、B 定论:emappdata 对 VPS 云 IP 针对性断连(家宽同分钟全通)。0923/24/25 三连断触发「连续≥3 晚」换源决策线。
  • 处置(09-25 用户拍板):采集迁 NAS 家宽出口(spec §20.14)——corpus 班尾 run_hot_rank_nas.sh(17:35 一次性容器采 emappdata+腾讯 join,scp 推回 static/hot_rank/,.pushed marker 补推);ak_events_wrapper.ps1 同批摘除 hot_rank 类型(防双写);数据只维护 NAS/VPS 双机,Mac probe 留纯观测不留数据。缺口 09230925 三天快照型不可回补(消费方零现役因子,接受)。
  • 东财全景勘定(同晚实证):断连精确锁定 emappdata 一域——datacenter(龙虎榜/大宗/解禁)当晚 NoneType=EM 周五当日数据未出(Mac 直连同空对照,良性时序)非断连;push2ex/push2(涨停池/资金流)VPS 正常但对家宽出口恒空响应(hot_rank 迁移件 join 源因此弃 push2 用腾讯);reportapi 周域正常。
  • retry 班坑与修复:/sc hourly /st /du 被 Windows 建成「一次性+每小时重复」→ 跑完注册当晚即死(下次运行 N/A,09-25 晚发现当晚 20:30/21:30 两发漏跑)。已重注册 /sc weekly /d MON,TUE,WED,THU,FRI /st 20:30 /ri 60 /du 003:30(每周一至五四发;保留价值=兜 dragon_tiger 等 EM 当日未出数的时序失败,hot_rank 摘除后与 IP 断连无关)。
  • 连带发现(同晚巡检):①xueqiu_hot 09-21 起静默断供 5 晚——雪球上线 TLS 指纹反爬(requests 恒 418 空体、curl 放行,Mac/VPS/akshare 1.18.88 三方实测),修复=fetch 改 curl 子进程(spec §20.14,同批推 VPS);②ak-weekly 09-19 班 share_capital 新浪源 85 只失败触发断路器跳过后续类型(rc=1),当班 pledge/研报增量被连累跳过靠 09-22 回填兜底——下一班(周六 03:00)若再熔断三新域增量会缺一周,晨检重点盯,被跳过当天手动补拉。

7.6 P2 孵化梯运行件(2026-09-24 起,spec §4.5 决议 L)

件 位置 说明
周报重算 job APScheduler pipeline_weekly_report(常驻 sanguo-api 内,每日 20:45,晚于 20:30 live_step) 双机各跑各的(B');注册在 sanguo_trader/scheduler.py:register_pipeline_weekly_job,失败不影响 api 启动(try/except 兜底);手动重算=PYTHONPATH=. python -m sanguo_portfolio.weekly_report --as-of <date>(--db 缺省 data/backtest_results.db=影子/paper 实走同库,即正确值;⚠️勿指 quant_trading.db——09-25 VPS 冒烟实证影子 supervisor 落库=backtest_results.db)
毕业口令 env SANGUO_PROMOTION_PASSPHRASE 首班由用户设定后写进 api 启动环境(C:\sanguo_vnpy_v2\run_api.ps1 或系统 env);未配置→graduate 端点 503;口令不符→403
Gitea 开 issue env SANGUO_GITEA_BASE_URL(缺省 http://192.168.2.154:3000) --gitea-open/verdict 开 issue 的 API 地址;VPS=http://127.0.0.1:13000(FRP 映射家 Gitea,仅 VPS 可达);不设则 VPS 侧开 issue 静默降级=模板落盘
每机阈值库 data/pipeline.db(env SANGUO_PIPELINE_DB 可改) gate 运行值+审计行+周报三表;连接即幂等自建 schema(首跑自举);控制台「闸门阈值」页可改(PUT 落审计)
研判卡回放 CLI PYTHONPATH=. python -m sanguo_factor.verdict_replay --as-of <同月度批评>(月度批评链后跟一条,同机同 as-of;10-04 首班双机首跑) 产物 <monthly_dir>/verdict_replay.json(派生件可重建);触发点普查+七档事后成绩(近似估算,spec §4.7 P3 第一刀);GET /pipeline/research-card 读月报+此件出卡
研判裁决留痕 env SANGUO_VERDICT_RECORDS(缺省 data/verdict_records.jsonl) POST /pipeline/research-card/verdict 落档(月键一条,重复 409);七档全人工触点零自动执行(决议 C)
偏差日报(IS四分解) CLI PYTHONPATH=. python -m sanguo_portfolio.ishortfall_daily --as-of <今日>(每日 20:45 后、周报 job 之后跟跑,避开 20:30 paper 回放与 21:00 xt_eod;价格源=scripts/pipeline/is_price_source_vps.py 桥 xtdata shim 分钟 bar+dbbardata 日线;首跑/部署后必跑其 probe(<day>) fail-loud 自检) 产物 data/ishortfall/<day>.json+pipeline_store is_daily 表(GET /pipeline/attribution IS 四行+价格移动参考行数据源=latest_is());事件表 order_events 主库幂等自建(FIX 七态 append-only,老 backlog 委托入库就此闭环);回放=--from 2026-09-14 --to <日> 出首份真日报(幂等可重跑);⚠️回执缺供的'filled'终态单 cum 按快照兜不住→整腿按未全额计机会成本(identity_resid 非零可见,缺数非错算);spec §4.7 P3 第二刀
策略注册表 运行副本=data/strategy_registry.yaml+data/strategy_events.jsonl(env SANGUO_STRATEGY_REGISTRY/SANGUO_STRATEGY_EVENTS 名不变);git 种子=config/strategy_registry.yaml 首触自举+缺失条目自动 merge(运行副本缺失时从种子拷贝;已存在时种子新登记条目由 ensure_runtime_registry 每次 touch 自动补入,同名条目运行态为准——2026-09-27 挑战者双机漏登记、周报点名跳过实证后治本) promote.sh 每次 push 都 rsync config/——运行期转移(毕业/退回/延长)若写 config/ 会被下次部署静默回滚,故运行态一律落 data/(部署不覆盖;merge 只补缺、绝不覆盖同名运行态);因子 verdict 端点同款:data/factor_registry.yaml+data/registry_events.jsonl(种子 config/factor_registry.yaml,factors 容器同走 merge);跨机同步=人工 git 收编(运行副本改动抄回 config/ 种子后 commit;转移事件同时落 reports/registry_events/ 毕业模板,防丢)
存量补录 PYTHONPATH=. python -m sanguo_portfolio.strategy_registry register <name> --hypothesis <H-x> --composite-version <v> --backfilled [--paper-account-id <id>] [--stage <s>] 逐条补录在跑实例(gate 快照留空);现在写 data/ 运行副本(缺则从 config/ 种子自举;--stage 直落初档,如 --stage live);其余 CLI 子命令=transition(--stage/--gate-json/--capital-json/--cause)与 extend-shadow(--extra-weeks --note)
回测 gate 判定 PYTHONPATH=. python -m sanguo_portfolio.promotion_gate backtest --task-id <run> --db <主库>(或 --sharpe X --max-dd Y) 打印 gate JSON,喂 strategy_registry transition --gate-json
VPS 控制台 schtask sanguo-api(开机自启,run_api.ps1→run_web.py→uvicorn 8000,vnpy.mysanguo.top 外网绑定) B' 生产控制台;09-25 勘误:本就常驻跑纯 API(旧文「VPS 无常驻 web」过时);09-25 起挂前端 dist(frontend/dist,CI 只推 NAS 故 VPS 前端需手动 scp)+PASSPHRASE/GITEA_BASE_URL env 进 run_api.ps1;改代码后须 schtasks /end /tn sanguo-api && schtasks /run /tn sanguo-api 重启加载;env 优先级=SANGUO_DB_PATH env > config/backtest.yaml(yaml 里 db_path 是 NAS 容器路径,promote 种子直推,勿被误导)

部署班次台账(tag vps-deployed=部署真相,随班前移):70e7678(09-26 首)→ 16641f0(09-26 深夜)→ c97f449(09-27 审计修复波 10 条班车:影子A/B 2+偏差日报接线 1+factor 3+data 4;run 2104 success;影子 A/B 挑战者 id=63 当班落位,09-28 09:30 首跑)。

VPS 周报:过渡期 CLI schtask 已终结(09-25)——sanguo-api 常驻重启后 20:45 APScheduler job 自动跑(首班 09-25 晚);手动重算=CLI python -m sanguo_portfolio.weekly_report(不设 SANGUO_DB_PATH 即用缺省 data/backtest_results.db(正确库))。

P3 偏差日报批次(2026-09-26,回放毕/上 VPS 毕):已随 vps-deploy 16641f0 班车全量上 VPS(首班 70e7678,10-04 前各波次顺延);历史回放(09-14→09-25)已完成出首份真日报(幂等可重跑);此后每日 20:45 后随周报链跑。接线(routes_pipeline IS 五行+factorContribution 读真)已毕;09-27 补调度接线:ishortfall 日跑挂库内 APScheduler 20:50 job(register_ishortfall_daily_job,随 sanguo-api 常驻,审计终裁落地)。

⚠️手动跑 ishortfall_daily/probe 必预置全链 PYTHONPATH(09-26 VPS 冒烟实证)——_ensure_bridge_env() 运行时改 env 只利 spawn 子进程,不动当前进程 sys.path;缺此步 import xtdata 落到 site-packages 原生 xtquant 直连本机客户端,报「无法连接xtquant服务」。cmd 配方:

cd /d C:\sanguo_vnpy_v2
set PYTHONPATH=C:\sanguo_bigqmt\xtquant_bridge;C:\sanguo_vnpy_v2;C:\sanguo_vnpy_v2\vnpy_v4.4.0;C:\sanguo_vnpy_v2\vnpy_qmt_v0.3.3
python -m sanguo_portfolio.ishortfall_daily --from 2026-09-14 --to <日>
python -c "import sys; sys.path.insert(0,'.'); from scripts.pipeline.is_price_source_vps import probe; probe('<日>')"

(probe 是函数非 CLI 子命令,python -c 直调;env 其余件 DEFAULT_DATA_PROVIDER/REDIS 口令由 _ensure_bridge_env 运行时自设。)

非交易日桥断连定性(09-26 周六实证):客户端在跑但行情断连时 bridge 连 1d 都返空 DataFrame(shim 返空不报错)——probe 分钟空≠代码错。日线锚走 dbbardata 不受影响,分钟缺腿=legs_no_anchor 如实可见;数据自愈(下个交易日 xt_eod 21:00 班)后幂等重跑回放覆盖 no_anchor 腿。

基准延伸节律(te/vs 保真,09-25 定):策略挂的回测基准 equity 停在其 end_date;周报对齐窗(近 4 周)随 as_of 前移会滑出回测段 → te/vs 掉 None。每 ≤4 周重跑一次基准:同参数 POST /portfolio/backtest(end_date=最新交易日)→ done 后 strategy_registry register <name> --backtest-run <新tid>(upsert 换挂,te/vs 自动对齐新段)。锚点=月度批评首班前一天晚捎带(10-04 起);重跑占 orchestrator 回测池(max_workers=2),避开批评链与当日回测高峰。

部署尾节清单(首班用户在场时执行,不自动):①推 vps(口令)②VPS 设 SANGUO_PROMOTION_PASSPHRASE ③VPS 存量补录 CLI 逐条跑(live/shadow 实例挂 paper_account_id;backfill CLI 现在写 data/ 运行副本,--stage 可用,如 --stage live)④VPS 控制台起法定型⑤NAS 侧无需新动作(api 容器随 CI 自动部署,20:45 job 自动注册)。

7.7 NAS 长批模式(一次性容器,2026-09-26 定型)

铁律:多小时批一律跑一次性容器,禁常驻容器 docker exec——nas-deploy 每次 push 重启 sanguo_vnpy_v2 常驻容器=当时在跑的 docker exec 批静默死(SIGKILL 无 traceback+| tail 管道掩退出码;09-25/26 累计 6 撞实证,撞杀窗口=活跃 session 的 push 频率,无协调可依赖)。

标准命令(corpus 一次性容器先例转正):

DOCKER=/var/packages/Docker/target/usr/bin/docker
$DOCKER run --rm -d --name sanguo-<批名> \
  --user 1024:100 --group-add 101 \
  --entrypoint python \
  -e PYTHONPATH=/app:/app/vnpy_v4.4.0 -e HOME=/tmp -e MPLCONFIGDIR=/tmp/mpl \
  -e TZ=Asia/Shanghai \
  -v /volume1/homes/admin/.sanguo_projects/sanguo_vnpy_v2:/app \
  -v /volume1/stock:/volume1/stock -w /app \
  sanguo_vnpy_v2:lock-aligned -u <脚本.py>

三个 env 都是坑换来的:PYTHONPATH(entrypoint.sh 里设的会被 --entrypoint 覆写绕掉;脚本目录≠cwd,sanguo_*/vnpy import 不到)/HOME=/tmp(vnpy 导入要写 $HOME/.vntrader,uid 1024 下 HOME=/ 不可写→PermissionError 秒死)/MPLCONFIGDIR(matplotlib 缓存同因,警告级)。

配套纪律:①批脚本自带 append 日志(落 /volume1/stock 可跨容器重启存活)+分片+skip-if-exists(撞杀只丢在飞一片,重放即续)②判活=docker top <容器> -o pid,stat,time,cmd(容器内 busybox ps 截断 cmdline 假阴性;/proc 扫描自匹配模式字面量——判活一律 docker top)③批前查 CI 无 in_progress(窗口纪律,锦上添花非依赖)。

8. 在案遗留(观察项)

8. 在案遗留(观察项)

  • 探针撤单在集合竞价段不确认(0.01 永不成交+日切自愈,无害)
  • 冒烟 2 笔 ETF(510050+159915×100,残差 637.40)待用户手平
  • mini 栈闲置:09-18 停服后建议彻底清除引用(避免假 WARN)
  • upstream(xtquant_big_convert)归一化贡献 backlog

9. 历史:已退役架构(2026-07 时代,勿参照执行)

本 runbook 旧版描述的 FastAPI bridge(:8765) + Caddy 反代 + BRIDGE_TOKEN + miniQMT 进程内直连 已于 2026-09-08 全量切桥后退役:交易腿→Redis RPC 桥(本档 §1),数据腿→桥 shim(09-10), BRIDGE_SESSION_ID 换号、/health 三端点、Mac SSH 隧道等内容全部作废。 仍有效的通用内容(Windows ssh 跑命令三坑:GBK 编码/引号嵌套用 stdin/中文路径用搜索)已并入 本档 §7.3 与 §6.2E。git 历史可查旧版全文。