Update docs for CTP worker split and roll breakout off-session.

Refresh DEPLOY, TRADING, STRATEGY, CTP_LIVE, FEATURES, INDEX, and README to document qihuo-ctp architecture, dual PM2 restarts, and休盘突破加仓.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-01 12:56:27 +08:00
parent 9cd81a3ea7
commit 95156ca595
7 changed files with 130 additions and 43 deletions
+5 -2
View File
@@ -46,9 +46,12 @@ cd /opt/qihuo && bash deploy.sh
cd /opt/qihuo
git fetch origin && git reset --hard origin/main
source venv/bin/activate && pip install -r requirements.txt
pm2 restart qihuo
python scripts/run_schema_migrate.py
pm2 restart ecosystem.config.cjs --update-env
```
生产环境须同时维护 **`qihuo`**Web)与 **`qihuo-ctp`**CTP Worker)两个 PM2 进程。
详见 [部署文档](docs/DEPLOY.md)。
**本地开发**
@@ -69,7 +72,7 @@ python app.py
## 环境要求
- Python 3.10+vnpy_ctp
- PM2(生产部署)
- PM2(生产部署**qihuo** + **qihuo-ctp** 两个进程
- 网络:新浪行情、Git 仓库、SimNow/CTP 前置(见部署文档)
## 仓库
+17 -2
View File
@@ -2,7 +2,22 @@
本文说明如何接入 **期货公司实盘 CTP**,并对比 **SimNow 模拟盘****实盘** 的开平仓逻辑是否一致。
相关代码:`vnpy_bridge.py``ctp_settings.py``trading_context.py``install_trading.py`
相关代码:`vnpy_bridge.py``ctp_worker.py``ctp_ipc_client.py``ctp_settings.py``trading_context.py``install_trading.py`
---
## 进程架构(Web / CTP Worker
自 2026-03 起,CTP 与 vn.py **不在 Flask 进程内**运行:
| 组件 | PM2 名 | 说明 |
|------|--------|------|
| Web | `qihuo` | 页面与 API`QIHUO_CTP_ROLE=client`,经 `127.0.0.1:6601` IPC 访问 Worker |
| CTP Worker | `qihuo-ctp` | 唯一加载 vnpy_ctp;连接、报单、持仓回调、止盈止损、滚仓 pending 监控 |
SimNow 与期货公司实盘的 **报单代码路径不变**,仍走 `execute_order()``vnpy_bridge.send_order()`Web 侧为 IPC 代理,Worker 侧为原生调用。
部署与重启见 [DEPLOY.md](./DEPLOY.md)。
---
@@ -76,7 +91,7 @@ CTP_LIVE_ENV=实盘
3. **下单监控****连接 CTP**
4. 顶栏显示 **CTP 已连接**、**期货公司实盘**,权益为柜台资金
修改模式或前置后建议 **重连 CTP**`pm2 restart qihuo`
修改模式或前置后建议 **重连 CTP**`pm2 restart ecosystem.config.cjs --update-env`(同时重启 Web 与 Worker
---
+59 -22
View File
@@ -10,11 +10,21 @@
|------|--------|
| 部署目录 | `/opt/qihuo` |
| 运行用户 | `root`(与 `deploy.sh` / PM2 配置一致) |
| 服务端口 | `6600` |
| 进程管理 | PM2,应用名 `qihuo` |
| Web 端口 | `6600`(对外) |
| CTP Worker 端口 | `6601`(仅 `127.0.0.1`,Web 进程 IPC 调用,勿对外开放) |
| 进程管理 | PM2`qihuo`Flask Web+ `qihuo-ctp`CTP / vn.py 独立进程) |
| 数据库 | **生产推荐 PostgreSQL**(见 [POSTGRES.md](./POSTGRES.md));未配置 `DATABASE_URL` 时使用 SQLite `futures.db` |
| 仓库 | https://git.bz121.com/dekun/qihuo.git |
### 进程架构(2026-03 起)
| PM2 应用 | 角色 | 说明 |
|----------|------|------|
| `qihuo` | Web`QIHUO_CTP_ROLE=client`) | Flask、页面、API、数据库;通过 HTTP 调用本机 Worker |
| `qihuo-ctp` | Worker`QIHUO_CTP_ROLE=worker` | **唯一** 加载 vn.py / vnpy_ctp;CTP 连接、报单、持仓回调、止盈止损 tick、滚仓监控 |
Web 进程崩溃或重启 **不会** 直接带走 CTP 原生连接;Worker 重启后 Web 会自动通过 IPC 恢复读写。两个进程的 Token 须一致(见 `ecosystem.config.cjs``QIHUO_CTP_WORKER_TOKEN`)。
---
## 环境要求
@@ -54,7 +64,7 @@ bash deploy.sh
6. 首次生成 `.env`,并补全 `SIMNOW_ENV=实盘``CTP_AUTO_RECONNECT=true` 等缺项
7. **自动探测 SimNow 前置**`nc` 测端口),写入可用的 `SIMNOW_TD/MD_ADDRESS`(优先 `182.254.243.31`,其次 `180.168.146.187`
8. 若已配置 SimNow 账号,运行 `scripts/test_simnow.py` 验证连接
9. `pm2 restart --update-env` 或首次 `pm2 start`,并 `pm2 save`
9. `pm2 restart ecosystem.config.cjs --update-env` 或首次 `pm2 start ecosystem.config.cjs`,并 `pm2 save`(同时启动 **`qihuo`** 与 **`qihuo-ctp`**
部署完成后访问:`http://<服务器IP>:6600`
@@ -140,6 +150,9 @@ nano .env
| `SIMNOW_MD_ADDRESS` | SimNow 行情前置 |
| `CTP_LIVE_*` | 期货公司实盘 CTP(后期接入,见 `.env.example` |
| `TRADING_MODE` | `simulation`SimNow/ `live`(实盘) |
| `QIHUO_CTP_WORKER_TOKEN` | Web ↔ Worker IPC 鉴权(默认见 `ecosystem.config.cjs`,生产建议改随机串并保持两进程一致) |
| `QIHUO_CTP_WORKER_URL` | Web 侧 Worker 地址,默认 `http://127.0.0.1:6601` |
| `DATABASE_URL` | PostgreSQL 连接串(可选,见 [POSTGRES.md](./POSTGRES.md) |
示例:
@@ -171,11 +184,18 @@ SimNow 前置地址会随官网更新,部署前请到 [SimNow 官网](https://
```bash
cd /opt/qihuo
pm2 start ecosystem.config.cjs
pm2 start ecosystem.config.cjs # 启动 qihuo + qihuo-ctp
pm2 save
pm2 startup # 按提示执行命令,实现开机自启
```
确认两个进程均为 `online`
```bash
pm2 status
# 应看到 qihuo 与 qihuo-ctp
```
### 7. 创建日志目录(若不存在)
```bash
@@ -194,9 +214,13 @@ git fetch origin
git reset --hard origin/main
source venv/bin/activate
pip install -r requirements.txt
pm2 restart qihuo
python scripts/run_schema_migrate.py
pm2 restart ecosystem.config.cjs --update-env
pm2 save
```
> 须 **同时重启** `qihuo` 与 `qihuo-ctp`。仅 `pm2 restart qihuo` 会导致 Web 与 Worker 代码/协议不一致。
若服务器曾用 SCP 覆盖文件导致 `git pull` 冲突,用 `git reset --hard origin/main` 与远端对齐。
`vnpy_ctp` 安装失败(常见于缺少编译环境):
@@ -205,7 +229,7 @@ pm2 restart qihuo
apt install -y build-essential python3-dev pkg-config
source venv/bin/activate
pip install --no-cache-dir vnpy vnpy_ctp
pm2 restart qihuo
pm2 restart ecosystem.config.cjs --update-env
```
应用启动时会自动执行 SQLite 表结构迁移(`ALTER TABLE` 容错),一般无需手工改库。
@@ -213,8 +237,11 @@ pm2 restart qihuo
### 首次启用 CTP 下单
1. 浏览器登录 → **系统设置** 确认 **模拟盘 · SimNow**
2. 打开 **下单监控** 页 → 点击 **连接 CTP**
3. 连接成功后:权益来自柜台、显示 CTP 持仓、可报单与可开仓品种筛选
2. 确认 `pm2 status`**`qihuo-ctp` 为 online**
3. 打开 **下单监控** 页 → 点击 **连接 CTP**(或由后台自动重连)
4. 连接成功后:权益来自柜台、显示 CTP 持仓、可报单与可开仓品种筛选
CTP 连接与重连在 **`qihuo-ctp` Worker** 内执行;页面仅轮询状态,**切换页面不会重复发起连接**。
详见 [TRADING.md](./TRADING.md)。
@@ -223,19 +250,22 @@ pm2 restart qihuo
## PM2 常用命令
```bash
pm2 status # 查看状态
pm2 logs qihuo # 查看日志
pm2 status # 查看 qihuo / qihuo-ctp 状态
pm2 logs qihuo # Web 日志
pm2 logs qihuo-ctp # CTP Worker 日志
pm2 logs qihuo --lines 100
pm2 restart qihuo # 重启
pm2 stop qihuo # 停止
pm2 delete qihuo # 删除进程
pm2 save # 保存进程列表
pm2 restart ecosystem.config.cjs --update-env # 同时重启两个进程(推荐)
pm2 restart qihuo # 仅重启 Web
pm2 restart qihuo-ctp # 仅重启 CTP WorkerWeb 应仍可访问)
pm2 stop qihuo # 停止 Web
pm2 delete qihuo # 删除 Web 进程
pm2 save # 保存进程列表
```
日志文件:
- `/opt/qihuo/logs/pm2-out.log`
- `/opt/qihuo/logs/pm2-error.log`
- `/opt/qihuo/logs/pm2-out.log``pm2-error.log` — Web`qihuo`
- `/opt/qihuo/logs/pm2-ctp-out.log``pm2-ctp-error.log` — CTP Worker`qihuo-ctp`
---
@@ -260,7 +290,7 @@ python app.py
| 场景 | 操作 |
|------|------|
| 首次部署 | `.env` 中设置 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 后启动 |
| 已部署后改 `.env` 密码 | 设 `ADMIN_SYNC_FROM_ENV=true``pm2 restart qihuo` |
| 已部署后改 `.env` 密码 | 设 `ADMIN_SYNC_FROM_ENV=true``pm2 restart ecosystem.config.cjs --update-env` |
| 网页改密码 | 登录 → 系统设置 |
| 忘记密码 | `cd /opt/qihuo && source venv/bin/activate && python reset_admin.py` |
@@ -340,6 +370,9 @@ ufw allow 6600/tcp
| 现象 | 可能原因 | 处理 |
|------|----------|------|
| 无法访问 6600 | 服务未启动 / 防火墙 | `pm2 status``pm2 logs qihuo` |
| **`qihuo-ctp` 不在线 / 反复重启** | vnpy 崩溃、SimNow 前置不可达、locale 缺失 | `pm2 logs qihuo-ctp --lines 200`;核对 SimNow 前置与 `zh_CN.GB18030` |
| **页面显示 CTP 未连接但 Worker 正常** | Web 与 Worker Token 不一致 | 检查 `ecosystem.config.cjs` 两进程 `QIHUO_CTP_WORKER_TOKEN` 相同后重启 |
| **API 报 `CTP worker unavailable`** | Worker 未启动或 6601 不可达 | `curl -s http://127.0.0.1:6601/health``pm2 restart qihuo-ctp` |
| 登录失败 | 密码未同步 | 网页改密或 `reset_admin.py` |
| 现价一直 `--` | 新浪网络不可达 | 检查服务器能否访问 `hq.sinajs.cn` |
| 关键位 500 | 缺 `sina_code` 列 | `git pull` 重启;或手工 `ALTER TABLE` |
@@ -387,7 +420,7 @@ source venv/bin/activate
apt install -y build-essential python3-dev pkg-config # 首次需要
pip install -r requirements.txt
python -c "from vnpy_ctp import CtpGateway; print('OK')"
pm2 restart qihuo
pm2 restart ecosystem.config.cjs --update-env
```
**2. 配置 SimNow`.env`**
@@ -404,7 +437,7 @@ pm2 restart qihuo
|-----------|------|
| `pip install vnpy_ctp` 编译失败 / `Python dependency not found` | 安装 `build-essential python3-dev pkg-config` 后重试 |
| CTP 连接超时 | 检查前置 IP、端口、SimNow 是否维护、是否在允许连接时段 |
| 连接后立即崩溃 `locale::facet::_S_create_c_locale` | CTP 需 **zh_CN.GB18030**`sed -i '/^# zh_CN.GB18030/s/^# //' /etc/locale.gen && locale-gen zh_CN.GB18030`,再 `pm2 restart qihuo --update-env` |
| 连接后立即崩溃 `locale::facet::_S_create_c_locale` | CTP 需 **zh_CN.GB18030**`sed -i '/^# zh_CN.GB18030/s/^# //' /etc/locale.gen && locale-gen zh_CN.GB18030`,再 `pm2 restart ecosystem.config.cjs --update-env` |
| 服务器 `180.168.146.187` 超时 | 换 SimNow 备用前置 `182.254.243.31:30001/30011`(见 [SIMNOW.md](./SIMNOW.md) |
| 已连接但下单拒单 | 检查合约代码、价格精度、是否有足够保证金 |
@@ -424,7 +457,9 @@ pm2 restart qihuo
```
/opt/qihuo/
├── app.py
├── vnpy_bridge.py # CTP 执行层
├── vnpy_bridge.py # CTP 桥接(Web=IPC 代理,Worker=原生 vn.py
├── ctp_ipc_client.py # Web → Worker HTTP 客户端
├── ctp_worker.py # 独立 CTP Worker 入口(PM2: qihuo-ctp
├── recommend_store.py # 可开仓品种缓存
├── recommend_stream.py # 可开仓品种 SSE 推送
├── venv/
@@ -432,10 +467,12 @@ pm2 restart qihuo
├── .env
├── logs/
│ ├── pm2-out.log
── pm2-error.log
── pm2-error.log
│ ├── pm2-ctp-out.log
│ └── pm2-ctp-error.log
├── uploads/
├── data/fee_rates.json
├── ecosystem.config.cjs
├── ecosystem.config.cjs # PM2qihuo + qihuo-ctp
├── deploy.sh
├── requirements.txt # 含 vnpy、vnpy_ctp
└── docs/
+8 -4
View File
@@ -79,7 +79,8 @@
**路径**`/strategy``/strategy/records` · 详见 [STRATEGY.md](./STRATEGY.md)
- 趋势回调自动补仓、顺势加仓等(需 CTP 已连接且有 active 持仓监控
- 趋势回调(首仓/补仓/止盈须 CTP + 交易时段
- 顺势加仓:**市价**须交易时段;**突破**可休盘提交监控,开盘触价成交
- 策略记录单独归档
---
@@ -248,9 +249,10 @@
| 计划/关键位轮询 | 约 3 秒,触发判断与微信推送 |
| 可开仓品种刷新 | 每日 + 按需 |
| 持仓 SSE | 前端订阅 `/api/trading/stream` |
| CTP 开盘前连接 | 默认开盘前 30 分钟 |
| CTP 开盘前连接 | 默认开盘前 30 分钟`qihuo-ctp` Worker |
| 挂单超时撤单 | 可配置分钟数 |
| 止盈止损守护 | CTP 持仓监控线程 |
| 止盈止损守护 | `qihuo-ctp` Worker 内 tick 监控 |
| 滚仓 pending 监控 | `qihuo-ctp` Worker,交易时段扫描突破触价 |
| 数据库自动备份 | 每日定时(默认 03:00)写入 `/root/qihuo_backup` |
---
@@ -261,7 +263,9 @@
qihuo/
├── app.py # 主路由、计划/关键位/记录/统计
├── install_trading.py # 下单、可开仓品种、策略路由
├── vnpy_bridge.py # CTP 连接、报单、持仓
├── vnpy_bridge.py # CTP 桥接(Web=IPCWorker=vn.py
├── ctp_worker.py # 独立 CTP WorkerPM2: qihuo-ctp
├── ctp_ipc_client.py # Web → Worker HTTP 客户端
├── ctp_trade_sync.py # 柜台成交同步到 trade_logs
├── product_recommend.py # 可开仓品种计算
├── stats_engine.py # 统计分析
+2
View File
@@ -60,3 +60,5 @@
| 看板风控各指标什么意思 | [风控说明.md](./风控说明.md) |
| 移动保本怎么抬止损 | [ORDER_MONITOR.md#移动保本](./ORDER_MONITOR.md) |
| 实盘 CTP 怎么接、和 SimNow 开平是否一样 | [CTP_LIVE.md](./CTP_LIVE.md) |
| CTP 双进程、Worker 日志、6601 端口 | [DEPLOY.md](./DEPLOY.md) |
| 休盘能否提交突破滚仓 | [STRATEGY.md](./STRATEGY.md) |
+27 -13
View File
@@ -2,7 +2,7 @@
**页面路径**`/strategy``/strategy/records`
**相关文件**`install_trading.py`(趋势回调、顺势加仓/滚仓)
**相关文件**`install_trading.py``strategy/strategy_roll_lib.py``strategy/strategy_roll_monitor_lib.py`
---
@@ -13,7 +13,8 @@
| 趋势回调 | 首仓 + 网格补仓 + 统一止盈 |
| 顺势加仓(滚仓) | 对已有 active 持仓加仓,单独保证金上限 |
均需 **CTP 已连接** 且有对应持仓监控
趋势首仓与 **市价滚仓****交易时段内** **CTP 已连接**
**突破加仓** 可在 **休盘**(小节休息、午间、日盘收盘后)提交监控,开盘触价后由 Worker 自动市价加仓。
---
@@ -61,9 +62,18 @@
## 顺势加仓(滚仓)— 下单逻辑
针对 **已有 active 持仓** 的加仓预览与执行。
针对 **已有 active 持仓监控** 的加仓预览与执行。**固定金额(以损定仓)** 模式;**移动保本** 持仓不可滚仓。
**特殊风控**
### 加仓方式
| 方式 | 提交时机 | 执行 |
|------|----------|------|
| **市价加仓** | 仅 **交易时段** | 预览 → 10 秒倒计时 → 立即 CTP 市价成交 |
| **突破加仓** | **任意时间**(含休盘) | 预览 → **提交监控** → 标记价穿越突破价后 Worker 自动市价加仓 |
休盘提交突破加仓时,几何校验放宽为「止损 vs 突破价」关系,不强制要求实时现价;开盘后有行情后按触价逻辑成交。
### 特殊风控
| 项 | 说明 |
|----|------|
@@ -71,20 +81,24 @@
| `roll_max_margin_pct` | 滚仓后总保证金占用单独上限 |
| 手数收紧 | `cap_lots_for_margin_budget()` 按滚仓上限裁剪 |
流程:预览加仓价/手数/新止损 → 确认 → CTP 市价加仓 → 更新 monitor。
流程:
- **市价**:预览 → 确认 → CTP 市价加仓 → 更新 monitor
- **突破**:预览 → 提交 pending 腿 → `check_roll_monitors`(在 `qihuo-ctp` Worker 内)触价成交
---
## 风控规则
| 规则 | 趋势首仓 | 滚仓 |
|------|----------|------|
| assert_can_open | ✓ | 仓位冻结时仍可 |
| max_margin_pct | ✓ 首仓 | — |
| roll_max_margin_pct | — | ✓ |
| 交易时段 | ✓ | ✓ |
| 品种范围 | ✓ | ✓ |
| 单笔 50 手 | ✓ | ✓ |
| 规则 | 趋势首仓 | 市价滚仓 | 突破滚仓(pending) |
|------|----------|----------|---------------------|
| assert_can_open | ✓ | 仓位冻结时仍可 | 仓位冻结时仍可 |
| max_margin_pct | ✓ 首仓 | — | — |
| roll_max_margin_pct | — | ✓ | ✓(预览时按突破价估算) |
| 交易时段 | ✓ | ✓ | 提交 **不要求**;成交须交易时段 |
| CTP 连接 | ✓ | ✓ | 提交 **不要求**;触价成交须 CTP |
| 品种范围 | ✓ | ✓ | ✓ |
| 单笔 50 手 | ✓ | ✓ | ✓ |
全局规则见 [RISK.md](./RISK.md)。
+12
View File
@@ -23,6 +23,18 @@
模拟盘与实盘均走 **vnpy_ctp**,无本地假撮合。
**实盘接入与开平仓对比** → [CTP_LIVE.md](./CTP_LIVE.md) · SimNow → [SIMNOW.md](./SIMNOW.md)
### CTP 双进程与连接行为
| 项目 | 说明 |
|------|------|
| Web | PM2 `qihuo`,端口 6600 |
| CTP Worker | PM2 `qihuo-ctp`,端口 6601(本机) |
| 连接/重连 | 在 Worker 内执行;**小节休息、午间休盘** 仍保持连接(便于读缓存权益/持仓) |
| 页面行为 | 各页 **仅轮询** CTP 状态,**不会在打开页面时自动发起连接** |
| 权益缓存 | CTP 短暂断开时,看板/持仓可回退读最近快照 |
手动 **连接 CTP** 仍通过 **下单监控** 页按钮或 API;成功后顶栏显示「CTP 已连接」。
## 下单与持仓
- **限价开仓**:先显示「挂单中」,柜台成交后进入持仓监控;超时未成交自动撤单(时长见系统设置)