手工交易多账户中控(manual_trading_hub)
完整操作说明见 使用说明.md(监控区 / 下单区 / 系统设置、鉴权、四所能力与故障排查)。
本目录提供多账户 监控 + 下单转发 + 紧急全平。各 crypto_monitor_* 仅需注册 hub_bridge(见使用说明);策略与复盘仍在各实例网页。
功能概览
| 能力 | 说明 |
|---|---|
| 监控 | 汇总各子代理的永续持仓、未实现盈亏、余额(USDT)、持仓模式等 |
| 单账户全平 | 对某一子代理发起市价减仓,尽量平掉该所 USDT 永续仓位 |
| 全局全平 | 对当前「已开启监控」的子代理依次发起全平 |
| 关闭某账户 | 网页上取消「参与监控」,或环境变量 HUB_DISABLED_IDS;被关闭的不轮询、不参与全局全平 |
架构说明
浏览器 → 中控 hub.py(默认监听 0.0.0.0:5100,私网可访问;本机仍可用 127.0.0.1)
↓ HTTP
子代理 agent.py × N(默认 127.0.0.1:15200~15203,与 Flask 的 APP_PORT 错开)
↓ ccxt
各交易所 API
- 中控(hub):读配置、并行请求各子代理
/status;全平时转发POST /emergency/close-all。 - 子代理(agent):每个进程绑定一个交易所 API Key,只做只读状态 + 紧急平仓;与
crypto_monitor_*里的 Flask 独立进程,互不影响日常手工/策略操作。
与四个 crypto_monitor_* 目录的关系(已对照 app.py)
各策略项目在本目录用 .env(由 cp .env.example .env 生成,勿提交 Git;git pull 不覆盖)加载配置(load_env_file),并用其中的 APP_HOST / APP_PORT 启动 Flask 网页(app.py 里 HOST、PORT)。这是你在浏览器里打开策略/监控后台用的端口,例如 APP_PORT=5001。
子代理 不用 APP_PORT,而是用环境变量 PORT(FastAPI/uvicorn 监听)。若子代理与 Flask 抢同一端口,后启动的会起不来,因此中控默认把子代理配在 15200~15203,与常见 5000 段 Flask 配置错开。
子代理 PORT(建议) |
对应策略目录 | EXCHANGE |
|---|---|---|
| 15200 | crypto_monitor_binance |
binance |
| 15201 | crypto_monitor_okx |
okx |
| 15202 | crypto_monitor_gate |
gate |
| 15203 | crypto_monitor_gate_bot |
gate |
Flask 仍可继续用 APP_HOST=0.0.0.0 方便云服务器外网访问;子代理建议 HOST=127.0.0.1。中控默认 HUB_HOST=0.0.0.0 便于局域网打开页面;若只给自己用,设 HUB_HOST=127.0.0.1 或 HUB_TRUST_LAN=0。
依赖
- Python 3.10+(与仓库其他项目相近即可)
- 见
requirements.txt:fastapi、uvicorn、httpx、ccxt
安装:
cd manual_trading_hub
pip install -r requirements.txt
建议使用独立虚拟环境,避免与全局包冲突。
快速启动(本机)
1. 启动子代理(每个账户一个终端)
在对应策略目录下加载该目录已有 .env(含 API 密钥与可选代理),再启动 agent,避免密钥分散维护两套。
Binance(子代理端口 15200,与 Flask APP_PORT 无关)
cd ..\crypto_monitor_binance
$env:EXCHANGE="binance"
$env:PORT="15200"
$env:HOST="127.0.0.1"
python ..\manual_trading_hub\agent.py
OKX(15201)
cd ..\crypto_monitor_okx
$env:EXCHANGE="okx"
$env:PORT="15201"
python ..\manual_trading_hub\agent.py
Gate / Gate-Bot(15202 / 15203)
$env:EXCHANGE="gate"
$env:PORT="15202" # Gate-Bot 用 15203
python ..\manual_trading_hub\agent.py
2. 启动中控
cd manual_trading_hub
$env:HUB_HOST="0.0.0.0"
$env:HUB_PORT="5100"
# 可选:自定义各账户卡片标题(顺序与默认 HUB_AGENTS 一致:15200→15201→15202→15203)
# $env:HUB_AGENT_NAMES="币安主号,OKX,Gate主号,Gate机器人"
python hub.py
浏览器打开:http://127.0.0.1:5100/ 或 http://本机局域网IP:5100/
子代理(agent)环境变量
| 变量 | 含义 | 默认 |
|---|---|---|
EXCHANGE |
binance / okx / gate |
binance |
HOST |
监听地址 | 127.0.0.1 |
PORT |
子代理监听端口(勿与 Flask 的 APP_PORT 相同) |
15200 |
CONTROL_TOKEN |
若设置,请求须带头 X-Control-Token |
空 |
Binance:BINANCE_API_KEY、BINANCE_API_SECRET;可选 BINANCE_POSITION_MODE(hedge/oneway)、BINANCE_MARGIN_MODE;代理 BINANCE_SOCKS_PROXY 或 BINANCE_HTTP_PROXY / HTTPS_PROXY。/status 的 balance_usdt 为 U 本位永续合约账户 USDT(与 crypto_monitor_binance 合约口径一致,非现货钱包)。
OKX:OKX_API_KEY、OKX_API_SECRET、OKX_API_PASSPHRASE;可选 OKX_TD_MODE、OKX_POS_MODE;代理 OKX_SOCKS_PROXY 等。
Gate:GATE_API_KEY、GATE_API_SECRET;可选 GATE_TD_MODE、GATE_POS_MODE;代理 GATE_SOCKS_PROXY 等。
中控(hub)环境变量
| 变量 | 含义 | 默认 |
|---|---|---|
HUB_HOST |
监听地址 | 0.0.0.0(局域网可连);127.0.0.1 仅本机 |
HUB_PORT |
监听端口 | 5100 |
HUB_AGENTS |
子代理 base URL,逗号分隔 | http://127.0.0.1:15200 … 15203 |
HUB_AGENT_NAMES |
与 HUB_AGENTS 顺序一一对应的卡片显示名(逗号分隔)。不设则用内置默认名。改后需重启 hub,所有访问该中控的浏览器显示一致 |
内置与四目录对应的英文标签 |
HUB_DISABLED_IDS |
不参与监控与全局全平的账户 id,逗号分隔(如暂不用 OKX 写 1) |
空 |
HUB_TRUST_LAN |
默认 true;设为 0/false/off 则仅允许本机 IP 访问中控 |
开 |
CONTROL_TOKEN |
与子代理一致时,中控代发 X-Control-Token |
空 |
网页操作说明
- 立即刷新 / 自动刷新:拉取最新汇总;自动刷新默认约 3 秒一轮(仅请求已开启监控的账户)。
- 账户显示名:在运行
hub.py的机器上设置环境变量HUB_AGENT_NAMES(逗号分隔,顺序与HUB_AGENTS里每个子代理 URL 一致),重启中控后,任意电脑打开同一中控地址都会看到相同名称。名称里若含逗号,需整体用引号包裹或避免使用逗号。 - 参与监控:勾选则参与轮询与「全局一键全平」;取消则本浏览器记住(
localStorage键manual_trading_hub_excluded),不再请求该子代理。 - 该账户全平:仅针对该子代理;与是否关闭「参与监控」无关(仍可直接调交易所紧急平仓)。
- 全局一键全平:只对当前「参与监控」且未被
HUB_DISABLED_IDS关闭的账户发起全平;请求体中的exclude_ids与网页关闭状态一致。
服务端 HUB_DISABLED_IDS 与浏览器关闭取并集:任一方关闭即不轮询、不进全局全平。
HTTP API(访问控制与浏览器一致)
允许来源:本机或 RFC1918 私网 IPv4(与 HUB_TRUST_LAN 开启时一致);HUB_TRUST_LAN=0 时仅本机。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | / |
中控页面 |
| GET | /api/agents |
当前配置的账户列表(id、name、url) |
| GET | /api/snapshot |
聚合状态;可选查询参数 exclude_ids(逗号分隔 id) |
| POST | /api/close/{agent_id} |
单账户紧急全平 |
| POST | /api/close-all |
JSON 体可选 {"exclude_ids":["1"]},与 HUB_DISABLED_IDS 合并 |
子代理:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /health |
健康检查 |
| GET | /status |
余额、持仓、盈亏汇总 |
| POST | /emergency/close-all |
市价尽量平掉 USDT 永续仓位,并尝试撤该合约挂单 |
安全与边界
- 中控默认 监听 0.0.0.0 并放行私网访问,便于局域网使用;公网非私网 IP 仍会被中间件拒绝。
- 若机器有公网 IP,请用 防火墙 限制
HUB_PORT仅内网可进,或改为HUB_HOST=127.0.0.1+HUB_TRUST_LAN=0仅本机。 - 子代理建议仍用
HOST=127.0.0.1,不要对局域网暴露交易所密钥通道。 - 中控不具备开仓、改策略、划转账能力;全平为市价减仓,请谨慎操作。
- 子代理与主策略进程共用密钥时,注意权限与 IP 白名单仍按交易所要求配置。
常见问题
1. 某一行一直连不上
检查该端口上的 agent.py 是否已启动、防火墙是否放行本机回环、.env 密钥是否与交易所一致。
2. 暂时不用 OKX
网页取消该行的「参与监控」,或启动中控前设置 HUB_DISABLED_IDS=1(默认 OKX 的 id 为 1)。
3. 策略项目要不要改?
不需要改 crypto_monitor_* 代码;只需额外运行 agent.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。
Linux 常驻(PM2):python3 -m venv .venv → source .venv/bin/activate → pip install -r requirements.txt → pm2 start ecosystem.config.cjs(进程名 manual-trading-hub)。PM2 经 run_hub.sh 使用 .venv/bin/python,启动前不必保持 shell 处于 activate 状态。详见 《部署文档.md》。