中控增加

This commit is contained in:
dekun
2026-05-23 12:22:35 +08:00
parent c5f7f0c10d
commit 4222b657cb
10 changed files with 117 additions and 43 deletions
+1 -1
View File
@@ -70,7 +70,7 @@ cd crypto_monitor
- **中控** `hub.py``:5100`):多账户 **监控聚合**、**紧急全平**、系统设置;可选 **用户名+密码** 登录(反代公网时务必配置)。 - **中控** `hub.py``:5100`):多账户 **监控聚合**、**紧急全平**、系统设置;可选 **用户名+密码** 登录(反代公网时务必配置)。
- **子代理** `agent.py`:每账户一进程,默认 **`15200``15203`**,与四所 Flask **`APP_PORT`**5000/5001/5002/5004**必须错开**。 - **子代理** `agent.py`:每账户一进程,默认 **`15200``15203`**,与四所 Flask **`APP_PORT`**5000/5001/5002/5004**必须错开**。
- **下单、关键位、趋势、复盘**:在各 `crypto_monitor_*` 原网页操作(中控监控卡片 **「实例」** / **「复盘」**);中控**已移除下单区**。 - **下单、关键位、策略交易、复盘**:在各 `crypto_monitor_*` 原网页操作(中控 **「实例」** / **「复盘」**);中控**已移除下单区**。增加子账户见 [manual_trading_hub/使用说明.md §4.3](./manual_trading_hub/使用说明.md#43-增加账户例如再挂一个-gate)。
- 账户列表由 **`hub_settings.json`**(网页「系统设置」)维护,**不再使用** `HUB_AGENTS` - 账户列表由 **`hub_settings.json`**(网页「系统设置」)维护,**不再使用** `HUB_AGENTS`
- 部署与排障:[manual_trading_hub/README.md](./manual_trading_hub/README.md)、[常见问题.md](./manual_trading_hub/常见问题.md)。 - 部署与排障:[manual_trading_hub/README.md](./manual_trading_hub/README.md)、[常见问题.md](./manual_trading_hub/常见问题.md)。
+1 -1
View File
@@ -7665,7 +7665,7 @@ try:
app, app,
exchange="binance", exchange="binance",
capabilities=["order", "key"], capabilities=["order", "key"],
has_trend=False, has_trend=True,
get_db=get_db, get_db=get_db,
row_to_dict=row_to_dict, row_to_dict=row_to_dict,
meta_fn=_hub_meta_bundle, meta_fn=_hub_meta_bundle,
+1 -1
View File
@@ -7752,7 +7752,7 @@ try:
app, app,
exchange="gate", exchange="gate",
capabilities=["order", "key"], capabilities=["order", "key"],
has_trend=False, has_trend=True,
get_db=get_db, get_db=get_db,
row_to_dict=row_to_dict, row_to_dict=row_to_dict,
meta_fn=_hub_meta_bundle, meta_fn=_hub_meta_bundle,
+1 -1
View File
@@ -5942,7 +5942,7 @@ try:
app, app,
exchange="okx", exchange="okx",
capabilities=["order", "key"], capabilities=["order", "key"],
has_trend=False, has_trend=True,
get_db=get_db, get_db=get_db,
row_to_dict=row_to_dict, row_to_dict=row_to_dict,
meta_fn=_hub_meta_bundle, meta_fn=_hub_meta_bundle,
+2 -2
View File
@@ -2,7 +2,7 @@
> **完整说明**[使用说明.md](./使用说明.md) · **部署**[部署文档.md](./部署文档.md) · **故障实录**[常见问题.md](./常见问题.md) > **完整说明**[使用说明.md](./使用说明.md) · **部署**[部署文档.md](./部署文档.md) · **故障实录**[常见问题.md](./常见问题.md)
多账户 **监控聚合 + 紧急全平**;**不在中控网页下单**。人工下单、关键位、趋势回调、复盘请在各 `crypto_monitor_*` 实例网页操作(监控卡片 **「实例」** / **「复盘」** 跳转)。 多账户 **监控聚合 + 紧急全平**;**不在中控网页下单**。人工下单、关键位、**策略交易**`/strategy`、复盘请在各 `crypto_monitor_*` 实例网页操作(监控卡片 **「实例」** / **「复盘」**。**增加子账户**见 [使用说明 §4.3](./使用说明.md#43-增加账户例如再挂一个-gate)
--- ---
@@ -12,7 +12,7 @@
|------|------| |------|------|
| 监控区 | 持仓、余额、关键位摘要、趋势计划、机器人单(只读) | | 监控区 | 持仓、余额、关键位摘要、趋势计划、机器人单(只读) |
| 紧急全平 | 单户 / 全局市价减仓 | | 紧急全平 | 单户 / 全局市价减仓 |
| 系统设置 | `hub_settings.json` 管理四所 URL、启用状态、监控能力 | | 系统设置 | `hub_settings.json` 管理 URL、启用、**监控关键位 / 监控趋势计划**(不控制策略交易页) |
| Web 登录 | `.env``HUB_PASSWORD` 后用户名+密码保护(反代公网**务必**配置) | | Web 登录 | `.env``HUB_PASSWORD` 后用户名+密码保护(反代公网**务必**配置) |
| ~~下单区~~ | **已移除**(避免与实例重复、减少故障面) | | ~~下单区~~ | **已移除**(避免与实例重复、减少故障面) |
+4 -4
View File
@@ -18,7 +18,7 @@ DEFAULT_EXCHANGES = [
"flask_url": "http://127.0.0.1:5001", "flask_url": "http://127.0.0.1:5001",
"review_url": "http://127.0.0.1:5001/records", "review_url": "http://127.0.0.1:5001/records",
"enabled": True, "enabled": True,
"capabilities": ["order", "key"], "capabilities": ["key", "trend"],
}, },
{ {
"id": "1", "id": "1",
@@ -28,7 +28,7 @@ DEFAULT_EXCHANGES = [
"flask_url": "http://127.0.0.1:5004", "flask_url": "http://127.0.0.1:5004",
"review_url": "http://127.0.0.1:5004/records", "review_url": "http://127.0.0.1:5004/records",
"enabled": False, "enabled": False,
"capabilities": ["order", "key"], "capabilities": ["key", "trend"],
}, },
{ {
"id": "2", "id": "2",
@@ -38,7 +38,7 @@ DEFAULT_EXCHANGES = [
"flask_url": "http://127.0.0.1:5000", "flask_url": "http://127.0.0.1:5000",
"review_url": "http://127.0.0.1:5000/records", "review_url": "http://127.0.0.1:5000/records",
"enabled": True, "enabled": True,
"capabilities": ["order", "key"], "capabilities": ["key", "trend"],
}, },
{ {
"id": "3", "id": "3",
@@ -48,7 +48,7 @@ DEFAULT_EXCHANGES = [
"flask_url": "http://127.0.0.1:5002", "flask_url": "http://127.0.0.1:5002",
"review_url": "http://127.0.0.1:5002/records", "review_url": "http://127.0.0.1:5002/records",
"enabled": True, "enabled": True,
"capabilities": ["order", "trend"], "capabilities": ["trend"],
}, },
] ]
+19 -14
View File
@@ -192,7 +192,7 @@
}); });
} }
} }
if (trends.length) { if ((row.capabilities || []).includes("trend") && trends.length) {
inner += `<div class="section-title">趋势计划 · ${trends.length}</div>`; inner += `<div class="section-title">趋势计划 · ${trends.length}</div>`;
trends.forEach((t) => { trends.forEach((t) => {
inner += `<div class="list-line">#${t.id} ${esc(t.symbol)} ${t.direction} · SL ${t.stop_loss} · TP ${t.take_profit}</div>`; inner += `<div class="list-line">#${t.id} ${esc(t.symbol)} ${t.direction} · SL ${t.stop_loss} · TP ${t.take_profit}</div>`;
@@ -276,21 +276,26 @@
} catch (_) {} } catch (_) {}
} }
function renderSettingsList(data) {
const list = document.getElementById("settings-list");
if (!list) return;
list.innerHTML = (data.exchanges || [])
.map((ex, idx) => renderSettingsCard(ex, idx))
.join("");
list.querySelectorAll(".btn-del-ex").forEach((btn) => {
btn.onclick = () => {
const i = Number(btn.dataset.idx);
data.exchanges.splice(i, 1);
settingsCache = data;
renderSettingsList(data);
};
});
}
function loadSettingsUI() { function loadSettingsUI() {
loadSettingsMetaLine(); loadSettingsMetaLine();
loadSettings().then((data) => { loadSettings().then((data) => {
const list = document.getElementById("settings-list"); renderSettingsList(data);
document.getElementById("settings-list").innerHTML = (data.exchanges || [])
.map((ex, idx) => renderSettingsCard(ex, idx))
.join("");
list.querySelectorAll(".btn-del-ex").forEach((btn) => {
btn.onclick = () => {
const i = Number(btn.dataset.idx);
data.exchanges.splice(i, 1);
settingsCache = data;
loadSettingsUI();
};
});
}); });
} }
@@ -389,7 +394,7 @@
capabilities: ["key"], capabilities: ["key"],
}); });
settingsCache = data; settingsCache = data;
loadSettingsUI(); renderSettingsList(data);
}; };
initAuth().then((ok) => { initAuth().then((ok) => {
+86 -17
View File
@@ -1,6 +1,6 @@
# 多账户交易中控 — 使用说明 # 多账户交易中控 — 使用说明
本文档说明 **manual_trading_hub** 的架构、启动方式、界面操作与故障排查。中控聚合四所 **持仓/余额/关键位/趋势计划监控 + 紧急全平****人工下单、添加关键位、趋势回调、交易复盘** 均在各实例网页操作 本文档说明 **manual_trading_hub** 的架构、启动方式、界面操作与故障排查。中控聚合四所 **持仓/余额/关键位/趋势计划监控 + 紧急全平****人工下单、关键位、策略交易(趋势回调 / 顺势加仓)、交易复盘** 均在各实例网页操作(点监控卡片 **「实例」**
--- ---
@@ -29,9 +29,10 @@
| 0 | 币安 | :5001 | :15200 | 关键位 | 是 | | 0 | 币安 | :5001 | :15200 | 关键位 | 是 |
| 1 | OKX | :5004 | :15201 | 关键位 | **否**`HUB_DISABLED_IDS=1` | | 1 | OKX | :5004 | :15201 | 关键位 | **否**`HUB_DISABLED_IDS=1` |
| 2 | Gate 训练 | :5000 | :15202 | 关键位 | 是 | | 2 | Gate 训练 | :5000 | :15202 | 关键位 | 是 |
| 3 | Gate 趋势 | :5002 | :15203 | 趋势计划 | 是 | | 3 | Gate 趋势 | :5002 | :15203 | 趋势计划(默认不勾关键位) | 是 |
- **Gate 趋势户**监控区展示**趋势计划**;**不展示关键位**capabilities 无 `key`)。人工下单、趋势回调、关键位均在各实例网页操作 - **Gate 趋势户**默认只勾 **监控趋势计划**;一般不勾关键位(该户多用于趋势回调)。策略操作在实例 **`/strategy`**
- **币安 / Gate 训练 / OKX**:四所均已支持 **策略交易**;中控可同时勾 **监控关键位** + **监控趋势计划**(见 §4.2、§5)。
- **OKX**:默认关闭;需要时在「系统设置」勾选启用,并去掉环境变量 `HUB_DISABLED_IDS` 中的 `1` - **OKX**:默认关闭;需要时在「系统设置」勾选启用,并去掉环境变量 `HUB_DISABLED_IDS` 中的 `1`
### 1.2 实例侧改动(最小) ### 1.2 实例侧改动(最小)
@@ -178,8 +179,8 @@ curl -s http://127.0.0.1:5100/api/ping
| **2×2 卡片** | 仅显示「已启用」账户;每卡含子代理持仓、浮盈、余额 | | **2×2 卡片** | 仅显示「已启用」账户;每卡含子代理持仓、浮盈、余额 |
| **机器人持仓** | 来自实例 `/api/hub/monitor``order_monitors`active | | **机器人持仓** | 来自实例 `/api/hub/monitor``order_monitors`active |
| **关键位** | 仅 `capabilities``key` 的户;展示门控摘要(`/api/price_snapshot` | | **关键位** | 仅 `capabilities``key` 的户;展示门控摘要(`/api/price_snapshot` |
| **趋势计划** | 仅 Gate 趋势户;`trend_pullback_plans` active | | **趋势计划** | 仅当该户勾选 **监控趋势计划** 时展示 `trend_pullback_plans`active |
| **实例 / 复盘** | 「实例」→ 该户 Flask(**下单、关键位、趋势**均在此操作);「复盘」→ `/records`。若配置 **`HUB_PUBLIC_ORIGIN`**,外链替换 `127.0.0.1` | | **实例 / 复盘** | 「实例」→ 该户 Flask(**实盘下单、关键位、策略交易 `/strategy`、复盘**);「复盘」→ `/records`。若配置 **`HUB_PUBLIC_ORIGIN`**,外链替换 `127.0.0.1` |
| **关键位列表** | 来自 `/api/hub/monitor` + `/api/price_snapshot`;Flask 未连通时卡片提示原因;**Gate 趋势户**无关键位块 | | **关键位列表** | 来自 `/api/hub/monitor` + `/api/price_snapshot`;Flask 未连通时卡片提示原因;**Gate 趋势户**无关键位块 |
| **该户全平** | `POST` 子代理 `/emergency/close-all`,仅平该 API Key 仓位 | | **该户全平** | `POST` 子代理 `/emergency/close-all`,仅平该 API Key 仓位 |
| **全局紧急全平** | 对所有已启用户依次全平(不含 `HUB_DISABLED_IDS` 强制关闭的 id | | **全局紧急全平** | 对所有已启用户依次全平(不含 `HUB_DISABLED_IDS` 强制关闭的 id |
@@ -191,7 +192,7 @@ curl -s http://127.0.0.1:5100/api/ping
**可用**:打开 http://127.0.0.1:5100/settings ,修改表格后点 **保存设置** 即写入 `hub_settings.json`;**重新加载** 从磁盘/默认再读(会重新套用 `HUB_DISABLED_IDS`)。保存后监控区立即使用新 URL/启用状态,**无需重启 hub**。 **可用**:打开 http://127.0.0.1:5100/settings ,修改表格后点 **保存设置** 即写入 `hub_settings.json`;**重新加载** 从磁盘/默认再读(会重新套用 `HUB_DISABLED_IDS`)。保存后监控区立即使用新 URL/启用状态,**无需重启 hub**。
**下单关键位**:请在监控卡片点击「实例」,进入各 `crypto_monitor_*` 网页操作(与中控上线前相同) **下单关键位、策略交易**:请在监控卡片点击 **「实例」**,进入各 `crypto_monitor_*` 网页`/trade``/key_monitor``/strategy` 等)。中控 **不** 提供下单区
| 列 | 含义 | | 列 | 含义 |
|----|------| |----|------|
@@ -200,23 +201,91 @@ curl -s http://127.0.0.1:5100/api/ping
| Flask URL | 实例根地址,如 `http://127.0.0.1:5001` | | Flask URL | 实例根地址,如 `http://127.0.0.1:5001` |
| Agent URL | 子代理根地址,如 `http://127.0.0.1:15200` | | Agent URL | 子代理根地址,如 `http://127.0.0.1:15200` |
| 复盘链接 | 一般为 `{Flask}/records` | | 复盘链接 | 一般为 `{Flask}/records` |
| 能力 | 勾选「监控关键位」「监控趋势计划」,控制监控卡片展示块 | | **监控关键位** | 勾选后卡片展示 **关键位** 列表 + 门控价(读 Flask `/api/price_snapshot` |
| id | 与 `HUB_DISABLED_IDS`、全平 API 路径中的 id 对应 | | **监控趋势计划** | 勾选后卡片展示 **趋势回调** 运行中计划(`trend_pullback_plans` active |
| id | 与 `HUB_DISABLED_IDS`、全平 API 路径中的 id 对应;新增户勿与已有 id 重复 |
- **保存设置**:写入 `hub_settings.json`,重启 hub 后仍生效。 - **保存设置**:写入 `hub_settings.json`,重启 hub 后仍生效。
- **添加交易所**可增第五所等,需自行启动对应 Flask + agent 并填写 URL - **添加交易所**见下文 §4.3(须先自建 Flask + agent,再在中控登记)
- **删**:从列表移除(保存后生效)。 - **删**:从列表移除(保存后生效)。
#### 能力与「策略交易」的关系(重要)
| 能力勾选 | 中控监控区 | 策略交易(趋势回调 / 顺势加仓) |
|----------|------------|----------------------------------|
| 监控关键位 | 显示关键位块 | **不控制**;在实例页 `/key_monitor` |
| 监控趋势计划 | 显示趋势计划块 | **不控制**;在实例页 `/strategy` 左栏操作 |
| 均未勾选 | 仅持仓、余额、机器人单 | 仍可在实例网页使用策略交易 |
四所 Flask 均已注册 `hub_bridge`**`has_trend=true`**,勾选「监控趋势计划」后才会从 `/api/hub/monitor` 拉取趋势数据。修改勾选后 **保存即可**,须 **重启对应 Flask** 仅在你刚升级了 `hub_bridge` 相关代码时。
--- ---
## 5. 能力矩阵(监控展示 ### 4.3 增加账户(例如再挂一个 Gate
| 账户 | 监控关键位 | 监控趋势计划 | 中控 **不会** 自动启动进程,也 **不** 保存交易所 API Key。新增一户 = **复制/新建一套实例目录 + 独立 `.env` + 新端口 Flask/agent + 在中控登记一行**
|------|:----------:|:--------------:|
| 币安 | ✓ | — | #### 4.3.1 端口勿冲突(示例)
| OKX | ✓ | — |
| Gate 训练 | ✓ | — | | 用途 | 目录(示例) | Flask `APP_PORT` | Agent `PORT` |
| Gate 趋势 | — | ✓ | |------|----------------|------------------|--------------|
| Gate 训练(已有) | `crypto_monitor_gate` | 5000 | 15202 |
| Gate 趋势(已有) | `crypto_monitor_gate_bot` | 5002 | 15203 |
| **新增 Gate 子账户** | 复制为 `crypto_monitor_gate_2` 等 | **5005**(自定) | **15204**(自定) |
`agent``PORT` 与 Flask 的 `APP_PORT` **必须不同**;且不要与币安 5001、OKX 5004、中控 5100 等占用端口相同。
#### 4.3.2 新建实例目录
1. 复制整个 `crypto_monitor_gate` 到新目录(仓库内副本或 `/opt/` 下均可)。
2. 在新目录:`cp .env.example .env`,至少修改:
- `APP_PORT` → 新 Flask 端口(如 5005
- `DB_PATH` → 独立库(如 `crypto_gate2.db`),**勿**与 5000/5002 共用 `crypto.db`
- `GATE_API_KEY` / `GATE_API_SECRET`**该子账户** 密钥
- `HUB_BRIDGE_TOKEN` → 与中控、其它实例 **相同**
3. 安装 venv 与依赖(与 Gate 部署文档相同),启动:
```powershell
cd crypto_monitor_gate_2
$env:PYTHONPATH=".."
python app.py
```
4. 另开终端,**cwd 必须为新目录**,启动子代理:
```powershell
cd crypto_monitor_gate_2
$env:EXCHANGE="gate"
$env:PORT="15204"
python ..\manual_trading_hub\agent.py
```
验收:`curl http://127.0.0.1:5005/login` 能开页;`curl http://127.0.0.1:15204/status` 返回 `ok`
#### 4.3.3 在中控登记
1. 打开 **系统设置****添加交易所**(或手改 `manual_trading_hub/hub_settings.json`)。
2. 填写 **Flask URL**、**Agent URL**、**id**(如 `4`)、**显示名**。
3. 能力建议:
- 训练/关键位户:**监控关键位** + **监控趋势计划**(若也要在中控看趋势计划);
- 纯趋势户:只勾 **监控趋势计划**
4. 勾选 **启用****保存设置**
5. 在 **监控区** 应出现新卡片;点 **实例** 进入该户网页做下单与 **策略交易**
PM2:仓库 `ecosystem.config.cjs` 默认只有四 agent;第五户需自行 `pm2 start` 或手工终端,与是否改 hub 源码无关。
---
## 5. 能力矩阵(监控展示,建议勾选)
| 账户 | 监控关键位 | 监控趋势计划 | 策略交易(实例页) |
|------|:----------:|:--------------:|:------------------:|
| 币安 | ✓ 建议 | ✓ 建议 | `/strategy` |
| OKX | ✓ 建议 | ✓ 建议 | `/strategy` |
| Gate 训练 | ✓ 建议 | ✓ 建议 | `/strategy` |
| Gate 趋势 | —(通常不勾) | ✓ | `/strategy` |
「建议」表示中控卡片展示对应块;**不勾** 仍可在该实例网页使用关键位或策略交易。
--- ---
@@ -363,7 +432,7 @@ pm2 save && pm2 startup
4. 复盘、导出记录 → 点击「复盘」进入 `/records` 4. 复盘、导出记录 → 点击「复盘」进入 `/records`
5. 异常行情 → 单户全平或全局紧急全平。 5. 异常行情 → 单户全平或全局紧急全平。
如有新交易所,在 **系统设置** 添加一行并勾选能力,无需改 hub.py 源码(需该所有 Flask 注册 `hub_bridge` 且 agent 已部署 增加账户步骤见 **§4.3**无需改 `hub.py` 源码,但须该户 Flask `git pull`**重启**`hub_bridge` + `has_trend`),且 agent 已部署。
--- ---
+1 -1
View File
@@ -162,7 +162,7 @@ HUB_PUBLIC_ORIGIN=http://192.168.8.6
### 5.2 中控监控区 Gate 趋势户「无关键位」 ### 5.2 中控监控区 Gate 趋势户「无关键位」
**设计如此**Gate 趋势户 capabilities 为趋势,不含 `key`;关键位在 Gate 训练户(`crypto_monitor_gate` **设计如此**Gate 趋势户通常只勾 **监控趋势计划**,不勾关键位;关键位在 Gate 训练户。四所 **策略交易** 均在各实例 `/strategy`,与中控勾选无关。增加 Gate 子账户见 [使用说明.md](./使用说明.md) **§4.3**
--- ---
+1 -1
View File
@@ -166,7 +166,7 @@ bash scripts/run_hub.sh
1. **http://127.0.0.1:5100/login** — 若 `.env` 已设 `HUB_PASSWORD`,用 `HUB_USERNAME` / `HUB_PASSWORD` 登录。 1. **http://127.0.0.1:5100/login** — 若 `.env` 已设 `HUB_PASSWORD`,用 `HUB_USERNAME` / `HUB_PASSWORD` 登录。
2. **http://127.0.0.1:5100/monitor** — 已启用账户显示持仓;Flask 已起时有关键位/趋势信息。 2. **http://127.0.0.1:5100/monitor** — 已启用账户显示持仓;Flask 已起时有关键位/趋势信息。
3. **http://127.0.0.1:5100/settings** — 保存后生成 `hub_settings.json` 3. **http://127.0.0.1:5100/settings** — 保存后生成 `hub_settings.json`(增加第五户、Gate 子账户等见 [使用说明.md §4.3](./使用说明.md#43-增加账户例如再挂一个-gate)
4. 监控卡片 **「实例」** — 在各 `crypto_monitor_*` 网页做下单、关键位、趋势;中控**不提供**下单表单。 4. 监控卡片 **「实例」** — 在各 `crypto_monitor_*` 网页做下单、关键位、趋势;中控**不提供**下单表单。
**命令行验收**(推荐): **命令行验收**(推荐):