生产与研究分家:实盘执行器独立成 live/ 子树,加 AWS 部署

实盘要跑在 AWS(API key 绑了 IP 白名单),而信号在新加坡那台算。借这次
把生产从研究侧摘出来,四条具体代价里第一条已经咬过:

1. live_state.json 原先落在 research/out/,而那里 shadow_hb 会自动 rename
   归档、研究脚本会写、人也手工清过。那文件装的是 MAX_DAY_LOSS 累计与已
   处理信号键,被清掉不报错,只是两道闸静默失效。改到 LIVE_HOME。
2. 采集器十币清空 300~560ms 直接叠在信号到达执行器的延迟上。
3. 研究侧探针 OOM 过一次(14.9GB),当时若有仓位在场会连坐执行器。
4. 为读两个常量 import 研究侧 step43,把 numpy/pandas/pyarrow 拖进实盘
   进程。抽出 stdlib-only 的 live/exit_params.py,install.sh 加断言挡回归。

新增 live/ship_signals.py:AWS 侧 ssh tail 拉总线,每次重连从文件头重放
+ 按幂等键去重,断线期间的信号自愈;旧信号由 staleness 闸挡掉不补做。
带时钟倒流检测——两机时钟不同步会让那道闸静默放宽。

部署件:systemd 两单元(搬运挂了执行器仍管在场仓位的超时平仓)、
install.sh、dryrun.sh(验密钥/白名单/时钟/ssh/取整)、status.sh、README。

验证:live_exec 重构后端到端空跑,SOL 多头与 ADA 空头的止损/两级止盈/
数量取整逐项核对正确,isolated + post_only + reduceOnly 都在;搬运的去重、
重启不重复追加、脏数据跳过、断线重连重放均已测。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jack
2026-08-28 17:03:03 +08:00
co-authored by Cursor
parent af029bc26e
commit 335d891478
16 changed files with 884 additions and 15 deletions
+48
View File
@@ -0,0 +1,48 @@
[Unit]
Description=chan 小额实盘执行器(读信号总线,直接调 Bitget REST
# 搬运挂了执行器仍要活着——它得继续管在场仓位的 48 分钟超时平仓。
# 所以这里只写 Wants(弱依赖),不写 Requires
Wants=network-online.target chan-live-ship.service
After=network-online.target chan-live-ship.service
# 频繁重启说明有真问题,别让它无限打交易所。5 分钟内起 5 次就停下等人。
# 注意这两项在 systemd 229+ 属于 [Unit],写在 [Service] 里会被忽略
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
User=chan
Group=chan
WorkingDirectory=/opt/chan
# 密钥与参数在这个文件里,权限必须 600。用 EnvironmentFile 而不是
# Environment=,后者会出现在 `systemctl show` 的输出里
EnvironmentFile=/etc/chan-live/live.env
ExecStart=/opt/chan/.venv/bin/python /opt/chan/live/live_exec.py
Restart=always
RestartSec=5
# 收到 stop 时给足时间:执行器要平掉在场仓位再退出
KillSignal=SIGINT
TimeoutStopSec=90
StandardOutput=journal
StandardError=journal
SyslogIdentifier=chan-live-exec
# ── 收紧权限 ──────────────────────────────────────────────────────
# 生产进程只需要读 /opt/chan 和读写状态目录,别的一概不给。这几条很廉价,
# 但真出了远程代码执行,爆炸半径小很多——而这个进程手里有交易权限的密钥
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/chan-live
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryMax=512M
[Install]
WantedBy=multi-user.target