# `crypto_monitor_okx` 部署文档(Ubuntu)

Ubuntu 环境(Python / Node / PM2)见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**。授权见 **[docs/license.md](../docs/license.md)**。

---

# 本地部署 + SSH SOCKS 转发 + PM2 启动指南(Ubuntu)

本文面向:**本地 Ubuntu 机器运行项目**,但 **本机直连 OKX 会被 TLS/SNI reset** 的场景.解决思路是:

- 本机启动 `ssh -D` 动态转发,把 **SOCKS5 出口**放到你可正常访问 OKX 的 VPS 上
- 项目通过环境变量 `OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080` 让 `ccxt` 走 SOCKS
- **SSH 隧道**用 `ssh -D` 常驻(可用 tmux / autossh);**Flask 应用** 仅用 **PM2** 托管(见 [docs/ubuntu-server.md](../docs/ubuntu-server.md))

> 安全提醒:不要把 `.env`,私钥 `.pem`,OKX API Key 提交到 Git;文档里只用占位符.

---

## 0. 你需要准备的东西

- 一台 **Ubuntu** 本地机器(下文称“本机”)
- 一台可 SSH 登录,且 **能正常访问 OKX** 的 VPS(示例公网 IP:`47.76.87.111`,用户:`root`)
- VPS 登录方式:**SSH 私钥**(推荐)或密码(不推荐用于无人值守)
- 本机已安装:
  - `python3`,`python3-venv`,`pip`(或 `python3-pip`)
  - `git`(可选)
  - `curl`,`ssh`
  - `node` + `npm`(用于安装 `pm2`)

---

## 1. 从云服务器把项目同步到本地(推荐:打包下载)

在云服务器项目目录(包含 `app.py` 的目录)执行:

```bash
cd /opt/crypto_monitor_user/crypto_monitor_okx

# 可选:清理 Python 缓存,减少小文件传输
find . -type d -name __pycache__ -prune -exec rm -rf {} +
find . -type f -name "*.pyc" -delete

tar -czf crypto_monitor.tgz .
```

下载 `crypto_monitor.tgz` 到本机后解压:

```bash
mkdir -p /opt/crypto_monitor_user/crypto_monitor_okx
cd /opt/crypto_monitor_user
tar -xzf crypto_monitor.tgz -C crypto_monitor_okx
cd crypto_monitor_okx
cp -n .env.example .env    # 若尚无 .env
```

---

## 2. 配置 SSH 私钥与 `~/.ssh/config`(推荐)

把私钥放到本机(示例:`~/.ssh/vps1.pem`),并设置权限:

```bash
mkdir -p ~/.ssh
chmod 700 ~/.ssh
mv ~/Downloads/vps1.pem ~/.ssh/vps1.pem
chmod 600 ~/.ssh/vps1.pem
```

编辑 `~/.ssh/config`(没有就创建),添加:

```sshconfig
Host okx-vps
  HostName 47.76.87.111
  User root
  IdentityFile ~/.ssh/vps1.pem
  IdentitiesOnly yes
  ServerAliveInterval 30
  ServerAliveCountMax 3
  ExitOnForwardFailure yes
  BatchMode yes
```

测试:

```bash
ssh okx-vps true
```

> 如果你还没完全切到密钥登录(还会交互要密码),先把 `BatchMode yes` 注释掉,等密钥登录稳定后再打开.

---

## 3. 先手工验证:SSH SOCKS + OKX API

### 3.1 开一个本地 SOCKS(1080)

```bash
ssh -N -D 127.0.0.1:1080 okx-vps
```

保持该进程运行(另开终端继续下面步骤).

### 3.2 验证 OKX 走 SOCKS 可用

```bash
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.

---

## 4. Python 虚拟环境(venv)

在本机项目目录:

```bash
cd /opt/crypto_monitor_user/crypto_monitor_okx

python3 -m venv .venv
source .venv/bin/activate

python -m pip install -U pip
pip install flask requests ccxt werkzeug PySocks Pillow
```

> 说明:本仓库当前没有 `requirements.txt`.如果你希望“完全复刻云服务器依赖”,可以在云服务器项目环境里执行 `pip freeze > requirements.txt` 带回本机再 `pip install -r requirements.txt`(记得删掉明显无关/体积巨大的包).

建议减少 `.pyc` 垃圾文件(可选):

```bash
export PYTHONDONTWRITEBYTECODE=1
```

---

## 5. 配置环境变量(`.env.example` → `.env`)

| 文件 | 是否进 Git | 说明 |
|------|------------|------|
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |

### 5.1 首次配置

```bash
cd /opt/crypto_monitor_user/crypto_monitor_okx

cp -n .env.example .env    # 已存在 .env 时不覆盖
nano .env
```

### 5.2 备份与 `git pull`

- **`.env` 不在 Git 中**:`git pull` **不会**覆盖本地 `.env`.
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`.
- **升级前备份**:`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`.
- **换机**:`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填.

**AI 复盘**:三所共用根目录 **`ai_client.py`**.默认 **`AI_PROVIDER=openai`**,网关 `https://op.bz121.com/v1`,模型 `gemma4:e4b`;或改 **`ollama`** 走本机 Ollama.PM2 须 **`PYTHONPATH=..`**.AI 配置建议在中控 **系统设置 → AI 配置** 统一修改并同步三所。

### 5.3 必填项检查(OKX + 代理)

至少确认/填写这些关键项(示例):

```env
APP_HOST=127.0.0.1
APP_PORT=5000

# OKX(如需实盘)
LIVE_TRADING_ENABLED=false
OKX_API_KEY=...
OKX_API_SECRET=...
OKX_API_PASSPHRASE=...

# OKX 出口:走本机 SSH 动态转发 SOCKS
OKX_SOCKS_PROXY=socks5h://127.0.0.1:1080

# 开仓多周期K线图(可选)
# ORDER_CHART_ENABLED=true
# ORDER_CHART_TFS=4h,1h,15m,5m
# ORDER_CHART_LIMIT=100
# ORDER_CHART_DIR=static/images/order_charts
# DAILY_OPEN_ALERT_THRESHOLD=5
# DAILY_OPEN_HARD_LIMIT=0
# 说明见仓库 docs/daily-open-limit.md

# AI 复盘(默认 OpenAI 兼容网关;与 Ollama 二选一)
AI_PROVIDER=openai
AI_TIMEOUT_SECONDS=120
OPENAI_API_BASE=https://op.bz121.com/v1
OPENAI_API_KEY=你的密钥
OPENAI_MODEL=gemma4:e4b
# 本机 Ollama(仅 AI_PROVIDER=ollama)
OLLAMA_API=http://127.0.0.1:11434/api/generate
AI_MODEL=你的模型名
```

> `OPENAI_API_KEY` 在 [op.bz121.com](https://op.bz121.com/) 的 `gateway.json` 获取。也可在中控系统设置中配置 AI。

> `OKX_SOCKS_PROXY` 使用 `socks5h`:让 SOCKS 侧做域名解析(更贴近你 `curl --proxy socks5h://...` 的成功路径).

---

## 6. 本机手工启动(验证 Flask)

确保:

1. SOCKS 隧道已运行(127.0.0.1:1080)
2. 虚拟环境已 `activate`
3. `.env` 已配置

启动:

```bash
cd /opt/crypto_monitor_user/crypto_monitor_okx
source .venv/bin/activate
python app.py
```

浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 配的端口).

---

## 7. 安装 PM2(Node)

```bash
sudo npm i -g pm2
pm2 -v
```

---

## 8. 用 PM2 启动 SSH SOCKS 隧道(推荐:密钥免交互)

### 8.1 启动隧道进程

```bash
pm2 start "ssh" --name okx-socks-tunnel -- \
  -N -D 127.0.0.1:1080 okx-vps \
  -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
  -o ExitOnForwardFailure=yes -o BatchMode=yes
```

查看日志:

```bash
pm2 logs okx-socks-tunnel --lines 200
```

### 8.2 仍然验证 OKX

```bash
curl -4 -Iv --max-time 15 --proxy socks5h://127.0.0.1:1080 https://www.okx.com/api/v5/public/time
```

### 8.3 开机自启(可选)

```bash
pm2 save
pm2 startup
```

---

## 9. 用 PM2 启动 Flask(`app.py`)

`pm2` 管理 Python 的常用方式是直接启动解释器:

```bash
cd /opt/crypto_monitor_user/crypto_monitor_okx

pm2 start /opt/crypto_monitor_user/crypto_monitor_okx/.venv/bin/python --name crypto-monitor -- \
  /opt/crypto_monitor_user/crypto_monitor_okx/app.py
```

> 若项目目录与上文不一致,请替换为实际绝对路径;或用 `readlink -f app.py` 得到绝对路径.

查看日志:

```bash
pm2 logs crypto-monitor --lines 200
```

保存进程列表:

```bash
pm2 save
```

---

## 10. 常见问题排查(高频)

### 10.1 OKX 仍然失败:先看隧道是否在

```bash
ss -lntp | grep 1080 || true
pm2 status
```

### 10.2 `pm2` 里的 `ssh` 立刻退出

常见原因:

- 私钥权限不对(`chmod 600`)
- `~/.ssh/config` 写错 `HostName/User/IdentityFile`
- 开了 `BatchMode yes` 但仍需要密码(会失败)

### 10.3 `ccxt` SOCKS 报错 / 代理不生效

本机 Python 依赖通常需要:

```bash
source .venv/bin/activate
pip install PySocks
```

### 10.4 `.pyc` 很多导致同步慢

`.pyc` 是缓存,删除不影响功能:

```bash
find . -type d -name __pycache__ -prune -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
```

---

## 11. 推荐的启动顺序(固定习惯)

1. `pm2` 启动 `okx-socks-tunnel`
2. `curl --proxy socks5h://127.0.0.1:1080 ...` 验证 OKX
3. `pm2` 启动 `crypto-monitor`

---

## 12. 免责声明

交易所有合规与地区政策要求.请确保你的使用方式符合当地法律法规与交易所条款.本文仅描述网络与工程部署技术路径.




写好了,脚本路径:

- `scripts/fix_breakeven_labels.py`

你在 Ubuntu 上这样用:

1) 先预览(不写库):
```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
```

2) 确认后执行:
```bash
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
```

默认修复条件就是你要的:
- `monitor_type='下单监控'`
- `result='止损'`
- `pnl_amount > 0`
- 改成 `result='保本止盈'`

如果你想,我还可以再给你一条“先自动备份 DB 再执行”的一键命令.