增加一键部署脚本

This commit is contained in:
dekun
2026-05-21 11:45:49 +08:00
parent 2301590a97
commit 39815c1df6
20 changed files with 3426 additions and 2931 deletions
+130 -121
View File
@@ -1,121 +1,130 @@
# 复盘交易系统(crypto_monitor # 复盘交易系统(crypto_monitor
本仓库为 **多交易所 USDT 永续** 的下单监控、关键位监控与交易复盘工具集:四个子项目分别对接 **Binance、Gate.io(主号)、Gate.io(机器人/趋势策略)、OKX**,共享相似的 Flask 架构与本地 SQLite 记账思路,可按账户独立部署、独立端口运行。 本仓库为 **多交易所 USDT 永续** 的下单监控、关键位监控与交易复盘工具集:四个子项目分别对接 **Binance、Gate.io(主号)、Gate.io(机器人/趋势策略)、OKX**,共享相似的 Flask 架构与本地 SQLite 记账思路,可按账户独立部署、独立端口运行。
**远程仓库(克隆地址)**[https://git.bz121.com/dekun/crypto_monitor.git](https://git.bz121.com/dekun/crypto_monitor.git) **远程仓库(克隆地址)**[https://git.bz121.com/dekun/crypto_monitor.git](https://git.bz121.com/dekun/crypto_monitor.git)
```bash ```bash
git clone https://git.bz121.com/dekun/crypto_monitor.git git clone https://git.bz121.com/dekun/crypto_monitor.git
cd crypto_monitor cd crypto_monitor
``` ```
--- ### 一键环境部署
## 一、仓库目录一览 | 系统 | 命令 |
|------|------|
| 目录 | 交易所 / 角色 | 说明文档 | | **Windows** | 双击根目录 **`一键部署.bat`**,或 `.\deploy\setup_env.ps1` |
|------|-----------------|----------| | **Linux / macOS** | `bash deploy/setup_env.sh` |
| `crypto_monitor_binance/` | Binance USDT-M 永续 | [部署文档.md](./crypto_monitor_binance/部署文档.md) · [README.md](./crypto_monitor_binance/README.md) |
| `crypto_monitor_gate/` | Gate.io 永续(主号) | [部署文档.md](./crypto_monitor_gate/部署文档.md) | 会为各子项目创建 `.venv`、安装依赖、从 `.env.example` 生成 `.env`(不覆盖已有)。详见 **[deploy/README.md](./deploy/README.md)**。
| `crypto_monitor_gate_bot/` | Gate.io 永续(机器人;含趋势回调等) | [部署文档.md](./crypto_monitor_gate_bot/部署文档.md) · [趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md) |
| `crypto_monitor_okx/` | OKX 永续 | [部署文档.md](./crypto_monitor_okx/部署文档.md) | ---
| `manual_trading_hub/` | 多账户中控(监控 + 紧急全平,**不参与开仓**) | [README.md](./manual_trading_hub/README.md) · [部署文档.md](./manual_trading_hub/部署文档.md) · [scripts/后台运行-Ubuntu.md](./manual_trading_hub/scripts/后台运行-Ubuntu.md) |
## 一、仓库目录一览
前四列为四个 **`crypto_monitor_*`** 交易/监控应用;`manual_trading_hub` 与四者 **进程独立**,无需改四者代码即可并行使用。
| 目录 | 交易所 / 角色 | 说明文档 |
--- |------|-----------------|----------|
| `crypto_monitor_binance/` | Binance USDT-M 永续 | [部署文档.md](./crypto_monitor_binance/部署文档.md) · [README.md](./crypto_monitor_binance/README.md) |
## 二、四个 `crypto_monitor_*` 子项目:共同点 | `crypto_monitor_gate/` | Gate.io 永续(主号) | [部署文档.md](./crypto_monitor_gate/部署文档.md) |
| `crypto_monitor_gate_bot/` | Gate.io 永续(机器人;含趋势回调等) | [部署文档.md](./crypto_monitor_gate_bot/部署文档.md) · [趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md) |
- **技术栈**Python 3.10+、`Flask` Web、`ccxt` 调交易所 API、本地 SQLite(默认 `crypto.db`)等。 | `crypto_monitor_okx/` | OKX 永续 | [部署文档.md](./crypto_monitor_okx/部署文档.md) |
- **能力类型**(各所细节见各自 README / 部署文档): | `manual_trading_hub/` | 多账户中控(监控 + 紧急全平,**不参与开仓**) | [README.md](./manual_trading_hub/README.md) · [部署文档.md](./manual_trading_hub/部署文档.md) · [scripts/后台运行-Ubuntu.md](./manual_trading_hub/scripts/后台运行-Ubuntu.md) |
- **关键位监控**、**下单监控**(含风控与移动保本等逻辑)、**交易复盘**;
- **实盘(可选)**:在对应 `.env` 中开启 `LIVE_TRADING_ENABLED=true` 并配置各所 API 后,由程序发起真实委托(请务必理解风险并做好权限与 IP 白名单控制) 前四列为四个 **`crypto_monitor_*`** 交易/监控应用;`manual_trading_hub` 与四者 **进程独立**,无需改四者代码即可并行使用
- **网络**:若本机直连交易所不稳定,可通过 **SSH 动态转发 SOCKS** 或 HTTP/S 代理;经 SOCKS 时依赖中需包含 **`PySocks`**(各《部署文档》中有说明)。
- **进程托管**Linux 上常用 **PM2** 托管 `app.py`;各目录内一般有 `ecosystem.config.cjs` 或文档中的等价命令。 ---
--- ## 二、四个 `crypto_monitor_*` 子项目:共同点
## 三、四个子项目:差异速查 - **技术栈**Python 3.10+、`Flask` Web、`ccxt` 调交易所 API、本地 SQLite(默认 `crypto.db`)等。
- **能力类型**(各所细节见各自 README / 部署文档):
| 项目 | 环境变量前缀(示例) | 典型用途区分 | - **关键位监控**、**下单监控**(含风控与移动保本等逻辑)、**交易复盘**;
|------|----------------------|--------------| - **实盘(可选)**:在对应 `.env` 中开启 `LIVE_TRADING_ENABLED=true` 并配置各所 API 后,由程序发起真实委托(请务必理解风险并做好权限与 IP 白名单控制)。
| `crypto_monitor_binance` | `BINANCE_*` | 币安 U 本位永续;止盈止损以 `STOP_MARKET` / `TAKE_PROFIT_MARKET` 等与币安规则对齐 | - **网络**:若本机直连交易所不稳定,可通过 **SSH 动态转发 SOCKS** 或 HTTP/S 代理;经 SOCKS 时依赖中需包含 **`PySocks`**(各《部署文档》中有说明)。
| `crypto_monitor_gate` | `GATE_*` | Gate 主账户监控与交易页面 | - **进程托管**Linux 上常用 **PM2** 托管 `app.py`;各目录内一般有 `ecosystem.config.cjs` 或文档中的等价命令。
| `crypto_monitor_gate_bot` | `GATE_*` | Gate 侧 **独立子账户 / 机器人**;文档中含 **趋势回调** 等策略说明 |
| `crypto_monitor_okx` | `OKX_*` | OKX 永续;需 API Key / Secret / Passphrase | ---
各目录根下: ## 三、四个子项目:差异速查
- **`.env.example`**:配置模板(**可** `git pull` 同步),新机执行 `cp .env.example .env` 后编辑。 | 项目 | 环境变量前缀(示例) | 典型用途区分 |
- **`.env`**:本机真实配置(**勿**提交 Git);`app.py` 只读此文件。`git pull` **不会**覆盖 `.env`;升级前建议 `cp .env .env.backup.$(date +%Y%m%d)` |------|----------------------|--------------|
| `crypto_monitor_binance` | `BINANCE_*` | 币安 U 本位永续;止盈止损以 `STOP_MARKET` / `TAKE_PROFIT_MARKET` 等与币安规则对齐 |
变量名以前缀区分,**不可混用**(例如在 Gate 项目中写 OKX 变量会导致代理与密钥不生效)。 | `crypto_monitor_gate` | `GATE_*` | Gate 主账户监控与交易页面 |
| `crypto_monitor_gate_bot` | `GATE_*` | Gate 侧 **独立子账户 / 机器人**;文档中含 **趋势回调** 等策略说明 |
--- | `crypto_monitor_okx` | `OKX_*` | OKX 永续;需 API Key / Secret / Passphrase |
## 四、与 `manual_trading_hub` 的关系(可选) 各目录根下:
- **中控** `hub.py`:汇总各子代理状态,提供网页与 HTTP API。 - **`.env.example`**:配置模板(**可** `git pull` 同步),新机执行 `cp .env.example .env` 后编辑。
- **子代理** `agent.py`:每个进程绑定一个交易所账户,默认监听 **`15200``15203`**,与四个 Flask 应用的 **`APP_PORT`**(如 5000、5001**必须错开**。 - **`.env`**:本机真实配置(**勿**提交 Git);`app.py` 只读此文件。`git pull` **不会**覆盖 `.env`;升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`
- 详细端口、`EXCHANGE``HUB_AGENTS` 等见 [manual_trading_hub/README.md](./manual_trading_hub/README.md)。
变量名以前缀区分,**不可混用**(例如在 Gate 项目中写 OKX 变量会导致代理与密钥不生效)。
---
---
## 五、Linux 推荐目录布局(可选)
## 四、与 `manual_trading_hub` 的关系(可选)
为与仓库内《部署文档》示例一致,可将整个克隆结果置于 **`/opt/crypto_monitor/`** 下,例如:
- **中控** `hub.py`:汇总各子代理状态,提供网页与 HTTP API。
- `/opt/crypto_monitor/crypto_monitor_binance` - **子代理** `agent.py`:每个进程绑定一个交易所账户,默认监听 **`15200``15203`**,与四个 Flask 应用的 **`APP_PORT`**(如 5000、5001**必须错开**。
- `/opt/crypto_monitor/crypto_monitor_gate` - 详细端口、`EXCHANGE``HUB_AGENTS` 等见 [manual_trading_hub/README.md](./manual_trading_hub/README.md)。
- `/opt/crypto_monitor/crypto_monitor_gate_bot`
- `/opt/crypto_monitor/crypto_monitor_okx` ---
- `/opt/crypto_monitor/manual_trading_hub`
## 五、Linux 推荐目录布局(可选)
具体 `mkdir``venv``pm2`**SSH SOCKS** 步骤以各子目录 **《部署文档.md》** 为准。
为与仓库内《部署文档》示例一致,可将整个克隆结果置于 **`/opt/crypto_monitor/`** 下,例如:
### 备份与恢复(服务器必读)
- `/opt/crypto_monitor/crypto_monitor_binance`
项目路径 **`/opt/crypto_monitor`**,数据备份 **`/root/backups`** - `/opt/crypto_monitor/crypto_monitor_gate`
- `/opt/crypto_monitor/crypto_monitor_gate_bot`
| 类型 | 说明 | - `/opt/crypto_monitor/crypto_monitor_okx`
|------|------| - `/opt/crypto_monitor/manual_trading_hub`
| **数据库 + 复盘图片** | 每天北京时间 0:00 自动备份,保留 30 天 |
| **`.env`** | 升级 / 改配置前手动备份与恢复 | 具体 `mkdir``venv``pm2`**SSH SOCKS** 步骤以各子目录 **《部署文档.md》** 为准。
**一键复制命令(Ubuntu SSH** 见根目录 **[备份与恢复.md](./备份与恢复.md)**:含安装 cron、手动备份、`.env` 备份/恢复、从备份还原数据库等整段脚本。 ### 备份与恢复(服务器必读)
--- 项目路径 **`/opt/crypto_monitor`**,数据备份 **`/root/backups`**
## 六、推荐阅读顺序 | 类型 | 说明 |
|------|------|
1. 克隆本仓库后,根据你实际交易的所,进入对应 **`crypto_monitor_*`** 目录。 | **数据库 + 复盘图片** | 每天北京时间 0:00 自动备份,保留 30 天 |
2. 在该目录执行 **`cp -n .env.example .env`** 并编辑 `.env`(填入 API 与密码等)。 | **`.env`** | 升级 / 改配置前手动备份与恢复 |
3. 阅读该目录下的 **《部署文档.md》**Ubuntu / PM2 / 代理 / 升级说明)。
4. 服务器部署完成后,按 **[备份与恢复.md](./备份与恢复.md)** 配置自动备份`.env` 备份习惯。 **一键复制命令(Ubuntu SSH** 见根目录 **[备份与恢复.md](./备份与恢复.md)**:含安装 cron、手动备份`.env` 备份/恢复、从备份还原数据库等整段脚本。
5. 需要 **Gate 趋势回调** 规则时,阅读 [crypto_monitor_gate_bot/趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md)。
6. 需要 **多账户一块看 + 紧急全平** 时,阅读 [manual_trading_hub](./manual_trading_hub/) 下 README 与部署文档。 ---
--- ## 六、推荐阅读顺序
## 七、安全与合规 1. 克隆本仓库后,执行 **一键环境部署**(上表),或手动在各子目录 `python -m venv .venv``pip install`
2. 根据实际交易所进入对应 **`crypto_monitor_*`** 目录,编辑 **`.env`**(填入 API 与密码等;部署脚本已可从 `.env.example` 复制)。
- **切勿**将 `.env``.env.backup*`、API Secret、SSH 私钥 `.pem` 等提交到版本库或公开渠道;仅 **`.env.example`** 可提交(占位符,无真实密钥)。 3. 阅读该目录下的 **《部署文档.md》**Ubuntu / PM2 / 代理 / 升级说明)。
4. 服务器部署完成后,按 **[备份与恢复.md](./备份与恢复.md)** 配置自动备份与 `.env` 备份习惯。
### 从旧版仓库升级(曾把 `.env` 提交进 Git 5. 需要 **Gate 趋势回调** 规则时,阅读 [crypto_monitor_gate_bot/趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md)。
6. 需要 **多账户一块看 + 紧急全平** 时,阅读 [manual_trading_hub](./manual_trading_hub/) 下 README 与部署文档。
**`git pull` 之前**按 **[备份与恢复.md](./备份与恢复.md)** 备份 `.env` 与数据库;pull 后若本地 `.env` 被误删,用备份恢复;再对照新的 **`.env.example`** 补全可能新增的变量名。
- 实盘前务必在 **`LIVE_TRADING_ENABLED=false`** 下验证页面与网络;API 权限与 IP 白名单遵循各交易所要求。 ---
- 使用本仓库进行实盘交易的风险由使用者自行承担;请遵守当地法律法规与交易所用户协议。
## 七、安全与合规
---
- **切勿**将 `.env``.env.backup*`、API Secret、SSH 私钥 `.pem` 等提交到版本库或公开渠道;仅 **`.env.example`** 可提交(占位符,无真实密钥)。
## 八、仓库信息摘要
### 从旧版仓库升级(曾把 `.env` 提交进 Git
| 项 | 内容 |
|----|------| **`git pull` 之前**按 **[备份与恢复.md](./备份与恢复.md)** 备份 `.env` 与数据库;pull 后若本地 `.env` 被误删,用备份恢复;再对照新的 **`.env.example`** 补全可能新增的变量名。
| 远程地址 | `https://git.bz121.com/dekun/crypto_monitor.git` | - 实盘前务必在 **`LIVE_TRADING_ENABLED=false`** 下验证页面与网络;API 权限与 IP 白名单遵循各交易所要求。
| 说明 | 复盘交易系统(骆驼比特币私有代码仓库,Gitea) | - 使用本仓库进行实盘交易的风险由使用者自行承担;请遵守当地法律法规与交易所用户协议。
| 本说明 | 仓库根目录 `README.md`,仅描述结构与文档索引,不包含业务代码变更说明 |
---
若各子项目 README 与根说明不一致,以 **子目录内当前代码与《部署文档》** 为准。
## 八、仓库信息摘要
| 项 | 内容 |
|----|------|
| 远程地址 | `https://git.bz121.com/dekun/crypto_monitor.git` |
| 说明 | 复盘交易系统(骆驼比特币私有代码仓库,Gitea) |
| 本说明 | 仓库根目录 `README.md`,仅描述结构与文档索引,不包含业务代码变更说明 |
若各子项目 README 与根说明不一致,以 **子目录内当前代码与《部署文档》** 为准。
+134 -134
View File
@@ -1,134 +1,134 @@
# 使用说明 # 使用说明
**本文件对应仓库:`crypto_monitor_binance`Binance U 本位永续)。** **本文件对应仓库:`crypto_monitor_binance`Binance U 本位永续)。**
功能、界面与 **Gate.io USDT 永续版**(目录 `crypto_monitor_gate`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**`BINANCE_*` / `GATE_*`),文末有对照。 功能、界面与 **Gate.io USDT 永续版**(目录 `crypto_monitor_gate`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**`BINANCE_*` / `GATE_*`),文末有对照。
**部署、代理、PM2 等**请参考本仓库说明或 **`crypto_monitor_gate`** 下的 **`部署文档.md`**(该文以 Gate + SSH SOCKS 为例;Binance 侧将 API 与密钥改为 `BINANCE_*` 即可类比)。 **部署、代理、PM2 等**请参考本仓库说明或 **`crypto_monitor_gate`** 下的 **`部署文档.md`**(该文以 Gate + SSH SOCKS 为例;Binance 侧将 API 与密钥改为 `BINANCE_*` 即可类比)。
**关键位自动开仓的规则、RR、结案原因**见本目录 **`关键位自动下单说明.md`**。 **关键位自动开仓的规则、RR、结案原因**见本目录 **`关键位自动下单说明.md`**。
--- ---
## 1. 它能做什么 ## 1. 它能做什么
面向个人盘面的 **Web 控制台**,主要能力包括: 面向个人盘面的 **Web 控制台**,主要能力包括:
| 模块 | 说明 | | 模块 | 说明 |
|------|------| |------|------|
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 | | **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 |
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 | | **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 |
| **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出。 | | **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出。 |
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。 后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。
--- ---
## 2. 运行前必须配置(`.env` ## 2. 运行前必须配置(`.env`
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env``.env` 勿提交 Git`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。 首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env``.env` 勿提交 Git`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。
至少检查以下项(具体键名以 **`.env.example`** 为准): 至少检查以下项(具体键名以 **`.env.example`** 为准):
| 类别 | 说明 | | 类别 | 说明 |
|------|------| |------|------|
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 | | **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 |
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 | | **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 |
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 | | **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 |
| **交易所 API** | **本仓库:** `BINANCE_API_KEY``BINANCE_API_SECRET`;永续相关见 `BINANCE_MARGIN_MODE``BINANCE_POSITION_MODE``BINANCE_TRIGGER_WORKING_TYPE` 等。**勿**把 `.env` 提交到 Git。 | | **交易所 API** | **本仓库:** `BINANCE_API_KEY``BINANCE_API_SECRET`;永续相关见 `BINANCE_MARGIN_MODE``BINANCE_POSITION_MODE``BINANCE_TRIGGER_WORKING_TYPE` 等。**勿**把 `.env` 提交到 Git。 |
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR``KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 | | **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR``KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 |
网络需要代理时可配置 **`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY`**(与 Gate 版 `GATE_*_PROXY` 用法类似)。 网络需要代理时可配置 **`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY`**(与 Gate 版 `GATE_*_PROXY` 用法类似)。
--- ---
## 3. 如何启动与登录 ## 3. 如何启动与登录
1. 准备 Python 虚拟环境并安装依赖(如 `flask``requests``ccxt`、按需 `Pillow``PySocks` 等),配置好 `.env` 1. 准备 Python 虚拟环境并安装依赖(如 `flask``requests``ccxt`、按需 `Pillow``PySocks` 等),配置好 `.env`
2. 启动 Flask 应用(可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。 2. 启动 Flask 应用(可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。 3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。
登录后顶栏为四页:**关键位监控** | **实盘下单**(默认首页)| **交易记录与复盘** | **统计分析** 登录后顶栏为四页:**关键位监控** | **实盘下单**(默认首页)| **交易记录与复盘** | **统计分析**
--- ---
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor` ## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`
### 4.1 添加一条关键位 ### 4.1 添加一条关键位
1. **币种**:如 `BTC``BTC/USDT`(会规范成内部符号)。 1. **币种**:如 `BTC``BTC/USDT`(会规范成内部符号)。
2. **类型**(必选其一): 2. **类型**(必选其一):
| 类型 | 行为摘要 | | 类型 | 行为摘要 |
|------|----------| |------|----------|
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 | | **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 |
| **收敛突破** | 同上(自动开仓类)。 | | **收敛突破** | 同上(自动开仓类)。 |
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 | | **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 |
| **关键支撑位** | 同上(仅提醒)。 | | **关键支撑位** | 同上(仅提醒)。 |
3. **方向**:做多 / 做空(必选)。 3. **方向**:做多 / 做空(必选)。
4. **上沿 / 下沿**:必填;保存时会按交易所 **价格精度** 取整。 4. **上沿 / 下沿**:必填;保存时会按交易所 **价格精度** 取整。
**限制:** **限制:**
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。 活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。
**4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示****不阻挡**提交。 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示****不阻挡**提交。
### 4.2 触发后会发生什么(简版) ### 4.2 触发后会发生什么(简版)
- **箱体 / 收敛**:门控通过后算计划 SL/TP 与 RR;不达标 → 微信说明 + **`rr_insufficient`** 结案;达标 → **市价开仓**,成功 **`auto_opened`** / 失败 **`exchange_failed`**,均不重试同一关键位。 - **箱体 / 收敛**:门控通过后算计划 SL/TP 与 RR;不达标 → 微信说明 + **`rr_insufficient`** 结案;达标 → **市价开仓**,成功 **`auto_opened`** / 失败 **`exchange_failed`**,均不重试同一关键位。
- **阻力 / 支撑**:仅 **单次推送****`key_level_alert_only`** 结案。 - **阻力 / 支撑**:仅 **单次推送****`key_level_alert_only`** 结案。
详细公式与字段见 **`关键位自动下单说明.md`**。 详细公式与字段见 **`关键位自动下单说明.md`**。
### 4.3 列表与历史 ### 4.3 列表与历史
当前条目与历史记录的用法与 Gate 版相同;结案后可在历史区查阅 **`close_reason`**。 当前条目与历史记录的用法与 Gate 版相同;结案后可在历史区查阅 **`close_reason`**。
--- ---
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`) ## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1)。 - 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1)。
- **人工开仓**计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1)。 - **人工开仓**计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1)。
- 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单)。 - 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单)。
- 移动保本等选项按页面与 `.env` 默认。 - 移动保本等选项按页面与 `.env` 默认。
开仓成功后卡片 **「来源」**:手工一般为 **下单监控**;关键位自动为 **关键位监控** 开仓成功后卡片 **「来源」**:手工一般为 **下单监控**;关键位自动为 **关键位监控**
--- ---
## 6. 企业微信 ## 6. 企业微信
推送逻辑与 Gate 版一致;未配置 **`WECHAT_WEBHOOK`** 时可能没有消息,请以 **交易所端** 核对持仓与挂单。 推送逻辑与 Gate 版一致;未配置 **`WECHAT_WEBHOOK`** 时可能没有消息,请以 **交易所端** 核对持仓与挂单。
--- ---
## 7. 强烈建议的风险与运维习惯 ## 7. 强烈建议的风险与运维习惯
1. **先用 `LIVE_TRADING_ENABLED=false`** 熟悉流程再实盘。 1. **先用 `LIVE_TRADING_ENABLED=false`** 熟悉流程再实盘。
2. **API 权限**最小化,密钥勿泄露。 2. **API 权限**最小化,密钥勿泄露。
3. **同一账户避免多程序重复开仓** 3. **同一账户避免多程序重复开仓**
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。 4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
5. 升级代码后留意 **首轮启动**有无数据库迁移报错。 5. 升级代码后留意 **首轮启动**有无数据库迁移报错。
--- ---
## 8. 常见问题(简要) ## 8. 常见问题(简要)
| 现象 | 可自查 | | 现象 | 可自查 |
|------|--------| |------|--------|
| 关键位永远不触发 | 门控五项、日成交量排名、`KLINE_TIMEFRAME`。 | | 关键位永远不触发 | 门控五项、日成交量排名、`KLINE_TIMEFRAME`。 |
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`、RR 阈值、是否已有持仓、API/保证金错误信息。 | | 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`、RR 阈值、是否已有持仓、API/保证金错误信息。 |
| 加不了箱体/收敛 | 是否已有持仓。 | | 加不了箱体/收敛 | 是否已有持仓。 |
| 推送收不到 | Webhook、网络。 | | 推送收不到 | Webhook、网络。 |
--- ---
## 9. Gate 版(`crypto_monitor_gate`)差异速查 ## 9. Gate 版(`crypto_monitor_gate`)差异速查
| 项目 | Binance 本仓库 | Gate 版 | | 项目 | Binance 本仓库 | Gate 版 |
|------|----------------|--------| |------|----------------|--------|
| API 变量 | `BINANCE_API_KEY``BINANCE_API_SECRET``BINANCE_*` | `GATE_API_KEY``GATE_API_SECRET``GATE_*` | | API 变量 | `BINANCE_API_KEY``BINANCE_API_SECRET``BINANCE_*` | `GATE_API_KEY``GATE_API_SECRET``GATE_*` |
| 代理示例 | `BINANCE_SOCKS_PROXY` | `GATE_SOCKS_PROXY` | | 代理示例 | `BINANCE_SOCKS_PROXY` | `GATE_SOCKS_PROXY` |
| TP/SL 实现 | `_binance_place_tp_sl_orders` | `_gate_place_tp_sl_orders``GATE_TPSL_*` | | TP/SL 实现 | `_binance_place_tp_sl_orders` | `_gate_place_tp_sl_orders``GATE_TPSL_*` |
| 资金舍入口径 | **`FUNDS_DECIMALS`**(与记账一致) | 以 Gate 仓库实现为准 | | 资金舍入口径 | **`FUNDS_DECIMALS`**(与记账一致) | 以 Gate 仓库实现为准 |
业务流程(登录、四种关键位、手工单、单仓)两份程序对齐;仅需更换目录与 `.env` 业务流程(登录、四种关键位、手工单、单仓)两份程序对齐;仅需更换目录与 `.env`
@@ -1,101 +1,101 @@
# 关键位自动下单说明 # 关键位自动下单说明
**适用仓库:`crypto_monitor_binance`|交易所:Binance U 本位永续**Gate 版见同名的 `crypto_monitor_gate` 目录。) **适用仓库:`crypto_monitor_binance`|交易所:Binance U 本位永续**Gate 版见同名的 `crypto_monitor_gate` 目录。)
本文档与 `.env``app.check_key_monitors``app.add_key``_market_open_for_key_monitor` 的实现一致。 本文档与 `.env``app.check_key_monitors``app.add_key``_market_open_for_key_monitor` 的实现一致。
--- ---
## 结构与是否自动开仓 ## 结构与是否自动开仓
| `key_monitors.monitor_type`(录入类型) | 自动下单 | 触发后处置 | | `key_monitors.monitor_type`(录入类型) | 自动下单 | 触发后处置 |
|---------------------------------------|----------|------------| |---------------------------------------|----------|------------|
| **箱体突破** | 是(满足全部条件) | **一次性结案**:写 `key_monitor_history` → 从 `key_monitors` **删除** | | **箱体突破** | 是(满足全部条件) | **一次性结案**:写 `key_monitor_history` → 从 `key_monitors` **删除** |
| **收敛突破** | 是(同上) | 同上 | | **收敛突破** | 是(同上) | 同上 |
| **关键阻力位** | 否 | 企业微信 **1 次**`close_reason=key_level_alert_only`**失效** | | **关键阻力位** | 否 | 企业微信 **1 次**`close_reason=key_level_alert_only`**失效** |
| **关键支撑位** | 否 | 同上 | | **关键支撑位** | 否 | 同上 |
触发条件:**5m 收线硬门控** `_key_hard_checks`(量能、突破幅度、第二根收盘确认、日成交量前 30 等)。 触发条件:**5m 收线硬门控** `_key_hard_checks`(量能、突破幅度、第二根收盘确认、日成交量前 30 等)。
--- ---
## 录入限制(`/add_key` ## 录入限制(`/add_key`
- 存在 **`order_monitors.status='active'`** 时:**禁止添加** 「箱体突破」「收敛突破」。 - 存在 **`order_monitors.status='active'`** 时:**禁止添加** 「箱体突破」「收敛突破」。
- **关键阻力位 / 关键支撑位**:不受上条限制;触发后 **仅单次微信提醒**,然后结案。 - **关键阻力位 / 关键支撑位**:不受上条限制;触发后 **仅单次微信提醒**,然后结案。
- **4h EMA55 与所选方向逆势**:**不拦截**;添加成功后 **Flash** 提示。 - **4h EMA55 与所选方向逆势**:**不拦截**;添加成功后 **Flash** 提示。
- 上下沿入库前经 **`round_price_to_exchange`** 按合约 **价格精度** 取整。 - 上下沿入库前经 **`round_price_to_exchange`** 按合约 **价格精度** 取整。
--- ---
## 环境与参数(`.env` ## 环境与参数(`.env`
| 变量 | 含义 | 默认 | | 变量 | 含义 | 默认 |
|------|------|------| |------|------|------|
| `KEY_AUTO_MIN_PLANNED_RR` | 计划 RR 阈值:**仅当严格大于该值** 才自动开仓(按下方 `E` 计算) | `1.5` | | `KEY_AUTO_MIN_PLANNED_RR` | 计划 RR 阈值:**仅当严格大于该值** 才自动开仓(按下方 `E` 计算) | `1.5` |
| `KEY_STOP_OUTSIDE_BREAKOUT_PCT` | 止损:突破 K 极值向外 **百分比**(多:`低×(1p/100)`;空:`高×(1+p/100)` | `0.5` | | `KEY_STOP_OUTSIDE_BREAKOUT_PCT` | 止损:突破 K 极值向外 **百分比**(多:`低×(1p/100)`;空:`高×(1+p/100)` | `0.5` |
**其余与本仓库手动实盘一致:** `KLINE_TIMEFRAME``RISK_PERCENT``LIVE_TRADING_ENABLED``BREAKEVEN_*``DAILY_OPEN_ALERT_THRESHOLD`,以及 **`BINANCE_*`**(密钥、`BINANCE_MARGIN_MODE``BINANCE_POSITION_MODE``BINANCE_TRIGGER_WORKING_TYPE` 等)。资金字段舍入端口径与 **`FUNDS_DECIMALS`** 一致。 **其余与本仓库手动实盘一致:** `KLINE_TIMEFRAME``RISK_PERCENT``LIVE_TRADING_ENABLED``BREAKEVEN_*``DAILY_OPEN_ALERT_THRESHOLD`,以及 **`BINANCE_*`**(密钥、`BINANCE_MARGIN_MODE``BINANCE_POSITION_MODE``BINANCE_TRIGGER_WORKING_TYPE` 等)。资金字段舍入端口径与 **`FUNDS_DECIMALS`** 一致。
--- ---
## 计价与下单口径 ## 计价与下单口径
| 用途 | 价格 | | 用途 | 价格 |
|------|------| |------|------|
| 企业微信展示、**与 RR 门槛比较的计划 RR** | 确认 K(第二根闭合 5m)收盘 **`E`** | | 企业微信展示、**与 RR 门槛比较的计划 RR** | 确认 K(第二根闭合 5m)收盘 **`E`** |
| **实际开仓** | **市价**`place_exchange_order`,与 `/add_order` 一致);成交价可能与 `E` **滑点** | | **实际开仓** | **市价**`place_exchange_order`,与 `/add_order` 一致);成交价可能与 `E` **滑点** |
| **以损定仓** | `calc_risk_fraction(direction, 当前市价, 止损)` + `RISK_PERCENT`(保证金等 **`FUNDS_DECIMALS`** 舍入,与 `/add_order` 一致) | | **以损定仓** | `calc_risk_fraction(direction, 当前市价, 止损)` + `RISK_PERCENT`(保证金等 **`FUNDS_DECIMALS`** 舍入,与 `/add_order` 一致) |
- 开仓成功后:`order_monitors.monitor_type`**关键位监控**;持仓卡片「来源」显示之。手动开仓为 **下单监控** - 开仓成功后:`order_monitors.monitor_type`**关键位监控**;持仓卡片「来源」显示之。手动开仓为 **下单监控**
- 持仓列表中的 **盈亏比**:按 **实际成交价** 相对 SL/TP 重算,可与「按 `E` 算的计划 RR」略有偏差。 - 持仓列表中的 **盈亏比**:按 **实际成交价** 相对 SL/TP 重算,可与「按 `E` 算的计划 RR」略有偏差。
- **本仓库止盈止损挂单**:开仓后由 **`_binance_place_tp_sl_orders`** 挂载(与手动一致:U 本位条件/Algo 类触发单;具体类型以 ccxt / 交易所为准)。 - **本仓库止盈止损挂单**:开仓后由 **`_binance_place_tp_sl_orders`** 挂载(与手动一致:U 本位条件/Algo 类触发单;具体类型以 ccxt / 交易所为准)。
--- ---
## 自动单止盈 / 止损(仅箱体突破、收敛突破) ## 自动单止盈 / 止损(仅箱体突破、收敛突破)
添加关键位时在页面选择 **止盈止损方案**(写入 `key_monitors.sl_tp_mode`)。确认 K 收盘 **E**,箱体高 **H = |upper lower|`** 添加关键位时在页面选择 **止盈止损方案**(写入 `key_monitors.sl_tp_mode`)。确认 K 收盘 **E**,箱体高 **H = |upper lower|`**
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP | | 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|------|--------------|-------------|-------------| |------|--------------|-------------|-------------|
| 标准突破(默认) | `standard` | 突破 K 低 × (1`KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) / **E+H** | 突破 K 高 × (1+外侧%) / **EH** | | 标准突破(默认) | `standard` | 突破 K 低 × (1`KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) / **E+H** | 突破 K 高 × (1+外侧%) / **EH** |
| 箱体1R·止盈1.5H | `box_1p5` | **EH** / **E+1.5×H**RR≈1.5 | **E+H** / **E1.5×H** | | 箱体1R·止盈1.5H | `box_1p5` | **EH** / **E+1.5×H**RR≈1.5 | **E+H** / **E1.5×H** |
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高 × (1+外侧%) / **录入止盈** | | 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高 × (1+外侧%) / **录入止盈** |
计划 **`RR = calc_rr_ratio(direction, E, SL, TP)`**。若为 `None`**RR ≤ `KEY_AUTO_MIN_PLANNED_RR`****不下单**,走 `rr_insufficient` 结案。 计划 **`RR = calc_rr_ratio(direction, E, SL, TP)`**。若为 `None`**RR ≤ `KEY_AUTO_MIN_PLANNED_RR`****不下单**,走 `rr_insufficient` 结案。
**移动保本:** 添加时可勾选(默认关);开仓写入 `order_monitors.breakeven_enabled` 与勾选一致。详见仓库根目录 `关键位止盈止损与移动保本更新说明.md` **移动保本:** 添加时可勾选(默认关);开仓写入 `order_monitors.breakeven_enabled` 与勾选一致。详见仓库根目录 `关键位止盈止损与移动保本更新说明.md`
--- ---
## 一次性结案(`close_reason` ## 一次性结案(`close_reason`
以下任一发生:**按需发微信** → **`key_monitor_history`** → **从 `key_monitors` 删除**;**不会对同一条关键位重复轮询重试开仓**。 以下任一发生:**按需发微信** → **`key_monitor_history`** → **从 `key_monitors` 删除**;**不会对同一条关键位重复轮询重试开仓**。
| `close_reason` | 含义 | | `close_reason` | 含义 |
|----------------|------| |----------------|------|
| `rr_insufficient` | 门控通过,但计划 RR 未达标或 SL/TP / RR **几何无效** | | `rr_insufficient` | 门控通过,但计划 RR 未达标或 SL/TP / RR **几何无效** |
| `exchange_failed` | 计划 RR 达标,但未开实盘、`LIVE_TRADING_ENABLED=false`、风控、保证金或 **交易所报错** 等导致 **开仓失败** | | `exchange_failed` | 计划 RR 达标,但未开实盘、`LIVE_TRADING_ENABLED=false`、风控、保证金或 **交易所报错** 等导致 **开仓失败** |
| `auto_opened` | 计划 RR 达标且 **市价开仓成功**(已写 `order_monitors`,并已挂止盈止损) | | `auto_opened` | 计划 RR 达标且 **市价开仓成功**(已写 `order_monitors`,并已挂止盈止损) |
| `key_level_alert_only` | 阻力/支撑位 **仅推送**结案 | | `key_level_alert_only` | 阻力/支撑位 **仅推送**结案 |
--- ---
## 与企业微信推送 ## 与企业微信推送
每种结案路径 **至多一条**主业务推送(RR 不足 / 下单失败 / 开仓成功 / 阻力支撑仅提醒)。 每种结案路径 **至多一条**主业务推送(RR 不足 / 下单失败 / 开仓成功 / 阻力支撑仅提醒)。
旧版「满 `KEY_ALERT_MAX_TIMES` 次再归档」对已触发结案的路径 **不再适用**;表中 `notification_count``max_notify` 等字段仍可能存在,以 **导出、兼容** 为主。 旧版「满 `KEY_ALERT_MAX_TIMES` 次再归档」对已触发结案的路径 **不再适用**;表中 `notification_count``max_notify` 等字段仍可能存在,以 **导出、兼容** 为主。
--- ---
## 相关代码位置(通用) ## 相关代码位置(通用)
| 说明 | 符号 | | 说明 | 符号 |
|------|------| |------|------|
| 门控与主循环 | `check_key_monitors` | | 门控与主循环 | `check_key_monitors` |
| 录入、有仓拦截、4h Flash | `add_key` | | 录入、有仓拦截、4h Flash | `add_key` |
| 市价开仓 + 写 `order_monitors` | `_market_open_for_key_monitor` | | 市价开仓 + 写 `order_monitors` | `_market_open_for_key_monitor` |
| 计划 RR | `calc_rr_ratio(direction, E, SL, TP)` | | 计划 RR | `calc_rr_ratio(direction, E, SL, TP)` |
| 价格精度 | `round_price_to_exchange` | | 价格精度 | `round_price_to_exchange` |
+147 -147
View File
@@ -1,147 +1,147 @@
# 界面与风控更新说明(Binance 实例) # 界面与风控更新说明(Binance 实例)
## 顶栏导航(4 项) ## 顶栏导航(4 项)
| 顺序 | 名称 | 路由 | 说明 | | 顺序 | 名称 | 路由 | 说明 |
|------|------|------|------| |------|------|------|------|
| 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 | | 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 |
| 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/``/trade` | | 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/``/trade` |
| 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) | | 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 | | 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
## 关键位监控页 ## 关键位监控页
- 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。 - 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。 - 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。 - 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。
- 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Gate 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。 - 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Gate 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。
### 斐波关键位监控(方案 A:交易所限价) ### 斐波关键位监控(方案 A:交易所限价)
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) | | 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
| 上下沿 | 上沿 **H**、下沿 **L**(须 H > L | | 上下沿 | 上沿 **H**、下沿 **L**(须 H > L |
| 挂单价 E | **做多** `E = H ratio × (H L)`(自 H 向下回撤);**做空** `E = L + ratio × (H L)`(自 L 向上反弹) | | 挂单价 E | **做多** `E = H ratio × (H L)`(自 H 向下回撤);**做空** `E = L + ratio × (H L)`(自 L 向上反弹) |
| 做多 | 限价 @ E,止损 L,止盈 H | | 做多 | 限价 @ E,止损 L,止盈 H |
| 做空 | 限价 @ E,止损 H,止盈 L | | 做空 | 限价 @ E,止损 H,止盈 L |
| 添加后 | **立即**在 Binance U 本位挂限价单;卡片显示 **挂E**、限价单 ID | | 添加后 | **立即**在 Binance U 本位挂限价单;卡片显示 **挂E**、限价单 ID |
| 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案 | | 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案 |
| 成交后 | 挂交易所 TP/SL(含 Algo 通道条件单)→ 写入 **实盘下单监控**`monitor_type=关键位监控``key_signal_type=斐波回调…`)→ 从关键位列表移除 | | 成交后 | 挂交易所 TP/SL(含 Algo 通道条件单)→ 写入 **实盘下单监控**`monitor_type=关键位监控``key_signal_type=斐波回调…`)→ 从关键位列表移除 |
| 撤单 | 仅撤本条斐波的订单 ID,**不会**对该合约 `cancel_all_orders` / 全撤 Algo,避免误伤其他委托 | | 撤单 | 仅撤本条斐波的订单 ID,**不会**对该合约 `cancel_all_orders` / 全撤 Algo,避免误伤其他委托 |
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`0.618 理论约 1.6:10.786 约 3.7:1 | | 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`0.618 理论约 1.6:10.786 约 3.7:1 |
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 | | 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
后台轮询:`check_fib_key_monitors()`;箱体/收敛仍走 `check_key_monitors()` 后台轮询:`check_fib_key_monitors()`;箱体/收敛仍走 `check_key_monitors()`
手动删除关键位时,未成交斐波会先撤限价再删库。 手动删除关键位时,未成交斐波会先撤限价再删库。
### 箱体 / 收敛自动开仓(来源标注) ### 箱体 / 收敛自动开仓(来源标注)
- 自动开仓写入 `order_monitors.key_signal_type``箱体突破``收敛突破` - 自动开仓写入 `order_monitors.key_signal_type``箱体突破``收敛突破`
- 持仓与交易记录展示「来源 · 信号类型」。 - 持仓与交易记录展示「来源 · 信号类型」。
## 列表时间窗(UTC,全站顶栏) ## 列表时间窗(UTC,全站顶栏)
共用模块:仓库根目录 `history_window_lib.py`Gate / Binance 主站一致)。 共用模块:仓库根目录 `history_window_lib.py`Gate / Binance 主站一致)。
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 默认 | **UTC 当日**`win_preset=utc_today`,从 UTC 0:00 至当前时刻) | | 默认 | **UTC 当日**`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local` | | 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local` |
| 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 | | 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 |
| 与统计的关系 | **仅影响列表/导出****统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** | | 与统计的关系 | **仅影响列表/导出****统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 | | 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…` | | 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…` |
查询参数示例: 查询参数示例:
- `?win_preset=utc_today` - `?win_preset=utc_today`
- `?win_preset=utc_last24h` / `utc_last7d` - `?win_preset=utc_last24h` / `utc_last7d`
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00` - `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
## 交易记录与复盘 ## 交易记录与复盘
- 交易记录盈亏以**本地估算**为准(平仓时按成交/计划价计算);盈亏列可标注 **估** - 交易记录盈亏以**本地估算**为准(平仓时按成交/计划价计算);盈亏列可标注 **估**
- 与币安 App 不一致时,请在「核对修改」或复盘中 **手工填写** `reviewed_pnl_amount` 覆盖展示(不再提供批量「同步交易所盈亏」)。 - 与币安 App 不一致时,请在「核对修改」或复盘中 **手工填写** `reviewed_pnl_amount` 覆盖展示(不再提供批量「同步交易所盈亏」)。
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。 - **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。 - 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。
- 平仓写入 `trade_records` 时:`stop_loss``initial_stop_loss` 均写入**开仓时止损快照**`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。 - 平仓写入 `trade_records` 时:`stop_loss``initial_stop_loss` 均写入**开仓时止损快照**`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。
- **开仓类型**`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。 - **开仓类型**`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。
| `key_signal_type` | 自动写入的 `entry_reason` | | `key_signal_type` | 自动写入的 `entry_reason` |
|-------------------|---------------------------| |-------------------|---------------------------|
| 箱体突破 | 关键位箱体突破 | | 箱体突破 | 关键位箱体突破 |
| 收敛突破 | 关键位收敛突破 | | 收敛突破 | 关键位收敛突破 |
| 斐波回调0.618 | 关键位斐波0.618 | | 斐波回调0.618 | 关键位斐波0.618 |
| 斐波回调0.786 | 关键位斐波0.786 | | 斐波回调0.786 | 关键位斐波0.786 |
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。 - 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。 - 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。 - 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。
- `/api/journals``/api/reviews` 支持同一时间窗 query,与列表一致。 - `/api/journals``/api/reviews` 支持同一时间窗 query,与列表一致。
### 导出(交易记录 v3 ### 导出(交易记录 v3
- 文件名:`trade_records_v3_YYYYMMDD.csv` - 文件名:`trade_records_v3_YYYYMMDD.csv`
- 相对 v2 增加:`key_signal_type``initial_stop_loss`(及开仓快照列)、`planned_rr``actual_rr``risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。 - 相对 v2 增加:`key_signal_type``initial_stop_loss`(及开仓快照列)、`planned_rr``actual_rr``risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。
- 「关键位历史」导出同样受 UTC 时间窗限制。 - 「关键位历史」导出同样受 UTC 时间窗限制。
## 实盘下单页 ## 实盘下单页
- 左列:实盘下单监控(表单、划转、规则)。 - 左列:实盘下单监控(表单、划转、规则)。
- 右列:实时持仓(独立模块)。 - 右列:实时持仓(独立模块)。
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。 - **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——**先撤**该合约全部 TP/SL(含 Algo 条件单)**再挂**新止损 + 原止盈(`replace_active_monitor_tpsl_on_exchange`)。仅交易所成功后才写库;失败发企业微信告警。未配置实盘 API 时仍只更新本地。 - **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——**先撤**该合约全部 TP/SL(含 Algo 条件单)**再挂**新止损 + 原止盈(`replace_active_monitor_tpsl_on_exchange`)。仅交易所成功后才写库;失败发企业微信告警。未配置实盘 API 时仍只更新本地。
## 统计分析页(`/stats` ## 统计分析页(`/stats`
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00``.env` 默认 **8** | | 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00``.env` 默认 **8** |
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 | | 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 |
| URL | 切换后写入 `stats_segment=`(如 `all``manual``key_box``key_conv``key_fib618``key_fib786`),刷新 `/stats` 可保持选项 | | URL | 切换后写入 `stats_segment=`(如 `all``manual``key_box``key_conv``key_fib618``key_fib786`),刷新 `/stats` 可保持选项 |
| 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) | | 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) |
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 | | 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 | | 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
## 持仓与计仓 ## 持仓与计仓
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。 - `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(字段 `trading_sessions.key_sizing_capital_snapshot`)。 - 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(字段 `trading_sessions.key_sizing_capital_snapshot`)。
## 配置 ## 配置
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。 详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。
## 自动备份(服务器) ## 自动备份(服务器)
- 脚本:`scripts/backup_data.sh``crypto.db` + `static/images` - 脚本:`scripts/backup_data.sh``crypto.db` + `static/images`
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** - 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30**
- 详见 `部署文档.md` 第 5.3 节 - 详见 `部署文档.md` 第 5.3 节
## 数据库(启动时自动迁移) ## 数据库(启动时自动迁移)
`key_monitors` 斐波字段:`fib_limit_order_id``fib_entry_price``fib_stop_loss``fib_take_profit``fib_order_amount``fib_margin_capital``fib_leverage` `key_monitors` 斐波字段:`fib_limit_order_id``fib_entry_price``fib_stop_loss``fib_take_profit``fib_order_amount``fib_margin_capital``fib_leverage`
`trade_records` / `order_monitors``key_signal_type``exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key``entry_reason``reviewed_entry_reason``initial_stop_loss` `trade_records` / `order_monitors``key_signal_type``exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key``entry_reason``reviewed_entry_reason``initial_stop_loss`
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。 **历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。
## 涉及文件(便于排查) ## 涉及文件(便于排查)
| 路径 | 说明 | | 路径 | 说明 |
|------|------| |------|------|
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 | | `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
| `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL``entry_reason_from_key_signal` | | `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL``entry_reason_from_key_signal` |
| `crypto_monitor_binance/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 | | `crypto_monitor_binance/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 |
| `crypto_monitor_binance/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 | | `crypto_monitor_binance/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 |
## 升级步骤 ## 升级步骤
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env` 1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。 2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
3. 重启 Binance 实例(如 `pm2 restart crypto_binance`);SQLite 会自动 `ALTER` 缺列(斐波、交易所盈亏、`entry_reason` 等)。 3. 重启 Binance 实例(如 `pm2 restart crypto_binance`);SQLite 会自动 `ALTER` 缺列(斐波、交易所盈亏、`entry_reason` 等)。
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。 4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**`/stats` 可见分品类统计与「北京 8:00 切日」说明。 5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**`/stats` 可见分品类统计与「北京 8:00 切日」说明。
6. 建议先用测试币验证斐波:限价挂出、标记价失效撤单、成交后 TP/SL 与订单监控是否正常;平仓后检查交易记录止损(开仓)与开仓类型。 6. 建议先用测试币验证斐波:限价挂出、标记价失效撤单、成交后 TP/SL 与订单监控是否正常;平仓后检查交易记录止损(开仓)与开仓类型。
+378 -378
View File
@@ -1,378 +1,378 @@
# `crypto_monitor_binance` 部署指南:SSH SOCKS + Binance + PM2Ubuntu # `crypto_monitor_binance` 部署指南:SSH SOCKS + Binance + PM2Ubuntu
项目功能、环境变量总览与本地运行说明见 **[README.md](./README.md)**。 项目功能、环境变量总览与本地运行说明见 **[README.md](./README.md)**。
本文面向:**在本机或 VPS 上运行本项目**,但 **直连 Binance API 不稳定、超时或被网络策略拦截** 的场景。思路是: 本文面向:**在本机或 VPS 上运行本项目**,但 **直连 Binance API 不稳定、超时或被网络策略拦截** 的场景。思路是:
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能稳定访问 Binance 的机器(常见为一台境外 VPS) - 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能稳定访问 Binance 的机器(常见为一台境外 VPS)
- 项目在 `.env` 中设置 **`BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所 - 项目在 `.env` 中设置 **`BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
- **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2** - **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2**
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 默认进程名为 **`crypto-monitor-binance`** - 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 默认进程名为 **`crypto-monitor-binance`**
> 安全提醒:不要把 `.env`、私钥 `.pem`、Binance API Key / Secret 提交到 Git;下文只用占位符。 > 安全提醒:不要把 `.env`、私钥 `.pem`、Binance API Key / Secret 提交到 Git;下文只用占位符。
--- ---
## 0. 你需要准备的东西 ## 0. 你需要准备的东西
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」) - 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
- 一台可 SSH 登录、且 **能正常访问 Binance API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root` - 一台可 SSH 登录、且 **能正常访问 Binance API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守) - SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
- 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2 - 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2
- Binance 账户:已开通 **USDT-M 永续合约**API Key 勾选 **合约**、**万向划转**(若使用资金↔合约划转)等所需权限,并配置 **IP 白名单**(若启用) - Binance 账户:已开通 **USDT-M 永续合约**API Key 勾选 **合约**、**万向划转**(若使用资金↔合约划转)等所需权限,并配置 **IP 白名单**(若启用)
--- ---
## 1. 获取代码与目录 ## 1. 获取代码与目录
将包含 `app.py` 的项目放到固定目录,例如: 将包含 `app.py` 的项目放到固定目录,例如:
```bash ```bash
mkdir -p /opt/crypto_monitor mkdir -p /opt/crypto_monitor
cd /opt/crypto_monitor cd /opt/crypto_monitor
git clone https://git.bz121.com/dekun/crypto_monitor.git git clone https://git.bz121.com/dekun/crypto_monitor.git
cd crypto_monitor/crypto_monitor_binance cd crypto_monitor/crypto_monitor_binance
``` ```
下文用 **`/opt/crypto_monitor/crypto_monitor_binance`** 仅为示例,请换成你的实际绝对路径。 下文用 **`/opt/crypto_monitor/crypto_monitor_binance`** 仅为示例,请换成你的实际绝对路径。
拉取代码后,若目录下尚无 `.env`,先从模板生成(**勿**把填好密钥的 `.env` 提交 Git): 拉取代码后,若目录下尚无 `.env`,先从模板生成(**勿**把填好密钥的 `.env` 提交 Git):
```bash ```bash
cp -n .env.example .env # -n:已存在 .env 时不覆盖 cp -n .env.example .env # -n:已存在 .env 时不覆盖
``` ```
--- ---
## 2. 配置 SSH 私钥与 `~/.ssh/config` ## 2. 配置 SSH 私钥与 `~/.ssh/config`
```bash ```bash
mkdir -p ~/.ssh mkdir -p ~/.ssh
chmod 700 ~/.ssh chmod 700 ~/.ssh
# 私钥示例:~/.ssh/vps1.pem # 私钥示例:~/.ssh/vps1.pem
chmod 600 ~/.ssh/vps1.pem chmod 600 ~/.ssh/vps1.pem
``` ```
编辑 `~/.ssh/config`(示例别名 **`bn-vps`**,与你手工启动 `ssh -D ... bn-vps` 一致即可): 编辑 `~/.ssh/config`(示例别名 **`bn-vps`**,与你手工启动 `ssh -D ... bn-vps` 一致即可):
```sshconfig ```sshconfig
Host bn-vps Host bn-vps
HostName 你的_VPS_IP HostName 你的_VPS_IP
User root User root
IdentityFile ~/.ssh/vps1.pem IdentityFile ~/.ssh/vps1.pem
IdentitiesOnly yes IdentitiesOnly yes
ServerAliveInterval 30 ServerAliveInterval 30
ServerAliveCountMax 3 ServerAliveCountMax 3
ExitOnForwardFailure yes ExitOnForwardFailure yes
BatchMode yes BatchMode yes
``` ```
测试: 测试:
```bash ```bash
ssh bn-vps true ssh bn-vps true
``` ```
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。 > 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
--- ---
## 3. 手工验证:SSH SOCKS + Binance API ## 3. 手工验证:SSH SOCKS + Binance API
### 3.1 本地 SOCKS(示例端口 1080 ### 3.1 本地 SOCKS(示例端口 1080
```bash ```bash
ssh -N -D 127.0.0.1:1080 bn-vps ssh -N -D 127.0.0.1:1080 bn-vps
``` ```
保持运行,另开终端继续。 保持运行,另开终端继续。
### 3.2 验证经 SOCKS 可访问 Binance(公开接口) ### 3.2 验证经 SOCKS 可访问 Binance(公开接口)
```bash ```bash
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time
``` ```
应返回 JSON(含 `serverTime` 字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。 应返回 JSON(含 `serverTime` 字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
--- ---
## 4. Python 虚拟环境 ## 4. Python 虚拟环境
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
python3 -m venv .venv python3 -m venv .venv
source .venv/bin/activate source .venv/bin/activate
python -m pip install -U pip python -m pip install -U pip
pip install flask requests ccxt werkzeug PySocks Pillow pip install flask requests ccxt werkzeug PySocks Pillow
``` ```
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。 走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
可选: 可选:
```bash ```bash
export PYTHONDONTWRITEBYTECODE=1 export PYTHONDONTWRITEBYTECODE=1
``` ```
--- ---
## 5. 配置环境变量(`.env.example` → `.env` ## 5. 配置环境变量(`.env.example` → `.env`
| 文件 | 是否进 Git | 说明 | | 文件 | 是否进 Git | 说明 |
|------|------------|------| |------|------------|------|
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 | | **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** | | **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
### 5.1 首次配置 ### 5.1 首次配置
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
cp -n .env.example .env # 已存在 .env 时不覆盖 cp -n .env.example .env # 已存在 .env 时不覆盖
nano .env # 填入 API、登录密码、端口、代理等 nano .env # 填入 API、登录密码、端口、代理等
``` ```
### 5.2 备份与 `git pull` ### 5.2 备份与 `git pull`
- **`.env` 已被仓库根目录 `.gitignore` 忽略**`git pull` **不会**覆盖或删除你本地的 `.env` - **`.env` 已被仓库根目录 `.gitignore` 忽略**`git pull` **不会**覆盖或删除你本地的 `.env`
- 若远端更新了 **`.env.example`**(新增变量名),pull 后请对照模板,**手动把新行补进你的 `.env`**(不会自动合并进 `.env`)。 - 若远端更新了 **`.env.example`**(新增变量名),pull 后请对照模板,**手动把新行补进你的 `.env`**(不会自动合并进 `.env`)。
- **建议在每次 `git pull` 或大批量改配置前备份** - **建议在每次 `git pull` 或大批量改配置前备份**
```bash ```bash
cp .env .env.backup.$(date +%Y%m%d) cp .env .env.backup.$(date +%Y%m%d)
# 恢复示例:cp .env.backup.20260516 .env # 恢复示例:cp .env.backup.20260516 .env
``` ```
- **换机 / 迁移**:用 `scp` 复制整份 `.env` 到新机器对应目录;或在新机重新 `cp .env.example .env` 后填写。 - **换机 / 迁移**:用 `scp` 复制整份 `.env` 到新机器对应目录;或在新机重新 `cp .env.example .env` 后填写。
### 5.3 自动备份(数据库 + 复盘图片) ### 5.3 自动备份(数据库 + 复盘图片)
默认每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天** 后自动删除更早的目录。 默认每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天** 后自动删除更早的目录。
备份内容(路径来自 `.env``DB_PATH``UPLOAD_DIR`): 备份内容(路径来自 `.env``DB_PATH``UPLOAD_DIR`):
- `crypto.db`(优先 `sqlite3 .backup` 热备) - `crypto.db`(优先 `sqlite3 .backup` 热备)
- `static/images` 打包为 `static_images.tar.gz` - `static/images` 打包为 `static_images.tar.gz`
目录结构示例: 目录结构示例:
```text ```text
/root/backups/crypto_monitor_binance/2026-05-17/ /root/backups/crypto_monitor_binance/2026-05-17/
crypto.db crypto.db
static_images.tar.gz static_images.tar.gz
manifest.txt manifest.txt
``` ```
**一次性安装定时任务**(在对应项目目录执行,Binance / Gate 各执行一次): **一次性安装定时任务**(在对应项目目录执行,Binance / Gate 各执行一次):
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
bash scripts/install_backup_cron.sh bash scripts/install_backup_cron.sh
``` ```
Gate 实例: Gate 实例:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
bash scripts/install_backup_cron.sh bash scripts/install_backup_cron.sh
``` ```
Gate Bot 实例(趋势回调等): Gate Bot 实例(趋势回调等):
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
bash scripts/install_backup_cron.sh bash scripts/install_backup_cron.sh
``` ```
**立即试跑**(不写 cron): **立即试跑**(不写 cron):
```bash ```bash
bash scripts/backup_data.sh bash scripts/backup_data.sh
``` ```
日志默认:`/var/log/crypto-monitor-backup-<项目目录名>.log`。可选在 `.env` 中覆盖:`BACKUP_ROOT``BACKUP_RETENTION_DAYS``BACKUP_INSTANCE` 日志默认:`/var/log/crypto-monitor-backup-<项目目录名>.log`。可选在 `.env` 中覆盖:`BACKUP_ROOT``BACKUP_RETENTION_DAYS``BACKUP_INSTANCE`
**恢复示例**(先停 PM2,再覆盖文件): **恢复示例**(先停 PM2,再覆盖文件):
```bash ```bash
pm2 stop crypto-monitor-binance pm2 stop crypto-monitor-binance
cp /root/backups/crypto_monitor_binance/2026-05-16/crypto.db ./crypto.db cp /root/backups/crypto_monitor_binance/2026-05-16/crypto.db ./crypto.db
tar -xzf /root/backups/crypto_monitor_binance/2026-05-16/static_images.tar.gz -C . tar -xzf /root/backups/crypto_monitor_binance/2026-05-16/static_images.tar.gz -C .
pm2 start ecosystem.config.cjs pm2 start ecosystem.config.cjs
``` ```
建议安装:`apt install -y sqlite3`(热备更稳)。 建议安装:`apt install -y sqlite3`(热备更稳)。
### 5.4 必填项检查(Binance + 代理) ### 5.4 必填项检查(Binance + 代理)
与交易所相关的变量使用 **`BINANCE_`** 前缀(与代码一致)。至少确认: 与交易所相关的变量使用 **`BINANCE_`** 前缀(与代码一致)。至少确认:
```env ```env
APP_HOST=127.0.0.1 APP_HOST=127.0.0.1
APP_PORT=5000 APP_PORT=5000
# 实盘(按需) # 实盘(按需)
LIVE_TRADING_ENABLED=false LIVE_TRADING_ENABLED=false
BINANCE_API_KEY=你的_Key BINANCE_API_KEY=你的_Key
BINANCE_API_SECRET=你的_Secret BINANCE_API_SECRET=你的_Secret
# 保证金:cross=全仓 isolated=逐仓(与币安账户/习惯一致) # 保证金:cross=全仓 isolated=逐仓(与币安账户/习惯一致)
BINANCE_MARGIN_MODE=cross BINANCE_MARGIN_MODE=cross
# 持仓模式:hedge=双向(需在币安开启双向持仓);oneway=单向 # 持仓模式:hedge=双向(需在币安开启双向持仓);oneway=单向
BINANCE_POSITION_MODE=hedge BINANCE_POSITION_MODE=hedge
# 条件单触发参考:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价 # 条件单触发参考:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价
BINANCE_TRIGGER_WORKING_TYPE=CONTRACT_PRICE BINANCE_TRIGGER_WORKING_TYPE=CONTRACT_PRICE
# 经本机 SSH 动态转发访问 Binance(端口与隧道一致) # 经本机 SSH 动态转发访问 Binance(端口与隧道一致)
BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080 BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一) # 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
# BINANCE_HTTP_PROXY=http://127.0.0.1:7890 # BINANCE_HTTP_PROXY=http://127.0.0.1:7890
# BINANCE_HTTPS_PROXY=http://127.0.0.1:7890 # BINANCE_HTTPS_PROXY=http://127.0.0.1:7890
``` ```
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。 说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
**止盈止损说明(应用逻辑)**:实盘开仓后,程序会在 Binance USDT-M 永续上挂 **`STOP_MARKET`(止损)** 与 **`TAKE_PROFIT_MARKET`(止盈)**`BINANCE_POSITION_MODE=hedge` 时会自动带 **`positionSide`**,须与币安合约「双向持仓」开关一致。不显式传 **`reduceOnly`**(否则易触发 API **`-1106`**`Parameter 'reduceOnly' sent when not required`)。 **止盈止损说明(应用逻辑)**:实盘开仓后,程序会在 Binance USDT-M 永续上挂 **`STOP_MARKET`(止损)** 与 **`TAKE_PROFIT_MARKET`(止盈)**`BINANCE_POSITION_MODE=hedge` 时会自动带 **`positionSide`**,须与币安合约「双向持仓」开关一致。不显式传 **`reduceOnly`**(否则易触发 API **`-1106`**`Parameter 'reduceOnly' sent when not required`)。
--- ---
## 6. 自检脚本(可选) ## 6. 自检脚本(可选)
在已配置 `.env` 且网络可达的前提下: 在已配置 `.env` 且网络可达的前提下:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
source .venv/bin/activate source .venv/bin/activate
python scripts/verify_binance_funding.py python scripts/verify_binance_funding.py
``` ```
用于粗测资金钱包与合约钱包 USDT 读取(需有效 API 与权限)。 用于粗测资金钱包与合约钱包 USDT 读取(需有效 API 与权限)。
--- ---
## 7. 手工启动 Flask(验证) ## 7. 手工启动 Flask(验证)
1. SOCKS 已监听 `127.0.0.1:1080`(若使用代理) 1. SOCKS 已监听 `127.0.0.1:1080`(若使用代理)
2.`source .venv/bin/activate` 2.`source .venv/bin/activate`
3. `.env` 已按需配置 `BINANCE_SOCKS_PROXY` 3. `.env` 已按需配置 `BINANCE_SOCKS_PROXY`
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
source .venv/bin/activate source .venv/bin/activate
python app.py python app.py
``` ```
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。 浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
--- ---
## 8. 安装 PM2 ## 8. 安装 PM2
```bash ```bash
sudo npm i -g pm2 sudo npm i -g pm2
pm2 -v pm2 -v
``` ```
--- ---
## 9. PM2:使用仓库内 `ecosystem.config.cjs`(推荐) ## 9. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
在项目根目录: 在项目根目录:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
pm2 start ecosystem.config.cjs pm2 start ecosystem.config.cjs
pm2 status pm2 status
pm2 logs --lines 200 pm2 logs --lines 200
``` ```
默认只启动 **`crypto-monitor-binance`**`.venv/bin/python app.py`)。 默认只启动 **`crypto-monitor-binance`**`.venv/bin/python app.py`)。
### 本机已可直连 Binance、不需要隧道时 ### 本机已可直连 Binance、不需要隧道时
`.env` 里应 **去掉或留空** `BINANCE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs` `.env` 里应 **去掉或留空** `BINANCE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`
### 开机自启 ### 开机自启
```bash ```bash
pm2 save pm2 save
pm2 startup pm2 startup
# 按屏幕提示执行一条 sudo 命令 # 按屏幕提示执行一条 sudo 命令
``` ```
--- ---
## 10. 等价手工命令(不使用 ecosystem 文件时) ## 10. 等价手工命令(不使用 ecosystem 文件时)
### 10.1 SSH SOCKS(自行后台常驻,不推荐用 PM2) ### 10.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd): 示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd):
```bash ```bash
ssh -N -D 127.0.0.1:1080 bn-vps \ ssh -N -D 127.0.0.1:1080 bn-vps \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -o ExitOnForwardFailure=yes
``` ```
### 10.2 Flask ### 10.2 Flask
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_binance cd /opt/crypto_monitor/crypto_monitor_binance
pm2 start /opt/crypto_monitor/crypto_monitor_binance/.venv/bin/python --name crypto-monitor-binance -- \ pm2 start /opt/crypto_monitor/crypto_monitor_binance/.venv/bin/python --name crypto-monitor-binance -- \
/opt/crypto_monitor/crypto_monitor_binance/app.py /opt/crypto_monitor/crypto_monitor_binance/app.py
``` ```
--- ---
## 11. 交易所「连接不上」排查清单 ## 11. 交易所「连接不上」排查清单
1. **`.env` 是否为 Binance 变量**`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` / `BINANCE_API_KEY` / `BINANCE_API_SECRET` 等前缀需与代码一致。 1. **`.env` 是否为 Binance 变量**`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` / `BINANCE_API_KEY` / `BINANCE_API_SECRET` 等前缀需与代码一致。
2. **隧道是否在本机端口监听**(若配置了 `BINANCE_SOCKS_PROXY`): 2. **隧道是否在本机端口监听**(若配置了 `BINANCE_SOCKS_PROXY`):
```bash ```bash
ss -lntp | grep 1080 || true ss -lntp | grep 1080 || true
``` ```
3. **curl 复测 Binance**(与第 3.2 节相同);curl 不通则应用也不会通。 3. **curl 复测 Binance**(与第 3.2 节相同);curl 不通则应用也不会通。
4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。 4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。 5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
6. **API 权限与 IP 白名单**:Secret 错误、权限不足、未放行当前出口 IP 时,私有接口会失败。 6. **API 权限与 IP 白名单**:Secret 错误、权限不足、未放行当前出口 IP 时,私有接口会失败。
7. **启动顺序**:若走代理,先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。 7. **启动顺序**:若走代理,先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
--- ---
## 12. 推荐启动顺序(习惯) ## 12. 推荐启动顺序(习惯)
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time` 成功 1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time` 成功
2. `pm2 start ecosystem.config.cjs` 2. `pm2 start ecosystem.config.cjs`
3. 再确认页面与余额等接口正常 3. 再确认页面与余额等接口正常
--- ---
## 13. 免责声明 ## 13. 免责声明
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。 交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
--- ---
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py` ## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
在 Ubuntu 上: 在 Ubuntu 上:
1)预览(不写库): 1)预览(不写库):
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
``` ```
2)确认后执行: 2)确认后执行:
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
``` ```
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。 默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
+143 -143
View File
@@ -1,143 +1,143 @@
# 使用说明 # 使用说明
**本文件对应仓库:`crypto_monitor_gate`Gate.io USDT 永续)。** **本文件对应仓库:`crypto_monitor_gate`Gate.io USDT 永续)。**
功能、界面与 **Binance U 本位版**(目录 `crypto_monitor_binance`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**`GATE_*` / `BINANCE_*`),文末有对照。 功能、界面与 **Binance U 本位版**(目录 `crypto_monitor_binance`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**`GATE_*` / `BINANCE_*`),文末有对照。
**更细的部署(SSH 代理、PM2、依赖安装)** 见同目录 **`部署文档.md`**。 **更细的部署(SSH 代理、PM2、依赖安装)** 见同目录 **`部署文档.md`**。
**关键位自动开仓的规则、RR、结案原因****`关键位自动下单说明.md`**。 **关键位自动开仓的规则、RR、结案原因****`关键位自动下单说明.md`**。
--- ---
## 1. 它能做什么 ## 1. 它能做什么
面向个人盘面的 **Web 控制台**,主要能力包括: 面向个人盘面的 **Web 控制台**,主要能力包括:
| 模块 | 说明 | | 模块 | 说明 |
|------|------| |------|------|
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 | | **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 |
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 | | **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 |
| **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出。 | | **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出。 |
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。 后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。
--- ---
## 2. 运行前必须配置(`.env` ## 2. 运行前必须配置(`.env`
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env``.env` 勿提交 Git`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。 首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env``.env` 勿提交 Git`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。
至少检查以下项(具体键名以 **`.env.example`** 为准): 至少检查以下项(具体键名以 **`.env.example`** 为准):
| 类别 | 说明 | | 类别 | 说明 |
|------|------| |------|------|
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 | | **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 |
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 | | **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 |
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 | | **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 |
| **交易所 API** | **本仓库:** `GATE_API_KEY``GATE_API_SECRET`;合约相关见 `GATE_MARGIN_MODE``GATE_POS_MODE``GATE_TPSL_*` 等。**勿**把 `.env` 提交到 Git。 | | **交易所 API** | **本仓库:** `GATE_API_KEY``GATE_API_SECRET`;合约相关见 `GATE_MARGIN_MODE``GATE_POS_MODE``GATE_TPSL_*` 等。**勿**把 `.env` 提交到 Git。 |
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR``KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 | | **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR``KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 |
网络不稳定时可为 Gate 配置 **`GATE_SOCKS_PROXY`** 等(见 **`部署文档.md`**)。 网络不稳定时可为 Gate 配置 **`GATE_SOCKS_PROXY`** 等(见 **`部署文档.md`**)。
--- ---
## 3. 如何启动与登录 ## 3. 如何启动与登录
1.**`部署文档.md`** 建好虚拟环境、安装依赖(如 `flask``requests``ccxt`、按需 `Pillow``PySocks` 等),配置好 `.env` 1.**`部署文档.md`** 建好虚拟环境、安装依赖(如 `flask``requests``ccxt`、按需 `Pillow``PySocks` 等),配置好 `.env`
2. 启动 Flask 应用(本仓库可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。 2. 启动 Flask 应用(本仓库可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。 3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。
登录后顶栏为四页:**关键位监控** | **实盘下单**(默认首页)| **交易记录与复盘** | **统计分析** 登录后顶栏为四页:**关键位监控** | **实盘下单**(默认首页)| **交易记录与复盘** | **统计分析**
--- ---
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor` ## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`
### 4.1 添加一条关键位 ### 4.1 添加一条关键位
1. **币种**:如 `BTC``BTC/USDT`(会规范成内部符号)。 1. **币种**:如 `BTC``BTC/USDT`(会规范成内部符号)。
2. **类型**(必选其一): 2. **类型**(必选其一):
| 类型 | 行为摘要 | | 类型 | 行为摘要 |
|------|----------| |------|----------|
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 | | **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 |
| **收敛突破** | 同上(自动开仓类)。 | | **收敛突破** | 同上(自动开仓类)。 |
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 | | **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 |
| **关键支撑位** | 同上(仅提醒)。 | | **关键支撑位** | 同上(仅提醒)。 |
3. **方向**:做多 / 做空(必选)。 3. **方向**:做多 / 做空(必选)。
4. **上沿 / 下沿**:必填;保存时会按交易所 **价格精度** 取整。 4. **上沿 / 下沿**:必填;保存时会按交易所 **价格精度** 取整。
**限制:** **限制:**
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。 活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。
**4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示****不阻挡**提交。 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示****不阻挡**提交。
### 4.2 触发后会发生什么(简版) ### 4.2 触发后会发生什么(简版)
- **箱体 / 收敛**:门控通过后计算计划 SL/TP 与 RR;不达标则 **微信说明 + `rr_insufficient` 结案**;达标则尝试 **市价开仓**,成功 **`auto_opened`**,失败 **`exchange_failed`**——均 **不重试同一关键位** - **箱体 / 收敛**:门控通过后计算计划 SL/TP 与 RR;不达标则 **微信说明 + `rr_insufficient` 结案**;达标则尝试 **市价开仓**,成功 **`auto_opened`**,失败 **`exchange_failed`**——均 **不重试同一关键位**
- **阻力 / 支撑**:仅 **单次推送****`key_level_alert_only`** 结案。 - **阻力 / 支撑**:仅 **单次推送****`key_level_alert_only`** 结案。
详细公式、结案字段、与企业微信文案口径见 **`关键位自动下单说明.md`**。 详细公式、结案字段、与企业微信文案口径见 **`关键位自动下单说明.md`**。
### 4.3 列表与历史 ### 4.3 列表与历史
- 当前条目可 **删除**(会按规则记入历史的情形见页面说明)。 - 当前条目可 **删除**(会按规则记入历史的情形见页面说明)。
- **关键位历史**:已结案记录;可配合导出链接(若有)做备份。 - **关键位历史**:已结案记录;可配合导出链接(若有)做备份。
--- ---
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`) ## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
用于 **自己点按钮** 开单: 用于 **自己点按钮** 开单:
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1,与关键位自动单共用)。 - 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1,与关键位自动单共用)。
- **人工开仓**时计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1),否则页面弹窗且后端拒绝。 - **人工开仓**时计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1),否则页面弹窗且后端拒绝。
- 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单说明)。 - 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单说明)。
- 勾选是否启用 **移动保本** 等行为以 `.env`/页面默认值为准。 - 勾选是否启用 **移动保本** 等行为以 `.env`/页面默认值为准。
平仓通过页面 **平仓**(或等价入口),会从交易所市价处理并更新记录。**删除/误操作可能造成真实盈亏**,请先确认环境与方向。 平仓通过页面 **平仓**(或等价入口),会从交易所市价处理并更新记录。**删除/误操作可能造成真实盈亏**,请先确认环境与方向。
开仓成功后持仓卡片上会显示 **「来源」**:手工单一般为 **下单监控**;来自关键位自动单的为 **关键位监控** 开仓成功后持仓卡片上会显示 **「来源」**:手工单一般为 **下单监控**;来自关键位自动单的为 **关键位监控**
--- ---
## 6. 企业微信会看到什么 ## 6. 企业微信会看到什么
- 关键位:按类型与结案结果推送(RR 不足、下单失败、自动开仓成功、仅阻力支撑提醒等),**每条关键位结案路径原则上一条主推送**(详见 `关键位自动下单说明.md`)。 - 关键位:按类型与结案结果推送(RR 不足、下单失败、自动开仓成功、仅阻力支撑提醒等),**每条关键位结案路径原则上一条主推送**(详见 `关键位自动下单说明.md`)。
- 手工开仓、平仓、部分异常也会在规则满足时推送(以代码与配置为准)。 - 手工开仓、平仓、部分异常也会在规则满足时推送(以代码与配置为准)。
若未配置 **`WECHAT_WEBHOOK`** 或网络失败,可能只是看不到推送,不代表逻辑未执行;要紧操作请以 **交易所端持仓与挂单** 为准核对。 若未配置 **`WECHAT_WEBHOOK`** 或网络失败,可能只是看不到推送,不代表逻辑未执行;要紧操作请以 **交易所端持仓与挂单** 为准核对。
--- ---
## 7. 强烈建议的风险与运维习惯 ## 7. 强烈建议的风险与运维习惯
1. **先用 `LIVE_TRADING_ENABLED=false`** 验证页面、录入、推送,再开小资金开实盘。 1. **先用 `LIVE_TRADING_ENABLED=false`** 验证页面、录入、推送,再开小资金开实盘。
2. **API 权限**:仅开所需合约权限;勿泄露密钥;定期轮换。 2. **API 权限**:仅开所需合约权限;勿泄露密钥;定期轮换。
3. **单进程控盘**:同一账户避免本程序与其他机器人 **重复开仓** 3. **单进程控盘**:同一账户避免本程序与其他机器人 **重复开仓**
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。 4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
5. **升级代码后**:启动时会跑 **数据库迁移**(如新列 `order_monitors.monitor_type`);首次启动关注一下日志或无报错页面。 5. **升级代码后**:启动时会跑 **数据库迁移**(如新列 `order_monitors.monitor_type`);首次启动关注一下日志或无报错页面。
--- ---
## 8. 常见问题(简要) ## 8. 常见问题(简要)
| 现象 | 可自查 | | 现象 | 可自查 |
|------|--------| |------|--------|
| 关键位永远不触发 | 5m 门控是否全通过(页面门控摘要)、币种日成交量是否在规则内、`KLINE_TIMEFRAME`。 | | 关键位永远不触发 | 5m 门控是否全通过(页面门控摘要)、币种日成交量是否在规则内、`KLINE_TIMEFRAME`。 |
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED``KEY_AUTO_MIN_PLANNED_RR`、计划 RR、是否已有持仓、API/余额报错(微信或日志)。 | | 有信号但不自动开仓 | `LIVE_TRADING_ENABLED``KEY_AUTO_MIN_PLANNED_RR`、计划 RR、是否已有持仓、API/余额报错(微信或日志)。 |
| 加不了箱体/收敛 | 是否已有活跃持仓;先平仓或改用「阻力/支撑位」仅提醒。 | | 加不了箱体/收敛 | 是否已有活跃持仓;先平仓或改用「阻力/支撑位」仅提醒。 |
| 推送收不到 | `WECHAT_WEBHOOK`、企业微信机器人配额与网络。 | | 推送收不到 | `WECHAT_WEBHOOK`、企业微信机器人配额与网络。 |
--- ---
## 9. Binance 版(`crypto_monitor_binance`)差异速查 ## 9. Binance 版(`crypto_monitor_binance`)差异速查
| 项目 | Gate 本仓库 | Binance 版 | | 项目 | Gate 本仓库 | Binance 版 |
|------|-------------|------------| |------|-------------|------------|
| API 变量 | `GATE_API_KEY``GATE_API_SECRET``GATE_*` | `BINANCE_API_KEY``BINANCE_API_SECRET``BINANCE_*` | | API 变量 | `GATE_API_KEY``GATE_API_SECRET``GATE_*` | `BINANCE_API_KEY``BINANCE_API_SECRET``BINANCE_*` |
| 实盘开关 | `LIVE_TRADING_ENABLED`(通用) | 同上 | | 实盘开关 | `LIVE_TRADING_ENABLED`(通用) | 同上 |
| 止盈止损挂载路径 | `_gate_place_tp_sl_orders``GATE_TPSL_*` | `_binance_place_tp_sl_orders`U 本位条件单) | | 止盈止损挂载路径 | `_gate_place_tp_sl_orders``GATE_TPSL_*` | `_binance_place_tp_sl_orders`U 本位条件单) |
| 资金显示舍入 | 以本仓库为准 | 与 **`FUNDS_DECIMALS`** 等一致 | | 资金显示舍入 | 以本仓库为准 | 与 **`FUNDS_DECIMALS`** 等一致 |
| 专门文档 | **`关键位自动下单说明.md`**(各仓库有一份,开头标明交易所) | 同左 | | 专门文档 | **`关键位自动下单说明.md`**(各仓库有一份,开头标明交易所) | 同左 |
操作流程(登录、关键位四类、手工单、单仓)**两份程序一致**:换目录、换 `.env` 即可对照使用。 操作流程(登录、关键位四类、手工单、单仓)**两份程序一致**:换目录、换 `.env` 即可对照使用。
+148 -148
View File
@@ -1,148 +1,148 @@
# 界面与风控更新说明(Gate 实例) # 界面与风控更新说明(Gate 实例)
## 顶栏导航(4 项) ## 顶栏导航(4 项)
| 顺序 | 名称 | 路由 | 说明 | | 顺序 | 名称 | 路由 | 说明 |
|------|------|------|------| |------|------|------|------|
| 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 | | 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 |
| 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/``/trade` | | 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/``/trade` |
| 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) | | 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 | | 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
## 关键位监控页 ## 关键位监控页
- 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。 - 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。 - 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。 - 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。
- 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Binance 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。 - 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Binance 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。
### 斐波关键位监控(方案 A:交易所限价) ### 斐波关键位监控(方案 A:交易所限价)
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) | | 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
| 上下沿 | 上沿 **H**、下沿 **L**(须 H > L | | 上下沿 | 上沿 **H**、下沿 **L**(须 H > L |
| 挂单价 E | **做多** `E = H ratio × (H L)`(自 H 向下回撤);**做空** `E = L + ratio × (H L)`(自 L 向上反弹) | | 挂单价 E | **做多** `E = H ratio × (H L)`(自 H 向下回撤);**做空** `E = L + ratio × (H L)`(自 L 向上反弹) |
| 做多 | 限价 @ E,止损 L,止盈 H | | 做多 | 限价 @ E,止损 L,止盈 H |
| 做空 | 限价 @ E,止损 H,止盈 L | | 做空 | 限价 @ E,止损 H,止盈 L |
| 添加后 | **立即**在 Gate 挂限价单;卡片显示 **挂E**、限价单 ID | | 添加后 | **立即**在 Gate 挂限价单;卡片显示 **挂E**、限价单 ID |
| 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案(不写历史开仓) | | 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案(不写历史开仓) |
| 成交后 | 按仓位挂交易所 TP/SL → 写入 **实盘下单监控**`monitor_type=关键位监控``key_signal_type=斐波回调0.618/0.786`)→ 从关键位列表移除 | | 成交后 | 按仓位挂交易所 TP/SL → 写入 **实盘下单监控**`monitor_type=关键位监控``key_signal_type=斐波回调0.618/0.786`)→ 从关键位列表移除 |
| 撤单 | 仅撤本条斐波的 `fib_limit_order_id`**不会** `cancel_all`,避免误伤其他委托 | | 撤单 | 仅撤本条斐波的 `fib_limit_order_id`**不会** `cancel_all`,避免误伤其他委托 |
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(与箱体/收敛一致);0.618 理论约 1.6:10.786 约 3.7:1 | | 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(与箱体/收敛一致);0.618 理论约 1.6:10.786 约 3.7:1 |
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 | | 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
后台轮询:`check_fib_key_monitors()`(标记价失效 / 成交检测);箱体/收敛仍走 `check_key_monitors()`,互不干扰。 后台轮询:`check_fib_key_monitors()`(标记价失效 / 成交检测);箱体/收敛仍走 `check_key_monitors()`,互不干扰。
手动删除关键位时,若斐波限价尚未成交,会先撤交易所限价再删库记录。 手动删除关键位时,若斐波限价尚未成交,会先撤交易所限价再删库记录。
### 箱体 / 收敛自动开仓(来源标注) ### 箱体 / 收敛自动开仓(来源标注)
- 自动开仓写入 `order_monitors.key_signal_type``箱体突破``收敛突破` - 自动开仓写入 `order_monitors.key_signal_type``箱体突破``收敛突破`
- 持仓卡片、交易记录列表会显示「来源 · 信号类型」。 - 持仓卡片、交易记录列表会显示「来源 · 信号类型」。
## 列表时间窗(UTC,全站顶栏) ## 列表时间窗(UTC,全站顶栏)
共用模块:仓库根目录 `history_window_lib.py`Gate / Binance 主站一致)。 共用模块:仓库根目录 `history_window_lib.py`Gate / Binance 主站一致)。
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 默认 | **UTC 当日**`win_preset=utc_today`,从 UTC 0:00 至当前时刻) | | 默认 | **UTC 当日**`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local` | | 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local` |
| 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 | | 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 |
| 与统计的关系 | **仅影响列表/导出****统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** | | 与统计的关系 | **仅影响列表/导出****统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 | | 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…` | | 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…` |
查询参数示例: 查询参数示例:
- `?win_preset=utc_today` - `?win_preset=utc_today`
- `?win_preset=utc_last24h` / `utc_last7d` - `?win_preset=utc_last24h` / `utc_last7d`
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00` - `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
## 交易记录与复盘 ## 交易记录与复盘
- 平仓记录可同步交易所已实现盈亏(Gate 仓位历史等);列表盈亏列优先显示交易所数据,标注 **所** / **估** - 平仓记录可同步交易所已实现盈亏(Gate 仓位历史等);列表盈亏列优先显示交易所数据,标注 **所** / **估**
- 记录页提供 **立即同步**`POST /api/sync_exchange_pnl`),用于补全或刷新 `exchange_realized_pnl` 等字段。 - 记录页提供 **立即同步**`POST /api/sync_exchange_pnl`),用于补全或刷新 `exchange_realized_pnl` 等字段。
- 未做人工复盘时,展示以交易所盈亏为准(有同步数据时)。 - 未做人工复盘时,展示以交易所盈亏为准(有同步数据时)。
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。 - **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。 - 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。
- 平仓写入 `trade_records` 时:`stop_loss``initial_stop_loss` 均写入**开仓时止损快照**`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。 - 平仓写入 `trade_records` 时:`stop_loss``initial_stop_loss` 均写入**开仓时止损快照**`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。
- **开仓类型**`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。 - **开仓类型**`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。
| `key_signal_type` | 自动写入的 `entry_reason` | | `key_signal_type` | 自动写入的 `entry_reason` |
|-------------------|---------------------------| |-------------------|---------------------------|
| 箱体突破 | 关键位箱体突破 | | 箱体突破 | 关键位箱体突破 |
| 收敛突破 | 关键位收敛突破 | | 收敛突破 | 关键位收敛突破 |
| 斐波回调0.618 | 关键位斐波0.618 | | 斐波回调0.618 | 关键位斐波0.618 |
| 斐波回调0.786 | 关键位斐波0.786 | | 斐波回调0.786 | 关键位斐波0.786 |
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。 - 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。 - 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。 - 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。
- `/api/journals``/api/reviews` 支持同一时间窗 query,与列表一致。 - `/api/journals``/api/reviews` 支持同一时间窗 query,与列表一致。
### 导出(交易记录 v3 ### 导出(交易记录 v3
- 文件名:`trade_records_v3_YYYYMMDD.csv` - 文件名:`trade_records_v3_YYYYMMDD.csv`
- 相对 v2 增加:`key_signal_type``initial_stop_loss`(及开仓快照列)、`planned_rr``actual_rr``risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。 - 相对 v2 增加:`key_signal_type``initial_stop_loss`(及开仓快照列)、`planned_rr``actual_rr``risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。
- 「关键位历史」导出同样受 UTC 时间窗限制。 - 「关键位历史」导出同样受 UTC 时间窗限制。
## 实盘下单页 ## 实盘下单页
- 左列:实盘下单监控(表单、划转、规则)。 - 左列:实盘下单监控(表单、划转、规则)。
- 右列:实时持仓(独立模块)。 - 右列:实时持仓(独立模块)。
- **人工开仓门控**:计划盈亏比 &lt; `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。 - **人工开仓门控**:计划盈亏比 &lt; `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——调用与页面「挂止盈止损」相同的 **先撤后挂**`replace_active_monitor_tpsl_on_exchange`:撤该合约全部 TP/SL 条件单 → 按新止损 + 原止盈重挂)。仅交易所成功后才写库;失败发企业微信告警,本地止损不变。未配置实盘 API 时仍只更新本地(与旧行为一致)。 - **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——调用与页面「挂止盈止损」相同的 **先撤后挂**`replace_active_monitor_tpsl_on_exchange`:撤该合约全部 TP/SL 条件单 → 按新止损 + 原止盈重挂)。仅交易所成功后才写库;失败发企业微信告警,本地止损不变。未配置实盘 API 时仍只更新本地(与旧行为一致)。
## 统计分析页(`/stats` ## 统计分析页(`/stats`
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00``.env` 默认 **8** | | 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00``.env` 默认 **8** |
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 | | 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 |
| URL | 切换后写入 `stats_segment=`(如 `all``manual``key_box``key_conv``key_fib618``key_fib786`),刷新 `/stats` 可保持选项 | | URL | 切换后写入 `stats_segment=`(如 `all``manual``key_box``key_conv``key_fib618``key_fib786`),刷新 `/stats` 可保持选项 |
| 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) | | 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) |
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 | | 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 | | 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
## 持仓与计仓 ## 持仓与计仓
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。 - `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(`trading_sessions.key_sizing_capital_snapshot`)。 - 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(`trading_sessions.key_sizing_capital_snapshot`)。
## 配置 ## 配置
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。Gate 专用项(`GATE_*`、止盈止损触发等)保持原有段落不变。 详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。Gate 专用项(`GATE_*`、止盈止损触发等)保持原有段落不变。
## 自动备份(服务器) ## 自动备份(服务器)
- 脚本:`scripts/backup_data.sh``crypto.db` + `static/images` - 脚本:`scripts/backup_data.sh``crypto.db` + `static/images`
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** - 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30**
- 详见 `部署文档.md` 第 5.3 节 - 详见 `部署文档.md` 第 5.3 节
## 数据库(启动时自动迁移) ## 数据库(启动时自动迁移)
`key_monitors` 新增斐波字段(示例):`fib_limit_order_id``fib_entry_price``fib_stop_loss``fib_take_profit``fib_order_amount``fib_margin_capital``fib_leverage` `key_monitors` 新增斐波字段(示例):`fib_limit_order_id``fib_entry_price``fib_stop_loss``fib_take_profit``fib_order_amount``fib_margin_capital``fib_leverage`
`trade_records` / `order_monitors` 新增或沿用:`key_signal_type``exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key``entry_reason``reviewed_entry_reason``initial_stop_loss` `trade_records` / `order_monitors` 新增或沿用:`key_signal_type``exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key``entry_reason``reviewed_entry_reason``initial_stop_loss`
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。 **历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。
## 涉及文件(便于排查) ## 涉及文件(便于排查)
| 路径 | 说明 | | 路径 | 说明 |
|------|------| |------|------|
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 | | `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
| `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL``entry_reason_from_key_signal` | | `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL``entry_reason_from_key_signal` |
| `crypto_monitor_gate/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 | | `crypto_monitor_gate/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 |
| `crypto_monitor_gate/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 | | `crypto_monitor_gate/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 |
## 升级步骤 ## 升级步骤
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env` 1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。 2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
3. 重启 Gate 实例服务(如 `pm2 restart crypto_gate`);首次启动会自动 `ALTER TABLE` 缺列(斐波、交易所盈亏、`entry_reason` 等)。 3. 重启 Gate 实例服务(如 `pm2 restart crypto_gate`);首次启动会自动 `ALTER TABLE` 缺列(斐波、交易所盈亏、`entry_reason` 等)。
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。 4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**`/stats` 可见分品类统计与「北京 8:00 切日」说明。 5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**`/stats` 可见分品类统计与「北京 8:00 切日」说明。
6. 建议在测试币上先添加一条斐波监控,确认:限价已挂出、标记价失效会撤单、成交后出现持仓监控且 TP/SL 已挂上;平仓后交易记录止损(开仓)与开仓类型是否正确。 6. 建议在测试币上先添加一条斐波监控,确认:限价已挂出、标记价失效会撤单、成交后出现持仓监控且 TP/SL 已挂上;平仓后交易记录止损(开仓)与开仓类型是否正确。
+299 -299
View File
@@ -1,299 +1,299 @@
# `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2Ubuntu # `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2Ubuntu
本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是: 本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是:
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS) - 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS)
- 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所 - 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
- **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2** - **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2**
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate` - 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate`
> 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。 > 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。
--- ---
## 0. 你需要准备的东西 ## 0. 你需要准备的东西
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」) - 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
- 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root` - 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守) - SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
- 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2 - 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2
--- ---
## 1. 获取代码与目录 ## 1. 获取代码与目录
将包含 `app.py` 的项目放到固定目录,例如: 将包含 `app.py` 的项目放到固定目录,例如:
```bash ```bash
mkdir -p /opt/crypto_monitor mkdir -p /opt/crypto_monitor
cd /opt/crypto_monitor cd /opt/crypto_monitor
git clone https://git.bz121.com/dekun/crypto_monitor.git git clone https://git.bz121.com/dekun/crypto_monitor.git
cd crypto_monitor/crypto_monitor_gate cd crypto_monitor/crypto_monitor_gate
``` ```
下文用 **`/opt/crypto_monitor/crypto_monitor_gate`** 仅为示例,请换成你的实际绝对路径。 下文用 **`/opt/crypto_monitor/crypto_monitor_gate`** 仅为示例,请换成你的实际绝对路径。
拉取代码后,若目录下尚无 `.env` 拉取代码后,若目录下尚无 `.env`
```bash ```bash
cp -n .env.example .env cp -n .env.example .env
``` ```
--- ---
## 2. 配置 SSH 私钥与 `~/.ssh/config` ## 2. 配置 SSH 私钥与 `~/.ssh/config`
```bash ```bash
mkdir -p ~/.ssh mkdir -p ~/.ssh
chmod 700 ~/.ssh chmod 700 ~/.ssh
# 私钥示例:~/.ssh/vps1.pem # 私钥示例:~/.ssh/vps1.pem
chmod 600 ~/.ssh/vps1.pem chmod 600 ~/.ssh/vps1.pem
``` ```
编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可): 编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可):
```sshconfig ```sshconfig
Host gate-vps Host gate-vps
HostName 你的_VPS_IP HostName 你的_VPS_IP
User root User root
IdentityFile ~/.ssh/vps1.pem IdentityFile ~/.ssh/vps1.pem
IdentitiesOnly yes IdentitiesOnly yes
ServerAliveInterval 30 ServerAliveInterval 30
ServerAliveCountMax 3 ServerAliveCountMax 3
ExitOnForwardFailure yes ExitOnForwardFailure yes
BatchMode yes BatchMode yes
``` ```
测试: 测试:
```bash ```bash
ssh gate-vps true ssh gate-vps true
``` ```
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。 > 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
--- ---
## 3. 手工验证:SSH SOCKS + Gate API ## 3. 手工验证:SSH SOCKS + Gate API
### 3.1 本地 SOCKS(示例端口 1080 ### 3.1 本地 SOCKS(示例端口 1080
```bash ```bash
ssh -N -D 127.0.0.1:1080 gate-vps ssh -N -D 127.0.0.1:1080 gate-vps
``` ```
保持运行,另开终端继续。 保持运行,另开终端继续。
### 3.2 验证经 SOCKS 可访问 Gate ### 3.2 验证经 SOCKS 可访问 Gate
```bash ```bash
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time
``` ```
应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。 应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
--- ---
## 4. Python 虚拟环境 ## 4. Python 虚拟环境
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
python3 -m venv .venv python3 -m venv .venv
source .venv/bin/activate source .venv/bin/activate
python -m pip install -U pip python -m pip install -U pip
pip install flask requests ccxt werkzeug PySocks Pillow pip install flask requests ccxt werkzeug PySocks Pillow
``` ```
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。 走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
可选: 可选:
```bash ```bash
export PYTHONDONTWRITEBYTECODE=1 export PYTHONDONTWRITEBYTECODE=1
``` ```
--- ---
## 5. 配置环境变量(`.env.example` → `.env` ## 5. 配置环境变量(`.env.example` → `.env`
| 文件 | 是否进 Git | 说明 | | 文件 | 是否进 Git | 说明 |
|------|------------|------| |------|------------|------|
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 | | **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** | | **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
### 5.1 首次配置 ### 5.1 首次配置
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
cp -n .env.example .env cp -n .env.example .env
nano .env nano .env
``` ```
### 5.2 备份与 `git pull` ### 5.2 备份与 `git pull`
- **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env` - **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env`
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env` - 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`
- **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env` - **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`
- **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。 - **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。
### 5.3 自动备份(数据库 + 复盘图片) ### 5.3 自动备份(数据库 + 复盘图片)
与 Binance 实例相同:每天 **北京时间 0:00****`/root/backups`**,保留 **30 天** 与 Binance 实例相同:每天 **北京时间 0:00****`/root/backups`**,保留 **30 天**
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
bash scripts/install_backup_cron.sh bash scripts/install_backup_cron.sh
bash scripts/backup_data.sh # 试跑 bash scripts/backup_data.sh # 试跑
``` ```
备份目录:`/root/backups/crypto_monitor_gate/YYYY-MM-DD/`。详见 Binance 项目 `部署文档.md` 第 5.3 节(恢复步骤、可选 `.env` 变量相同)。 备份目录:`/root/backups/crypto_monitor_gate/YYYY-MM-DD/`。详见 Binance 项目 `部署文档.md` 第 5.3 节(恢复步骤、可选 `.env` 变量相同)。
若还部署了 **`crypto_monitor_gate_bot`**,请在该目录同样执行 `bash scripts/install_backup_cron.sh` 若还部署了 **`crypto_monitor_gate_bot`**,请在该目录同样执行 `bash scripts/install_backup_cron.sh`
### 5.4 必填项检查(Gate + 代理) ### 5.4 必填项检查(Gate + 代理)
与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认: 与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认:
```env ```env
APP_HOST=127.0.0.1 APP_HOST=127.0.0.1
APP_PORT=5000 APP_PORT=5000
# 实盘(按需) # 实盘(按需)
LIVE_TRADING_ENABLED=false LIVE_TRADING_ENABLED=false
GATE_API_KEY=你的_Key GATE_API_KEY=你的_Key
GATE_API_SECRET=你的_Secret GATE_API_SECRET=你的_Secret
# 经本机 SSH 动态转发访问 Gate(端口与隧道一致) # 经本机 SSH 动态转发访问 Gate(端口与隧道一致)
GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080 GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一) # 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
# GATE_HTTP_PROXY=http://127.0.0.1:7890 # GATE_HTTP_PROXY=http://127.0.0.1:7890
# GATE_HTTPS_PROXY=http://127.0.0.1:7890 # GATE_HTTPS_PROXY=http://127.0.0.1:7890
``` ```
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。 说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
--- ---
## 6. 手工启动 Flask(验证) ## 6. 手工启动 Flask(验证)
1. SOCKS 已监听 `127.0.0.1:1080` 1. SOCKS 已监听 `127.0.0.1:1080`
2.`source .venv/bin/activate` 2.`source .venv/bin/activate`
3. `.env` 已含 `GATE_SOCKS_PROXY` 3. `.env` 已含 `GATE_SOCKS_PROXY`
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
source .venv/bin/activate source .venv/bin/activate
python app.py python app.py
``` ```
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。 浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
--- ---
## 7. 安装 PM2 ## 7. 安装 PM2
```bash ```bash
sudo npm i -g pm2 sudo npm i -g pm2
pm2 -v pm2 -v
``` ```
--- ---
## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐) ## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
在项目根目录: 在项目根目录:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
pm2 start ecosystem.config.cjs pm2 start ecosystem.config.cjs
pm2 status pm2 status
pm2 logs --lines 200 pm2 logs --lines 200
``` ```
默认只启动 **`crypto-monitor-gate`**`.venv/bin/python app.py`)。 默认只启动 **`crypto-monitor-gate`**`.venv/bin/python app.py`)。
### 本机已可直连 Gate、不需要隧道时 ### 本机已可直连 Gate、不需要隧道时
`.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs` `.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`
### 开机自启 ### 开机自启
```bash ```bash
pm2 save pm2 save
pm2 startup pm2 startup
# 按屏幕提示执行一条 sudo 命令 # 按屏幕提示执行一条 sudo 命令
``` ```
--- ---
## 9. 等价手工命令(不使用 ecosystem 文件时) ## 9. 等价手工命令(不使用 ecosystem 文件时)
### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2) ### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd): 示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd):
```bash ```bash
ssh -N -D 127.0.0.1:1080 gate-vps \ ssh -N -D 127.0.0.1:1080 gate-vps \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -o ExitOnForwardFailure=yes
``` ```
### 9.2 Flask ### 9.2 Flask
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate cd /opt/crypto_monitor/crypto_monitor_gate
pm2 start /opt/crypto_monitor/crypto_monitor_gate/.venv/bin/python --name crypto-monitor-gate -- \ pm2 start /opt/crypto_monitor/crypto_monitor_gate/.venv/bin/python --name crypto-monitor-gate -- \
/opt/crypto_monitor/crypto_monitor_gate/app.py /opt/crypto_monitor/crypto_monitor_gate/app.py
``` ```
--- ---
## 10. 交易所「连接不上」排查清单 ## 10. 交易所「连接不上」排查清单
1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。 1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。
2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`): 2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`):
```bash ```bash
ss -lntp | grep 1080 || true ss -lntp | grep 1080 || true
``` ```
3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。 3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。
4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。 4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。 5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。 6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
--- ---
## 11. 推荐启动顺序(习惯) ## 11. 推荐启动顺序(习惯)
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功 1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功
2. `pm2 start ecosystem.config.cjs` 2. `pm2 start ecosystem.config.cjs`
3. 再确认页面与余额等接口正常 3. 再确认页面与余额等接口正常
--- ---
## 12. 免责声明 ## 12. 免责声明
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。 交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
--- ---
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py` ## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
在 Ubuntu 上: 在 Ubuntu 上:
1)预览(不写库): 1)预览(不写库):
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
``` ```
2)确认后执行: 2)确认后执行:
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
``` ```
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。 默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
@@ -1,125 +1,125 @@
# 趋势回调策略(机器人)说明 # 趋势回调策略(机器人)说明
本文描述本仓库内 **「趋势回调」** 自动交易计划的业务规则与实现口径,便于单独策略账户使用与审计。 本文描述本仓库内 **「趋势回调」** 自动交易计划的业务规则与实现口径,便于单独策略账户使用与审计。
--- ---
## 1. 适用场景 ## 1. 适用场景
- 单独用于跑策略的 **Gate.io USDT 永续** 子账户(建议与主资金隔离)。 - 单独用于跑策略的 **Gate.io USDT 永续** 子账户(建议与主资金隔离)。
- 你已明确:**方向、止损价、补仓区间边界价、止盈价、杠杆**,并接受程序按风险预算拆分 **首仓 50% + 多档补仓 50%** - 你已明确:**方向、止损价、补仓区间边界价、止盈价、杠杆**,并接受程序按风险预算拆分 **首仓 50% + 多档补仓 50%**
--- ---
## 2. 名词与参数 ## 2. 名词与参数
| 名称 | 含义 | | 名称 | 含义 |
|------|------| |------|------|
| **合约 USDT 可用余额** | **生成预览**时通过 API 读取的 **swap 账户 USDT `free`** 快照;**确认执行**时再次读取并与快照比对偏差。 | | **合约 USDT 可用余额** | **生成预览**时通过 API 读取的 **swap 账户 USDT `free`** 快照;**确认执行**时再次读取并与快照比对偏差。 |
| **风险比例** | 默认 **5%**:指「若整笔计划在 **补仓区间远侧边界**(做多=上沿、做空=下沿)这一侧的最坏价格结构下触及止损」,目标亏损上限约为 **可用余额快照 × 风险比例**(实现上用 `calc_risk_fraction``prepare_order_amount` 反推总张数,受交易所最小张数与精度约束)。 | | **风险比例** | 默认 **5%**:指「若整笔计划在 **补仓区间远侧边界**(做多=上沿、做空=下沿)这一侧的最坏价格结构下触及止损」,目标亏损上限约为 **可用余额快照 × 风险比例**(实现上用 `calc_risk_fraction``prepare_order_amount` 反推总张数,受交易所最小张数与精度约束)。 |
| **止损价** | 用户填写;开仓后挂 **交易所仓位类止损触发单**(全平)。 | | **止损价** | 用户填写;开仓后挂 **交易所仓位类止损触发单**(全平)。 |
| **补仓区间边界**(库字段 `add_upper`) | 用户填写;**仅在该价位与止损价构成的区间内** 才允许程序触发剩余 50% 的市价补仓。**界面文案**:做多显示「补仓上沿」,做空显示「补仓下沿」。校验:做多 `止损 < 边界价`;做空 `止损 > 边界价`。 | | **补仓区间边界**(库字段 `add_upper`) | 用户填写;**仅在该价位与止损价构成的区间内** 才允许程序触发剩余 50% 的市价补仓。**界面文案**:做多显示「补仓上沿」,做空显示「补仓下沿」。校验:做多 `止损 < 边界价`;做空 `止损 > 边界价`。 |
| **止盈价** | 用户填写的 **固定价格**;**不由交易所条件止盈单触发**,由应用后台 **按标记价/行情价轮询**,达到后 **市价全平**。 | | **止盈价** | 用户填写的 **固定价格**;**不由交易所条件止盈单触发**,由应用后台 **按标记价/行情价轮询**,达到后 **市价全平**。 |
| **杠杆** | 计划内固定写入;用于 `set_leverage` 与名义换算。 | | **杠杆** | 计划内固定写入;用于 `set_leverage` 与名义换算。 |
| **补仓档位数** | 默认 **5** 档(环境变量 `TREND_PULLBACK_DCA_LEGS` 可调);程序在满足最小张数前提下可能 **自动减少档数**。 | | **补仓档位数** | 默认 **5** 档(环境变量 `TREND_PULLBACK_DCA_LEGS` 可调);程序在满足最小张数前提下可能 **自动减少档数**。 |
--- ---
## 3. 执行流程(时间顺序) ## 3. 执行流程(时间顺序)
### 3.0 列表时间窗(交易记录 / 计划历史) ### 3.0 列表时间窗(交易记录 / 计划历史)
- **交易记录**、**计划历史**(含预览快照)列表与 **交易记录 CSV 导出** 支持 **UTC** 时间筛选(默认 UTC 当日;可选近 24h、近 7d、自定义起止)。 - **交易记录**、**计划历史**(含预览快照)列表与 **交易记录 CSV 导出** 支持 **UTC** 时间筛选(默认 UTC 当日;可选近 24h、近 7d、自定义起止)。
- 查询参数:`win_preset``utc_today` / `utc_last24h` / `utc_last7d` / `custom`)、自定义时另传 `from_utc``to_utc` - 查询参数:`win_preset``utc_today` / `utc_last24h` / `utc_last7d` / `custom`)、自定义时另传 `from_utc``to_utc`
- **统计分析**页仍按北京时间 `TRADING_DAY_RESET_HOUR` 切日,不受列表窗影响。 - **统计分析**页仍按北京时间 `TRADING_DAY_RESET_HOUR` 切日,不受列表窗影响。
### 3.1 预览阶段(不下单) ### 3.1 预览阶段(不下单)
1. **风控**:与「机器人下单监控」**互斥**——存在活跃机器人持仓或运行中趋势计划时,不可生成预览。 1. **风控**:与「机器人下单监控」**互斥**——存在活跃机器人持仓或运行中趋势计划时,不可生成预览。
2. **读取可用余额快照** `get_available_trading_usdt()`,失败则拒绝。 2. **读取可用余额快照** `get_available_trading_usdt()`,失败则拒绝。
3. **计算**(写入表 `trend_pullback_previews`,并跳转带 `preview_id`): 3. **计算**(写入表 `trend_pullback_previews`,并跳转带 `preview_id`):
-**补仓区间边界 ↔ 止损** 区间内生成 `N` 个补仓触发价(做多从上沿向止损、做空从下沿向止损); -**补仓区间边界 ↔ 止损** 区间内生成 `N` 个补仓触发价(做多从上沿向止损、做空从下沿向止损);
-**剩余 50% 计划张数** 拆成 `N` 份写入 `leg_amounts_json` -**剩余 50% 计划张数** 拆成 `N` 份写入 `leg_amounts_json`
4. **预览有效期**:默认 **120 秒**`TREND_PULLBACK_PREVIEW_TTL_SECONDS`),超时须重新点「生成预览」。 4. **预览有效期**:默认 **120 秒**`TREND_PULLBACK_PREVIEW_TTL_SECONDS`),超时须重新点「生成预览」。
### 3.2 确认执行(实盘) ### 3.2 确认执行(实盘)
5. 再次校验:预览未过期;**当前可用余额**与预览快照相对偏差 ≤ `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT`(默认 **5%**),否则拒绝执行并要求重新预览。 5. 再次校验:预览未过期;**当前可用余额**与预览快照相对偏差 ≤ `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT`(默认 **5%**),否则拒绝执行并要求重新预览。
6. **首仓****立即市价** 开立 **总计划张数 × 50%**(不附带交易所止盈单)。 6. **首仓****立即市价** 开立 **总计划张数 × 50%**(不附带交易所止盈单)。
7. **止损**:撤销旧条件单后,挂 **仅止损** 的仓位触发单;之后每次补仓成交会 **刷新** 止损挂单。 7. **止损**:撤销旧条件单后,挂 **仅止损** 的仓位触发单;之后每次补仓成交会 **刷新** 止损挂单。
7b. **手动保本**(可选):首仓完成且交易所有持仓后,可在运行中计划卡片点击「应用保本止损」——将止损移至 **持仓均价 ± 偏移%**(默认 **+0.3%** 多 / **0.3%** 空);仅当新止损 **优于** 当前止损时生效,并同步 Gate 仓位止损单。 7b. **手动保本**(可选):首仓完成且交易所有持仓后,可在运行中计划卡片点击「应用保本止损」——将止损移至 **持仓均价 ± 偏移%**(默认 **+0.3%** 多 / **0.3%** 空);仅当新止损 **优于** 当前止损时生效,并同步 Gate 仓位止损单。
8. **补仓**:当价格 **穿越** 下一档触发价(做多为自上向下穿越,做空为自下向上穿越)时,按该档张数 **市价加仓**;直至 `N` 档执行完毕或计划结束。 8. **补仓**:当价格 **穿越** 下一档触发价(做多为自上向下穿越,做空为自下向上穿越)时,按该档张数 **市价加仓**;直至 `N` 档执行完毕或计划结束。
9. **止盈监控**:后台线程若发现价格触及止盈,则 **市价全平** 9. **止盈监控**:后台线程若发现价格触及止盈,则 **市价全平**
10. **止损触发**:若仓位被交易所止损打光,本地检测到 **持仓为 0** 后记账为 **止损** 并结束计划。 10. **止损触发**:若仓位被交易所止损打光,本地检测到 **持仓为 0** 后记账为 **止损** 并结束计划。
11. **计划结束**:任一结束路径(止盈 / 止损 / 用户手动结束)均会 **撤单**(条件单 + 普通挂单,尽力而为)。 11. **计划结束**:任一结束路径(止盈 / 止损 / 用户手动结束)均会 **撤单**(条件单 + 普通挂单,尽力而为)。
### 3.3 取消预览 ### 3.3 取消预览
用户可「取消预览」删除 `trend_pullback_previews` 中对应记录;过期记录会在新预览或页面加载时清理。 用户可「取消预览」删除 `trend_pullback_previews` 中对应记录;过期记录会在新预览或页面加载时清理。
### 3.4 界面:计划历史与运行中浮动盈亏 ### 3.4 界面:计划历史与运行中浮动盈亏
- **计划历史(页顶卡片)** - **计划历史(页顶卡片)**
- 仅展示 **`trend_pullback_plans` 中已结束的计划**`status != 'active'`,如止盈结束、止损结束、手动结束)。 - 仅展示 **`trend_pullback_plans` 中已结束的计划**`status != 'active'`,如止盈结束、止损结束、手动结束)。
- **不包含**仅存在于 `trend_pullback_previews`、从未「确认执行」的预览。 - **不包含**仅存在于 `trend_pullback_previews`、从未「确认执行」的预览。
- 每行提供 **删除**:删除该计划行,并删除 `trade_records`**`trend_plan_id` 与之相同** 且类型为「趋势回调」的记录(用于与计划一一对应的新数据;历史旧行若无 `trend_plan_id` 则不会随删)。 - 每行提供 **删除**:删除该计划行,并删除 `trade_records`**`trend_plan_id` 与之相同** 且类型为「趋势回调」的记录(用于与计划一一对应的新数据;历史旧行若无 `trend_plan_id` 则不会随删)。
- **运行中的计划(交易执行页)** - **运行中的计划(交易执行页)**
- 在计划摘要下方展示 **浮盈亏(交易所)**:来自 Gate 当前持仓接口的 **未实现盈亏**(及标记价,若可得);与本地按均价估算可能略有差异,以交易所为准便于对照。 - 在计划摘要下方展示 **浮盈亏(交易所)**:来自 Gate 当前持仓接口的 **未实现盈亏**(及标记价,若可得);与本地按均价估算可能略有差异,以交易所为准便于对照。
- **补仓边界**按方向显示「补仓上沿」或「补仓下沿」(数值仍为 `add_upper` 字段)。 - **补仓边界**按方向显示「补仓上沿」或「补仓下沿」(数值仍为 `add_upper` 字段)。
- **手动保本**:表单可改偏移 %(默认见 `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT`);成功后显示「已保本」时间与原止损(若与当前不同)。 - **手动保本**:表单可改偏移 %(默认见 `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT`);成功后显示「已保本」时间与原止损(若与当前不同)。
### 3.5 交易记录与交易所「已实现盈亏」对齐 ### 3.5 交易记录与交易所「已实现盈亏」对齐
- 平仓时仍会写入一条 **`trade_records`**`monitor_type=趋势回调`),其中的 **`pnl_amount` 等为本地估算**`calc_pnl`,不含手续费、资金费等完整账单口径)。 - 平仓时仍会写入一条 **`trade_records`**`monitor_type=趋势回调`),其中的 **`pnl_amount` 等为本地估算**`calc_pnl`,不含手续费、资金费等完整账单口径)。
- 打开 **「交易执行」或「交易记录」** 页面时,若已配置 **`GATE_API_KEY` / `GATE_API_SECRET`**(不要求 `LIVE_TRADING_ENABLED=true`,只读即可),应用会按节流策略(同进程约 **25 秒**内最多一次)调用 Gate **`fetch_positions_history`(平仓历史)**,为尚未写入 `exchange_sync_key` 的趋势回调记录 **匹配一条平仓记录**,并回填: - 打开 **「交易执行」或「交易记录」** 页面时,若已配置 **`GATE_API_KEY` / `GATE_API_SECRET`**(不要求 `LIVE_TRADING_ENABLED=true`,只读即可),应用会按节流策略(同进程约 **25 秒**内最多一次)调用 Gate **`fetch_positions_history`(平仓历史)**,为尚未写入 `exchange_sync_key` 的趋势回调记录 **匹配一条平仓记录**,并回填:
- **`exchange_realized_pnl`**:交易所口径已实现盈亏(与 App「历史仓位」更接近); - **`exchange_realized_pnl`**:交易所口径已实现盈亏(与 App「历史仓位」更接近);
- **`exchange_opened_at` / `exchange_closed_at`**:换算为应用时区(默认北京)下的开、平时间字符串。 - **`exchange_opened_at` / `exchange_closed_at`**:换算为应用时区(默认北京)下的开、平时间字符串。
- **交易记录表**展示列「开仓(展示) / 平仓(展示) / 盈亏U(展示)」:对「趋势回调」行,若已同步则优先显示交易所字段(界面小字 **「所」**);未同步前仍显示本地复盘字段(小字 **「估」**)。 - **交易记录表**展示列「开仓(展示) / 平仓(展示) / 盈亏U(展示)」:对「趋势回调」行,若已同步则优先显示交易所字段(界面小字 **「所」**);未同步前仍显示本地复盘字段(小字 **「估」**)。
- 匹配规则概要:同品种、同方向、平仓时间与本地 `closed_at` 接近,并结合 **`trend_plan_id`** 对应计划的 `opened_at` 收窄时间窗;极端情况下若短时间多笔同向同品种,仍存在错配可能,可对照 `exchange_sync_key` 与交易所记录。 - 匹配规则概要:同品种、同方向、平仓时间与本地 `closed_at` 接近,并结合 **`trend_plan_id`** 对应计划的 `opened_at` 收窄时间窗;极端情况下若短时间多笔同向同品种,仍存在错配可能,可对照 `exchange_sync_key` 与交易所记录。
--- ---
## 4. 与「机器人下单监控」的差异 ## 4. 与「机器人下单监控」的差异
| 项目 | 机器人下单监控 | 趋势回调 | | 项目 | 机器人下单监控 | 趋势回调 |
|------|------------------|----------| |------|------------------|----------|
| 开仓 | 单次市价 + 条件止盈+止损 | 首仓 50% 市价 + 多档补仓 + **仅止损在交易所** | | 开仓 | 单次市价 + 条件止盈+止损 | 首仓 50% 市价 + 多档补仓 + **仅止损在交易所** |
| 止盈 | 条件单 + 本地监控 | **仅本地监控市价止盈** | | 止盈 | 条件单 + 本地监控 | **仅本地监控市价止盈** |
| 仓位基数 | 以损定仓(表单/会话基数) | **可用余额快照 × 风险比例** 推导 | | 仓位基数 | 以损定仓(表单/会话基数) | **可用余额快照 × 风险比例** 推导 |
| 移动保本 | 支持(按 R 自动上移) | **手动保本**(首仓后有持仓即可点;默认均价 +0.3%,可改偏移;同步 Gate 止损单;**无**自动 R 保本) | | 移动保本 | 支持(按 R 自动上移) | **手动保本**(首仓后有持仓即可点;默认均价 +0.3%,可改偏移;同步 Gate 止损单;**无**自动 R 保本) |
--- ---
## 5. 风险声明(必读) ## 5. 风险声明(必读)
- 市价单存在 **滑点**;极端行情下实际亏损可能 **大于** 理论 5%。 - 市价单存在 **滑点**;极端行情下实际亏损可能 **大于** 理论 5%。
- 补仓触发依赖应用 **轮询间隔**`MONITOR_POLL_SECONDS`),非毫秒级高频。 - 补仓触发依赖应用 **轮询间隔**`MONITOR_POLL_SECONDS`),非毫秒级高频。
- 交易所 **最小张数 / 精度** 可能导致计划张数被截断,实际风险略低于或偏离纸面计算。 - 交易所 **最小张数 / 精度** 可能导致计划张数被截断,实际风险略低于或偏离纸面计算。
- 请使用 **单独 API Key / 子账户**,并先在 `LIVE_TRADING_ENABLED=false` 环境验证流程(若需沙盒请自行对接测试网,本仓库默认实盘接口)。 - 请使用 **单独 API Key / 子账户**,并先在 `LIVE_TRADING_ENABLED=false` 环境验证流程(若需沙盒请自行对接测试网,本仓库默认实盘接口)。
--- ---
## 6. 相关环境变量 ## 6. 相关环境变量
| 变量 | 说明 | 默认 | | 变量 | 说明 | 默认 |
|------|------|------| |------|------|------|
| `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT` | 手动保本默认偏移(相对持仓均价,%) | `0.3` | | `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT` | 手动保本默认偏移(相对持仓均价,%) | `0.3` |
| `TREND_PULLBACK_DCA_LEGS` | 剩余 50% 拆档数量上限 | `5` | | `TREND_PULLBACK_DCA_LEGS` | 剩余 50% 拆档数量上限 | `5` |
| `TREND_PULLBACK_PREVIEW_TTL_SECONDS` | 预览有效时间(秒) | `120` | | `TREND_PULLBACK_PREVIEW_TTL_SECONDS` | 预览有效时间(秒) | `120` |
| `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT` | 确认执行时允许「当前可用 / 预览快照」最大相对偏差(%) | `5` | | `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT` | 确认执行时允许「当前可用 / 预览快照」最大相对偏差(%) | `5` |
| `MONITOR_POLL_SECONDS` | 监控轮询间隔(秒) | `3` | | `MONITOR_POLL_SECONDS` | 监控轮询间隔(秒) | `3` |
| `LIVE_TRADING_ENABLED` | 是否允许真实下单 | `false` | | `LIVE_TRADING_ENABLED` | 是否允许真实下单 | `false` |
| `FULL_MARGIN_BUFFER_RATIO` | 计划保证金相对可用余额上限比例 | `0.98` | | `FULL_MARGIN_BUFFER_RATIO` | 计划保证金相对可用余额上限比例 | `0.98` |
| `APP_TIMEZONE` | 应用墙钟与「北京日期」同步起点时区(如 `Asia/Shanghai` | `Asia/Shanghai` | | `APP_TIMEZONE` | 应用墙钟与「北京日期」同步起点时区(如 `Asia/Shanghai` | `Asia/Shanghai` |
| `EXCHANGE_POSITION_SYNC_FROM_BJ` | 拉取 Gate **平仓历史** 的最早日期(`YYYY-MM-DD`,按 `APP_TIMEZONE` 当日 **00:00** 起算)。**留空**则从近 **90 天** 起拉取 | 空 | | `EXCHANGE_POSITION_SYNC_FROM_BJ` | 拉取 Gate **平仓历史** 的最早日期(`YYYY-MM-DD`,按 `APP_TIMEZONE` 当日 **00:00** 起算)。**留空**则从近 **90 天** 起拉取 | 空 |
| `EXCHANGE_POSITION_HISTORY_LIMIT` | 单次拉取平仓历史条数上限(50–1000) | `200` | | `EXCHANGE_POSITION_HISTORY_LIMIT` | 单次拉取平仓历史条数上限(50–1000) | `200` |
--- ---
## 7. 数据库 ## 7. 数据库
- **`trend_pullback_previews`**:未执行的预览行(含 `expires_at_ms`),执行成功或取消后删除;过期可被清理。 - **`trend_pullback_previews`**:未执行的预览行(含 `expires_at_ms`),执行成功或取消后删除;过期可被清理。
- **`trend_pullback_plans`**:趋势回调计划。执行后写入一行,`status='active'` 表示运行中;止盈 / 止损 / 手动结束后变为 **`stopped_tp` / `stopped_sl` / `stopped_manual`** 等非 `active` 状态,并出现在页顶 **计划历史**。字段含快照可用余额、计划保证金、总张数、首仓张数、补仓 JSON、网格价 JSON、已补仓档数、均价、`opened_at``message`(结束说明)等;**`add_upper`** 存补仓区间远侧边界价(做多=上沿、做空=下沿)。 - **`trend_pullback_plans`**:趋势回调计划。执行后写入一行,`status='active'` 表示运行中;止盈 / 止损 / 手动结束后变为 **`stopped_tp` / `stopped_sl` / `stopped_manual`** 等非 `active` 状态,并出现在页顶 **计划历史**。字段含快照可用余额、计划保证金、总张数、首仓张数、补仓 JSON、网格价 JSON、已补仓档数、均价、`opened_at``message`(结束说明)等;**`add_upper`** 存补仓区间远侧边界价(做多=上沿、做空=下沿)。
- **`trade_records`**`monitor_type=趋势回调`):每次计划结束插入一行;含本地估算盈亏等。新写入行带 **`trend_plan_id`** 指向 `trend_pullback_plans.id`。另含 **`exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key`**,由页面触发的交易所平仓历史同步填充(见 3.5)。 - **`trade_records`**`monitor_type=趋势回调`):每次计划结束插入一行;含本地估算盈亏等。新写入行带 **`trend_plan_id`** 指向 `trend_pullback_plans.id`。另含 **`exchange_realized_pnl``exchange_opened_at``exchange_closed_at``exchange_sync_key`**,由页面触发的交易所平仓历史同步填充(见 3.5)。
**CSV 导出**:交易记录导出为 **v3**,包含上述交易所对齐字段及 `trend_plan_id` **CSV 导出**:交易记录导出为 **v3**,包含上述交易所对齐字段及 `trend_plan_id`
+333 -333
View File
@@ -1,333 +1,333 @@
# `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2Ubuntu # `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2Ubuntu
本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是: 本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是:
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS) - 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS)
- 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所 - 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
- **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2** - **SSH 隧道**:用 `ssh -D` 在本机常驻即可(screen / tmux / systemd 等),**不必交给 PM2**
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate` - 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate`
> 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。 > 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。
--- ---
## 0. 你需要准备的东西 ## 0. 你需要准备的东西
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」) - 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
- 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root` - 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守) - SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
- 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2 - 本机已安装:`python3``python3-venv``pip``curl``ssh``git`(可选)、`node` + `npm`(安装 PM2
--- ---
## 1. 获取代码与目录 ## 1. 获取代码与目录
将包含 `app.py` 的项目放到固定目录,例如: 将包含 `app.py` 的项目放到固定目录,例如:
```bash ```bash
mkdir -p /opt/crypto_monitor mkdir -p /opt/crypto_monitor
cd /opt/crypto_monitor cd /opt/crypto_monitor
git clone https://git.bz121.com/dekun/crypto_monitor.git git clone https://git.bz121.com/dekun/crypto_monitor.git
cd crypto_monitor/crypto_monitor_gate_bot cd crypto_monitor/crypto_monitor_gate_bot
``` ```
下文用 **`/opt/crypto_monitor/crypto_monitor_gate_bot`** 仅为示例,请换成你的实际绝对路径。 下文用 **`/opt/crypto_monitor/crypto_monitor_gate_bot`** 仅为示例,请换成你的实际绝对路径。
拉取代码后,若目录下尚无 `.env` 拉取代码后,若目录下尚无 `.env`
```bash ```bash
cp -n .env.example .env cp -n .env.example .env
``` ```
--- ---
## 2. 配置 SSH 私钥与 `~/.ssh/config` ## 2. 配置 SSH 私钥与 `~/.ssh/config`
```bash ```bash
mkdir -p ~/.ssh mkdir -p ~/.ssh
chmod 700 ~/.ssh chmod 700 ~/.ssh
# 私钥示例:~/.ssh/vps1.pem # 私钥示例:~/.ssh/vps1.pem
chmod 600 ~/.ssh/vps1.pem chmod 600 ~/.ssh/vps1.pem
``` ```
编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可): 编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可):
```sshconfig ```sshconfig
Host gate-vps Host gate-vps
HostName 你的_VPS_IP HostName 你的_VPS_IP
User root User root
IdentityFile ~/.ssh/vps1.pem IdentityFile ~/.ssh/vps1.pem
IdentitiesOnly yes IdentitiesOnly yes
ServerAliveInterval 30 ServerAliveInterval 30
ServerAliveCountMax 3 ServerAliveCountMax 3
ExitOnForwardFailure yes ExitOnForwardFailure yes
BatchMode yes BatchMode yes
``` ```
测试: 测试:
```bash ```bash
ssh gate-vps true ssh gate-vps true
``` ```
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。 > 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
--- ---
## 3. 手工验证:SSH SOCKS + Gate API ## 3. 手工验证:SSH SOCKS + Gate API
### 3.1 本地 SOCKS(示例端口 1080 ### 3.1 本地 SOCKS(示例端口 1080
```bash ```bash
ssh -N -D 127.0.0.1:1080 gate-vps ssh -N -D 127.0.0.1:1080 gate-vps
``` ```
保持运行,另开终端继续。 保持运行,另开终端继续。
### 3.2 验证经 SOCKS 可访问 Gate ### 3.2 验证经 SOCKS 可访问 Gate
```bash ```bash
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time
``` ```
应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。 应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
--- ---
## 4. Python 虚拟环境 ## 4. Python 虚拟环境
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
python3 -m venv .venv python3 -m venv .venv
source .venv/bin/activate source .venv/bin/activate
python -m pip install -U pip python -m pip install -U pip
pip install flask requests ccxt werkzeug PySocks Pillow pip install flask requests ccxt werkzeug PySocks Pillow
``` ```
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。 走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
可选: 可选:
```bash ```bash
export PYTHONDONTWRITEBYTECODE=1 export PYTHONDONTWRITEBYTECODE=1
``` ```
--- ---
## 5. 配置环境变量(`.env.example` → `.env` ## 5. 配置环境变量(`.env.example` → `.env`
| 文件 | 是否进 Git | 说明 | | 文件 | 是否进 Git | 说明 |
|------|------------|------| |------|------------|------|
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 | | **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** | | **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
### 5.1 首次配置 ### 5.1 首次配置
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
cp -n .env.example .env cp -n .env.example .env
nano .env nano .env
``` ```
### 5.2 备份与 `git pull` ### 5.2 备份与 `git pull`
- **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env` - **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env`
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env` - 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`
- **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env` - **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`
- **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。 - **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。
### 5.3 自动备份(数据库 + 复盘图片) ### 5.3 自动备份(数据库 + 复盘图片)
每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天**`crypto.db` + `static/images`)。 每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天**`crypto.db` + `static/images`)。
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
bash scripts/install_backup_cron.sh bash scripts/install_backup_cron.sh
bash scripts/backup_data.sh # 试跑 bash scripts/backup_data.sh # 试跑
``` ```
备份目录:`/root/backups/crypto_monitor_gate_bot/YYYY-MM-DD/`。与 Binance / Gate 实例规则相同,详见 `crypto_monitor_binance/部署文档.md` 第 5.3 节(恢复步骤、可选 `.env` 变量)。 备份目录:`/root/backups/crypto_monitor_gate_bot/YYYY-MM-DD/`。与 Binance / Gate 实例规则相同,详见 `crypto_monitor_binance/部署文档.md` 第 5.3 节(恢复步骤、可选 `.env` 变量)。
若服务器同时跑 **binance、gate、gate_bot** 三个实例,请在**各自项目目录**各执行一次 `install_backup_cron.sh` 若服务器同时跑 **binance、gate、gate_bot** 三个实例,请在**各自项目目录**各执行一次 `install_backup_cron.sh`
### 5.4 必填项检查(Gate + 代理) ### 5.4 必填项检查(Gate + 代理)
与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认: 与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认:
```env ```env
APP_HOST=127.0.0.1 APP_HOST=127.0.0.1
APP_PORT=5000 APP_PORT=5000
# 实盘(按需) # 实盘(按需)
LIVE_TRADING_ENABLED=false LIVE_TRADING_ENABLED=false
GATE_API_KEY=你的_Key GATE_API_KEY=你的_Key
GATE_API_SECRET=你的_Secret GATE_API_SECRET=你的_Secret
# 经本机 SSH 动态转发访问 Gate(端口与隧道一致) # 经本机 SSH 动态转发访问 Gate(端口与隧道一致)
GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080 GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一) # 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
# GATE_HTTP_PROXY=http://127.0.0.1:7890 # GATE_HTTP_PROXY=http://127.0.0.1:7890
# GATE_HTTPS_PROXY=http://127.0.0.1:7890 # GATE_HTTPS_PROXY=http://127.0.0.1:7890
``` ```
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。 说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
### 5.4 趋势回调策略(可选) ### 5.4 趋势回调策略(可选)
若使用「交易执行」页的 **趋势回调** 计划: 若使用「交易执行」页的 **趋势回调** 计划:
- 详细规则见项目根目录 **`趋势回调策略说明.md`**。 - 详细规则见项目根目录 **`趋势回调策略说明.md`**。
- **两阶段**:先「生成预览」(默认 **120 秒**内有效),再「确认执行」;执行时若可用余额与预览快照偏差超过 **5%** 会拒绝(可调 `.env`)。 - **两阶段**:先「生成预览」(默认 **120 秒**内有效),再「确认执行」;执行时若可用余额与预览快照偏差超过 **5%** 会拒绝(可调 `.env`)。
- 补仓档位数默认 **5**,预览有效期与余额偏差阈值可在 `.env` 覆盖: - 补仓档位数默认 **5**,预览有效期与余额偏差阈值可在 `.env` 覆盖:
```env ```env
TREND_PULLBACK_DCA_LEGS=5 TREND_PULLBACK_DCA_LEGS=5
TREND_PULLBACK_PREVIEW_TTL_SECONDS=120 TREND_PULLBACK_PREVIEW_TTL_SECONDS=120
TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT=5 TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT=5
``` ```
- **生成预览**与**确认执行**时都会读取 **Gate 永续账户 USDT 可用余额**;请尽量使用 **单独子账户** 承载策略资金。 - **生成预览**与**确认执行**时都会读取 **Gate 永续账户 USDT 可用余额**;请尽量使用 **单独子账户** 承载策略资金。
**界面与对账(与策略说明 3.4–3.5 节一致)** **界面与对账(与策略说明 3.4–3.5 节一致)**
- 页顶 **计划历史**:仅 **已结束** 的趋势计划(不含未执行预览);可 **删除** 计划行,并删除 `trend_plan_id` 关联的「趋势回调」`trade_records`(新数据;旧行无 `trend_plan_id` 不级联)。 - 页顶 **计划历史**:仅 **已结束** 的趋势计划(不含未执行预览);可 **删除** 计划行,并删除 `trend_plan_id` 关联的「趋势回调」`trade_records`(新数据;旧行无 `trend_plan_id` 不级联)。
- **运行中计划**展示交易所 **未实现盈亏**(浮盈亏)。 - **运行中计划**展示交易所 **未实现盈亏**(浮盈亏)。
- **交易记录**:趋势单在配置 API Key 后,打开「交易执行 / 交易记录」页会按节流(约 **25 秒**内同进程最多一次)拉取 Gate **平仓历史**,回填 **`exchange_realized_pnl`** 等;列表展示优先用交易所口径(见策略说明)。 - **交易记录**:趋势单在配置 API Key 后,打开「交易执行 / 交易记录」页会按节流(约 **25 秒**内同进程最多一次)拉取 Gate **平仓历史**,回填 **`exchange_realized_pnl`** 等;列表展示优先用交易所口径(见策略说明)。
**与交易所对齐的可选环境变量** **与交易所对齐的可选环境变量**
```env ```env
# 平仓历史同步起点:北京日期 YYYY-MM-DD 的 0 点(与 APP_TIMEZONE 一致);留空则从近 90 天拉取 # 平仓历史同步起点:北京日期 YYYY-MM-DD 的 0 点(与 APP_TIMEZONE 一致);留空则从近 90 天拉取
# EXCHANGE_POSITION_SYNC_FROM_BJ=2026-05-14 # EXCHANGE_POSITION_SYNC_FROM_BJ=2026-05-14
# EXCHANGE_POSITION_HISTORY_LIMIT=200 # EXCHANGE_POSITION_HISTORY_LIMIT=200
``` ```
说明:同步 **只读** 交易所接口,**不要求** `LIVE_TRADING_ENABLED=true`;无 Key 时不拉取,界面仍可用(浮盈亏可能为「—」、交易记录仍为本地「估」)。 说明:同步 **只读** 交易所接口,**不要求** `LIVE_TRADING_ENABLED=true`;无 Key 时不拉取,界面仍可用(浮盈亏可能为「—」、交易记录仍为本地「估」)。
**交易记录 CSV**:导出为 **v3**,含 `trend_plan_id` 与交易所对齐列(详见策略说明数据库一节)。 **交易记录 CSV**:导出为 **v3**,含 `trend_plan_id` 与交易所对齐列(详见策略说明数据库一节)。
--- ---
## 6. 手工启动 Flask(验证) ## 6. 手工启动 Flask(验证)
1. SOCKS 已监听 `127.0.0.1:1080` 1. SOCKS 已监听 `127.0.0.1:1080`
2.`source .venv/bin/activate` 2.`source .venv/bin/activate`
3. `.env` 已含 `GATE_SOCKS_PROXY` 3. `.env` 已含 `GATE_SOCKS_PROXY`
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
source .venv/bin/activate source .venv/bin/activate
python app.py python app.py
``` ```
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。 浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
--- ---
## 7. 安装 PM2 ## 7. 安装 PM2
```bash ```bash
sudo npm i -g pm2 sudo npm i -g pm2
pm2 -v pm2 -v
``` ```
--- ---
## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐) ## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
在项目根目录: 在项目根目录:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
pm2 start ecosystem.config.cjs pm2 start ecosystem.config.cjs
pm2 status pm2 status
pm2 logs --lines 200 pm2 logs --lines 200
``` ```
默认只启动 **`crypto-monitor-gate`**`.venv/bin/python app.py`)。 默认只启动 **`crypto-monitor-gate`**`.venv/bin/python app.py`)。
### 本机已可直连 Gate、不需要隧道时 ### 本机已可直连 Gate、不需要隧道时
`.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs` `.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`
### 开机自启 ### 开机自启
```bash ```bash
pm2 save pm2 save
pm2 startup pm2 startup
# 按屏幕提示执行一条 sudo 命令 # 按屏幕提示执行一条 sudo 命令
``` ```
--- ---
## 9. 等价手工命令(不使用 ecosystem 文件时) ## 9. 等价手工命令(不使用 ecosystem 文件时)
### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2) ### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd): 示例(前台;实际可用 `screen`/`tmux`/`-f` 后台化或 systemd):
```bash ```bash
ssh -N -D 127.0.0.1:1080 gate-vps \ ssh -N -D 127.0.0.1:1080 gate-vps \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -o ExitOnForwardFailure=yes
``` ```
### 9.2 Flask ### 9.2 Flask
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_gate_bot cd /opt/crypto_monitor/crypto_monitor_gate_bot
pm2 start /opt/crypto_monitor/crypto_monitor_gate_bot/.venv/bin/python --name crypto-monitor-gate -- \ pm2 start /opt/crypto_monitor/crypto_monitor_gate_bot/.venv/bin/python --name crypto-monitor-gate -- \
/opt/crypto_monitor/crypto_monitor_gate_bot/app.py /opt/crypto_monitor/crypto_monitor_gate_bot/app.py
``` ```
--- ---
## 10. 交易所「连接不上」排查清单 ## 10. 交易所「连接不上」排查清单
1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。 1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。
2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`): 2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`):
```bash ```bash
ss -lntp | grep 1080 || true ss -lntp | grep 1080 || true
``` ```
3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。 3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。
4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。 4. **PySocks**`pip show PySocks`,缺失则 `pip install PySocks`。
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。 5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。 6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
--- ---
## 11. 推荐启动顺序(习惯) ## 11. 推荐启动顺序(习惯)
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功 1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功
2. `pm2 start ecosystem.config.cjs` 2. `pm2 start ecosystem.config.cjs`
3. 再确认页面与余额等接口正常 3. 再确认页面与余额等接口正常
--- ---
## 12. 免责声明 ## 12. 免责声明
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。 交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
--- ---
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py` ## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
在 Ubuntu 上: 在 Ubuntu 上:
1)预览(不写库): 1)预览(不写库):
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
``` ```
2)确认后执行: 2)确认后执行:
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
``` ```
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。 默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
+79 -79
View File
@@ -1,79 +1,79 @@
# 界面与风控更新说明(OKX 实例) # 界面与风控更新说明(OKX 实例)
与 Gate / Binance 主站对齐的列表窗、统计分品类、交易记录展示、复盘与移动保本交易所同步;OKX 仍为 **三页导航**(交易执行 / 记录复盘 / 统计),关键位监控合并在 **交易执行** 页,**无** Gate 独立「关键位监控」页与斐波限价监控。 与 Gate / Binance 主站对齐的列表窗、统计分品类、交易记录展示、复盘与移动保本交易所同步;OKX 仍为 **三页导航**(交易执行 / 记录复盘 / 统计),关键位监控合并在 **交易执行** 页,**无** Gate 独立「关键位监控」页与斐波限价监控。
## 顶栏导航(3 项) ## 顶栏导航(3 项)
| 顺序 | 名称 | 路由 | 说明 | | 顺序 | 名称 | 路由 | 说明 |
|------|------|------|------| |------|------|------|------|
| 1 | 交易执行 | `/trade` | 关键位监控 + 实盘下单(**默认首页** `/``/trade` | | 1 | 交易执行 | `/trade` | 关键位监控 + 实盘下单(**默认首页** `/``/trade` |
| 2 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) | | 2 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
| 3 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 | | 3 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
## 列表时间窗(UTC,全站顶栏) ## 列表时间窗(UTC,全站顶栏)
共用模块:仓库根目录 `history_window_lib.py`(与 Gate / Binance 一致)。 共用模块:仓库根目录 `history_window_lib.py`(与 Gate / Binance 一致)。
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 默认 | **UTC 当日**`win_preset=utc_today` | | 默认 | **UTC 当日**`win_preset=utc_today` |
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC) | | 可选 | 近 24 小时、近 7 天、自定义起止(UTC) |
| 作用范围 | 关键位历史、交易记录列表、复盘 API、AI 历史 API、导出「交易记录」「关键位历史」 | | 作用范围 | 关键位历史、交易记录列表、复盘 API、AI 历史 API、导出「交易记录」「关键位历史」 |
| 与统计 | **仅影响列表/导出**;统计页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切日 | | 与统计 | **仅影响列表/导出**;统计页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切日 |
| 切换 | 顶栏「列表筛选(UTC)」→ 应用(保留当前路由 query) | | 切换 | 顶栏「列表筛选(UTC)」→ 应用(保留当前路由 query) |
## 交易记录与复盘 ## 交易记录与复盘
- 列表 **止损(开仓)**:展示 `initial_stop_loss` 快照(`display_open_stop_loss`)。 - 列表 **止损(开仓)**:展示 `initial_stop_loss` 快照(`display_open_stop_loss`)。
- 类型列显示 `monitor_type``key_signal_type`(若有)。 - 类型列显示 `monitor_type``key_signal_type`(若有)。
- 平仓入库:`stop_loss` / `initial_stop_loss` 为开仓止损快照;机器单 `entry_reason` 可按 `key_signal_type` 自动映射(箱体突破 / 收敛突破 → 四条固定关键位开仓类型文案)。 - 平仓入库:`stop_loss` / `initial_stop_loss` 为开仓止损快照;机器单 `entry_reason` 可按 `key_signal_type` 自动映射(箱体突破 / 收敛突破 → 四条固定关键位开仓类型文案)。
- 复盘:开仓类型下拉含四条关键位固定文案 +「其他」;离场触发含 **「止盈」**;从交易记录填入时按结果与信号预填。 - 复盘:开仓类型下拉含四条关键位固定文案 +「其他」;离场触发含 **「止盈」**;从交易记录填入时按结果与信号预填。
- 复盘 K 线图:以 **平仓时间** 为锚点向前约 `ORDER_CHART_LIMIT`(默认 100)根(`_fetch_ohlcv_ending_at`)。 - 复盘 K 线图:以 **平仓时间** 为锚点向前约 `ORDER_CHART_LIMIT`(默认 100)根(`_fetch_ohlcv_ending_at`)。
- `/api/journals``/api/reviews` 与顶栏 UTC 窗一致。 - `/api/journals``/api/reviews` 与顶栏 UTC 窗一致。
### 导出(交易记录 v3 ### 导出(交易记录 v3
- 文件名:`trade_records_v3_YYYYMMDD.csv` - 文件名:`trade_records_v3_YYYYMMDD.csv`
-`key_signal_type``initial_stop_loss`、计划/实际 RR、`risk_amount` 等;末列「开仓类型」为有效展示文案。 -`key_signal_type``initial_stop_loss`、计划/实际 RR、`risk_amount` 等;末列「开仓类型」为有效展示文案。
- 受 UTC 列表窗限制;关键位历史导出同理。 - 受 UTC 列表窗限制;关键位历史导出同理。
## 实盘下单(交易执行页) ## 实盘下单(交易执行页)
- **移动保本**:表单可勾选「启用移动保本」;触发阶梯上移后 **先撤后挂** 交易所 TP/SL`replace_active_monitor_tpsl_on_exchange`),仅成功后才写库;企业微信提示含「交易所:已先撤后挂止盈止损」。未配置实盘 API 时仅更新本地止损。 - **移动保本**:表单可勾选「启用移动保本」;触发阶梯上移后 **先撤后挂** 交易所 TP/SL`replace_active_monitor_tpsl_on_exchange`),仅成功后才写库;企业微信提示含「交易所:已先撤后挂止盈止损」。未配置实盘 API 时仅更新本地止损。
- 开仓 TP/SL 仍通过 OKX `attachAlgoOrds`(与原有逻辑一致);重挂使用 ccxt `stopLoss` / `takeProfit` 参数,触发价经 `_okx_algo_trigger_price_str` 格式化。 - 开仓 TP/SL 仍通过 OKX `attachAlgoOrds`(与原有逻辑一致);重挂使用 ccxt `stopLoss` / `takeProfit` 参数,触发价经 `_okx_algo_trigger_price_str` 格式化。
## 统计分析页(`/stats` ## 统计分析页(`/stats`
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 切日 | 北京时间;边界 = `TRADING_DAY_RESET_HOUR:00`(默认 8 | | 切日 | 北京时间;边界 = `TRADING_DAY_RESET_HOUR:00`(默认 8 |
| 品类下拉 | 全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786 | | 品类下拉 | 全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786 |
| URL | `stats_segment=``all` / `manual` / `key_box` / `key_conv` / `key_fib618` / `key_fib786` | | URL | `stats_segment=``all` / `manual` / `key_box` / `key_conv` / `key_fib618` / `key_fib786` |
| 与 UTC 窗 | 统计 **不** 随顶栏列表窗变化 | | 与 UTC 窗 | 统计 **不** 随顶栏列表窗变化 |
## 斐波关键位监控(与 Gate / Binance 对齐) ## 斐波关键位监控(与 Gate / Binance 对齐)
| 项 | 说明 | | 项 | 说明 |
|----|------| |----|------|
| 类型 | **斐波回调0.618**、**斐波回调0.786**(交易执行页关键位表单) | | 类型 | **斐波回调0.618**、**斐波回调0.786**(交易执行页关键位表单) |
| 同币互斥 | 每币仅一条斐波监控 | | 同币互斥 | 每币仅一条斐波监控 |
| 挂单价 E | 做多 `E = H ratio×(HL)`;做空 `E = L + ratio×(HL)`SL/TP 为 L/H | | 挂单价 E | 做多 `E = H ratio×(HL)`;做空 `E = L + ratio×(HL)`SL/TP 为 L/H |
| 添加后 | 立即在 OKX 挂限价单;卡片显示 **挂E**、限价单 ID | | 添加后 | 立即在 OKX 挂限价单;卡片显示 **挂E**、限价单 ID |
| 失效 | 标记价触达止盈侧且限价未成交 → 仅撤本条限价单(`cancel_fib_limit_order` | | 失效 | 标记价触达止盈侧且限价未成交 → 仅撤本条限价单(`cancel_fib_limit_order` |
| 成交后 | 挂交易所 TP/SL → 写入 `order_monitors``monitor_type=关键位监控``key_signal_type=斐波回调…`)→ 从关键位表移除 | | 成交后 | 挂交易所 TP/SL → 写入 `order_monitors``monitor_type=关键位监控``key_signal_type=斐波回调…`)→ 从关键位表移除 |
| 轮询 | `check_fib_key_monitors()`(与箱体/收敛 `check_key_monitors()` 分离) | | 轮询 | `check_fib_key_monitors()`(与箱体/收敛 `check_key_monitors()` 分离) |
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5 | | 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5 |
| 日成交量 | 排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30 | | 日成交量 | 排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30 |
计算逻辑见仓库根目录 `fib_key_monitor_lib.py` 计算逻辑见仓库根目录 `fib_key_monitor_lib.py`
## 与 Gate 的差异(其余) ## 与 Gate 的差异(其余)
- 无独立「关键位监控」导航页(斐波在 **交易执行** 页添加)。 - 无独立「关键位监控」导航页(斐波在 **交易执行** 页添加)。
- 无交易所已实现盈亏同步(`/api/sync_exchange_pnl`)。 - 无交易所已实现盈亏同步(`/api/sync_exchange_pnl`)。
- 箱体/收敛仍为 **提醒** 模式,不自动市价开仓(Gate/Binance 主站为自动开仓)。 - 箱体/收敛仍为 **提醒** 模式,不自动市价开仓(Gate/Binance 主站为自动开仓)。
## 配置与部署 ## 配置与部署
- 详见 `.env.example` 中 OKX`OKX_*`)与通用风控项。 - 详见 `.env.example` 中 OKX`OKX_*`)与通用风控项。
- 代码更新后请 **重启 OKX 监控进程**;旧库行不做批量回填,展示字段有则用之、无则回退。 - 代码更新后请 **重启 OKX 监控进程**;旧库行不做批量回填,展示字段有则用之、无则回退。
+348 -348
View File
@@ -1,349 +1,349 @@
# `crypto_monitor` 本地部署 + SSH SOCKS 转发 + PM2 启动指南(Ubuntu # `crypto_monitor` 本地部署 + SSH SOCKS 转发 + PM2 启动指南(Ubuntu
本文面向:**本地 Ubuntu 机器运行项目**,但 **本机直连 OKX 会被 TLS/SNI reset** 的场景。解决思路是: 本文面向:**本地 Ubuntu 机器运行项目**,但 **本机直连 OKX 会被 TLS/SNI reset** 的场景。解决思路是:
- 本机启动 `ssh -D` 动态转发,把 **SOCKS5 出口**放到你可正常访问 OKX 的 VPS 上 - 本机启动 `ssh -D` 动态转发,把 **SOCKS5 出口**放到你可正常访问 OKX 的 VPS 上
- 项目通过环境变量 `OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080``ccxt` 走 SOCKS - 项目通过环境变量 `OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080``ccxt` 走 SOCKS
-`pm2` 托管 **SSH 隧道****Flask 应用**(你也可以只用 `screen`,但本文按你要求用 PM2 -`pm2` 托管 **SSH 隧道****Flask 应用**(你也可以只用 `screen`,但本文按你要求用 PM2
> 安全提醒:不要把 `.env`、私钥 `.pem`、OKX API Key 提交到 Git;文档里只用占位符。 > 安全提醒:不要把 `.env`、私钥 `.pem`、OKX API Key 提交到 Git;文档里只用占位符。
--- ---
## 0. 你需要准备的东西 ## 0. 你需要准备的东西
- 一台 **Ubuntu** 本地机器(下文称“本机”) - 一台 **Ubuntu** 本地机器(下文称“本机”)
- 一台可 SSH 登录、且 **能正常访问 OKX** 的 VPS(示例公网 IP`47.76.87.111`,用户:`root` - 一台可 SSH 登录、且 **能正常访问 OKX** 的 VPS(示例公网 IP`47.76.87.111`,用户:`root`
- VPS 登录方式:**SSH 私钥**(推荐)或密码(不推荐用于无人值守) - VPS 登录方式:**SSH 私钥**(推荐)或密码(不推荐用于无人值守)
- 本机已安装: - 本机已安装:
- `python3``python3-venv``pip`(或 `python3-pip` - `python3``python3-venv``pip`(或 `python3-pip`
- `git`(可选) - `git`(可选)
- `curl``ssh` - `curl``ssh`
- `node` + `npm`(用于安装 `pm2` - `node` + `npm`(用于安装 `pm2`
--- ---
## 1. 从云服务器把项目同步到本地(推荐:打包下载) ## 1. 从云服务器把项目同步到本地(推荐:打包下载)
在云服务器项目目录(包含 `app.py` 的目录)执行: 在云服务器项目目录(包含 `app.py` 的目录)执行:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_okx cd /opt/crypto_monitor/crypto_monitor_okx
# 可选:清理 Python 缓存,减少小文件传输 # 可选:清理 Python 缓存,减少小文件传输
find . -type d -name __pycache__ -prune -exec rm -rf {} + find . -type d -name __pycache__ -prune -exec rm -rf {} +
find . -type f -name "*.pyc" -delete find . -type f -name "*.pyc" -delete
tar -czf crypto_monitor.tgz . tar -czf crypto_monitor.tgz .
``` ```
下载 `crypto_monitor.tgz` 到本机后解压: 下载 `crypto_monitor.tgz` 到本机后解压:
```bash ```bash
mkdir -p /opt/crypto_monitor/crypto_monitor_okx mkdir -p /opt/crypto_monitor/crypto_monitor_okx
cd /opt/crypto_monitor cd /opt/crypto_monitor
tar -xzf crypto_monitor.tgz -C crypto_monitor_okx tar -xzf crypto_monitor.tgz -C crypto_monitor_okx
cd crypto_monitor_okx cd crypto_monitor_okx
cp -n .env.example .env # 若尚无 .env cp -n .env.example .env # 若尚无 .env
``` ```
--- ---
## 2. 配置 SSH 私钥与 `~/.ssh/config`(推荐) ## 2. 配置 SSH 私钥与 `~/.ssh/config`(推荐)
把私钥放到本机(示例:`~/.ssh/vps1.pem`),并设置权限: 把私钥放到本机(示例:`~/.ssh/vps1.pem`),并设置权限:
```bash ```bash
mkdir -p ~/.ssh mkdir -p ~/.ssh
chmod 700 ~/.ssh chmod 700 ~/.ssh
mv ~/Downloads/vps1.pem ~/.ssh/vps1.pem mv ~/Downloads/vps1.pem ~/.ssh/vps1.pem
chmod 600 ~/.ssh/vps1.pem chmod 600 ~/.ssh/vps1.pem
``` ```
编辑 `~/.ssh/config`(没有就创建),添加: 编辑 `~/.ssh/config`(没有就创建),添加:
```sshconfig ```sshconfig
Host okx-vps Host okx-vps
HostName 47.76.87.111 HostName 47.76.87.111
User root User root
IdentityFile ~/.ssh/vps1.pem IdentityFile ~/.ssh/vps1.pem
IdentitiesOnly yes IdentitiesOnly yes
ServerAliveInterval 30 ServerAliveInterval 30
ServerAliveCountMax 3 ServerAliveCountMax 3
ExitOnForwardFailure yes ExitOnForwardFailure yes
BatchMode yes BatchMode yes
``` ```
测试: 测试:
```bash ```bash
ssh okx-vps true ssh okx-vps true
``` ```
> 如果你还没完全切到密钥登录(还会交互要密码),先把 `BatchMode yes` 注释掉,等密钥登录稳定后再打开。 > 如果你还没完全切到密钥登录(还会交互要密码),先把 `BatchMode yes` 注释掉,等密钥登录稳定后再打开。
--- ---
## 3. 先手工验证:SSH SOCKS + OKX API ## 3. 先手工验证:SSH SOCKS + OKX API
### 3.1 开一个本地 SOCKS1080 ### 3.1 开一个本地 SOCKS1080
```bash ```bash
ssh -N -D 127.0.0.1:1080 okx-vps ssh -N -D 127.0.0.1:1080 okx-vps
``` ```
保持该进程运行(另开终端继续下面步骤)。 保持该进程运行(另开终端继续下面步骤)。
### 3.2 验证 OKX 走 SOCKS 可用 ### 3.2 验证 OKX 走 SOCKS 可用
```bash ```bash
curl -4 -Iv --max-time 15 --proxy socks5h://127.0.0.1:1080 https://www.okx.com/api/v5/public/time curl -4 -Iv --max-time 15 --proxy socks5h://127.0.0.1:1080 https://www.okx.com/api/v5/public/time
``` ```
看到 `HTTP/2 200`(或至少 TLS 握手成功且返回 JSON)即 OK。 看到 `HTTP/2 200`(或至少 TLS 握手成功且返回 JSON)即 OK。
--- ---
## 4. Python 虚拟环境(venv ## 4. Python 虚拟环境(venv
在本机项目目录: 在本机项目目录:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_okx cd /opt/crypto_monitor/crypto_monitor_okx
python3 -m venv .venv python3 -m venv .venv
source .venv/bin/activate source .venv/bin/activate
python -m pip install -U pip python -m pip install -U pip
pip install flask requests ccxt werkzeug PySocks Pillow pip install flask requests ccxt werkzeug PySocks Pillow
``` ```
> 说明:本仓库当前没有 `requirements.txt`。如果你希望“完全复刻云服务器依赖”,可以在云服务器项目环境里执行 `pip freeze > requirements.txt` 带回本机再 `pip install -r requirements.txt`(记得删掉明显无关/体积巨大的包)。 > 说明:本仓库当前没有 `requirements.txt`。如果你希望“完全复刻云服务器依赖”,可以在云服务器项目环境里执行 `pip freeze > requirements.txt` 带回本机再 `pip install -r requirements.txt`(记得删掉明显无关/体积巨大的包)。
建议减少 `.pyc` 垃圾文件(可选): 建议减少 `.pyc` 垃圾文件(可选):
```bash ```bash
export PYTHONDONTWRITEBYTECODE=1 export PYTHONDONTWRITEBYTECODE=1
``` ```
--- ---
## 5. 配置环境变量(`.env.example` → `.env` ## 5. 配置环境变量(`.env.example` → `.env`
| 文件 | 是否进 Git | 说明 | | 文件 | 是否进 Git | 说明 |
|------|------------|------| |------|------------|------|
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 | | **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** | | **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
### 5.1 首次配置 ### 5.1 首次配置
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_okx cd /opt/crypto_monitor/crypto_monitor_okx
cp -n .env.example .env # 已存在 .env 时不覆盖 cp -n .env.example .env # 已存在 .env 时不覆盖
nano .env nano .env
``` ```
### 5.2 备份与 `git pull` ### 5.2 备份与 `git pull`
- **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env` - **`.env` 不在 Git 中**`git pull` **不会**覆盖本地 `.env`
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env` - 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`
- **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env` - **升级前备份**`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`
- **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。 - **换机**`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。
### 5.3 必填项检查(OKX + 代理) ### 5.3 必填项检查(OKX + 代理)
至少确认/填写这些关键项(示例): 至少确认/填写这些关键项(示例):
```env ```env
APP_HOST=127.0.0.1 APP_HOST=127.0.0.1
APP_PORT=5000 APP_PORT=5000
# OKX(如需实盘) # OKX(如需实盘)
LIVE_TRADING_ENABLED=false LIVE_TRADING_ENABLED=false
OKX_API_KEY=... OKX_API_KEY=...
OKX_API_SECRET=... OKX_API_SECRET=...
OKX_API_PASSPHRASE=... OKX_API_PASSPHRASE=...
# OKX 出口:走本机 SSH 动态转发 SOCKS # OKX 出口:走本机 SSH 动态转发 SOCKS
OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080 OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080
# 开仓多周期K线图(可选) # 开仓多周期K线图(可选)
# ORDER_CHART_ENABLED=true # ORDER_CHART_ENABLED=true
# ORDER_CHART_TFS=4h,1h,15m,5m # ORDER_CHART_TFS=4h,1h,15m,5m
# ORDER_CHART_LIMIT=100 # ORDER_CHART_LIMIT=100
# ORDER_CHART_DIR=static/images/order_charts # ORDER_CHART_DIR=static/images/order_charts
# DAILY_OPEN_ALERT_THRESHOLD=5 # DAILY_OPEN_ALERT_THRESHOLD=5
# Ollama(如本机跑) # Ollama(如本机跑)
OLLAMA_API=http://127.0.0.1:11434/api/generate OLLAMA_API=http://127.0.0.1:11434/api/generate
AI_MODEL=你的模型名 AI_MODEL=你的模型名
``` ```
> `OKX_SOCKS_PROXY` 使用 `socks5h`:让 SOCKS 侧做域名解析(更贴近你 `curl --proxy socks5h://...` 的成功路径)。 > `OKX_SOCKS_PROXY` 使用 `socks5h`:让 SOCKS 侧做域名解析(更贴近你 `curl --proxy socks5h://...` 的成功路径)。
--- ---
## 6. 本机手工启动(验证 Flask) ## 6. 本机手工启动(验证 Flask)
确保: 确保:
1. SOCKS 隧道已运行(127.0.0.1:1080 1. SOCKS 隧道已运行(127.0.0.1:1080
2. 虚拟环境已 `activate` 2. 虚拟环境已 `activate`
3. `.env` 已配置 3. `.env` 已配置
启动: 启动:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_okx cd /opt/crypto_monitor/crypto_monitor_okx
source .venv/bin/activate source .venv/bin/activate
python app.py python app.py
``` ```
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 配的端口)。 浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 配的端口)。
--- ---
## 7. 安装 PM2Node ## 7. 安装 PM2Node
```bash ```bash
sudo npm i -g pm2 sudo npm i -g pm2
pm2 -v pm2 -v
``` ```
--- ---
## 8. 用 PM2 启动 SSH SOCKS 隧道(推荐:密钥免交互) ## 8. 用 PM2 启动 SSH SOCKS 隧道(推荐:密钥免交互)
### 8.1 启动隧道进程 ### 8.1 启动隧道进程
```bash ```bash
pm2 start "ssh" --name okx-socks-tunnel -- \ pm2 start "ssh" --name okx-socks-tunnel -- \
-N -D 127.0.0.1:1080 okx-vps \ -N -D 127.0.0.1:1080 okx-vps \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -o BatchMode=yes -o ExitOnForwardFailure=yes -o BatchMode=yes
``` ```
查看日志: 查看日志:
```bash ```bash
pm2 logs okx-socks-tunnel --lines 200 pm2 logs okx-socks-tunnel --lines 200
``` ```
### 8.2 仍然验证 OKX ### 8.2 仍然验证 OKX
```bash ```bash
curl -4 -Iv --max-time 15 --proxy socks5h://127.0.0.1:1080 https://www.okx.com/api/v5/public/time curl -4 -Iv --max-time 15 --proxy socks5h://127.0.0.1:1080 https://www.okx.com/api/v5/public/time
``` ```
### 8.3 开机自启(可选) ### 8.3 开机自启(可选)
```bash ```bash
pm2 save pm2 save
pm2 startup pm2 startup
``` ```
--- ---
## 9. 用 PM2 启动 Flask`app.py` ## 9. 用 PM2 启动 Flask`app.py`
`pm2` 管理 Python 的常用方式是直接启动解释器: `pm2` 管理 Python 的常用方式是直接启动解释器:
```bash ```bash
cd /opt/crypto_monitor/crypto_monitor_okx cd /opt/crypto_monitor/crypto_monitor_okx
pm2 start /opt/crypto_monitor/crypto_monitor_okx/.venv/bin/python --name crypto-monitor -- \ pm2 start /opt/crypto_monitor/crypto_monitor_okx/.venv/bin/python --name crypto-monitor -- \
/opt/crypto_monitor/crypto_monitor_okx/app.py /opt/crypto_monitor/crypto_monitor_okx/app.py
``` ```
> 若项目目录与上文不一致,请替换为实际绝对路径;或用 `readlink -f app.py` 得到绝对路径。 > 若项目目录与上文不一致,请替换为实际绝对路径;或用 `readlink -f app.py` 得到绝对路径。
查看日志: 查看日志:
```bash ```bash
pm2 logs crypto-monitor --lines 200 pm2 logs crypto-monitor --lines 200
``` ```
保存进程列表: 保存进程列表:
```bash ```bash
pm2 save pm2 save
``` ```
--- ---
## 10. 常见问题排查(高频) ## 10. 常见问题排查(高频)
### 10.1 OKX 仍然失败:先看隧道是否在 ### 10.1 OKX 仍然失败:先看隧道是否在
```bash ```bash
ss -lntp | grep 1080 || true ss -lntp | grep 1080 || true
pm2 status pm2 status
``` ```
### 10.2 `pm2` 里的 `ssh` 立刻退出 ### 10.2 `pm2` 里的 `ssh` 立刻退出
常见原因: 常见原因:
- 私钥权限不对(`chmod 600` - 私钥权限不对(`chmod 600`
- `~/.ssh/config` 写错 `HostName/User/IdentityFile` - `~/.ssh/config` 写错 `HostName/User/IdentityFile`
- 开了 `BatchMode yes` 但仍需要密码(会失败) - 开了 `BatchMode yes` 但仍需要密码(会失败)
### 10.3 `ccxt` SOCKS 报错 / 代理不生效 ### 10.3 `ccxt` SOCKS 报错 / 代理不生效
本机 Python 依赖通常需要: 本机 Python 依赖通常需要:
```bash ```bash
source .venv/bin/activate source .venv/bin/activate
pip install PySocks pip install PySocks
``` ```
### 10.4 `.pyc` 很多导致同步慢 ### 10.4 `.pyc` 很多导致同步慢
`.pyc` 是缓存,删除不影响功能: `.pyc` 是缓存,删除不影响功能:
```bash ```bash
find . -type d -name __pycache__ -prune -exec rm -rf {} + find . -type d -name __pycache__ -prune -exec rm -rf {} +
find . -type f -name "*.pyc" -delete find . -type f -name "*.pyc" -delete
``` ```
--- ---
## 11. 推荐的启动顺序(固定习惯) ## 11. 推荐的启动顺序(固定习惯)
1. `pm2` 启动 `okx-socks-tunnel` 1. `pm2` 启动 `okx-socks-tunnel`
2. `curl --proxy socks5h://127.0.0.1:1080 ...` 验证 OKX 2. `curl --proxy socks5h://127.0.0.1:1080 ...` 验证 OKX
3. `pm2` 启动 `crypto-monitor` 3. `pm2` 启动 `crypto-monitor`
--- ---
## 12. 免责声明 ## 12. 免责声明
交易所有合规与地区政策要求。请确保你的使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署技术路径。 交易所有合规与地区政策要求。请确保你的使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署技术路径。
写好了,脚本路径: 写好了,脚本路径:
- `scripts/fix_breakeven_labels.py` - `scripts/fix_breakeven_labels.py`
你在 Ubuntu 上这样用: 你在 Ubuntu 上这样用:
1) 先预览(不写库): 1) 先预览(不写库):
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
``` ```
2) 确认后执行: 2) 确认后执行:
```bash ```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
``` ```
默认修复条件就是你要的: 默认修复条件就是你要的:
- `monitor_type='下单监控'` - `monitor_type='下单监控'`
- `result='止损'` - `result='止损'`
- `pnl_amount > 0` - `pnl_amount > 0`
- 改成 `result='保本止盈'` - 改成 `result='保本止盈'`
如果你想,我还可以再给你一条“先自动备份 DB 再执行”的一键命令。 如果你想,我还可以再给你一条“先自动备份 DB 再执行”的一键命令。
+68
View File
@@ -0,0 +1,68 @@
# 环境一键部署
为仓库内各子项目创建 Python 虚拟环境、安装依赖、初始化 `.env` 与静态目录。
## Windows(推荐)
双击仓库根目录 **`一键部署.bat`**,或在 PowerShell 中:
```powershell
cd C:\path\to\crypto_monitor
.\deploy\setup_env.ps1
```
仅部署部分项目:
```powershell
.\deploy\setup_env.ps1 -Only binance,gate_bot
```
重建虚拟环境:
```powershell
.\deploy\setup_env.ps1 -RecreateVenv
```
跳过 PM2、跳过复制 `.env`
```powershell
.\deploy\setup_env.ps1 -SkipPm2 -SkipEnvCopy
```
## Linux / macOS
```bash
cd /opt/crypto_monitor
bash deploy/setup_env.sh
bash deploy/setup_env.sh --only binance,gate
bash deploy/setup_env.sh --recreate-venv
```
## 脚本会做什么
| 步骤 | 说明 |
|------|------|
| 检查 Python | 需要 **3.10+** |
| `crypto_monitor_*` | 各目录 `.venv` + `pip install -r ../requirements.txt` |
| `manual_trading_hub` | 独立 `requirements.txt` |
| `.env` | 若不存在则从 `.env.example` 复制(**不覆盖**已有) |
| 目录 | 创建 `static/images``static/images/order_charts` |
| PM2 | 若已装 Node.js 且未 `-SkipPm2`,尝试 `npm install -g pm2` |
## 部署之后
1. 编辑各子目录 **`.env`**(API、登录密码、SOCKS 代理等)。
2. 本地试运行(以 Binance 为例):
```bash
cd crypto_monitor_binance
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
python app.py
```
3. 服务器长期运行见各目录 **《部署文档.md》**SSH SOCKS、PM2)。
## 依赖说明
- 四个监控子项目共用仓库根目录 **[requirements.txt](../requirements.txt)**。
- 走 SOCKS 代理时必须安装 **PySocks**(已包含在 requirements 中)。
+210
View File
@@ -0,0 +1,210 @@
#Requires -Version 5.1
<#
.SYNOPSIS
crypto_monitor 一键环境部署Windows PowerShell
.DESCRIPTION
- 为各子项目创建 Python venv 并安装依赖
- .env.example 复制 .env不覆盖已有
- 创建 static/images 等运行时目录
- 可选安装 PM2需已安装 Node.js
.EXAMPLE
.\deploy\setup_env.ps1
.\deploy\setup_env.ps1 -Only binance,gate_bot
.\deploy\setup_env.ps1 -SkipPm2
#>
param(
[string]$Only = "all",
[switch]$SkipPm2,
[switch]$SkipEnvCopy,
[switch]$RecreateVenv
)
$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$DeployDir = $PSScriptRoot
$RepoRoot = (Resolve-Path (Join-Path $DeployDir "..")).Path
$ReqFile = Join-Path $RepoRoot "requirements.txt"
$HubReqFile = Join-Path $RepoRoot "manual_trading_hub\requirements.txt"
$MonitorProjects = @(
@{ Key = "binance"; Dir = "crypto_monitor_binance" },
@{ Key = "gate"; Dir = "crypto_monitor_gate" },
@{ Key = "gate_bot"; Dir = "crypto_monitor_gate_bot" },
@{ Key = "okx"; Dir = "crypto_monitor_okx" }
)
$HubProject = @{ Key = "hub"; Dir = "manual_trading_hub" }
function Write-Step([string]$Msg) {
Write-Host ""
Write-Host "==> $Msg" -ForegroundColor Cyan
}
function Test-Python310 {
$py = Get-Command python -ErrorAction SilentlyContinue
if (-not $py) {
throw "未找到 python。请安装 Python 3.10+ 并加入 PATHhttps://www.python.org/downloads/"
}
$verText = & python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"
$parts = $verText.Trim() -split "\."
$major = [int]$parts[0]
$minor = [int]$parts[1]
if ($major -lt 3 -or ($major -eq 3 -and $minor -lt 10)) {
throw "需要 Python 3.10+,当前: $verText"
}
Write-Host "Python: $(python --version 2>&1)" -ForegroundColor DarkGray
}
function Should-Include([string]$Key, [string[]]$Selected) {
if ($Selected -contains "all") { return $true }
return $Selected -contains $Key
}
function Setup-MonitorProject([hashtable]$Proj) {
$projPath = Join-Path $RepoRoot $Proj.Dir
if (-not (Test-Path $projPath)) {
Write-Host " 跳过(目录不存在): $($Proj.Dir)" -ForegroundColor Yellow
return
}
Write-Step "$($Proj.Dir)"
Push-Location $projPath
try {
$venvDir = Join-Path $projPath ".venv"
$venvPy = Join-Path $venvDir "Scripts\python.exe"
$venvPip = Join-Path $venvDir "Scripts\pip.exe"
if ($RecreateVenv -and (Test-Path $venvDir)) {
Write-Host " 删除旧 venv ..."
Remove-Item -Recurse -Force $venvDir
}
if (-not (Test-Path $venvPy)) {
Write-Host " 创建 venv ..."
& python -m venv .venv
}
Write-Host " 升级 pip ..."
& $venvPy -m pip install -U pip setuptools wheel -q
Write-Host " 安装依赖 (requirements.txt) ..."
& $venvPip install -r $ReqFile -q
if (-not $SkipEnvCopy) {
$envExample = Join-Path $projPath ".env.example"
$envFile = Join-Path $projPath ".env"
if ((Test-Path $envExample) -and -not (Test-Path $envFile)) {
Copy-Item $envExample $envFile
Write-Host " 已复制 .env.example -> .env" -ForegroundColor Green
} elseif (Test-Path $envFile) {
Write-Host " 保留已有 .env" -ForegroundColor DarkGray
} else {
Write-Host " 无 .env.example,请手动配置 .env" -ForegroundColor Yellow
}
}
$staticDirs = @(
"static\images",
"static\images\order_charts"
)
foreach ($d in $staticDirs) {
$full = Join-Path $projPath $d
if (-not (Test-Path $full)) {
New-Item -ItemType Directory -Path $full -Force | Out-Null
}
}
Write-Host " 完成: $venvPy" -ForegroundColor Green
} finally {
Pop-Location
}
}
function Setup-HubProject() {
$projPath = Join-Path $RepoRoot $HubProject.Dir
if (-not (Test-Path $projPath)) {
Write-Host " 跳过 hub(目录不存在)" -ForegroundColor Yellow
return
}
Write-Step $HubProject.Dir
Push-Location $projPath
try {
$venvDir = Join-Path $projPath ".venv"
$venvPy = Join-Path $venvDir "Scripts\python.exe"
$venvPip = Join-Path $venvDir "Scripts\pip.exe"
if ($RecreateVenv -and (Test-Path $venvDir)) {
Remove-Item -Recurse -Force $venvDir
}
if (-not (Test-Path $venvPy)) {
& python -m venv .venv
}
& $venvPy -m pip install -U pip setuptools wheel -q
if (Test-Path $HubReqFile) {
& $venvPip install -r $HubReqFile -q
}
if (-not $SkipEnvCopy) {
$envExample = Join-Path $projPath ".env.example"
$envFile = Join-Path $projPath ".env"
if ((Test-Path $envExample) -and -not (Test-Path $envFile)) {
Copy-Item $envExample $envFile
Write-Host " 已复制 .env.example -> .env" -ForegroundColor Green
}
}
Write-Host " 完成: $venvPy" -ForegroundColor Green
} finally {
Pop-Location
}
}
function Install-Pm2IfNeeded() {
if ($SkipPm2) { return }
$node = Get-Command node -ErrorAction SilentlyContinue
if (-not $node) {
Write-Host "未检测到 Node.js,跳过 PM2。安装 Node 后执行: npm install -g pm2" -ForegroundColor Yellow
return
}
Write-Step "PM2(可选进程托管)"
$pm2 = Get-Command pm2 -ErrorAction SilentlyContinue
if ($pm2) {
Write-Host " PM2 已安装: $(pm2 -v)" -ForegroundColor Green
return
}
Write-Host " 正在全局安装 pm2 ..."
& npm install -g pm2
Write-Host " PM2 安装完成。在各子目录执行: pm2 start ecosystem.config.cjs" -ForegroundColor Green
}
# --- main ---
Write-Host "crypto_monitor 环境部署" -ForegroundColor White
Write-Host "仓库根目录: $RepoRoot" -ForegroundColor DarkGray
if (-not (Test-Path $ReqFile)) {
throw "缺少 $ReqFile"
}
Test-Python310
$selected = ($Only -split "[,;\s]+" | ForEach-Object { $_.Trim().ToLower() } | Where-Object { $_ })
if (-not $selected -or $selected.Count -eq 0) { $selected = @("all") }
foreach ($p in $MonitorProjects) {
if (Should-Include $p.Key $selected) {
Setup-MonitorProject $p
}
}
if (Should-Include $HubProject.Key $selected) {
Setup-HubProject
}
Install-Pm2IfNeeded
Write-Host ""
Write-Host "部署完成。下一步:" -ForegroundColor Green
Write-Host " 1. 编辑各子目录 .env(API Key、密码、代理等)"
Write-Host " 2. 启动示例(Binance):"
Write-Host " cd crypto_monitor_binance"
Write-Host " .\.venv\Scripts\activate"
Write-Host " python app.py"
Write-Host " 3. Linux 服务器可用: bash deploy/setup_env.sh"
Write-Host ""
+184
View File
@@ -0,0 +1,184 @@
#!/usr/bin/env bash
# crypto_monitor 一键环境部署(Linux / macOS / Git Bash
#
# 用法:
# bash deploy/setup_env.sh
# bash deploy/setup_env.sh --only binance,gate_bot
# bash deploy/setup_env.sh --skip-pm2
# bash deploy/setup_env.sh --recreate-venv
#
set -euo pipefail
DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
REQ_FILE="${REPO_ROOT}/requirements.txt"
HUB_REQ="${REPO_ROOT}/manual_trading_hub/requirements.txt"
ONLY="all"
SKIP_PM2=0
SKIP_ENV_COPY=0
RECREATE_VENV=0
usage() {
sed -n '2,12p' "$0" | sed 's/^# \?//'
exit "${1:-0}"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--only) ONLY="${2:-all}"; shift 2 ;;
--skip-pm2) SKIP_PM2=1; shift ;;
--skip-env-copy) SKIP_ENV_COPY=1; shift ;;
--recreate-venv) RECREATE_VENV=1; shift ;;
-h|--help) usage 0 ;;
*) echo "未知参数: $1" >&2; usage 1 ;;
esac
done
step() { echo ""; echo "==> $*"; }
should_include() {
local key="$1"
if [[ "${ONLY}" == "all" ]]; then
return 0
fi
local item
IFS=',' read -ra PARTS <<< "${ONLY}"
for item in "${PARTS[@]}"; do
item="$(echo "${item}" | tr '[:upper:]' '[:lower:]' | xargs)"
[[ "${item}" == "${key}" ]] && return 0
done
return 1
}
find_python() {
if command -v python3 >/dev/null 2>&1; then
echo python3
return
fi
if command -v python >/dev/null 2>&1; then
echo python
return
fi
echo "未找到 python3/python,请先安装 Python 3.10+" >&2
exit 1
}
check_python_version() {
local py="$1"
local ver
ver="$("${py}" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
local major minor
major="${ver%%.*}"
minor="${ver#*.}"
if [[ "${major}" -lt 3 ]] || [[ "${major}" -eq 3 && "${minor}" -lt 10 ]]; then
echo "需要 Python 3.10+,当前: ${ver}" >&2
exit 1
fi
echo "Python: $("${py}" --version 2>&1)"
}
setup_monitor() {
local dir_name="$1"
local proj="${REPO_ROOT}/${dir_name}"
if [[ ! -d "${proj}" ]]; then
echo " 跳过(目录不存在): ${dir_name}"
return
fi
step "${dir_name}"
cd "${proj}"
local py
py="$(find_python)"
if [[ "${RECREATE_VENV}" -eq 1 && -d .venv ]]; then
echo " 删除旧 venv ..."
rm -rf .venv
fi
if [[ ! -x .venv/bin/python ]]; then
echo " 创建 venv ..."
"${py}" -m venv .venv
fi
echo " 升级 pip ..."
.venv/bin/python -m pip install -U pip setuptools wheel -q
echo " 安装依赖 ..."
.venv/bin/pip install -r "${REQ_FILE}" -q
if [[ "${SKIP_ENV_COPY}" -eq 0 ]]; then
if [[ -f .env.example && ! -f .env ]]; then
cp -n .env.example .env 2>/dev/null || cp .env.example .env
echo " 已复制 .env.example -> .env"
elif [[ -f .env ]]; then
echo " 保留已有 .env"
else
echo " 无 .env.example,请手动配置 .env"
fi
fi
mkdir -p static/images/order_charts
echo " 完成: ${proj}/.venv/bin/python"
}
setup_hub() {
local proj="${REPO_ROOT}/manual_trading_hub"
if [[ ! -d "${proj}" ]]; then
echo " 跳过 hub(目录不存在)"
return
fi
step "manual_trading_hub"
cd "${proj}"
local py
py="$(find_python)"
if [[ "${RECREATE_VENV}" -eq 1 && -d .venv ]]; then
rm -rf .venv
fi
if [[ ! -x .venv/bin/python ]]; then
"${py}" -m venv .venv
fi
.venv/bin/python -m pip install -U pip setuptools wheel -q
if [[ -f "${HUB_REQ}" ]]; then
.venv/bin/pip install -r "${HUB_REQ}" -q
fi
if [[ "${SKIP_ENV_COPY}" -eq 0 && -f .env.example && ! -f .env ]]; then
cp -n .env.example .env 2>/dev/null || cp .env.example .env
echo " 已复制 .env.example -> .env"
fi
echo " 完成: ${proj}/.venv/bin/python"
}
install_pm2() {
if [[ "${SKIP_PM2}" -eq 1 ]]; then
return
fi
step "PM2(可选)"
if ! command -v node >/dev/null 2>&1; then
echo " 未检测到 Node.js,跳过。安装后执行: npm install -g pm2"
return
fi
if command -v pm2 >/dev/null 2>&1; then
echo " PM2 已安装: $(pm2 -v)"
return
fi
echo " 正在安装 pm2 ..."
npm install -g pm2
echo " 各子目录: pm2 start ecosystem.config.cjs"
}
echo "crypto_monitor 环境部署"
echo "仓库根目录: ${REPO_ROOT}"
[[ -f "${REQ_FILE}" ]] || { echo "缺少 ${REQ_FILE}" >&2; exit 1; }
PY="$(find_python)"
check_python_version "${PY}"
should_include binance && setup_monitor crypto_monitor_binance
should_include gate && setup_monitor crypto_monitor_gate
should_include gate_bot && setup_monitor crypto_monitor_gate_bot
should_include okx && setup_monitor crypto_monitor_okx
should_include hub && setup_hub
install_pm2
echo ""
echo "部署完成。下一步:"
echo " 1. 编辑各子目录 .env"
echo " 2. 启动示例: cd crypto_monitor_binance && source .venv/bin/activate && python app.py"
echo " 3. Windows 可用: powershell -File deploy/setup_env.ps1"
echo ""
+191 -191
View File
@@ -1,191 +1,191 @@
# Ubuntu 后台运行(中控 + 子代理) # Ubuntu 后台运行(中控 + 子代理)
`crypto_monitor_*` 策略目录:首次 **`cp .env.example .env`** 并编辑;**`.env` 不进 Git**`git pull` 不覆盖。升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`。子代理启动前须 **`source` 该目录 `.env`**(见下文)。 `crypto_monitor_*` 策略目录:首次 **`cp .env.example .env`** 并编辑;**`.env` 不进 Git**`git pull` 不覆盖。升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`。子代理启动前须 **`source` 该目录 `.env`**(见下文)。
前台跑 `python agent.py` / `python hub.py` 时,关掉终端进程会结束。要**常驻后台**,可用下面三种之一(推荐 **systemd**)。 前台跑 `python agent.py` / `python hub.py` 时,关掉终端进程会结束。要**常驻后台**,可用下面三种之一(推荐 **systemd**)。
--- ---
## 一、tmux / screen(最简单,适合先试用) ## 一、tmux / screen(最简单,适合先试用)
仓库已提供 **一键起 3 个 agent(不含 OKX** 的 screen 脚本(需可执行权限): 仓库已提供 **一键起 3 个 agent(不含 OKX** 的 screen 脚本(需可执行权限):
```bash ```bash
chmod +x manual_trading_hub/scripts/start_agents_3screen.sh chmod +x manual_trading_hub/scripts/start_agents_3screen.sh
chmod +x manual_trading_hub/scripts/start_hub_screen.sh chmod +x manual_trading_hub/scripts/start_hub_screen.sh
chmod +x manual_trading_hub/scripts/stop_agents_3screen.sh chmod +x manual_trading_hub/scripts/stop_agents_3screen.sh
chmod +x manual_trading_hub/scripts/stop_hub_screen.sh chmod +x manual_trading_hub/scripts/stop_hub_screen.sh
./manual_trading_hub/scripts/start_agents_3screen.sh ./manual_trading_hub/scripts/start_agents_3screen.sh
./manual_trading_hub/scripts/start_hub_screen.sh ./manual_trading_hub/scripts/start_hub_screen.sh
# 关闭: # 关闭:
./manual_trading_hub/scripts/stop_hub_screen.sh ./manual_trading_hub/scripts/stop_hub_screen.sh
./manual_trading_hub/scripts/stop_agents_3screen.sh ./manual_trading_hub/scripts/stop_agents_3screen.sh
``` ```
脚本默认认为:`manual_trading_hub` 的**上一级目录**里并列放着三个 `crypto_monitor_*`。若你把 hub 单独放在 `/opt/crypto_monitor/manual_trading_hub`,而策略项目在例如 `/opt/crypto_monitor/` 下的其他位置,请先执行 脚本默认认为:`manual_trading_hub` 的**上一级目录**里并列放着三个 `crypto_monitor_*`。若你把 hub 单独放在 `/opt/crypto_monitor/manual_trading_hub`,而策略项目在例如 `/opt/crypto_monitor/` 下的其他位置,请先执行
`export MANUAL_TRADING_REPO_ROOT=/opt/crypto_monitor` 再运行 `start_agents_3screen.sh` `export MANUAL_TRADING_REPO_ROOT=/opt/crypto_monitor` 再运行 `start_agents_3screen.sh`
启动后若 `screen -ls` 里没有 `mt-agent-*`,看日志:`tail -80 /opt/crypto_monitor/manual_trading_hub/logs/mt-agent-bn.log` 启动后若 `screen -ls` 里没有 `mt-agent-*`,看日志:`tail -80 /opt/crypto_monitor/manual_trading_hub/logs/mt-agent-bn.log`
### 局域网内其他电脑访问中控 ### 局域网内其他电脑访问中控
中控 **默认** `HUB_HOST=0.0.0.0``HUB_TRUST_LAN=开启`,同一局域网内可用 `http://<中控机局域网IP>:5100/` 打开页面(本机仍可用 `http://127.0.0.1:5100/`)。请确保防火墙放行端口,例如:`sudo ufw allow 5100/tcp` 中控 **默认** `HUB_HOST=0.0.0.0``HUB_TRUST_LAN=开启`,同一局域网内可用 `http://<中控机局域网IP>:5100/` 打开页面(本机仍可用 `http://127.0.0.1:5100/`)。请确保防火墙放行端口,例如:`sudo ufw allow 5100/tcp`
若改为 **仅本机** 访问:`HUB_HOST=127.0.0.1``HUB_TRUST_LAN=0`,重启 hub。 若改为 **仅本机** 访问:`HUB_HOST=127.0.0.1``HUB_TRUST_LAN=0`,重启 hub。
也可把上述变量写进 `manual_trading_hub/.env`,再用 `start_hub_screen.sh` 启动。 也可把上述变量写进 `manual_trading_hub/.env`,再用 `start_hub_screen.sh` 启动。
以下为手工 tmux 示例: 以下为手工 tmux 示例:
```bash ```bash
# 新建会话,在里面照常启动 agent 或 hub,然后按键 Ctrl+B 再按 D 脱离 # 新建会话,在里面照常启动 agent 或 hub,然后按键 Ctrl+B 再按 D 脱离
tmux new -s hub tmux new -s hub
cd /opt/crypto_monitor/manual_trading_hub && source .venv/bin/activate && python hub.py cd /opt/crypto_monitor/manual_trading_hub && source .venv/bin/activate && python hub.py
# Ctrl+B, D # Ctrl+B, D
tmux new -s agent-bn tmux new -s agent-bn
cd /opt/crypto_monitor/crypto_monitor_binance && set -a && source .env && set +a cd /opt/crypto_monitor/crypto_monitor_binance && set -a && source .env && set +a
export EXCHANGE=binance PORT=15200 HOST=127.0.0.1 export EXCHANGE=binance PORT=15200 HOST=127.0.0.1
source /opt/crypto_monitor/manual_trading_hub/.venv/bin/activate source /opt/crypto_monitor/manual_trading_hub/.venv/bin/activate
python /opt/crypto_monitor/manual_trading_hub/agent.py python /opt/crypto_monitor/manual_trading_hub/agent.py
# Ctrl+B, D # Ctrl+B, D
``` ```
重新连上:`tmux attach -t hub` 重新连上:`tmux attach -t hub`
--- ---
## 二、nohup(快速、无守护重启) ## 二、nohup(快速、无守护重启)
```bash ```bash
cd /opt/crypto_monitor/manual_trading_hub cd /opt/crypto_monitor/manual_trading_hub
source .venv/bin/activate source .venv/bin/activate
nohup python hub.py > /tmp/manual-hub.log 2>&1 & nohup python hub.py > /tmp/manual-hub.log 2>&1 &
``` ```
子代理同理(每个账户一条):**先 `source` 该策略目录的 `.env`**`agent.py` 不会自己读文件),再 `nohup python …/agent.py` 子代理同理(每个账户一条):**先 `source` 该策略目录的 `.env`**`agent.py` 不会自己读文件),再 `nohup python …/agent.py`
停进程:`ps aux | grep hub.py``grep agent.py`,再 `kill <pid>` 停进程:`ps aux | grep hub.py``grep agent.py`,再 `kill <pid>`
--- ---
## 三、systemd(推荐:开机自启、崩溃自动拉起) ## 三、systemd(推荐:开机自启、崩溃自动拉起)
1. 把下面两个示例里的 **`YOUR_REPO`** 改成 **`/opt/crypto_monitor`**(或你本机实际仓库根目录),`YOUR_USER` 改成 Linux 用户名。 1. 把下面两个示例里的 **`YOUR_REPO`** 改成 **`/opt/crypto_monitor`**(或你本机实际仓库根目录),`YOUR_USER` 改成 Linux 用户名。
2. 复制到 `/etc/systemd/system/`(需 sudo),文件名例如 `manual-hub.service``manual-agent-binance.service` 2. 复制到 `/etc/systemd/system/`(需 sudo),文件名例如 `manual-hub.service``manual-agent-binance.service`
3. 执行: 3. 执行:
```bash ```bash
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable --now manual-hub.service sudo systemctl enable --now manual-hub.service
sudo systemctl enable --now manual-agent-binance.service sudo systemctl enable --now manual-agent-binance.service
# 其余 OKX / Gate 同理再建 3 个 unit 或合并为多条 # 其余 OKX / Gate 同理再建 3 个 unit 或合并为多条
``` ```
查看状态:`sudo systemctl status manual-hub` 查看状态:`sudo systemctl status manual-hub`
日志:`journalctl -u manual-hub -f` 日志:`journalctl -u manual-hub -f`
### 示例:`/etc/systemd/system/manual-hub.service` ### 示例:`/etc/systemd/system/manual-hub.service`
```ini ```ini
[Unit] [Unit]
Description=手工交易中控 hub Description=手工交易中控 hub
After=network-online.target After=network-online.target
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
User=YOUR_USER User=YOUR_USER
WorkingDirectory=YOUR_REPO/manual_trading_hub WorkingDirectory=YOUR_REPO/manual_trading_hub
Environment=HUB_HOST=0.0.0.0 Environment=HUB_HOST=0.0.0.0
Environment=HUB_TRUST_LAN=1 Environment=HUB_TRUST_LAN=1
Environment=HUB_PORT=5100 Environment=HUB_PORT=5100
ExecStart=YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/hub.py ExecStart=YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/hub.py
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
**注意:** `agent.py` **不会**像 Flask 那样自动加载目录里的 `.env`,密钥必须由 **systemd 的 `EnvironmentFile=`** 注入,或用下面 `bash -c` 方式 `source .env` 后再启动。 **注意:** `agent.py` **不会**像 Flask 那样自动加载目录里的 `.env`,密钥必须由 **systemd 的 `EnvironmentFile=`** 注入,或用下面 `bash -c` 方式 `source .env` 后再启动。
### 示例:`/etc/systemd/system/manual-agent-binance.service` ### 示例:`/etc/systemd/system/manual-agent-binance.service`
```ini ```ini
[Unit] [Unit]
Description=手工交易子代理 Binance Description=手工交易子代理 Binance
After=network-online.target After=network-online.target
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
User=YOUR_USER User=YOUR_USER
WorkingDirectory=YOUR_REPO/crypto_monitor_binance WorkingDirectory=YOUR_REPO/crypto_monitor_binance
Environment=PATH=YOUR_REPO/manual_trading_hub/.venv/bin:/usr/bin:/bin Environment=PATH=YOUR_REPO/manual_trading_hub/.venv/bin:/usr/bin:/bin
Environment=EXCHANGE=binance Environment=EXCHANGE=binance
Environment=PORT=15200 Environment=PORT=15200
Environment=HOST=127.0.0.1 Environment=HOST=127.0.0.1
# 把该账户的 .env 注入进程(与 Flask 同一份即可;仅支持 KEY=VALUE 行,勿写 shell 语法) # 把该账户的 .env 注入进程(与 Flask 同一份即可;仅支持 KEY=VALUE 行,勿写 shell 语法)
EnvironmentFile=-YOUR_REPO/crypto_monitor_binance/.env EnvironmentFile=-YOUR_REPO/crypto_monitor_binance/.env
ExecStart=YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/agent.py ExecStart=YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/agent.py
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
`.env`**systemd 无法解析** 的内容(复杂引号、`export` 等),改用: `.env`**systemd 无法解析** 的内容(复杂引号、`export` 等),改用:
```ini ```ini
ExecStart=/bin/bash -lc 'set -a; source YOUR_REPO/crypto_monitor_binance/.env; set +a; exec YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/agent.py' ExecStart=/bin/bash -lc 'set -a; source YOUR_REPO/crypto_monitor_binance/.env; set +a; exec YOUR_REPO/manual_trading_hub/.venv/bin/python YOUR_REPO/manual_trading_hub/agent.py'
``` ```
并删掉或注释掉 `EnvironmentFile=` 行,避免重复注入。 并删掉或注释掉 `EnvironmentFile=` 行,避免重复注入。
**OKX / Gate / Gate-Bot**:各复制一份 `.service`,改 `Description``WorkingDirectory`、以及 `EXCHANGE` / `PORT``15201``15202``15203`)。 **OKX / Gate / Gate-Bot**:各复制一份 `.service`,改 `Description``WorkingDirectory`、以及 `EXCHANGE` / `PORT``15201``15202``15203`)。
--- ---
## 四、常见问题(子代理 / screen / 依赖) ## 四、常见问题(子代理 / screen / 依赖)
1. **`curl http://127.0.0.1:15202/status`(或其它端口)返回 `ok:false`,错误里提到 pysocks / SOCKS** 1. **`curl http://127.0.0.1:15202/status`(或其它端口)返回 `ok:false`,错误里提到 pysocks / SOCKS**
策略目录 `.env` 里配置了 `GATE_SOCKS_PROXY`(或 `BINANCE_SOCKS_PROXY``OKX_SOCKS_PROXY`)时,ccxt 需要 **PySocks**。在 **`/opt/crypto_monitor/manual_trading_hub/.venv`**(或你本机的 `manual_trading_hub/.venv`)中执行: 策略目录 `.env` 里配置了 `GATE_SOCKS_PROXY`(或 `BINANCE_SOCKS_PROXY``OKX_SOCKS_PROXY`)时,ccxt 需要 **PySocks**。在 **`/opt/crypto_monitor/manual_trading_hub/.venv`**(或你本机的 `manual_trading_hub/.venv`)中执行:
`pip install PySocks``pip install -r requirements.txt` `pip install PySocks``pip install -r requirements.txt`
2. **已经 `pip install PySocks`,错误文案完全不变** 2. **已经 `pip install PySocks`,错误文案完全不变**
子代理是**常驻进程**,首次请求已创建 ccxt;在运行中的进程里**仅安装包不会自动生效**。须**重启**该 agent:例如 子代理是**常驻进程**,首次请求已创建 ccxt;在运行中的进程里**仅安装包不会自动生效**。须**重启**该 agent:例如
`screen -S mt-agent-gate -X quit` `screen -S mt-agent-gate -X quit`
再执行 `start_agents_3screen.sh`(或你的等价启动方式)。**不要**依赖「会话还在、以为已经更新」的旧进程。 再执行 `start_agents_3screen.sh`(或你的等价启动方式)。**不要**依赖「会话还在、以为已经更新」的旧进程。
3. **`start_agents_3screen.sh` 打印「已存在会话、跳过」** 3. **`start_agents_3screen.sh` 打印「已存在会话、跳过」**
脚本检测到 `mt-agent-*` 已在跑会跳过创建。需要先停再启: 脚本检测到 `mt-agent-*` 已在跑会跳过创建。需要先停再启:
`./stop_agents_3screen.sh` `./stop_agents_3screen.sh`
或对单个会话:`screen -S mt-agent-gate -X quit`,再跑启动脚本。 或对单个会话:`screen -S mt-agent-gate -X quit`,再跑启动脚本。
4. **确认 15200/15202/15203 上的进程用的是 hub 的 venv** 4. **确认 15200/15202/15203 上的进程用的是 hub 的 venv**
```bash ```bash
ps aux | grep agent.py ps aux | grep agent.py
tr '\0' ' ' < /proc/<PID>/cmdline; echo tr '\0' ' ' < /proc/<PID>/cmdline; echo
``` ```
应看到 `…/manual_trading_hub/.venv/bin/python``…/manual_trading_hub/agent.py`。若用的是系统 `python3`,要么在**同一解释器环境**里装依赖,要么改为用 `start_agents_3screen.sh` 启动(脚本内写死 `VENV_PY`)。 应看到 `…/manual_trading_hub/.venv/bin/python``…/manual_trading_hub/agent.py`。若用的是系统 `python3`,要么在**同一解释器环境**里装依赖,要么改为用 `start_agents_3screen.sh` 启动(脚本内写死 `VENV_PY`)。
5. **中控某账户一直红 / 非 JSON** 5. **中控某账户一直红 / 非 JSON**
对应该端口的 agent 未启动,或 `HUB_AGENTS` 与 agent 的 `PORT` 不一致。本机先测: 对应该端口的 agent 未启动,或 `HUB_AGENTS` 与 agent 的 `PORT` 不一致。本机先测:
`curl -sS http://127.0.0.1:1520x/status | head -c 400` `curl -sS http://127.0.0.1:1520x/status | head -c 400`
再看 `logs/mt-agent-*.log` 再看 `logs/mt-agent-*.log`
6. **子代理端口与 Flask 冲突** 6. **子代理端口与 Flask 冲突**
agent 使用环境变量 **`PORT`**(脚本里 15200、15202、15203);各策略 `.env` 里的 **`APP_PORT`** 给 Flask。二者**不能**相同。 agent 使用环境变量 **`PORT`**(脚本里 15200、15202、15203);各策略 `.env` 里的 **`APP_PORT`** 给 Flask。二者**不能**相同。
7. **systemd 下改依赖或 `.env` 后** 7. **systemd 下改依赖或 `.env` 后**
与 screen 相同:`pip install` 或改 `EnvironmentFile` 后需 **`systemctl restart <unit>`**,否则仍是旧进程。 与 screen 相同:`pip install` 或改 `EnvironmentFile` 后需 **`systemctl restart <unit>`**,否则仍是旧进程。
--- ---
## 五、注意 ## 五、注意
- 子代理与中控仍建议只监听 **127.0.0.1**Flask 的 `APP_HOST=0.0.0.0` 与中控无关。 - 子代理与中控仍建议只监听 **127.0.0.1**Flask 的 `APP_HOST=0.0.0.0` 与中控无关。
- 若策略项目用**自己的** `.venv`,把 `ExecStart` 里的 Python 改成该 venv 的 `python`,但 `agent.py` 路径仍指向 `manual_trading_hub/agent.py` - 若策略项目用**自己的** `.venv`,把 `ExecStart` 里的 Python 改成该 venv 的 `python`,但 `agent.py` 路径仍指向 `manual_trading_hub/agent.py`
同目录下另有 `example-systemd/*.service.example` 可复制后改路径使用。 同目录下另有 `example-systemd/*.service.example` 可复制后改路径使用。
+220 -220
View File
@@ -1,220 +1,220 @@
# 手工交易中控 — 部署文档 # 手工交易中控 — 部署文档
本文档描述在本机(以 Windows 为主)将 **manual_trading_hub** 部署为「多账户监控 + 紧急全平」的推荐步骤、验收方法与注意事项。功能说明与配置项详见同目录 **《README.md》**。 本文档描述在本机(以 Windows 为主)将 **manual_trading_hub** 部署为「多账户监控 + 紧急全平」的推荐步骤、验收方法与注意事项。功能说明与配置项详见同目录 **《README.md》**。
--- ---
## 一、部署目标 ## 一、部署目标
- 本机或局域网可访问 **中控页面**(默认监听 `0.0.0.0:5100`,私网 IP 可打开;本机可用 `127.0.0.1`)。 - 本机或局域网可访问 **中控页面**(默认监听 `0.0.0.0:5100`,私网 IP 可打开;本机可用 `127.0.0.1`)。
- 每个需要纳入监控的交易所账户,有独立的 **子代理** 进程(默认端口 **`15200``15203`**,与各 `crypto_monitor_*` 里 Flask 的 **`APP_PORT`** 错开)。 - 每个需要纳入监控的交易所账户,有独立的 **子代理** 进程(默认端口 **`15200``15203`**,与各 `crypto_monitor_*` 里 Flask 的 **`APP_PORT`** 错开)。
- 策略项目 `crypto_monitor_binance` / `crypto_monitor_okx` / `crypto_monitor_gate` / `crypto_monitor_gate_bot` **无需修改代码**,与中控并行运行。 - 策略项目 `crypto_monitor_binance` / `crypto_monitor_okx` / `crypto_monitor_gate` / `crypto_monitor_gate_bot` **无需修改代码**,与中控并行运行。
--- ---
## 二、前置条件 ## 二、前置条件
1. 已安装 **Python 3.10+**,且 `pip` 可用。 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)` 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` 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` 4. **Linux 路径约定(可选)**:若部署在 Ubuntu 等环境,建议将整个代码树放在 **`/opt/crypto_monitor/`** 下(与 `scripts/后台运行-Ubuntu.md` 示例一致),例如策略目录为 `/opt/crypto_monitor/crypto_monitor_binance`、中控为 `/opt/crypto_monitor/manual_trading_hub`
--- ---
## 三、目录与文件 ## 三、目录与文件
``` ```
manual_trading_hub/ manual_trading_hub/
agent.py # 子代理(单账户) agent.py # 子代理(单账户)
hub.py # 中控 hub.py # 中控
requirements.txt # Python 依赖 requirements.txt # Python 依赖
static/ static/
index.html # 中控前端页面 index.html # 中控前端页面
README.md # 说明文档 README.md # 说明文档
部署文档.md # 本文档 部署文档.md # 本文档
``` ```
--- ---
## 四、安装依赖 ## 四、安装依赖
`manual_trading_hub` 目录执行: `manual_trading_hub` 目录执行:
```powershell ```powershell
cd manual_trading_hub cd manual_trading_hub
python -m venv .venv python -m venv .venv
.\.venv\Scripts\Activate.ps1 .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt pip install -r requirements.txt
``` ```
Linux / macOS Linux / macOS
```bash ```bash
cd manual_trading_hub cd manual_trading_hub
python3 -m venv .venv python3 -m venv .venv
source .venv/bin/activate source .venv/bin/activate
pip install -r requirements.txt pip install -r requirements.txt
``` ```
后续启动 `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` 即可)。 后续启动 `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` 即可)。
--- ---
## 五、部署步骤(推荐顺序) ## 五、部署步骤(推荐顺序)
### 步骤 1:确认策略进程(可选) ### 步骤 1:确认策略进程(可选)
若你平时已运行各目录下的 Flask`app.py`),可保持运行;中控与子代理**不依赖** Flask 是否启动。 若你平时已运行各目录下的 Flask`app.py`),可保持运行;中控与子代理**不依赖** Flask 是否启动。
### 步骤 2:为每个账户启动子代理 ### 步骤 2:为每个账户启动子代理
**每个账户一个终端窗口**,在对应策略项目目录进入后加载环境变量,再启动 agent(路径按你仓库实际位置调整)。 **每个账户一个终端窗口**,在对应策略项目目录进入后加载环境变量,再启动 agent(路径按你仓库实际位置调整)。
示例:**Binance 账户 → 子代理端口 15200**Flask 的 `APP_PORT` 可为 5000、5001 等,由该目录 `.env` 决定,二者不同即可) 示例:**Binance 账户 → 子代理端口 15200**Flask 的 `APP_PORT` 可为 5000、5001 等,由该目录 `.env` 决定,二者不同即可)
```powershell ```powershell
cd D:\你的路径\交易复盘系统\crypto_monitor_binance cd D:\你的路径\交易复盘系统\crypto_monitor_binance
.\.venv\Scripts\Activate.ps1 # 若策略项目使用独立 venv,可在此激活 .\.venv\Scripts\Activate.ps1 # 若策略项目使用独立 venv,可在此激活
# 确保已加载 .env(若你用 dotenv-cli 等工具,在此执行) # 确保已加载 .env(若你用 dotenv-cli 等工具,在此执行)
$env:EXCHANGE="binance" $env:EXCHANGE="binance"
$env:PORT="15200" $env:PORT="15200"
$env:HOST="127.0.0.1" $env:HOST="127.0.0.1"
python ..\manual_trading_hub\agent.py python ..\manual_trading_hub\agent.py
``` ```
**OKX → 子代理 `PORT=15201`**、`EXCHANGE=okx`**Gate → 15202**、**Gate-Bot → 15203**`EXCHANGE=gate` **OKX → 子代理 `PORT=15201`**、`EXCHANGE=okx`**Gate → 15202**、**Gate-Bot → 15203**`EXCHANGE=gate`
**可选安全**:各 agent 与中控制台设置相同随机串: **可选安全**:各 agent 与中控制台设置相同随机串:
```powershell ```powershell
$env:CONTROL_TOKEN="你的长随机串" $env:CONTROL_TOKEN="你的长随机串"
``` ```
子代理与中控均需设置同一 `CONTROL_TOKEN` 子代理与中控均需设置同一 `CONTROL_TOKEN`
### 步骤 3:启动中控 ### 步骤 3:启动中控
新开终端: 新开终端:
```powershell ```powershell
cd D:\你的路径\交易复盘系统\manual_trading_hub cd D:\你的路径\交易复盘系统\manual_trading_hub
.\.venv\Scripts\Activate.ps1 .\.venv\Scripts\Activate.ps1
$env:HUB_HOST="0.0.0.0" $env:HUB_HOST="0.0.0.0"
$env:HUB_PORT="5100" $env:HUB_PORT="5100"
# 若暂不使用 OKX,可在服务端固定关闭 id=1: # 若暂不使用 OKX,可在服务端固定关闭 id=1:
# $env:HUB_DISABLED_IDS="1" # $env:HUB_DISABLED_IDS="1"
python hub.py python hub.py
``` ```
控制台无报错即表示监听成功(日志级别为 `warning`,默认不刷屏)。 控制台无报错即表示监听成功(日志级别为 `warning`,默认不刷屏)。
### 步骤 4:浏览器验收 ### 步骤 4:浏览器验收
1. 打开 **http://127.0.0.1:5100/****http://本机局域网IP:5100/** 1. 打开 **http://127.0.0.1:5100/****http://本机局域网IP:5100/**
2. 应看到与 `HUB_AGENTS` 配置一致的账户卡片;已启动子代理的行应能显示余额或持仓(无持仓则显示「无持仓」)。 2. 应看到与 `HUB_AGENTS` 配置一致的账户卡片;已启动子代理的行应能显示余额或持仓(无持仓则显示「无持仓」)。
3. 点击 **立即刷新**,数据应更新。 3. 点击 **立即刷新**,数据应更新。
4. 取消某一行的 **「参与监控」**,该行应变灰且不再刷新数据;再勾选应恢复。 4. 取消某一行的 **「参与监控」**,该行应变灰且不再刷新数据;再勾选应恢复。
**不建议**在生产环境对实盘轻易点击「全平」做测试;若必须测试,请使用测试网或小资金账户。 **不建议**在生产环境对实盘轻易点击「全平」做测试;若必须测试,请使用测试网或小资金账户。
--- ---
## 六、接口验收(可选) ## 六、接口验收(可选)
在已启动 hub 的本机 PowerShell 在已启动 hub 的本机 PowerShell
```powershell ```powershell
Invoke-RestMethod "http://127.0.0.1:5100/api/agents" Invoke-RestMethod "http://127.0.0.1:5100/api/agents"
Invoke-RestMethod "http://127.0.0.1:5100/api/snapshot" Invoke-RestMethod "http://127.0.0.1:5100/api/snapshot"
``` ```
子代理单测(需 agent 已启动): 子代理单测(需 agent 已启动):
```powershell ```powershell
Invoke-RestMethod "http://127.0.0.1:15200/health" Invoke-RestMethod "http://127.0.0.1:15200/health"
Invoke-RestMethod "http://127.0.0.1:15200/status" Invoke-RestMethod "http://127.0.0.1:15200/status"
``` ```
若启用了 `CONTROL_TOKEN`,需加请求头(PowerShell 示例): 若启用了 `CONTROL_TOKEN`,需加请求头(PowerShell 示例):
```powershell ```powershell
$h = @{ "X-Control-Token" = "你的长随机串" } $h = @{ "X-Control-Token" = "你的长随机串" }
Invoke-RestMethod "http://127.0.0.1:15200/status" -Headers $h Invoke-RestMethod "http://127.0.0.1:15200/status" -Headers $h
``` ```
--- ---
## 七、自定义端口与账户数量 ## 七、自定义端口与账户数量
仅部署 3 个账户时,可只启动 3 个 agent,并设置: 仅部署 3 个账户时,可只启动 3 个 agent,并设置:
```powershell ```powershell
$env:HUB_AGENTS="http://127.0.0.1:15200,http://127.0.0.1:15202,http://127.0.0.1:15203" $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" $env:HUB_AGENT_NAMES="Binance,Gate,Gate-Bot"
``` ```
`HUB_AGENT_NAMES` 与 URL **数量、顺序**一一对应。 `HUB_AGENT_NAMES` 与 URL **数量、顺序**一一对应。
--- ---
## 八、常驻运行(可选) ## 八、常驻运行(可选)
**不必一直开着终端。** Ubuntu 下可用 **tmux 脱离**、**nohup &**、或 **systemd**(推荐:崩溃自启、可开机启动)。 **不必一直开着终端。** Ubuntu 下可用 **tmux 脱离**、**nohup &**、或 **systemd**(推荐:崩溃自启、可开机启动)。
详细命令、**常见问题(screen / PySocks / 重启)**与 **systemd 单元示例**见: 详细命令、**常见问题(screen / PySocks / 重启)**与 **systemd 单元示例**见:
- `manual_trading_hub/scripts/后台运行-Ubuntu.md` - `manual_trading_hub/scripts/后台运行-Ubuntu.md`
- `manual_trading_hub/scripts/example-systemd/*.service.example`(改路径后复制到 `/etc/systemd/system/` - `manual_trading_hub/scripts/example-systemd/*.service.example`(改路径后复制到 `/etc/systemd/system/`
Windows 可将 `hub.py` 与各 `agent.py` 写入「启动」文件夹,或使用 **NSSM** / **任务计划程序** 在登录后启动;注意工作目录与环境变量要在任务里写全。 Windows 可将 `hub.py` 与各 `agent.py` 写入「启动」文件夹,或使用 **NSSM** / **任务计划程序** 在登录后启动;注意工作目录与环境变量要在任务里写全。
--- ---
## 九、升级与回滚 ## 九、升级与回滚
- **升级**:在仓库根目录 `git pull` 后,于 `manual_trading_hub` 重新 `pip install -r requirements.txt`(若依赖有变)。**各策略目录 `.env` 不会被 pull 覆盖**;若 `.env.example` 有新增变量,请对照模板**手动补进**你的 `.env` - **升级**:在仓库根目录 `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)` - **升级前备份(推荐)**:在每个用到的 `crypto_monitor_*` 目录执行 `cp .env .env.backup.$(date +%Y%m%d)`
- **回滚**:恢复上一版本代码与依赖;配置在各策略 `.env` 与浏览器 localStorage,无中控数据库。 - **回滚**:恢复上一版本代码与依赖;配置在各策略 `.env` 与浏览器 localStorage,无中控数据库。
--- ---
## 十、故障排查 ## 十、故障排查
### 10.1 现象速查表 ### 10.1 现象速查表
| 现象 | 可能原因 | 处理 | | 现象 | 可能原因 | 处理 |
|------|----------|------| |------|----------|------|
| 页面打不开 | 中控未启动或端口错 | 检查 `HUB_PORT`、防火墙、是否用 127.0.0.1 访问 | | 页面打不开 | 中控未启动或端口错 | 检查 `HUB_PORT`、防火墙、是否用 127.0.0.1 访问 |
| 某账户一直报错 | 子代理未启动或端口不一致 | 核对 `HUB_AGENTS` 与该 agent 的 `PORT` | | 某账户一直报错 | 子代理未启动或端口不一致 | 核对 `HUB_AGENTS` 与该 agent 的 `PORT` |
| 中控 JSON 报错 / `Expecting value` | 子代理未启动、返回非 JSON、或端口错 | 本机 `curl http://127.0.0.1:1520x/status`;确认 agent 已起且端口与 `HUB_AGENTS` 一致 | | 中控 JSON 报错 / `Expecting value` | 子代理未启动、返回非 JSON、或端口错 | 本机 `curl http://127.0.0.1:1520x/status`;确认 agent 已起且端口与 `HUB_AGENTS` 一致 |
| 401 / 连不上子代理 | `CONTROL_TOKEN` 不一致 | 中控与子代理设为同一令牌,或全部去掉令牌 | | 401 / 连不上子代理 | `CONTROL_TOKEN` 不一致 | 中控与子代理设为同一令牌,或全部去掉令牌 |
| 有密钥仍报缺密钥 | 启动 agent 时未加载策略目录的 `.env` | 在对应目录启动,或手动 export 全部密钥变量 | | 有密钥仍报缺密钥 | 启动 agent 时未加载策略目录的 `.env` | 在对应目录启动,或手动 export 全部密钥变量 |
| `/status``ok:false`,文案含 **pysocks** / **SOCKS** | 使用 SOCKS 代理但未装 **PySocks** | 在 **`manual_trading_hub/.venv`** 执行 `pip install PySocks``pip install -r requirements.txt` | | `/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` §四) | | **已安装 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` 后再启动 | | 跑 `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`(路径按你机器实际根目录调整);否则在**当前使用的解释器**对应环境中装依赖,或改用官方脚本启动 | | 子代理行为异常、依赖已装仍报错 | 实际用的不是 hub 的 venv | `ps aux` 查看命令行,应为 **`/opt/crypto_monitor/manual_trading_hub/.venv/bin/python`** `…/manual_trading_hub/agent.py`(路径按你机器实际根目录调整);否则在**当前使用的解释器**对应环境中装依赖,或改用官方脚本启动 |
| 子代理端口与 Flask 抢端口 | `PORT` 与策略目录 `.env``APP_PORT` 相同 | 子代理用 **1520015203**(或自改),Flask 继续用 `APP_PORT`,二者勿重复 | | 子代理端口与 Flask 抢端口 | `PORT` 与策略目录 `.env``APP_PORT` 相同 | 子代理用 **1520015203**(或自改),Flask 继续用 `APP_PORT`,二者勿重复 |
| 全平失败 | 持仓模式、精度、交易所维护 | 看返回 JSON 中 `errors` 字段;对照交易所 App | | 全平失败 | 持仓模式、精度、交易所维护 | 看返回 JSON 中 `errors` 字段;对照交易所 App |
### 10.2 依赖或代码更新后 ### 10.2 依赖或代码更新后
- **`pip install -r requirements.txt` 或单独 `pip install` 之后**:须**重启**受影响的 **hub**、**各子代理** 进程,变更才会生效。 - **`pip install -r requirements.txt` 或单独 `pip install` 之后**:须**重启**受影响的 **hub**、**各子代理** 进程,变更才会生效。
- **拉取新版本代码后**:同样重启进程;若曾遇 `'function' object has no attribute load_markets'` 等旧版 agent 异常,升级后重启子代理即可。 - **拉取新版本代码后**:同样重启进程;若曾遇 `'function' object has no attribute load_markets'` 等旧版 agent 异常,升级后重启子代理即可。
--- ---
## 十一、安全清单(部署前自检) ## 十一、安全清单(部署前自检)
- [ ] 若机器暴露在公网,已用防火墙限制 `HUB_PORT` 或已改为 `HUB_HOST=127.0.0.1` / `HUB_TRUST_LAN=0` 仅本机。 - [ ] 若机器暴露在公网,已用防火墙限制 `HUB_PORT` 或已改为 `HUB_HOST=127.0.0.1` / `HUB_TRUST_LAN=0` 仅本机。
- [ ] API Key 权限最小化;生产环境建议启用 IP 白名单。 - [ ] API Key 权限最小化;生产环境建议启用 IP 白名单。
- [ ] `CONTROL_TOKEN` 已设为足够长的随机串(若启用)。 - [ ] `CONTROL_TOKEN` 已设为足够长的随机串(若启用)。
- [ ] 已告知实际操作人员:**全局全平**不可撤销。 - [ ] 已告知实际操作人员:**全局全平**不可撤销。
--- ---
## 十二、与说明文档的关系 ## 十二、与说明文档的关系
- **《README.md》**:产品能力、架构、环境变量表、API 简表、常见问题。 - **《README.md》**:产品能力、架构、环境变量表、API 简表、常见问题。
- **《部署文档.md》**:按步骤安装、启动、验收与运维注意(本文)。 - **《部署文档.md》**:按步骤安装、启动、验收与运维注意(本文)。
两处如有端口/变量不一致,以**当前代码**与 **README 中的表格**为准。 两处如有端口/变量不一致,以**当前代码**与 **README 中的表格**为准。
+8
View File
@@ -0,0 +1,8 @@
# crypto_monitor 四个 Flask 子项目共用依赖(Binance / Gate / Gate_bot / OKX
# 安装:在各子目录 venv 内执行 pip install -r ../requirements.txt
flask>=3.0,<4
requests>=2.31,<3
ccxt>=4.2,<5
werkzeug>=3.0,<4
PySocks>=1.7,<2
Pillow>=10.0,<12
+16
View File
@@ -0,0 +1,16 @@
@echo off
chcp 65001 >nul
setlocal
cd /d "%~dp0"
echo crypto_monitor 一键环境部署 ...
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0deploy\setup_env.ps1" %*
set ERR=%ERRORLEVEL%
if not "%ERR%"=="0" (
echo.
echo 部署失败,退出码 %ERR%
pause
exit /b %ERR%
)
echo.
pause
exit /b 0
@@ -1,164 +1,164 @@
# 关键位止盈止损方案 & 移动保本开关 — 更新说明 # 关键位止盈止损方案 & 移动保本开关 — 更新说明
**版本日期:** 2026-05-21 **版本日期:** 2026-05-21
**影响实例:** `crypto_monitor_binance`(币安)、`crypto_monitor_gate`Gate)、`crypto_monitor_okx`OKX **影响实例:** `crypto_monitor_binance`(币安)、`crypto_monitor_gate`Gate)、`crypto_monitor_okx`OKX
**共用库:** 仓库根目录 `key_sl_tp_lib.py`(计算逻辑)、`fib_key_monitor_lib.py`(斐波 SL/TP 不变) **共用库:** 仓库根目录 `key_sl_tp_lib.py`(计算逻辑)、`fib_key_monitor_lib.py`(斐波 SL/TP 不变)
--- ---
## 1. 变更摘要 ## 1. 变更摘要
| 项 | 变更前 | 变更后 | | 项 | 变更前 | 变更后 |
|----|--------|--------| |----|--------|--------|
| 箱体/收敛 SL/TP | 仅一种(标准突破) | 添加时可三选一 | | 箱体/收敛 SL/TP | 仅一种(标准突破) | 添加时可三选一 |
| 移动保本(关键位) | 自动单写死开启 | 添加时可勾选,**默认关闭** | | 移动保本(关键位) | 自动单写死开启 | 添加时可勾选,**默认关闭** |
| 斐波 SL/TP | H/L 限价方案 | **不变**;仅增加移动保本开关 | | 斐波 SL/TP | H/L 限价方案 | **不变**;仅增加移动保本开关 |
| 历史 `key_monitors` | 无新字段 | 缺字段视为 **标准方案 + 保本关** | | 历史 `key_monitors` | 无新字段 | 缺字段视为 **标准方案 + 保本关** |
--- ---
## 2. 数据库(`key_monitors` 新增列) ## 2. 数据库(`key_monitors` 新增列)
启动时自动 `ALTER TABLE`(已有库兼容): 启动时自动 `ALTER TABLE`(已有库兼容):
| 字段 | 类型 | 默认 | 说明 | | 字段 | 类型 | 默认 | 说明 |
|------|------|------|------| |------|------|------|------|
| `sl_tp_mode` | TEXT | `standard` | `standard` / `box_1p5` / `trend_manual` | | `sl_tp_mode` | TEXT | `standard` | `standard` / `box_1p5` / `trend_manual` |
| `manual_take_profit` | REAL | NULL | 仅 `trend_manual` 使用 | | `manual_take_profit` | REAL | NULL | 仅 `trend_manual` 使用 |
| `breakeven_enabled` | INTEGER | `0` | 0=关,1=开 | | `breakeven_enabled` | INTEGER | `0` | 0=关,1=开 |
旧记录无上述列时,读取逻辑按 **`standard` + 保本关** 处理。 旧记录无上述列时,读取逻辑按 **`standard` + 保本关** 处理。
--- ---
## 3. 三种止盈止损方案(仅箱体突破 / 收敛突破) ## 3. 三种止盈止损方案(仅箱体突破 / 收敛突破)
计划价 **E** = 确认 K(倒数第 1 根已闭合 5m)收盘价;**H** = \|上沿 下沿\|。 计划价 **E** = 确认 K(倒数第 1 根已闭合 5m)收盘价;**H** = \|上沿 下沿\|。
自动开仓(币安/Gate)前仍须:**计划 RR(按 E> `KEY_AUTO_MIN_PLANNED_RR`**(默认 1.5)。 自动开仓(币安/Gate)前仍须:**计划 RR(按 E> `KEY_AUTO_MIN_PLANNED_RR`**(默认 1.5)。
### 3.1 标准突破 `standard`(原逻辑) ### 3.1 标准突破 `standard`(原逻辑)
| 方向 | 止损 SL | 止盈 TP | | 方向 | 止损 SL | 止盈 TP |
|------|---------|---------| |------|---------|---------|
| 多 | 突破 K 最低价 × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`/100) | E + 1×H | | 多 | 突破 K 最低价 × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`/100) | E + 1×H |
| 空 | 突破 K 最高价 × (1 + 外侧%) | E 1×H | | 空 | 突破 K 最高价 × (1 + 外侧%) | E 1×H |
默认外侧:**0.5%**`KEY_STOP_OUTSIDE_BREAKOUT_PCT`)。 默认外侧:**0.5%**`KEY_STOP_OUTSIDE_BREAKOUT_PCT`)。
### 3.2 箱体 1R / 止盈 1.5H `box_1p5` ### 3.2 箱体 1R / 止盈 1.5H `box_1p5`
**E 为当前价**,风险距离 = 1×H,止盈距离 = 1.5×H**计划 RR 固定约 1.5:1**。 **E 为当前价**,风险距离 = 1×H,止盈距离 = 1.5×H**计划 RR 固定约 1.5:1**。
| 方向 | 止损 SL | 止盈 TP | | 方向 | 止损 SL | 止盈 TP |
|------|---------|---------| |------|---------|---------|
| 多 | E H | E + 1.5×H | | 多 | E H | E + 1.5×H |
| 空 | E + H | E 1.5×H | | 空 | E + H | E 1.5×H |
### 3.3 趋势单 + 自填止盈 `trend_manual` ### 3.3 趋势单 + 自填止盈 `trend_manual`
| 方向 | 止损 SL | 止盈 TP | | 方向 | 止损 SL | 止盈 TP |
|------|---------|---------| |------|---------|---------|
| 多 | 突破 K 最低价 × (1 − `KEY_TREND_STOP_OUTSIDE_PCT`/100) | 添加时录入的 `manual_take_profit` | | 多 | 突破 K 最低价 × (1 − `KEY_TREND_STOP_OUTSIDE_PCT`/100) | 添加时录入的 `manual_take_profit` |
| 空 | 突破 K 最高价 × (1 + 外侧%) | 同上 | | 空 | 突破 K 最高价 × (1 + 外侧%) | 同上 |
- 环境变量 **`KEY_TREND_STOP_OUTSIDE_PCT`**,默认 **1**(即 1%)。 - 环境变量 **`KEY_TREND_STOP_OUTSIDE_PCT`**,默认 **1**(即 1%)。
- 添加时校验:做多止盈 > 上沿;做空止盈 < 下沿。 - 添加时校验:做多止盈 > 上沿;做空止盈 < 下沿。
--- ---
## 4. 斐波回调 0.618 / 0.786 ## 4. 斐波回调 0.618 / 0.786
- **SL/TP**:仍为 `calc_fib_plan`(多:SL=L、TP=H;空:SL=H、TP=L),**无**三方案下拉。 - **SL/TP**:仍为 `calc_fib_plan`(多:SL=L、TP=H;空:SL=H、TP=L),**无**三方案下拉。
- **移动保本**:添加时可勾选;成交写入 `order_monitors` 时带入该勾选状态(默认关)。 - **移动保本**:添加时可勾选;成交写入 `order_monitors` 时带入该勾选状态(默认关)。
--- ---
## 5. 移动保本 ## 5. 移动保本
| 场景 | 行为 | | 场景 | 行为 |
|------|------| |------|------|
| 关键位添加 | 复选框「移动保本」,**默认不勾选** | | 关键位添加 | 复选框「移动保本」,**默认不勾选** |
| 箱体/收敛自动开仓成功 | `order_monitors.breakeven_enabled` = 添加时的选择 | | 箱体/收敛自动开仓成功 | `order_monitors.breakeven_enabled` = 添加时的选择 |
| 斐波限价成交后 | 同上 | | 斐波限价成交后 | 同上 |
| 人工「实盘下单」 | **不变**:仍为表单勾选,默认仍可按原页面逻辑 | | 人工「实盘下单」 | **不变**:仍为表单勾选,默认仍可按原页面逻辑 |
触发参数仍用全局 `.env``BREAKEVEN_RR_TRIGGER``BREAKEVEN_STEP_R``BREAKEVEN_OFFSET_PCT` 触发参数仍用全局 `.env``BREAKEVEN_RR_TRIGGER``BREAKEVEN_STEP_R``BREAKEVEN_OFFSET_PCT`
--- ---
## 6. 前端(关键位添加表单) ## 6. 前端(关键位添加表单)
在「上沿 / 下沿」后增加: 在「上沿 / 下沿」后增加:
1. **止盈止损方案**(仅类型为箱体突破、收敛突破时显示) 1. **止盈止损方案**(仅类型为箱体突破、收敛突破时显示)
2. **趋势单止盈价**(仅选「趋势单·自填止盈」时显示且必填) 2. **趋势单止盈价**(仅选「趋势单·自填止盈」时显示且必填)
3. **移动保本**(箱体/收敛/斐波显示;默认不勾) 3. **移动保本**(箱体/收敛/斐波显示;默认不勾)
活跃列表卡片展示:**方案**、**保本:开/关**。 活跃列表卡片展示:**方案**、**保本:开/关**。
--- ---
## 7. 环境变量 ## 7. 环境变量
```env ```env
# 标准方案:突破 K 极值外侧 % # 标准方案:突破 K 极值外侧 %
KEY_STOP_OUTSIDE_BREAKOUT_PCT=0.5 KEY_STOP_OUTSIDE_BREAKOUT_PCT=0.5
# 趋势单方案:突破 K 极值外侧 % # 趋势单方案:突破 K 极值外侧 %
KEY_TREND_STOP_OUTSIDE_PCT=1 KEY_TREND_STOP_OUTSIDE_PCT=1
``` ```
已写入各实例 `.env.example`Binance / Gate / OKX)。 已写入各实例 `.env.example`Binance / Gate / OKX)。
--- ---
## 8. 交易所差异 ## 8. 交易所差异
| 实例 | 箱体/收敛触发后 | | 实例 | 箱体/收敛触发后 |
|------|----------------| |------|----------------|
| **Binance / Gate** | 门控通过 → 按方案算 SL/TP → 市价开仓 → 挂交易所 TP/SL → 写入下单监控 | | **Binance / Gate** | 门控通过 → 按方案算 SL/TP → 市价开仓 → 挂交易所 TP/SL → 写入下单监控 |
| **OKX** | 门控通过 → **企业微信提醒**(推送中含录入方案的计划 SL/TP/RR),**不自动市价开仓** | | **OKX** | 门控通过 → **企业微信提醒**(推送中含录入方案的计划 SL/TP/RR),**不自动市价开仓** |
OKX 用户按推送中的计划价自行下单;斐波仍为限价 + 成交后挂 TP/SL(与原先一致)。 OKX 用户按推送中的计划价自行下单;斐波仍为限价 + 成交后挂 TP/SL(与原先一致)。
--- ---
## 9. 涉及文件清单 ## 9. 涉及文件清单
| 路径 | 说明 | | 路径 | 说明 |
|------|------| |------|------|
| `key_sl_tp_lib.py` | **新建**,三方案计算与文案 | | `key_sl_tp_lib.py` | **新建**,三方案计算与文案 |
| `crypto_monitor_binance/app.py` | 门控触发、开仓、斐波、add_key | | `crypto_monitor_binance/app.py` | 门控触发、开仓、斐波、add_key |
| `crypto_monitor_binance/templates/index.html` | 表单 + JS + 列表展示 | | `crypto_monitor_binance/templates/index.html` | 表单 + JS + 列表展示 |
| `crypto_monitor_binance/.env.example` | `KEY_TREND_STOP_OUTSIDE_PCT` | | `crypto_monitor_binance/.env.example` | `KEY_TREND_STOP_OUTSIDE_PCT` |
| `crypto_monitor_gate/app.py` | 同 Binance | | `crypto_monitor_gate/app.py` | 同 Binance |
| `crypto_monitor_gate/templates/index.html` | 同 Binance | | `crypto_monitor_gate/templates/index.html` | 同 Binance |
| `crypto_monitor_gate/.env.example` | 同上 | | `crypto_monitor_gate/.env.example` | 同上 |
| `crypto_monitor_okx/app.py` | add_key、提醒文案、斐波保本 | | `crypto_monitor_okx/app.py` | add_key、提醒文案、斐波保本 |
| `crypto_monitor_okx/templates/index.html` | 表单 + JS | | `crypto_monitor_okx/templates/index.html` | 表单 + JS |
| `crypto_monitor_okx/.env.example` | 注释项 | | `crypto_monitor_okx/.env.example` | 注释项 |
--- ---
## 10. 部署与验证建议 ## 10. 部署与验证建议
1. `git pull` 后重启三个实例的 Flask 进程(会自动迁移 `key_monitors` 列)。 1. `git pull` 后重启三个实例的 Flask 进程(会自动迁移 `key_monitors` 列)。
2. 在 `.env` 中按需设置 `KEY_TREND_STOP_OUTSIDE_PCT`(不配则用默认 1)。 2. 在 `.env` 中按需设置 `KEY_TREND_STOP_OUTSIDE_PCT`(不配则用默认 1)。
3. **验证 Binance/Gate** 3. **验证 Binance/Gate**
- 添加箱体突破,选「箱体1R·止盈1.5H」,不勾保本 → 触发后微信应显示方案名、保本关、SL/TP 符合 E±H / E±1.5H。 - 添加箱体突破,选「箱体1R·止盈1.5H」,不勾保本 → 触发后微信应显示方案名、保本关、SL/TP 符合 E±H / E±1.5H。
- 添加趋势单,填止盈,勾保本 → 成交后持仓卡片「移动保本:开」。 - 添加趋势单,填止盈,勾保本 → 成交后持仓卡片「移动保本:开」。
4. **验证 OKX**:门控通过时微信应含「录入方案」与计划 SL/TP,并注明提醒模式不自动开仓。 4. **验证 OKX**:门控通过时微信应含「录入方案」与计划 SL/TP,并注明提醒模式不自动开仓。
5. 旧关键位条目:列表应显示「方案:标准突破」「保本:关」(除非库中已有新字段值)。 5. 旧关键位条目:列表应显示「方案:标准突破」「保本:关」(除非库中已有新字段值)。
--- ---
## 11. 代码入口(便于二次开发) ## 11. 代码入口(便于二次开发)
| 功能 | 符号 | | 功能 | 符号 |
|------|------| |------|------|
| 计划 SL/TP | `plan_key_sl_tp()` in `key_sl_tp_lib.py` | | 计划 SL/TP | `plan_key_sl_tp()` in `key_sl_tp_lib.py` |
| 按监控行计算 | `_key_plan_sl_tp_for_row()` in各 `app.py` | | 按监控行计算 | `_key_plan_sl_tp_for_row()` in各 `app.py` |
| 添加关键位 | `add_key()` | | 添加关键位 | `add_key()` |
| 箱体/收敛轮询 | `check_key_monitors()`OKX 仅提醒) | | 箱体/收敛轮询 | `check_key_monitors()`OKX 仅提醒) |
| 斐波添加 | `_add_fib_key_monitor(..., breakeven_enabled=)` | | 斐波添加 | `_add_fib_key_monitor(..., breakeven_enabled=)` |
| 自动开仓写监控 | `_market_open_for_key_monitor(..., breakeven_enabled=)` | | 自动开仓写监控 | `_market_open_for_key_monitor(..., breakeven_enabled=)` |