tradingSystem/REAL_TRADING_DEPLOY_PLAN.md

8.6 KiB
Raw Blame History

正式盘部署方案(模拟 / 正式双系统)

2026-08-28 定稿,同日随拍板收敛到最终口径:正式盘部署在 192.168.16.188,正式 QMT 在 192.168.16.98ws 端点 ws://192.168.16.98:9443/pms两套系统共用 my_quant_db 一个库,全部靠表名区分——正式 PMS 的 19 张自有表加表名前缀PMS_TABLE_PREFIX=real_ → real_pms_),下游表由正式 QMT 写另一套表名PMS 侧 PMS_DS_TABLE_ 指过去)。 不建新库、不动代理、不用跨库授权。现有这套 PMS 保留为模拟仓原地不动。 一份代码,两份 .env —— 不开分支、不复制仓库:两份代码必然分叉,修一个账务 bug 要 修两遍测两遍本仓库的设计本来就是「settings 只是初值,实例身份由 .env 与各自库里的 参数表决定」。

〇、先后次序(为什么先搭台架再测协议)

正式 QMT 侧从没成交过一笔真实买卖,所以第一优先级是把 ws 协议在正式侧跑通并用一笔 小额真实买卖判收,然后才谈全量部署与影子期。但协议测试本身需要的台架——出口表 pms_qmt_order、入站表 pms_qmt_inbox、ws 常驻进程、签名链路——就是这套系统的最小部署: ws_smoke 不是独立客户端,它往出口表塞单、由 pms-ws 进程签名发出。所以次序是:

阶段A  最小台架(只起 页面+ws 通道,**不起调度器**)→ 协议实测(握手/快照/一买一卖)
阶段B  协议判收后,全量部署(加调度)→ 影子期 ≥3 个交易日 → 切 ws、放自动档

阶段A 里 beat/worker 根本不存在,系统不可能自主做任何动作;下发模式默认 shadow ws_smoke 发的联调单绕开这个开关、且带 SMOKE 前缀——成交回报会被联调单闸挡在账本外。 绝不要拿模拟机那套临时把端点切到 98 去试:模拟的账本会吃进正式账户的回报,两边 密钥也不同,历史上 SMOKE 假成交污染账本的教训就是这么来的。

一、两套系统各自用什么、共用什么

资源 模拟(现状) 正式(新) 说明
代码 git 仓库 同一仓库 两边各自 git pull,永远同版本
PMS 自有表19 张) my_quant_db 的 pms_* 同库、加前缀 real_pms_*PMS_TABLE_PREFIX 表名映射在 SQL 唯一执行入口统一做
下游表 trading_* / strategy_daily_results 原库、原表名 原库、新表名.env 的 PMS_DS_TABLE_* 指过去) 正式 QMT 写一套新表名
Celery 总线 150 redis db8 150 redis db9 共用一个 db 两套 worker 互相抢任务
决策系统信号流 208 db2/db3只读共享 同左 流共享,消费组必须不同名
行情/大盘/mtf 208 db13 / 199 / 214 同左 纯只读,直接共用
QMT ws 通道 ws://192.168.18.182:9443/pms + 模拟密钥 ws://192.168.16.98:9443/pms + 新密钥对 密钥绝不复用
管理页面 tlai4090:38100 192.168.16.188:38100 不同机器,端口可同名

消费组为什么必须不同名Redis Stream 的一个消费组内,一条消息只投递给一个消费者。 两套系统若同组,风控卖出信号会被随机一家抢走,另一家永远看不见。组名在 .env 里设 PMS_SIGNAL_GROUPsettings 已声明该键,参数表为空时 .env 值直接生效。

二、部署前的准备件

  1. 库与表的接线(同库表名区分,什么都不用建)。PROXY_DB_URL 与模拟完全相同 (照抄,还是 153 代理的 my_quant_db。正式 PMS 的自有表靠前缀区分:.env 设 PMS_TABLE_PREFIX=real_db.session 在 SQL 执行唯一入口把 pms_* 统一映射成 real_pms_;首次 make deploy 建表自动带前缀建出 real_pms_ 这一套init_db 开头 会打印「表名前缀 real_ 生效」;个别 DDL 若被代理拒绝,脚本会打印带前缀的完整 语句,直接拿去物理库执行即可,与模拟当年建表同一套兜底)。下游表由正式 QMT 在同库 写一套新表名,向 QMT 侧要到四张表名填进 PMS_DS_TABLE_*。模拟与正式的数据从 表名上就分开,不会混。
  2. 正式密钥对:容器里 python scripts/gen_keys.py 生成seed 填正式 .env 的 PMS_QMT_SIGN_SEED_HEX公钥带外交给 QMT 侧,拿回对方公钥填 PMS_QMT_PEER_PUBKEY_B64。
  3. 真实账户规模与纪律参数PMS_TOTAL_SCALE 按真实资金;上线初期 shadow + propose_only + 新建仓 off。

三、正式服务器 .env 与模拟的差异清单

照抄模拟的 .env改动以下键其余全部照抄行情/信号这些共享源不要改

# 必须不同 (注意: PROXY_DB_URL **不在这里** —— 照抄模拟的, 同一个 my_quant_db)
PMS_TABLE_PREFIX=real_
PMS_REDIS_URL=redis://:<pass>@192.168.16.150:6379/9
PMS_SIGNAL_GROUP=pms_signal_consumer_real
PMS_SIGNAL_CONSUMER=pms_real_1
PMS_QMT_WS_URL=ws://192.168.16.98:9443/pms
PMS_QMT_SIGN_SEED_HEX=<gen_keys 新生成>
PMS_QMT_PEER_PUBKEY_B64=<QMT 正式侧公钥>
PMS_SESSION_SECRET=<新生成, 别抄模拟的>

# 下游表名: 按正式 QMT 实际写的表名填 (同库, 直接写表名)
PMS_DS_TABLE_POSITION=<正式持仓表名>
PMS_DS_TABLE_ORDER=<正式委托成交表名>
PMS_DS_TABLE_BUY_PLAN=<正式买入计划表名>
PMS_DS_TABLE_DAILY=<正式定性结论表名>

# 阶段A 先关, 密钥交换完再开
PMS_QMT_WS_ENABLED=false

# 可选 (单独服务器用默认即可; 将来若与模拟合并到一台机器才需要)
# PMS_STACK_PREFIX=real-
# PMS_IMAGE=pms-real:latest
# PMS_WEB_PORT_HOST=38200
# COMPOSE_PROJECT_NAME=pms-real

四、阶段A最小台架 + ws 协议实测(在 188 上)

  1. 装 docker 与 docker composegit clone 仓库;按第三节写好 .env密钥先留空
  2. 表名口径:.env 设 PMS_TABLE_PREFIX=real_向 QMT 侧要到四张正式下游表的表名, 填进 PMS_DS_TABLE_*。不用建库、不用授权、不动代理。
  3. 网络预检188 要能通 153:3307、150:6379、208:6379、199:3306、214:36379、98:9443。
  4. 建表前自证(最后一道闸):docker compose build 后跑 docker compose run --rm --no-deps pms-web python -c "from config.settings import settings; print(repr(settings.PMS_TABLE_PREFIX))" ——必须打印 'real_';打印空串绝不往下走(会建出与模拟同名的表)。
  5. 最小台架(只起 页面+ws不起调度PROFILES="--profile ws" ./scripts/deploy.sh --no-pull —— 建镜像、起 pms-web/pms-ws、幂等建表。输出必须出现 「[双实例] 表名前缀 'real_' 生效」COUNT 验证列出的全是 real_pms_*;没看到立即中止。
  6. make check(库/参数/通道逐项)与 make testALL SUITES PASS + 指纹一致)。
  7. 生成密钥、与 QMT 侧交换公钥;.env 里填好两把钥匙并把 PMS_QMT_WS_ENABLED=true 重跑 PROFILES="--profile ws" ./scripts/deploy.sh --no-pull 让新 env 生效。
  8. 通道判收(不动钱):make ws-status 看 连接 ONLINE、心跳在走、能读到持仓快照 ws_smoke.py inbox 里有 snapshot/心跳类上行。
  9. S2 式发单(挂不上才是预期):盘中发一张限价远离市价的买单(--ttl 5 到点对端自动撤), watch 里状态走 QUEUED→SENT→受理inbox 里有 ack 与回报。
  10. 一笔真实买卖判收核心建议选一只当日可回转T+0的跨境或货币 ETF一手 一两百块,当天买进当天卖出;用普通股票也行,但 A 股 T+1卖出要等次日。判收三条 两张单全成、inbox 有 trade 回报、账本零变化SMOKE 联调单闸把成交挡在账外)。
  11. 清场:测试买的货必须卖光再进阶段B——否则影子期对账会把它当真实持仓收编进账本。

五、阶段B全量部署与影子期协议判收后再做

make deploy(加上调度)→ 页面参数中心设 PMS_TOTAL_SCALE / PMS_AUTONOMY=propose_only / PMS_OPEN_AUTONOMY=off → 真实账户已有持仓则等盘前对账以 ws 快照建账 → 影子期 ≥3 个 交易日逐日判收(日报对得上、回放游标推进、无孤儿成交)→ 页面把 PMS_DISPATCH_MODE 改 ws管理员→ 按表现逐层放开自动档。逐条命令等阶段A 判收后再展开。

六、日常纪律

两台各自 git pull + make deploy收盘后部署;发版前后两边都 make test。 DEVLOG 单仓共用,节点里写清动的是模拟侧、正式侧还是两侧。模拟侧本次零改动