docs(ops): 唯二主文档定稿——发布=three-env-code-promote(收编impact-map触及面/标签判定为§12+前端构建发布§13)/运维=vps-production-runbook(收编unified-deploy三机角色/api env/web回测坑为§7);vps-unified-deploy+vps-impact-map收编后归档为墓碑;CLAUDE.md部署流程顶部立牌(任何部署运维发布知识只更新这两份,读也读这两份);ci-cd报错提示与pending文档引用改指§12(注:ci-cd.yml一行属nas) [vps]
CI/CD / test (push) Successful in 34s
CI/CD / nas-deploy (push) Successful in 24s
CI/CD / nas-verify (push) Successful in 6s

This commit is contained in:
2026-09-14 09:13:15 +08:00
parent 8373011061
commit b2d12a4cf9
7 changed files with 96 additions and 268 deletions
+6 -1
View File
@@ -139,10 +139,15 @@ NAS 上用于本项目部署的目录有两个(容器挂载源):
### 部署流程(NAS 自动 / VPS 主动触发,所有开发 session 必读)
> **📌 唯二主文档(2026-09-14 用户钦定,所有 session 遵守)**:
> - **发布**=`docs/three-env-code-promote.md`(晋升/rollback/数据铁律 + **§11 发布关联性检查清单**[推 VPS 前必过] + §12 commit 标签与触及面 + §13 前端构建发布)
> - **运维**=`docs/deployment/vps-production-runbook.md`(大QMT 桥栈生产架构 + schtask 全景 + 三层防御节律 + 非代码资产清单[promote 推不到的半边] + 已知问题库 + web/回测/数据面)
> - **任何部署/运维/发布知识一律更新进这两份,不再新开文档;查也优先查这两份。** 过时文档不并立新档——重写原文或收编后加「已归档」标注(例:vps-unified-deploy/vps-impact-map 已收编归档)。
> **职责边界(所有 session 必须遵守)**:开发/数据/策略 session 改完代码 `git push` 即完成(NAS 自动验证,到此为止);**VPS prod 部署绝不自动**,必须 nas-verify 绿后由人确认触发 `vps-deploy.yml`。**业务 session 不要自己推 VPS**(push 只到 NAS);推 VPS 是运维 agent + 人协作的决策。
> **commit 必须打环境标签(CI 强制,所有 session 必读)**:每条 commit message 末尾带 `[vps]`(VPS 也中招,含通用代码,待推 prod)或 `[nas]`(NAS/docker 专属,VPS 不中招)。`ci-cd.yml` 的 `enforce-label` 步骤:本次 push 的 commit 无标签 → **CI 直接 fail**(merge commit 豁免)。
> - **判定**:维度是「VPS 运行时是否触发」,不是「文件改了没」。触及面清单见 `docs/vps-impact-map.md`(VPS 触及=data/backtest/portfolio.runner_backtest/provider;不触及=orchestrator/api.web/web前端/docker/.gitea)。
> - **判定**:维度是「VPS 运行时是否触发」,不是「文件改了没」。触及面清单见 `docs/three-env-code-promote.md` §12(VPS 触及=data/backtest/portfolio.runner_backtest+runner_live/live/trader/provider/scripts.qmt_relogin;不触及=orchestrator/api.web/web前端/docker/.gitea)。
> - **`[vps]` 触发链**(Gitea 无 approval gate,用 issue+tag 替代 GitHub 的 action_required 黄色):nas-verify 绿后 CI 自动开/更新 `[待推VPS]` issue(**open=黄/待推**,持久可见);人工/agent 推 `vps-deploy.yml` 成功 → 打 `vps-deployed` tag + 自动关 issue(**close=绿/已推**)。CI run 保持绿(NAS 部署成功不污染)。
> - **查 VPS 还差哪些**:`git log vps-deployed..HEAD --grep='\[vps\]'`(VPS 版本真相 = 移动 tag `vps-deployed`,指向最后部署 VPS 的 sha)。
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
echo ""
echo "规范: <type>(<scope>): <desc> [vps] # VPS 也中招, 要推 prod"
echo " <type>(<scope>): <desc> [nas] # NAS/docker 专属, VPS 不中招"
echo "详见 docs/vps-impact-map.md"
echo "详见 docs/three-env-code-promote.md §12"
exit 1
fi
echo "✅ 本次 push commit 标签齐全"
+35 -5
View File
@@ -4,9 +4,9 @@
> 2026-09-08 全量切桥(miniQMT → 大QMT RPC 桥)后本文为权威运维文档;旧 FastAPI bridge(:8765)+Caddy+miniQMT 直连架构已退役(文末历史节)。
>
> 相关文档:
> - 发布流程与**发布关联性检查清单**:[`../three-env-code-promote.md`](../three-env-code-promote.md)
> - 发布流程与**发布关联性检查清单**:[`../three-env-code-promote.md`](../three-env-code-promote.md)(唯二主文档之「发布」)
> - 大QMT 无人值守登录:[`../qmt-headless-login-runbook.md`](../qmt-headless-login-runbook.md)
> - 三机角色/部署清单(web/回测/数据面):[`vps-unified-deploy.md`](./vps-unified-deploy.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`。
@@ -151,17 +151,47 @@ ssh 49.232.102.198 "powershell -Command \"Get-Content C:\sanguo_bigqmt\qmt_relog
`qmt-sentinel-gate-plan-20260909` / `xt-eod-bridge-leg-switch-20260910`;登录处置全流程=
[`../qmt-headless-login-runbook.md`](../qmt-headless-login-runbook.md)。
## 7. 在案遗留(观察项)
## 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 喂脚本 |
- 数据读取口径/灌库/备份**不在本档**:见数据设计活文档 `docs/superpowers/specs/2026-07-21-data-source-fusion-design.md` 与 provider 文档。
## 8. 在案遗留(观察项)
- 探针撤单在集合竞价段不确认(0.01 永不成交+日切自愈,无害)
- 冒烟 2 笔 ETF(510050+159915×100,残差 637.40)待用户手平
- mini 栈闲置:09-18 停服后建议彻底清除引用(避免假 WARN)
- upstream(xtquant_big_convert)归一化贡献 backlog
## 8. 历史:已退役架构(2026-07 时代,勿参照执行)
## 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/中文路径用搜索)已并入
`vps-unified-deploy.md` §10 与本档 §6.2E。git 历史可查旧版全文。
本档 §7.3 与 §6.2E。git 历史可查旧版全文。
+9 -177
View File
@@ -1,179 +1,11 @@
# VPS 统一部署(全量权威文档)
# VPS 统一部署 —— ⚠️ 已归档(2026-09-14)
> **状态:2026-07-17,端到端验证通过。** 本文档覆盖当前生产真实状态,**取代** `vps-native-brain.md`(07-15,架构已变)。
> 所有服务统一到 VPS;NAS 降为备份;Mac mini 仅开发。
> **本文档已收编并归档**,不再更新。唯二主文档(所有 session 读/写都走这两份):
>
> ⚠️ **2026-08-13 更新**:`mysanguo.online` ICP 备案完成 + DNS 指北京。vnpy web 已迁**北京直 serve** `https://vnpy.mysanguo.online`(北京 Caddy :443 自动签 LE 证书,不经首尔)。**本文的「首尔 HTTPS 入口 + header_up Host 绕 webblock」workaround(§2/§6)已废弃**,仅作历史记录;老 `vnpy.mysanguo.top` 首尔入口 502。详见 memory `mysanguo-online-icp-beian` + vps-access skill。
## 1. 三机角色(定稿)
| 机器 | IP / 角色 | 跑什么 |
|------|-----------|--------|
| **北京 VPS**(生产) | `49.232.102.198` Windows Server 2022,4C16G/180G,腾讯云**境内** | sanguo_api + 前端 dist + miniQMT + 进程内 qmt_gateway_client + 权威 DB + 数据采集 schtasks |
| **首尔 VPS**(HTTPS 入口) | `43.133.235.218` Ubuntu,腾讯云**境外** | Caddy 签 Let's Encrypt 证书(境外免备案)+ 反代到北京:8000 |
| **NAS** | `192.168.2.154` Synology | 纯备份(xtdata zip 历史库);sanguo_api 容器**已停用** |
| **Mac mini** | 开发机 | 改代码、构建前端、rsync/scp 部署;采集/同步 cron **已停用** |
> **为什么 HTTPS 入口在首尔**:北京(境内)用未备案域名 Host 走 80/443 会被腾讯**webblock**(见 §6)。首尔境外无需 ICP 备案,Caddy 自动签 LE 证书。北京只暴露 8000(API),由首尔反代。
## 2. 网络入口与域名
- **域名**:`vnpy.mysanguo.top` → A 记录指向**首尔** `43.133.235.218`(NameSilo/dnsowl 托管)。
- **访问**:`https://vnpy.mysanguo.top`(Mac 浏览器;ClashX 关闭或在 `/etc/hosts` 钉 `43.133.235.218 vnpy.mysanguo.top` 绕 fake-ip)。
- **北京防火墙**:已放行 22 / 80 / 443 / 3389 / 8000。
### 首尔 Caddyfile(vnpy block,关键:`header_up Host`)
```caddyfile
vnpy.mysanguo.top {
reverse_proxy 49.232.102.198:8000 {
header_up Host 49.232.102.198:8000
}
}
```
> **`header_up Host` 是 webblock 修复的核心**:不加它,Caddy 会透传 `Host: vnpy.mysanguo.top` 给北京:8000,腾讯基于该未备案域名 Host 对 **GET 请求** webblock(HEAD/POST 放行,故早先 login 能通、GET / 被拦)。改成北京 IP 后 Host 不带域名,北京不拦。备份在首尔 `/etc/caddy/Caddyfile.bak0716`。
> 北京本机的 `sanguo-caddy` schtasks **已 Disabled**——入口是首尔,北京不直接serve web。
## 3. 北京 VPS 安装清单(`C:\sanguo_vnpy_v2\`)
| 组件 | 来源 | 位置 |
|------|------|------|
| vnpy 4.4.0 源码 | 项目内 `vnpy_v4.4.0/`(纯 Python 零 C 扩展) | `C:\sanguo_vnpy_v2\vnpy_v4.4.0\`(`sys.path`/`PYTHONPATH` 引用,**不 pip install**)|
| sanguo_* 大脑包 | 项目 scp | `C:\sanguo_vnpy_v2\sanguo_*\` |
| Python 3.10 | 华为镜像 | `C:\Python310\python.exe` |
| vnpy-qmt 0.3.3(vendor 自维护)/ vnpy_ctastrategy 1.4.1 / vnpy_sqlite 1.1.3 / TA-Lib 0.6.8 / empyrical 0.5.5 / pandas / numpy / fastapi / uvicorn / apscheduler | pip(阿里镜像)| site-packages |
| 前端 dist | Mac 构建 scp | `C:\sanguo_vnpy_v2\frontend\dist\` |
pip 镜像:`pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/`(写 `C:\Users\Administrator\AppData\Roaming\pip\pip.ini`)。
## 4. 数据(DB 为主,parquet 兜底)
- **权威 DB**:`C:\sanguo_vnpy_v2\data\quant_trading.db`(vnpy sqlite,表 `dbbardata`/`dbbaroverview`)。
- 个股日线:**13,484,621 行 / 5201 只 / 2010-01-04 ~ 2026-07-16**。
- 指数:`000300`(沪深300)/`399001`(深证成指)/`399006`(创业板指)/`000905`(中证500) 全在 DB。
- **回测结果库**:`C:\sanguo_vnpy_v2\data\backtest_results.db`(表 `backtest_stats`)。
- **结果文件**:`C:\sanguo_vnpy_v2\data\{task_id}_{equity,trades,metrics}.json` + `{task_id}.log`(`file_dir = dirname(db_path)`)。
- **读取口径**(`sanguo_data/datareader.py`):
- `read_db_daily`(个股)→ vnpy `load_bar_data`(`guess_exchange` 判交易所)。
- `read_index_daily`(指数/基准)→ **从 DB 读**(前缀解析交易所:`sh→SSE`/`sz→SZSE`,避免 `guess_exchange` 把 000300 误判 SZSE)。返回 `pd.DataFrame`。parquet 仅备份不再读。
- **灌库**:`scripts/data_platform/import_vnpy_daily_fast.py`(parquet → DB,向量化,`INSERT OR REPLACE`)。env `VNPY_DB_PATH`/`DAILY_DIR`(Windows 用正斜杠 `C:/...`)。日线增量走 `daily_update_xtdata.py`(xtdata 本地缓存,零漂移)。
- **用户铁律**:下载质量不可控,**绝不直接写主库**——staging 隔离→验证→合并。
## 5. 后端服务 sanguo_api
- **进程**:`schtasks sanguo-api`(SYSTEM,开机自启)→ `C:\sanguo_vnpy_v2\run_api.ps1`。
- **端口**:8000(`/api/v1/*` + `/docs` + SPA `/`)。
- **日志**:`C:\Users\Administrator\sanguo_api.log`(**找 worker 异常/traceback 看 here**)。
- **回测执行**:`Orchestrator`(`sanguo_orchestrator/runner.py`)+ `ProcessPoolExecutor`(Windows spawn)。提交 → pool worker 跑 `run_cta_backtest` → 结果存 DB + JSON。状态走 WebSocket + 轮询 `/task/{id}`。
### env(`run_api.ps1`,保 git 真相,不改 yaml)
```powershell
$env:PYTHONUTF8 = "1"
$env:PYTHONPATH = "C:\sanguo_vnpy_v2;C:\sanguo_vnpy_v2\vnpy_v4.4.0"
$env:SANGUO_DATA_ROOT = "C:\sanguo_vnpy_v2\data" # 重映射 daily/raw/qfq/15min/vnpy_db
$env:SANGUO_DB_PATH = "C:\sanguo_vnpy_v2\data\backtest_results.db"
$env:SANGUO_FILE_DIR = "C:\sanguo_vnpy_v2\data\backtest_files"
$env:SANGUO_LIVE_ENABLED = "true"
$env:SANGUO_BRIDGE_URL = "http://127.0.0.1:8765" # 兼容留,进程内不用
$env:BRIDGE_TOKEN = "<见 windows-vps-access 记忆>"
$env:SANGUO_USE_QMT_GATEWAY = "1" # 进程内 qmt_gateway_client 直连 miniQMT
$env:SANGUO_QMT_ACCOUNT = "66639661"
# SPA_STATIC_DIR 未设 → 默认 repo/frontend/dist = C:\sanguo_vnpy_v2\frontend\dist
```
不设这些 env(NAS/Mac)则用 `config/backtest.yaml` 原值 → 三机共用同一份 git config。
## 6. 前端(Vue SPA)
- **同源相对路径**:`frontend/src/api/client.ts` 用 `/api/v1`,WebSocket 自适配协议/host → Caddy 反代即打通,无需 build 时配 host。
- **构建**:Mac 上 `cd frontend && npm run build` → `frontend/dist/`。
- **部署**:`scp -i ~/.ssh/id_ed25519 -r frontend/dist/* Administrator@49.232.102.198:C:/sanguo_vnpy_v2/frontend/dist/`。
- **挂载**:`sanguo_api/main.py::build_app` 把 `static_dir` 挂载在 `/`(history fallback,深链刷新可用)。
- **结果页**:`Result.vue` 用 `Promise.allSettled` 隔离 7 个接口(benchmark/risk 缺数据不拖垮整页);时间范围筛选前端本地过滤。
## 7. 实盘链路(miniQMT,进程内直连)—— ⚠️ 已被取代(2026-09-08)
> **本节为历史记录。** 2026-09-08 起实盘全量切**大QMT RPC 桥栈**(XtItClient 桥宿主+redis+12 引擎+三层防御),
> miniQMT 09-18 停服前已零生产依赖。现役架构/运维见 [`vps-production-runbook.md`](./vps-production-runbook.md),
> 发布关联检查见 [`../three-env-code-promote.md` §11](../three-env-code-promote.md)。
- miniQMT 模拟账户 `66639661`(`C:\国金QMT交易端模拟\`,XtMiniQmt.exe 常驻)。
- **进程内 `qmt_gateway_client`**(commit 992f53d):sanguo_trader 同进程直连 miniQMT(`connect=0` 成功),替 HTTP bridge。
- **bridge 已废弃**(`sanguo-bridge` schtasks = Plan B,仅 miniQMT 权限被收回/换券商/跨机时翻出,见记忆 `bigqmt-rpc-bridge-fallback`)。
- 实盘走影子模式(sanguo 影子下单 + xtquant 独立脚本),详见记忆 `d-phase-mock-trading-link`。
## 8. 回测(CTA + 优化 + 历史)
- **A股适配**:`sanguo_backtest/ashare_engine.py`(`AShareBacktestingEngine` 子类化修复 vnpy 失真:1股定寸 `size=N`/拒做空/费用)。记忆 `backtest-engine-ashare-adapter`。
- **指标**:`sanguo_backtest/metrics.py::compute_metrics`(empyrical,聚宽同源)。**关键修复**:导入 empyrical 前补回 NumPy 2.0 移除的别名,否则 `sortino_ratio` 崩 `np.NINF`:
```python
for _a,_v in (("NINF",-np.inf),("Inf",np.inf),("PINF",np.inf),("NaN",np.nan),("NAN",np.nan),("infty",np.inf)):
if not hasattr(np,_a): setattr(np,_a,_v)
```
> 不修则 compute_metrics 静默崩 → `_metrics.json` 不生成 → 结果页回退 vnpy 原始字段(单位混乱)→ 显示 3305% 收益 / -5000万% 回撤 / 无图表。记忆 `empyrical-numpy2-npinf-crash`。
- **结果页 7 端点**:`/result`(statistics+relative_metrics)/`/benchmark-curve`/`/risk-series`/`/equity-curve`/`/daily-pnl`/`/trades`/`/log`。benchmark/risk 缺 metrics 文件时返空 200(不再 404 拖垮整页)。
- **基准**:`hs300`(sh000300) / `zz500`(sz000905),从 DB 读。
- **老任务回填**:`backfill_metrics.py`(本地 `/tmp`,按需移 `scripts/`)从 `_equity.json`+基准重算 compute_metrics,UPDATE statistics + 补 `_metrics.json`。
## 9. 部署流程(Mac 开发 → VPS 生产)
```bash
# 1) 改代码(Mac ~/.openclaw/sanguo_projects/sanguo_vnpy_v2)
# 2) 前端构建
cd frontend && npm run build
# 3) 同步后端 + 前端到 VPS
scp -i ~/.ssh/id_ed25519 -r frontend/dist/* Administrator@49.232.102.198:C:/sanguo_vnpy_v2/frontend/dist/
scp -i ~/.ssh/id_ed25519 sanguo_backtest/metrics.py Administrator@49.232.102.198:C:/sanguo_vnpy_v2/sanguo_backtest/metrics.py
# (其余改动的 .py 同理 scp 到对应路径)
# 4) 重启 API(让新代码 + 新 worker 生效)
ssh -i ~/.ssh/id_ed25519 Administrator@49.232.102.198 "schtasks /end /tn sanguo-api & schtasks /run /tn sanguo-api"
```
## 10. 运维速查
```bash
# SSH / scp / RDP
ssh -i ~/.ssh/id_ed25519 Administrator@49.232.102.198
scp -i ~/.ssh/id_ed25519 本地文件 Administrator@49.232.102.198:C:/目标
# RDP 49.232.102.198:3389 (Administrator + 腾讯云控制台密码)
# 跑命令的坑(重要)
# - Python 一律 C:\Python310\python.exe -X utf8(emoji/中文不加 -X utf8 会 UnicodeEncodeError)
# - 复杂命令用 stdin 脚本:ssh ... "C:\Python310\python.exe -X utf8 -" < /tmp/script.py
# - Windows 路径在 ssh stdin 里用正斜杠 C:/...(\raw 等 \r 转义会炸)
# - .ps1 含中文路径用搜索代替字面量
# 服务管理
ssh -i ~/.ssh/id_ed25519 Administrator@49.232.102.198 "schtasks /end /tn sanguo-api & schtasks /run /tn sanguo-api"
# API 日志(worker traceback / 启动报错)
ssh -i ~/.ssh/id_ed25519 Administrator@49.232.102.198 "powershell -Command \"Get-Content C:\Users\Administrator\sanguo_api.log -Tail 50\""
```
## 11. 已知坑
| 坑 | 现象 | 解法 |
|----|------|------|
| **境内未备案 webblock** | GET vnpy.mysanguo.top 返腾讯备案页 | 入口走首尔境外 + Caddy `header_up Host <北京IP>` |
| **empyrical×numpy2.0** | 结果页垃圾值(3305%)+无图 | metrics.py 补回 np 别名(§8)|
| **SSH 密集连接触发限连/fail2ban** | `Connection closed by 49.232.102.198 port 22` | 等 ~30-60s 冷却;长脚本用 detached(`Start-Process`) + 轮询文件;或 Monitor 稀疏 20s 轮询 |
| **回测静默吞异常** | 指标崩被 `except` 吞,显示垃圾不报错 | cta_engine metrics 块已加 `traceback.format_exc()` 到 warning(见 sanguo_api.log)|
| **ProcessPool worker 缓存旧代码** | 改 .py 后 worker 仍旧行为 | `schtasks /end & /run sanguo-api` 重启(spawn 新 worker)|
## 12. 验证记录(2026-07-17,浏览器端到端)
- `https://vnpy.mysanguo.top` 登录(admin)→ 前端加载 ✓
- CTA 回测 DoubleMa 600000:统计正确(33.06%/-29.58%/Alpha9.30%/Beta0.524/Sortino1.02) + 5 图表渲染 + 成交明细 ✓
- zz500 基准切换:benchmark_return 80.3%(≠ hs300 36.7%)✓
- 参数优化、BollChannel 策略:跑通 ✓
- K线 / 每日收益(485点) / 日志:有数据 ✓
- 老任务回填:8 个有交易的修复(含历史垃圾值任务)✓
- 实盘链路:进程内 miniQMT connect=0 ✓(见 §7)
## 13. 相关文档与记忆
- 旧版(已取代):`vps-native-brain.md`(07-15)、`nas-deploy-plan.md`、`docker-deployment.md`。
- 数据:`data-download.md`、`env-version-matrix.md`。
- 记忆:`windows-vps-access`、`empyrical-numpy2-npinf-crash`、`backtest-engine-ashare-adapter`、`db-primary-parquet-fallback`、`bigqmt-rpc-bridge-fallback`、`d-phase-mock-trading-link`、`dep-baseline-locked`。
> - **发布**:[`docs/three-env-code-promote.md`](../three-env-code-promote.md) —— 晋升/rollback/数据铁律 + §11 发布关联性检查清单 + §12 commit 标签与触及面 + §13 前端构建发布
> - **运维**:[`docs/deployment/vps-production-runbook.md`](./vps-production-runbook.md) —— 大QMT 桥栈生产架构/schtask 全景/三层防御/非代码资产/已知问题库 + §7 web/回测/数据面(自本文收编)
>
> 内容去向:本文 §1 三机角色/§5 api env/§8 回测要点/§10 运维速查/§11 已知坑 → runbook §7;
> §6 前端/§9 部署流程 → promote §13;§2 网络入口 → runbook §7.1(首尔入口已废);
> §7 实盘链路(miniQMT 直连)→ 已被大QMT 桥栈取代(runbook §1)。
> 全文见 git 历史(本文最后完整版本=commit 8373011 的前一版)。
+38
View File
@@ -248,3 +248,41 @@ wrapper ps1、redis、DPAPI 凭证、schtask 注册**全部在代码流之外—
| 杀 auto-respawn 子进程不先 /end desk | 09-14:重拉赛跑,新树 8 秒全灭 |
| 裸跑 `python xt_eod.py` 无 wrapper | PYTHONPATH 回落旧腿,09-18 后必死 |
| 长断桥后以为引擎会自动重连 | 36h+ 重试环会死,桥活也不重连,须收割 |
## 12. Commit 环境标签与 VPS 触及面判定(2026-09-14 自 `vps-impact-map.md` 收编)
CI `enforce-label` 强制:本次 push 的 commit 必须带 `[vps]`(VPS 运行时也触发,待推 prod)或 `[nas]`(NAS/docker 专属),无标签 **CI 直接 fail**(merge commit 豁免)。
`[vps]` 触发链:nas-verify 绿后 CI 自动开/更新 `[待推VPS]` issue(open=待推);推 `vps-deploy.yml` 成功 → 打 `vps-deployed` tag + 自动关 issue。
查 VPS 未部署:`git log vps-deployed..HEAD --grep='\[vps\]'`(版本真相=移动 tag `vps-deployed`)。
**判定钥匙**:维度是「VPS 运行时是否触发」,**不是**「文件改了没」。
| 归属 | 模块/路径 | VPS 运行时场景 |
|------|-----------|----------------|
| 🔴 **VPS 触及**(=[vps],要考虑推) | `sanguo_data/` | schtask 每日采集(bs/xt/ak) |
| 🔴 | `sanguo_backtest/` | CTA 回测入口(load_data/metrics/引擎) |
| 🔴 | `sanguo_portfolio/runner_backtest.py` | VPS 直接调 run_backtest(不走 pool) |
| 🔴 | `sanguo_portfolio/runner_live.py` `sanguo_live/` `sanguo_trader/`(shadow) `sanguo_qmt_bridge/` | 实盘引擎 / 大QMT 桥栈 |
| 🔴 | `sanguo_common/` | 被上述引用 |
| 🔴 | `scripts/data_platform/*.py` | VPS schtask 跑的采集/merge/verify |
| 🔴 | `scripts/qmt_relogin/` | 三层防御本体;⚠️**promote 不部署它——须手动 scp 到 `C:\sanguo_bigqmt\`**(§11.3) |
| 🟡 弱触及 | `requirements-lock.txt` | VPS 手动 pip 装,lock 仅参考 |
| 🟢 **NAS 专属**(=[nas]) | `sanguo_orchestrator/`(仅 web 启动) | VPS 不跑 web→不跑 ProcessPool |
| 🟢 | `sanguo_api/`(routes/app/uvicorn) `sanguo_web/`(前端) | VPS 无常驻 web |
| 🟢 | `docker/` `Dockerfile` `entrypoint.sh` `.gitea/` | VPS 无 docker |
| 🟢 | `config/`(vnpy_db 等容器 config) | VPS 用 `SANGUO_DB_PATH` env 覆盖 |
- **混合模块**(`sanguo_portfolio/` 若只改 orchestrator 调度、`sanguo_api/` 若只改 routes)看 diff 具体文件对照上表,不整模块一刀切。
- **判定 3 步**:①看 commit 标签 → ②对照触及面表 → ③问「VPS 跑这段代码吗」。
- 物理层天然隔离:promote.sh 白名单推送,`docker/`、`.gitea/` 等进不了 VPS。
## 13. 前端构建与发布
- **NAS(自动)**:ci-cd.yml 的 nas-deploy 自动 `npm ci + vue-tsc + build + rsync dist`(dist 不进 git、不在 promote.sh)。
- **VPS(手动,mysanguo.online 北京直 serve)**:
```bash
cd frontend && npm run build
scp -r frontend/dist/* Administrator@49.232.102.198:C:/sanguo_vnpy_v2/frontend/dist/
ssh 49.232.102.198 "schtasks /end /tn sanguo-api && schtasks /run /tn sanguo-api"
```
(sanguo_api 的 ProcessPool worker 缓存旧代码,改后端必须重启 sanguo-api 才生效。)
+1 -1
View File
@@ -2,7 +2,7 @@
> **机制**:各业务 session 认领自己模块的 commit,判定 `[vps]`/`[nas]`/`存疑` + 理由,回传给基建。基建汇总后**统一推一次 VPS**(清技术债 + 建立 `vps-deployed` tag 基线);判定与基建初判不一致的 case by case 讨论。
>
> **判定标准**(详见 `docs/vps-impact-map.md`):维度是「VPS 运行时是否触发这个 bug」,**不是**「文件改了没」。
> **判定标准**(详见 `docs/three-env-code-promote.md` §12):维度是「VPS 运行时是否触发这个 bug」,**不是**「文件改了没」。
> - VPS 触及(→`[vps]`):`sanguo_data` / `sanguo_backtest` / `sanguo_portfolio.runner_backtest` / provider / `sanguo_common` / `scripts/data_platform`
> - VPS 不触及(→`[nas]`):`sanguo_orchestrator`(仅web启) / `sanguo_api`(uvicorn) / `sanguo_web`(前端) / docker / .gitea
>
+6 -83
View File
@@ -1,85 +1,8 @@
# VPS 触及面清单 + Commit 环境标签约定
# VPS 触及面清单 —— ⚠️ 已归档(2026-09-14)
> 解决痛点:NAS 上修了一堆 bug,事后回溯"哪些 VPS 也中招、要不要推 VPS"认知负担大、易错。
> 本文档把"事后回溯每个 commit"换成"事前对照一张稳定清单"。
> **本文档已收编并归档**,不再更新。触及面表/commit 标签规则/混合模块判定/3 步判定流程的现役版本=
> [`docs/three-env-code-promote.md` §12](./three-env-code-promote.md)(唯二主文档之「发布」)。
> 生产运维知识 → [`docs/deployment/vps-production-runbook.md`](./deployment/vps-production-runbook.md)(唯二主文档之「运维」)。
>
> **判定原则(钥匙)**:维度是「VPS 运行时是否触发这个 bug」,**不是**「文件改了没」。
> 改了文件 ≠ VPS 中招(可能只改注释 / VPS 不跑这段);没改文件 ≠ VPS 不中招。
## 一、核心事实:物理层已天然隔离
`promote.sh` 是**白名单推送**(`ALL_MODS` + `ROOT_FILES`,见 `scripts/nas_sync/promote.sh:22-25`):
`docker/` 被 exclude(line 49),`Dockerfile` / `entrypoint.sh` / `.gitea/` 不在白名单 → **物理上进不了 VPS**。
所以"NAS 专属文件会不会污染 VPS"无风险。真问题是「VPS 运行时是否也中招」——用下表判。
## 二、VPS 触及面表(基于代码核查 2026-08-02)
| 归属 | 模块 / 路径 | VPS 运行时场景 |
|------|-------------|----------------|
| 🔴 **VPS 触及**(改动落这 = 要考虑推 VPS) | `sanguo_data/` | schtask 每日采集(bs_eod/xt_eod/akshare) |
| 🔴 | `sanguo_backtest/` | CTA 回测入口(load_data / metrics / 引擎) |
| 🔴 | `sanguo_portfolio/runner_backtest.py` | 组合回测入口(VPS **直接调 run_backtest,不走 pool**) |
| 🔴 | `sanguo_portfolio/runner_live.py` `sanguo_live/` `sanguo_trader/`(shadow 引擎) `sanguo_qmt_bridge/` | 实盘引擎 / 大QMT 桥栈(2026-09-08 起) |
| 🔴 | `scripts/qmt_relogin/`(哨兵/探针/relogin/gate) | VPS schtask 三层防御本体;⚠️**promote 不部署它——须手动 scp 到 `C:\sanguo_bigqmt\`**(非代码资产清单见 `deployment/vps-production-runbook.md` §4) |
| 🔴 | `sanguo_common/` | 被上述引用 |
| 🔴 | provider 取数(`sanguo_data/` 内) | verify_unified_e2e.py 验证 |
| 🔴 | `scripts/data_platform/*.py` | VPS schtask 跑的采集/merge/verify 脚本 |
| 🟡 **弱触及** | `requirements-lock.txt` | VPS 手动 pip 装,lock 仅作参考(不自动装) |
| 🟢 **NAS 专属**(不用推 VPS) | `sanguo_orchestrator/` | **仅 web(uvicorn) 启动**;VPS 不跑 web→不跑 ProcessPool→不触发 spawn |
| 🟢 | `sanguo_api/`(routes/app/uvicorn 部分) | VPS 无常驻 web |
| 🟢 | `sanguo_web/`(前端) | VPS 不 serve 前端 |
| 🟢 | `docker/` `Dockerfile` `entrypoint.sh` | VPS 无 docker |
| 🟢 | `.gitea/workflows/` | NAS/Mac runner 跑 |
| 🟢 | `config/`(vnpy_db 等 NAS 容器 config) | VPS 用 `SANGUO_DB_PATH` env 覆盖,不读此 config |
### ⚠️ 混合模块(需看具体文件,不能整模块一刀切)
| 模块 | VPS 触及部分 | NAS 专属部分 |
|------|--------------|--------------|
| `sanguo_portfolio/` | `runner_backtest.py` `runner_live.py`(回测/实盘主体) | 若改动仅触及 orchestrator 调度(pool/worker/timeout)→ NAS 专属 |
| `sanguo_api/` | 若 model/schema 被 runner 复用(待核对) | routes/app(web) |
> 判定混合模块:看 diff 的具体文件路径,对照上表"VPS 触及部分"。
## 三、Commit 环境标签约定(CI 强制,以后 commit 必打)
CI 的 `enforce-label` 步骤强制:本次 push 的 commit **必须**带 `[vps]` 或 `[nas]`,无标签 → **CI 直接 fail**(merge commit 豁免)。
```
<type>(<scope>): <desc> [nas] # NAS/docker 专属(VPS 不中招)
<type>(<scope>): <desc> [vps] # VPS 也中招(含通用 shared 代码), 待推 VPS
```
- 一条 commit 混合多环境 → 打主导面 + 正文注明(如 `[nas] 注:runner_backtest.py 一行属 vps`)。
- `[vps]` 触发链:nas-verify 绿后 CI 自动开/更新 `[待推VPS]` issue(**open=黄/待推**);人工/agent 推 vps-deploy.yml → 成功打 `vps-deployed` tag → issue 自动关(**close=绿/已推**)。
## 四、判定流程(3 步,30 秒)
1. **看 scope/标签**:commit message 有 `[nas]/[vps]/[vps]` → 直接得结论。
2. **无标签则对照触及面表**:diff 的文件路径落在 🔴 区 = 要推 VPS;落在 🟢 区 = 不用推;🟡/混合 = 复核。
3. **复核运行时语义**(混合/存疑时):问"VPS 跑这段代码吗?"——对照上表 VPS 运行时场景列。
## 五、近期 commit 判定(2026-08-02 回溯,含技术债标注)
| commit | scope | 标签 | VPS 适用 | 说明 |
|--------|-------|------|----------|------|
| `b66a6c5` fix(ashare_engine) load_data 绕 peewee | sanguo_backtest | **[vps]** | 🔴 **要推** | VPS CTA 回测走 load_data,库大也死锁 |
| `2ff8eca` perf(metrics) rolling 向量化 | sanguo_backtest | **[vps]** | 🔴 **要推** | 分钟级卡死,VPS 算 metrics 也卡 |
| `b2c41c7` fix(backtest) benchmark 缺失降级 | sanguo_backtest | **[vps]** | 🔴 **要推** | VPS 回测也走 metrics |
| `9588a77` feat(portfolio) 回测可观测性 | runner_backtest | **[vps]** | 🔴 **要推** | VPS 回测入口 |
| `7a14d7d` feat(portfolio) strategy 全链透传 | runner_backtest | **[vps]** | 🔴 **要推** | 改到 runner_backtest(API→orchestrator 部分是 NAS) |
| `c263aa1` `3d934f5` chore(cta_engine) logging | sanguo_backtest | [vps] | 🟡 可推 | 无害 logging |
| `6d23f7b` fix(portfolio) worker _TIMEOUT | orchestrator worker | [nas] | 🟢 不用推 | pool 超时,VPS 不走 pool |
| `e22c8ee` feat(portfolio) max_pool 透传 | model+handler+前端 | [nas] | 🟢 不用推 | pool 调度参数,VPS 不走 pool |
| `2cb2ab0` fix(config) vnpy_db NAS dbbardata | config | [nas] | 🟢 不用推 | VPS 用 env 覆盖不读 config |
| `4c5270c` `c049e0e` `857d43c` fix(frontend) | sanguo_web | [nas] | 🟢 不用推 | 前端,VPS 无 web |
| `a17f291` fix(api) /health 端点 | sanguo_api | [nas] | 🟢 不用推 | VPS 不跑 web |
| `6d786fb` fix(orchestrator) spawn PYTHONPATH | orchestrator+entrypoint | [nas] | 🟢 不用推 | VPS 不跑 ProcessPool |
| `c210197` `0f6cdbe` `5c5bd9d` entrypoint/Dockerfile | docker | [nas] | 🟢 不用推 | NAS 专属 |
| `ca0ec01` ci(nas-verify) /health gate | .gitea | [nas] | 🟢 不用推 | 不推 VPS |
| `1989a54` fix(deps) requirements-lock | deps | [vps] | 🟡 弱 | VPS pip 参考 |
**⚠️ 技术债(🔴 标注的 5 条,VPS 回测逻辑修复)**:`b66a6c5` `2ff8eca` `b2c41c7` `9588a77` `7a14d7d`。
若 VPS 当前版本落后于这些 commit,VPS 回测仍带病(CTA 死锁/metrics 卡死/可观测性缺失/strategy 字段)。
→ **建议**:确认 VPS 当前 sha,若落后则触发一次 `vps-deploy.yml` 补推(nas-verify 已绿)。
> §五「近期 commit 判定(2026-08-02 回溯)」含的 5 条技术债当时已处置,未迁移;
> 其余全文见 git 历史。