生产与研究分家:实盘执行器独立成 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:
Executable
+134
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env bash
|
||||
# 在生产机(有 Bitget API key 白名单的那台)上装实盘执行器。
|
||||
#
|
||||
# 只装执行侧:标准库 + aiohttp。**不装** Docker / Hummingbot / pandas /
|
||||
# chanlun 引擎——那些是采集与研究侧的依赖,理由见 live/live_exec.py 文件头。
|
||||
#
|
||||
# sudo ./install.sh # 从当前 checkout 安装
|
||||
# sudo REPO=git@host:jack/chan.git ./install.sh # 或指定远程克隆
|
||||
#
|
||||
# 幂等:重复跑只会更新代码与依赖,不动 /etc/chan-live/live.env 和状态目录。
|
||||
set -euo pipefail
|
||||
|
||||
APP=/opt/chan
|
||||
STATE=/var/lib/chan-live
|
||||
CONF=/etc/chan-live
|
||||
USER_NAME=chan
|
||||
BRANCH="${BRANCH:-chan}"
|
||||
REPO="${REPO:-}"
|
||||
|
||||
die() { echo "⛔ $*" >&2; exit 1; }
|
||||
say() { echo " $*"; }
|
||||
|
||||
[[ $EUID -eq 0 ]] || die "要 root:sudo $0"
|
||||
|
||||
# ── 1. 系统依赖 ────────────────────────────────────────────────────
|
||||
say "装系统包"
|
||||
if command -v apt-get >/dev/null; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
# chrony 不是可选项:staleness 闸靠两机时钟一致才有意义,
|
||||
# 采集机时钟快 5 分钟就等于把闸放宽 5 分钟(见 ship_signals.py)
|
||||
apt-get install -y -qq python3-venv python3-pip git chrony openssh-client
|
||||
elif command -v dnf >/dev/null; then
|
||||
dnf install -y -q python3 python3-pip git chrony openssh-clients
|
||||
else
|
||||
die "只认 apt/dnf,其他发行版请手工装 python3-venv git chrony"
|
||||
fi
|
||||
systemctl enable --now chrony 2>/dev/null || systemctl enable --now chronyd
|
||||
|
||||
# ── 2. 专用用户与目录 ──────────────────────────────────────────────
|
||||
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
|
||||
say "建系统用户 $USER_NAME(无登录 shell)"
|
||||
useradd --system --home-dir "$STATE/home" --create-home \
|
||||
--shell /usr/sbin/nologin "$USER_NAME"
|
||||
fi
|
||||
install -d -o "$USER_NAME" -g "$USER_NAME" -m 750 "$STATE" "$STATE/state" "$STATE/home"
|
||||
install -d -o "$USER_NAME" -g "$USER_NAME" -m 700 "$STATE/home/.ssh"
|
||||
install -d -o root -g "$USER_NAME" -m 750 "$CONF"
|
||||
|
||||
# ── 3. 代码 ────────────────────────────────────────────────────────
|
||||
if [[ -n "$REPO" ]]; then
|
||||
if [[ -d "$APP/.git" ]]; then
|
||||
say "更新已有 checkout"
|
||||
git -C "$APP" fetch --quiet origin "$BRANCH"
|
||||
git -C "$APP" checkout --quiet "$BRANCH"
|
||||
git -C "$APP" reset --hard --quiet "origin/$BRANCH"
|
||||
else
|
||||
say "克隆 $REPO"
|
||||
rm -rf "$APP"; git clone --quiet --branch "$BRANCH" "$REPO" "$APP"
|
||||
fi
|
||||
else
|
||||
SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
[[ -f "$SRC/live/live_exec.py" ]] || die "$SRC 不像仓库根(缺 live/live_exec.py)"
|
||||
if [[ "$SRC" != "$APP" ]]; then
|
||||
say "从 $SRC 同步代码到 $APP"
|
||||
install -d "$APP"
|
||||
# 只同步生产要的那一个子树。研究侧的 research/ 不上生产机:
|
||||
# 它带 pandas/pyarrow/hummingbot,而且探针 OOM 过一次(14.9GB)
|
||||
cp -a "$SRC/live" "$APP/"
|
||||
fi
|
||||
fi
|
||||
chown -R root:root "$APP/live"
|
||||
find "$APP/live" -type f -exec chmod 644 {} + ; chmod 755 "$APP/live" "$APP/live/deploy"
|
||||
chmod 755 "$APP"/live/deploy/*.sh
|
||||
|
||||
# ── 4. venv ───────────────────────────────────────────────────────
|
||||
say "建 venv 并装依赖(应当只有 aiohttp)"
|
||||
[[ -d "$APP/.venv" ]] || python3 -m venv "$APP/.venv"
|
||||
"$APP/.venv/bin/pip" install --quiet --upgrade pip
|
||||
"$APP/.venv/bin/pip" install --quiet -r "$APP/live/requirements.txt"
|
||||
|
||||
# 断言生产进程没被拖进重量级依赖。这条会真挡住——曾经为读两个常量
|
||||
# import 研究侧的 step43,把 numpy/pandas/pyarrow 全拉进实盘进程
|
||||
say "验依赖面"
|
||||
"$APP/.venv/bin/python" - <<'PY' || die "生产进程拖进了重量级依赖,看上面输出"
|
||||
import sys
|
||||
sys.path.insert(0, "/opt/chan/live")
|
||||
import live_exec
|
||||
live_exec.assert_decomposable()
|
||||
heavy = [m for m in ("numpy", "pandas", "pyarrow", "hummingbot", "scipy")
|
||||
if m in sys.modules]
|
||||
if heavy:
|
||||
print(f" ⛔ 启动路径加载了 {heavy}")
|
||||
raise SystemExit(1)
|
||||
print(f" ✓ 只有标准库 + aiohttp · 出场结构 "
|
||||
f"{live_exec.SL_ATR}/{live_exec.SCALE_ATR}/{live_exec.RUNNER_ATR} ATR "
|
||||
f"/{live_exec.MAXB} 根")
|
||||
PY
|
||||
|
||||
# ── 5. 配置模板 ────────────────────────────────────────────────────
|
||||
if [[ ! -f "$CONF/live.env" ]]; then
|
||||
say "写配置模板 $CONF/live.env(密钥要你手工填)"
|
||||
install -o root -g "$USER_NAME" -m 640 \
|
||||
"$APP/live/deploy/live.env.example" "$CONF/live.env"
|
||||
NEED_FILL=1
|
||||
else
|
||||
say "$CONF/live.env 已存在,不动"
|
||||
fi
|
||||
|
||||
# ── 6. systemd ────────────────────────────────────────────────────
|
||||
say "装 systemd 单元"
|
||||
install -m 644 "$APP"/live/deploy/chan-live-*.service /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
|
||||
echo
|
||||
echo "装好了。接下来按顺序做(**不要**跳过空跑那步):"
|
||||
echo
|
||||
if [[ -n "${NEED_FILL:-}" ]]; then
|
||||
echo " 1. 填密钥与参数:sudo vi $CONF/live.env"
|
||||
echo " BITGET_API_KEY / SECRET / PASSPHRASE 用只读+交易权限,"
|
||||
echo " **不要开提币权限**。SHIP_FROM 填采集机的 ssh 目标。"
|
||||
echo
|
||||
fi
|
||||
echo " 2. 装拉总线用的 ssh key,并确认能连上采集机:"
|
||||
echo " sudo -u $USER_NAME ssh-keygen -t ed25519 -N '' -f $STATE/home/.ssh/id_ed25519"
|
||||
echo " # 把 $STATE/home/.ssh/id_ed25519.pub 加到采集机的 authorized_keys"
|
||||
echo " sudo -u $USER_NAME ssh -o BatchMode=yes <采集机> 'echo ok'"
|
||||
echo
|
||||
echo " 3. 空跑验全链(不下真单,跑够看到一次心跳再停):"
|
||||
echo " sudo $APP/live/deploy/dryrun.sh"
|
||||
echo
|
||||
echo " 4. 真跑:"
|
||||
echo " sudo systemctl enable --now chan-live-ship chan-live-exec"
|
||||
echo " $APP/live/deploy/status.sh"
|
||||
Reference in New Issue
Block a user