From 2d4926cee3a420d9a5d5dab0c0eeafe9c44c157e Mon Sep 17 00:00:00 2001 From: dekun Date: Fri, 22 May 2026 10:23:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E6=8E=A7=E5=A2=9E=E5=8A=A0=E4=B8=8B?= =?UTF-8?q?=E5=8D=95=EF=BC=8C=E5=85=B3=E9=94=AE=E4=BD=8D=EF=BC=8C=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manual_trading_hub/README.md | 2 +- .../ecosystem.agents.config.cjs | 45 +++ manual_trading_hub/ecosystem.config.cjs | 40 +++ manual_trading_hub/scripts/pm2_agents.sh | 58 +++ manual_trading_hub/scripts/pm2_hub.sh | 69 ++++ manual_trading_hub/scripts/run_hub.sh | 21 ++ manual_trading_hub/使用说明.md | 13 +- manual_trading_hub/部署文档.md | 339 ++++++++++-------- 8 files changed, 433 insertions(+), 154 deletions(-) create mode 100644 manual_trading_hub/ecosystem.agents.config.cjs create mode 100644 manual_trading_hub/ecosystem.config.cjs create mode 100644 manual_trading_hub/scripts/pm2_agents.sh create mode 100644 manual_trading_hub/scripts/pm2_hub.sh create mode 100644 manual_trading_hub/scripts/run_hub.sh diff --git a/manual_trading_hub/README.md b/manual_trading_hub/README.md index 6c7e5e9..9b0ab21 100644 --- a/manual_trading_hub/README.md +++ b/manual_trading_hub/README.md @@ -200,4 +200,4 @@ python hub.py **5. 局域网里别的电脑打不开中控** 默认应已可访问:中控监听 `0.0.0.0` 且 `HUB_TRUST_LAN` 默认开启。请检查:防火墙是否放行 `HUB_PORT`;浏览器是否使用 **中控机器的局域网 IP**(不要用另一台电脑上的 `127.0.0.1`)。若你曾设置 `HUB_TRUST_LAN=0` 或 `HUB_HOST=127.0.0.1`,改回默认或删掉环境变量后重启 hub。 -更细的安装顺序、验收清单与可选常驻方式见同目录 **《部署文档.md》**。 +**Linux 常驻(PM2)**:在 `manual_trading_hub` 目录执行 `pm2 start ecosystem.config.cjs`(进程名 `manual-trading-hub`),或 `bash scripts/pm2_hub.sh start`。子代理可选 `ecosystem.agents.config.cjs`。详见 **《部署文档.md》** 第五节。 diff --git a/manual_trading_hub/ecosystem.agents.config.cjs b/manual_trading_hub/ecosystem.agents.config.cjs new file mode 100644 index 0000000..44cd30c --- /dev/null +++ b/manual_trading_hub/ecosystem.agents.config.cjs @@ -0,0 +1,45 @@ +/** + * PM2:四路子代理 agent.py(可选,与中控分开管理) + * + * 每个 app 在对应 crypto_monitor_* 目录启动,以加载该目录 .env 中的 API 密钥。 + * Python 解释器使用 manual_trading_hub/.venv(须已 pip install -r requirements.txt)。 + * + * 启动: + * pm2 start ecosystem.agents.config.cjs + * + * 仅启动部分账户可编辑下方 apps 数组,或: + * pm2 start ecosystem.agents.config.cjs --only manual-agent-binance + */ +const path = require("path"); + +const HUB_DIR = __dirname; +const REPO_ROOT = path.join(HUB_DIR, ".."); +const PY = path.join(HUB_DIR, ".venv", "bin", "python"); +const AGENT = path.join(HUB_DIR, "agent.py"); + +function agentApp(name, exchangeDir, exchange, port) { + return { + name, + cwd: path.join(REPO_ROOT, exchangeDir), + script: AGENT, + interpreter: PY, + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: "400M", + env: { + EXCHANGE: exchange, + PORT: String(port), + HOST: "127.0.0.1", + }, + }; +} + +module.exports = { + apps: [ + agentApp("manual-agent-binance", "crypto_monitor_binance", "binance", 15200), + agentApp("manual-agent-okx", "crypto_monitor_okx", "okx", 15201), + agentApp("manual-agent-gate", "crypto_monitor_gate", "gate", 15202), + agentApp("manual-agent-gate-bot", "crypto_monitor_gate_bot", "gate", 15203), + ], +}; diff --git a/manual_trading_hub/ecosystem.config.cjs b/manual_trading_hub/ecosystem.config.cjs new file mode 100644 index 0000000..6f627de --- /dev/null +++ b/manual_trading_hub/ecosystem.config.cjs @@ -0,0 +1,40 @@ +/** + * PM2:多账户交易中控 hub.py(Ubuntu / Linux) + * + * 前置: + * cd manual_trading_hub + * cp .env.example .env # 按需修改 HUB_PORT、HUB_BRIDGE_TOKEN 等 + * python3 -m venv .venv && .venv/bin/pip install -r requirements.txt + * + * 启动: + * pm2 start ecosystem.config.cjs + * pm2 save && pm2 startup + * + * 常用: + * pm2 logs manual-trading-hub + * pm2 restart manual-trading-hub + * + * 子代理(agent)见 ecosystem.agents.config.cjs 或 scripts/后台运行-Ubuntu.md + */ +const path = require("path"); + +const HUB_DIR = __dirname; +const RUN_SH = path.join(HUB_DIR, "scripts", "run_hub.sh"); + +module.exports = { + apps: [ + { + name: "manual-trading-hub", + cwd: HUB_DIR, + script: RUN_SH, + interpreter: "bash", + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: "512M", + // 环境变量优先写在 manual_trading_hub/.env(由 run_hub.sh 加载) + // 也可在此覆盖,例如: + // env: { HUB_PORT: "5100", HUB_DISABLED_IDS: "1" }, + }, + ], +}; diff --git a/manual_trading_hub/scripts/pm2_agents.sh b/manual_trading_hub/scripts/pm2_agents.sh new file mode 100644 index 0000000..8368cbb --- /dev/null +++ b/manual_trading_hub/scripts/pm2_agents.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# 子代理 PM2 快捷脚本 +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HUB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +ECO="${HUB_DIR}/ecosystem.agents.config.cjs" + +usage() { + cat <<'EOF' +用法: bash scripts/pm2_agents.sh + + start 启动 ecosystem.agents.config.cjs 中全部子代理 + stop 停止全部 manual-agent-* + restart 重启全部 + status pm2 status + logs 全部子代理日志 + delete 从 PM2 移除 + +仅启动币安: pm2 start ecosystem.agents.config.cjs --only manual-agent-binance +EOF +} + +cmd="${1:-}" + +if ! command -v pm2 >/dev/null 2>&1; then + echo "未找到 pm2,请先: npm install -g pm2" >&2 + exit 1 +fi + +cd "${HUB_DIR}" + +case "${cmd}" in + start) + pm2 start "${ECO}" + pm2 save 2>/dev/null || true + ;; + stop) + pm2 stop manual-agent-binance manual-agent-okx manual-agent-gate manual-agent-gate-bot 2>/dev/null || true + ;; + restart) + pm2 restart manual-agent-binance manual-agent-okx manual-agent-gate manual-agent-gate-bot 2>/dev/null \ + || pm2 start "${ECO}" + ;; + status) + pm2 status + ;; + logs) + pm2 logs manual-agent-binance manual-agent-okx manual-agent-gate manual-agent-gate-bot --lines 100 + ;; + delete) + pm2 delete manual-agent-binance manual-agent-okx manual-agent-gate manual-agent-gate-bot 2>/dev/null || true + ;; + *) + usage + exit 1 + ;; +esac diff --git a/manual_trading_hub/scripts/pm2_hub.sh b/manual_trading_hub/scripts/pm2_hub.sh new file mode 100644 index 0000000..ece0e1c --- /dev/null +++ b/manual_trading_hub/scripts/pm2_hub.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# 中控 PM2 快捷脚本(在 manual_trading_hub 目录或任意路径执行均可) +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HUB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +ECO="${HUB_DIR}/ecosystem.config.cjs" + +usage() { + cat <<'EOF' +用法: bash scripts/pm2_hub.sh + + start 启动 manual-trading-hub(已存在则 pm2 restart) + stop 停止 + restart 重启 + status pm2 status + logs 跟踪日志(Ctrl+C 退出) + delete 从 PM2 列表移除 + +前置: npm i -g pm2;manual_trading_hub 下已建 .venv 并 pip install +可选: cp .env.example .env +EOF +} + +cmd="${1:-}" + +if ! command -v pm2 >/dev/null 2>&1; then + echo "未找到 pm2,请先: npm install -g pm2" >&2 + exit 1 +fi + +if [[ ! -f "${ECO}" ]]; then + echo "未找到 ${ECO}" >&2 + exit 1 +fi + +cd "${HUB_DIR}" + +case "${cmd}" in + start) + if pm2 describe manual-trading-hub >/dev/null 2>&1; then + pm2 restart manual-trading-hub + echo "已重启 manual-trading-hub" + else + pm2 start "${ECO}" + echo "已启动 manual-trading-hub" + fi + pm2 save 2>/dev/null || true + ;; + stop) + pm2 stop manual-trading-hub 2>/dev/null || echo "进程未在运行" + ;; + restart) + pm2 restart manual-trading-hub 2>/dev/null || pm2 start "${ECO}" + ;; + status) + pm2 status + ;; + logs) + pm2 logs manual-trading-hub --lines 200 + ;; + delete) + pm2 delete manual-trading-hub 2>/dev/null || echo "进程不存在" + ;; + *) + usage + exit 1 + ;; +esac diff --git a/manual_trading_hub/scripts/run_hub.sh b/manual_trading_hub/scripts/run_hub.sh new file mode 100644 index 0000000..5a25cc3 --- /dev/null +++ b/manual_trading_hub/scripts/run_hub.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# PM2 / 手动启动入口:加载 manual_trading_hub/.env 后运行 hub.py +set -euo pipefail + +HUB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "${HUB_DIR}" + +VENV_PY="${HUB_DIR}/.venv/bin/python" +if [[ ! -x "${VENV_PY}" ]]; then + echo "未找到 ${VENV_PY},请先: python3 -m venv .venv && pip install -r requirements.txt" >&2 + exit 1 +fi + +set -a +if [[ -f "${HUB_DIR}/.env" ]]; then + # shellcheck disable=SC1091 + . "${HUB_DIR}/.env" +fi +set +a + +exec "${VENV_PY}" "${HUB_DIR}/hub.py" diff --git a/manual_trading_hub/使用说明.md b/manual_trading_hub/使用说明.md index 8230290..f694ac6 100644 --- a/manual_trading_hub/使用说明.md +++ b/manual_trading_hub/使用说明.md @@ -322,7 +322,18 @@ Invoke-WebRequest -Uri "http://127.0.0.1:5001/api/hub/ping" -Headers @{"X-Hub-To 子代理 `agent.py` 仍负责持仓与全平;`HUB_AGENTS` 环境变量在新版 hub 中 **不再使用**(以设置文件为准)。 -更细的 Ubuntu screen / systemd 示例见同目录 **《部署文档.md》** 与 **scripts/**。 +**PM2 守护(推荐 Linux)**: + +```bash +cd manual_trading_hub +cp .env.example .env +pm2 start ecosystem.config.cjs # 进程名 manual-trading-hub +pm2 save && pm2 startup +``` + +子代理可选:`pm2 start ecosystem.agents.config.cjs`。快捷命令:`bash scripts/pm2_hub.sh start|restart|logs`。 + +更细的安装顺序、反代、验收见 **《部署文档.md》**;screen / systemd 见 **scripts/**。 --- diff --git a/manual_trading_hub/部署文档.md b/manual_trading_hub/部署文档.md index fa7757a..12a4cf5 100644 --- a/manual_trading_hub/部署文档.md +++ b/manual_trading_hub/部署文档.md @@ -1,220 +1,255 @@ -# 手工交易中控 — 部署文档 +# 多账户交易中控 — 部署文档(含 PM2) -本文档描述在本机(以 Windows 为主)将 **manual_trading_hub** 部署为「多账户监控 + 紧急全平」的推荐步骤、验收方法与注意事项。功能说明与配置项详见同目录 **《README.md》**。 +本文档说明在 **Ubuntu / Linux** 上部署 **manual_trading_hub**(监控区、下单区、系统设置)的推荐步骤。功能与界面操作见 **《使用说明.md》**;环境变量说明见 **`.env.example`** 与各 `crypto_monitor_*` 的 `.env.example`。 --- ## 一、部署目标 -- 本机或局域网可访问 **中控页面**(默认监听 `0.0.0.0:5100`,私网 IP 可打开;本机可用 `127.0.0.1`)。 -- 每个需要纳入监控的交易所账户,有独立的 **子代理** 进程(默认端口 **`15200`~`15203`**,与各 `crypto_monitor_*` 里 Flask 的 **`APP_PORT`** 错开)。 -- 策略项目 `crypto_monitor_binance` / `crypto_monitor_okx` / `crypto_monitor_gate` / `crypto_monitor_gate_bot` **无需修改代码**,与中控并行运行。 +| 组件 | 作用 | 默认监听 | +|------|------|----------| +| **hub.py** | 中控 Web + API | `0.0.0.0:5100` | +| **agent.py × N** | 各账户持仓 / 紧急全平 | `127.0.0.1:15200`~`15203` | +| **crypto_monitor_*.app** | 策略、关键位、下单逻辑 | 各目录 `.env` 的 `APP_PORT` | + +- 账户列表与 URL 由 **`hub_settings.json`**(网页「系统设置」保存)或内置默认维护;**不再使用** `HUB_AGENTS`。 +- 四实例 Flask **无需为中控改业务代码**(已注册 `hub_bridge`);与中控并行运行。 --- ## 二、前置条件 -1. 已安装 **Python 3.10+**,且 `pip` 可用。 -2. 各策略目录下已配置好交易所 API:在对应 `crypto_monitor_*` 目录执行过 **`cp .env.example .env`** 并填好密钥(与平时运行 Flask 时同一份 **`.env`**,或等价环境变量)。各项目 `app.py` 会读取同目录 `.env` 中的 **`APP_HOST` / `APP_PORT`** 用于 **Flask**;子代理使用环境变量 **`PORT`**,二者不能占用同一端口。策略目录的 **`.env` 不在 Git 中**,`git pull` 不会覆盖;升级前建议在各策略目录 `cp .env .env.backup.$(date +%Y%m%d)`。 -3. 本机端口 **`15200`~`15203`、5100**(及你各策略 `.env` 里的 `APP_PORT`)无冲突;若被占用,须改子代理 `PORT` 并同步修改 `HUB_AGENTS`。 -4. **Linux 路径约定(可选)**:若部署在 Ubuntu 等环境,建议将整个代码树放在 **`/opt/crypto_monitor/`** 下(与 `scripts/后台运行-Ubuntu.md` 示例一致),例如策略目录为 `/opt/crypto_monitor/crypto_monitor_binance`、中控为 `/opt/crypto_monitor/manual_trading_hub`。 +1. **Python 3.10+**、`python3-venv`、`pip`。 +2. **Node.js + npm**(用于安装 PM2):`sudo npm i -g pm2`。 +3. 各 `crypto_monitor_*` 目录已 **`cp .env.example .env`** 并填好 API 密钥。 +4. 端口无冲突:`5100`、`15200`~`15203`、各实例 `APP_PORT`(5000/5001/5002/5004)。 +5. 建议代码路径:`/opt/crypto_monitor/`(下文用此示例,请按实际路径替换)。 --- -## 三、目录与文件 - -``` -manual_trading_hub/ - agent.py # 子代理(单账户) - hub.py # 中控 - requirements.txt # Python 依赖 - static/ - index.html # 中控前端页面 - README.md # 说明文档 - 部署文档.md # 本文档 -``` - ---- - -## 四、安装依赖 - -在 `manual_trading_hub` 目录执行: - -```powershell -cd manual_trading_hub -python -m venv .venv -.\.venv\Scripts\Activate.ps1 -pip install -r requirements.txt -``` - -Linux / macOS: +## 三、安装中控依赖 ```bash -cd manual_trading_hub +cd /opt/crypto_monitor/manual_trading_hub python3 -m venv .venv -source .venv/bin/activate -pip install -r requirements.txt +.venv/bin/pip install -r requirements.txt +cp .env.example .env +# 编辑 .env:HUB_PORT、HUB_DISABLED_IDS、公网时 HUB_BRIDGE_TOKEN 等 +chmod +x scripts/run_hub.sh scripts/pm2_hub.sh scripts/pm2_agents.sh ``` -后续启动 `hub.py` / `agent.py` 时,请使用**同一虚拟环境**中的 `python`,保证已安装 `fastapi`、`uvicorn`、`httpx`、`ccxt`;若各策略 `.env` 中配置了 **SOCKS 代理**(`GATE_SOCKS_PROXY` / `BINANCE_SOCKS_PROXY` / `OKX_SOCKS_PROXY` 等),还需 **`PySocks`**(已写入 `requirements.txt`,新环境 `pip install -r requirements.txt` 即可)。 +子代理也使用 **本目录 `.venv`** 里的 Python(与各策略 Flask 的 venv 可分开)。 --- -## 五、部署步骤(推荐顺序) +## 四、推荐启动顺序 -### 步骤 1:确认策略进程(可选) - -若你平时已运行各目录下的 Flask(`app.py`),可保持运行;中控与子代理**不依赖** Flask 是否启动。 - -### 步骤 2:为每个账户启动子代理 - -**每个账户一个终端窗口**,在对应策略项目目录进入后加载环境变量,再启动 agent(路径按你仓库实际位置调整)。 - -示例:**Binance 账户 → 子代理端口 15200**(Flask 的 `APP_PORT` 可为 5000、5001 等,由该目录 `.env` 决定,二者不同即可) - -```powershell -cd D:\你的路径\交易复盘系统\crypto_monitor_binance -.\.venv\Scripts\Activate.ps1 # 若策略项目使用独立 venv,可在此激活 -# 确保已加载 .env(若你用 dotenv-cli 等工具,在此执行) -$env:EXCHANGE="binance" -$env:PORT="15200" -$env:HOST="127.0.0.1" -python ..\manual_trading_hub\agent.py +``` +1. 子代理 agent(15200~15203) ← PM2 或 screen +2. 各实例 Flask(APP_PORT) ← 各目录 ecosystem.config.cjs +3. 中控 hub(5100) ← 本目录 ecosystem.config.cjs ``` -**OKX → 子代理 `PORT=15201`**、`EXCHANGE=okx`;**Gate → 15202**、**Gate-Bot → 15203**,`EXCHANGE=gate`。 - -**可选安全**:各 agent 与中控制台设置相同随机串: - -```powershell -$env:CONTROL_TOKEN="你的长随机串" -``` - -子代理与中控均需设置同一 `CONTROL_TOKEN`。 - -### 步骤 3:启动中控 - -新开终端: - -```powershell -cd D:\你的路径\交易复盘系统\manual_trading_hub -.\.venv\Scripts\Activate.ps1 -$env:HUB_HOST="0.0.0.0" -$env:HUB_PORT="5100" -# 若暂不使用 OKX,可在服务端固定关闭 id=1: -# $env:HUB_DISABLED_IDS="1" -python hub.py -``` - -控制台无报错即表示监听成功(日志级别为 `warning`,默认不刷屏)。 - -### 步骤 4:浏览器验收 - -1. 打开 **http://127.0.0.1:5100/** 或 **http://本机局域网IP:5100/** 。 -2. 应看到与 `HUB_AGENTS` 配置一致的账户卡片;已启动子代理的行应能显示余额或持仓(无持仓则显示「无持仓」)。 -3. 点击 **立即刷新**,数据应更新。 -4. 取消某一行的 **「参与监控」**,该行应变灰且不再刷新数据;再勾选应恢复。 - -**不建议**在生产环境对实盘轻易点击「全平」做测试;若必须测试,请使用测试网或小资金账户。 +仅反代中控到公网时:Flask / agent 仍只监听 **127.0.0.1**;系统设置里 URL 填 `http://127.0.0.1:端口`。 --- -## 六、接口验收(可选) +## 五、PM2 托管中控(推荐) -在已启动 hub 的本机 PowerShell: +### 5.1 进程名与文件 -```powershell -Invoke-RestMethod "http://127.0.0.1:5100/api/agents" -Invoke-RestMethod "http://127.0.0.1:5100/api/snapshot" +| 文件 | PM2 进程名 | 说明 | +|------|------------|------| +| `ecosystem.config.cjs` | `manual-trading-hub` | 仅中控 | +| `ecosystem.agents.config.cjs` | `manual-agent-binance` 等 4 个 | 可选,子代理 | + +`run_hub.sh` 会加载 **`manual_trading_hub/.env`** 再执行 `hub.py`。 + +### 5.2 启动中控 + +```bash +cd /opt/crypto_monitor/manual_trading_hub + +# 方式 A:直接 PM2 +pm2 start ecosystem.config.cjs +pm2 save + +# 方式 B:快捷脚本 +bash scripts/pm2_hub.sh start ``` -子代理单测(需 agent 已启动): +### 5.3 常用运维命令 -```powershell -Invoke-RestMethod "http://127.0.0.1:15200/health" -Invoke-RestMethod "http://127.0.0.1:15200/status" +```bash +pm2 status +pm2 logs manual-trading-hub --lines 200 +pm2 restart manual-trading-hub +pm2 stop manual-trading-hub + +# 或 +bash scripts/pm2_hub.sh status +bash scripts/pm2_hub.sh logs +bash scripts/pm2_hub.sh restart ``` -若启用了 `CONTROL_TOKEN`,需加请求头(PowerShell 示例): +### 5.4 开机自启 -```powershell -$h = @{ "X-Control-Token" = "你的长随机串" } -Invoke-RestMethod "http://127.0.0.1:15200/status" -Headers $h +```bash +pm2 save +pm2 startup +# 按终端提示执行一行 sudo 命令后,再 pm2 save +``` + +### 5.5 可选:PM2 托管四路子代理 + +```bash +cd /opt/crypto_monitor/manual_trading_hub +pm2 start ecosystem.agents.config.cjs +# 仅币安: +# pm2 start ecosystem.agents.config.cjs --only manual-agent-binance + +bash scripts/pm2_agents.sh start # 等价启动全部 +pm2 save +``` + +| 进程名 | 工作目录 | PORT | +|--------|----------|------| +| manual-agent-binance | crypto_monitor_binance | 15200 | +| manual-agent-okx | crypto_monitor_okx | 15201 | +| manual-agent-gate | crypto_monitor_gate | 15202 | +| manual-agent-gate-bot | crypto_monitor_gate_bot | 15203 | + +OKX 默认被 `HUB_DISABLED_IDS=1` 关闭监控,但子代理仍可启动备用。 + +### 5.6 与各实例 Flask 一起查看 + +```bash +pm2 status +# 示例同时存在: +# manual-trading-hub +# manual-agent-binance +# crypto_binance (各目录自有 ecosystem.config.cjs) ``` --- -## 七、自定义端口与账户数量 +## 六、手动启动(不用 PM2 时) -仅部署 3 个账户时,可只启动 3 个 agent,并设置: +### 6.1 子代理(每账户一个终端或 screen) -```powershell -$env:HUB_AGENTS="http://127.0.0.1:15200,http://127.0.0.1:15202,http://127.0.0.1:15203" -$env:HUB_AGENT_NAMES="Binance,Gate,Gate-Bot" +```bash +cd /opt/crypto_monitor/crypto_monitor_binance +export EXCHANGE=binance PORT=15200 HOST=127.0.0.1 +/opt/crypto_monitor/manual_trading_hub/.venv/bin/python \ + /opt/crypto_monitor/manual_trading_hub/agent.py ``` -`HUB_AGENT_NAMES` 与 URL **数量、顺序**一一对应。 +其余端口见上表;也可用 `scripts/start_agents_3screen.sh`(不含 OKX)。 + +### 6.2 中控 + +```bash +cd /opt/crypto_monitor/manual_trading_hub +bash scripts/run_hub.sh +# 或 +bash scripts/start_hub_screen.sh # screen 会话 mt-hub +``` --- -## 八、常驻运行(可选) +## 七、浏览器验收 -**不必一直开着终端。** Ubuntu 下可用 **tmux 脱离**、**nohup &**、或 **systemd**(推荐:崩溃自启、可开机启动)。 +1. 打开 **http://127.0.0.1:5100/monitor**(局域网用本机私网 IP)。 +2. 已启用账户应显示持仓;Flask 已起时有关键位/趋势信息。 +3. **http://127.0.0.1:5100/settings** 保存后生成 `hub_settings.json`。 +4. **http://127.0.0.1:5100/trade** 选账户测试下单(实盘慎用)。 -详细命令、**常见问题(screen / PySocks / 重启)**与 **systemd 单元示例**见: +接口探测: -- `manual_trading_hub/scripts/后台运行-Ubuntu.md` -- `manual_trading_hub/scripts/example-systemd/*.service.example`(改路径后复制到 `/etc/systemd/system/`) - -Windows 可将 `hub.py` 与各 `agent.py` 写入「启动」文件夹,或使用 **NSSM** / **任务计划程序** 在登录后启动;注意工作目录与环境变量要在任务里写全。 +```bash +curl -s http://127.0.0.1:5100/api/settings | head +curl -s http://127.0.0.1:15200/health +``` --- -## 九、升级与回滚 +## 八、仅反代中控到公网(实例不反代) -- **升级**:在仓库根目录 `git pull` 后,于 `manual_trading_hub` 重新 `pip install -r requirements.txt`(若依赖有变)。**各策略目录 `.env` 不会被 pull 覆盖**;若 `.env.example` 有新增变量,请对照模板**手动补进**你的 `.env`。 -- **升级前备份(推荐)**:在每个用到的 `crypto_monitor_*` 目录执行 `cp .env .env.backup.$(date +%Y%m%d)`。 -- **回滚**:恢复上一版本代码与依赖;配置在各策略 `.env` 与浏览器 localStorage,无中控数据库。 +1. Nginx/Caddy 反代到 **`127.0.0.1:5100`**,配置 HTTPS。 +2. `hub_settings.json` 中 Flask/Agent 保持 **`http://127.0.0.1:...`**。 +3. 四实例 **`APP_AUTH_DISABLED=false`** + 与中控相同 **`HUB_BRIDGE_TOKEN`**(见 `.env.example` 注释)。 +4. 子代理 **`HOST=127.0.0.1`**,防火墙勿放行 `15200`~`15203`、各 `APP_PORT`。 +5. 监控页「复盘」链到本机 Flask,公网浏览器通常打不开,需 VPN/内网访问实例。 --- -## 十、故障排查 +## 九、环境变量(中控 `.env`) -### 10.1 现象速查表 +| 变量 | 默认 | 说明 | +|------|------|------| +| `HUB_HOST` | `0.0.0.0` | 监听地址 | +| `HUB_PORT` | `5100` | 端口 | +| `HUB_DISABLED_IDS` | `1` | 强制关闭的账户 id(OKX) | +| `HUB_TRUST_LAN` | `true` | 私网可访问;仅本机可 `false` | +| `HUB_BRIDGE_TOKEN` | 空 | 公网/开登录时建议配置 | -| 现象 | 可能原因 | 处理 | -|------|----------|------| -| 页面打不开 | 中控未启动或端口错 | 检查 `HUB_PORT`、防火墙、是否用 127.0.0.1 访问 | -| 某账户一直报错 | 子代理未启动或端口不一致 | 核对 `HUB_AGENTS` 与该 agent 的 `PORT` | -| 中控 JSON 报错 / `Expecting value` | 子代理未启动、返回非 JSON、或端口错 | 本机 `curl http://127.0.0.1:1520x/status`;确认 agent 已起且端口与 `HUB_AGENTS` 一致 | -| 401 / 连不上子代理 | `CONTROL_TOKEN` 不一致 | 中控与子代理设为同一令牌,或全部去掉令牌 | -| 有密钥仍报缺密钥 | 启动 agent 时未加载策略目录的 `.env` | 在对应目录启动,或手动 export 全部密钥变量 | -| `/status` 里 `ok:false`,文案含 **pysocks** / **SOCKS** | 使用 SOCKS 代理但未装 **PySocks** | 在 **`manual_trading_hub/.venv`** 执行 `pip install PySocks` 或 `pip install -r requirements.txt` | -| **已安装 PySocks**,`/status` 仍报同样 pysocks 文案 | 子代理进程未重启 | 子代理是常驻进程,**仅 pip 不会替换已运行进程**;退出对应 screen / systemd 单元后重新拉起(Ubuntu 见 `scripts/后台运行-Ubuntu.md` §四) | -| 跑 `start_agents_3screen.sh` 无新会话 | screen 会话已存在被脚本跳过 | 先 `stop_agents_3screen.sh`,或 `screen -S mt-agent-xxx -X quit` 后再启动 | -| 子代理行为异常、依赖已装仍报错 | 实际用的不是 hub 的 venv | `ps aux` 查看命令行,应为 **`/opt/crypto_monitor/manual_trading_hub/.venv/bin/python`** `…/manual_trading_hub/agent.py`(路径按你机器实际根目录调整);否则在**当前使用的解释器**对应环境中装依赖,或改用官方脚本启动 | -| 子代理端口与 Flask 抢端口 | `PORT` 与策略目录 `.env` 的 `APP_PORT` 相同 | 子代理用 **15200~15203**(或自改),Flask 继续用 `APP_PORT`,二者勿重复 | -| 全平失败 | 持仓模式、精度、交易所维护 | 看返回 JSON 中 `errors` 字段;对照交易所 App | - -### 10.2 依赖或代码更新后 - -- **`pip install -r requirements.txt` 或单独 `pip install` 之后**:须**重启**受影响的 **hub**、**各子代理** 进程,变更才会生效。 -- **拉取新版本代码后**:同样重启进程;若曾遇 `'function' object has no attribute load_markets'` 等旧版 agent 异常,升级后重启子代理即可。 +本地联调、实例 `APP_AUTH_DISABLED=true` 时可不配 `HUB_BRIDGE_TOKEN`。 --- -## 十一、安全清单(部署前自检) +## 十、升级与回滚 -- [ ] 若机器暴露在公网,已用防火墙限制 `HUB_PORT` 或已改为 `HUB_HOST=127.0.0.1` / `HUB_TRUST_LAN=0` 仅本机。 -- [ ] API Key 权限最小化;生产环境建议启用 IP 白名单。 -- [ ] `CONTROL_TOKEN` 已设为足够长的随机串(若启用)。 -- [ ] 已告知实际操作人员:**全局全平**不可撤销。 +```bash +cd /opt/crypto_monitor +git pull +cd manual_trading_hub +.venv/bin/pip install -r requirements.txt +pm2 restart manual-trading-hub +# 若改了 agent 依赖: +pm2 restart manual-agent-binance manual-agent-okx manual-agent-gate manual-agent-gate-bot +``` + +- **`hub_settings.json`**、**`.env`** 不在 Git 中,`git pull` 不会覆盖。 +- 升级前可备份:`cp hub_settings.json hub_settings.json.bak`。 --- -## 十二、与说明文档的关系 +## 十一、故障排查 -- **《README.md》**:产品能力、架构、环境变量表、API 简表、常见问题。 -- **《部署文档.md》**:按步骤安装、启动、验收与运维注意(本文)。 +| 现象 | 处理 | +|------|------| +| PM2 启动后立刻退出 | `pm2 logs manual-trading-hub`;检查 `.venv`、`.env`、`run_hub.sh` 可执行 | +| 监控无持仓 | 子代理未起或 Agent URL 错;`curl http://127.0.0.1:15200/status` | +| 无关键位/下单 401 | Flask 未起或 `HUB_BRIDGE_TOKEN` 不一致;或设 `APP_AUTH_DISABLED=true` | +| 子代理 SOCKS 报错 | 在 **manual_trading_hub/.venv** 安装 `PySocks` 后 **pm2 restart** 子代理 | +| 公网访问中控 403 | 反代未指向本机、或客户端非私网且 `HUB_TRUST_LAN=true`;反代改 `127.0.0.1:5100` 或在反代层鉴权 | +| 改 `.env` 不生效 | PM2 需 `pm2 restart manual-trading-hub`(`run_hub.sh` 每次启动会重读 `.env`) | -两处如有端口/变量不一致,以**当前代码**与 **README 中的表格**为准。 +--- + +## 十二、其它常驻方式 + +- **screen**:`scripts/start_hub_screen.sh` / `stop_hub_screen.sh` +- **systemd**:`scripts/example-systemd/manual-hub.service.example`(复制并改路径) + +与 PM2 **二选一** 即可,避免同一端口启动两份 hub。 + +--- + +## 十三、安全清单 + +- [ ] 公网仅暴露反代端口,不暴露 Flask/agent 端口 +- [ ] 公网已配置 `HUB_BRIDGE_TOKEN` + 实例关闭 `APP_AUTH_DISABLED` +- [ ] API Key 最小权限;交易所 IP 白名单 +- [ ] 已告知操作人员「全局全平」不可撤销 + +--- + +## 十四、文档索引 + +| 文档 | 内容 | +|------|------| +| **使用说明.md** | 三页功能、能力矩阵、鉴权说明 | +| **README.md** | 架构速览 | +| **.env.example** | 中控环境变量模板 | +| **scripts/后台运行-Ubuntu.md** | screen / systemd 补充 |