Files
crypto_okx/docs/系统架构与技术实现.md
T
2026-10-09 08:50:03 +08:00

479 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 系统架构与技术实现
> 定位:描述本仓库(OKX 币本位期权实例)的整体架构、运行时、模块划分与关键技术实现。
> 配套文档:
> - 业务主链:[系统分析-期权主链条.md](./系统分析-期权主链条.md)
> - 盈亏规格:[规格-期权交易账户盈亏结算.md](./规格-期权交易账户盈亏结算.md)
> - 操作说明:[../使用说明.md](../使用说明.md)
> - 部署:[../部署文档.md](../部署文档.md) · 实盘:[实盘说明.md](./实盘说明.md)
---
## 1. 系统定位
| 项 | 说明 |
|----|------|
| 角色 | 单交易所实例客户端(OKX),可独立使用,也可挂中控 `crypto_okx_hub` |
| 主业务 | **币本位期权**:USDT → 买 ETH/BTC → 开期权 → 平仓 → 卖回 → 按交易户 USDT 差分冻结盈亏 |
| 非目标 | 不再以永续实盘下单 / USDC 期权开仓 / 对冲计划为主路径(相关代码多已下线或残留) |
三条控制面:
```text
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 浏览器面板 │ │ 本机监控守护线程 │ │ 中控 Hub │
│ /options │ │ options-monitor │ │ /api/hub/* │
│ /api/options│ │ 目标/翻倍/条件单 │ │ 快照/条件单/全平 │
└──────┬──────┘ └────────┬─────────┘ └────────┬────────┘
│ │ │
└─────────────────────┼────────────────────────┘
▼
Flask app.py(单进程)
│
┌──────────────┼──────────────┐
▼ ▼ ▼
SQLite ccxt.okx 模拟 SimBroker
(crypto.db) (实盘/公开行情) (本地撮合)
```
---
## 2. 技术栈
| 层级 | 技术 | 说明 |
|------|------|------|
| 语言 / 运行时 | Python **3.10+** | 见 `README.md` / `requirements.txt` |
| Web 框架 | Flask ≥3、<4 | `threaded=True`;Jinja2 模板 |
| WSGI | Werkzeug | 开发/PM2 直跑 `app.py` |
| 交易所 SDK | **ccxt** ≥4.2(`ccxt.okx`) | 期权 `defaultType=option`;可配 SOCKS |
| HTTP / 代理 | requests、PySocks | `OKX_SOCKS_PROXY` |
| 持久化 | **SQLite** 单文件 | 默认 `DB_PATH=crypto.db` |
| 进程管理 | **PM2** | `ecosystem.config.cjs`:单实例、内存上限约 800M |
| 前端 | **原生 JS/CSS** | 无 React/Vue/`package.json`;静态资源在 `lib/common/static/` |
| 图像 | Pillow | 复盘/日记配图等 |
部署约定(见部署文档):常见路径 `/opt/crypto_okx`,端口 **`APP_PORT=5004`**(代码未配时 fallback 5000)。
---
## 3. 仓库与目录结构
```text
crypto_okx/
├── app.py # 应用入口:装配路由、线程、交易所句柄
├── ecosystem.config.cjs # PM2
├── requirements.txt
├── .env / .env.example
├── crypto.db # 运行时 SQLite(勿提交)
├── deploy/ # 安装 / 更新 / doctor 脚本
├── docs/ # 规格、架构、实盘说明
├── templates/ # Flask 默认模板目录(少量)
├── static/ # 上传等(如 images)
└── lib/
├── paths.py # 仓库根、静态/模板路径
├── options/ # 期权交易、监控、复盘、结算(核心)
├── exchange/ # OKX 期权 API 封装、账本适配
├── sim/ # 模拟钱包与 API hook
├── hub/ # 中控 Bridge 鉴权与路由
├── env/ # .env 读写、schema、配置页白名单
├── instance/ # 壳层 UI、设置、embed、备份、仪表盘
├── account_ledger/ # 资金流水同步
├── market/ # 行情、K 线、精度
├── trade/ # 入场模型/风控等(关键位等周边)
├── key_monitor/ # 关键位监控
└── common/ # 公共工具 + static 前端资源
```
原则:**业务按包 install/register 挂到 Flask**,避免全部逻辑堆在 `app.py`;`app.py` 仍保留登录、部分关键位与全局交易所对象。
---
## 4. 启动与装配顺序
### 4.1 引导流程
```text
load_env_file(.env) → os.environ
→ Flask(__name__) + Session(含中控 iframe SameSite=None/Secure)
→ attach_embed_templates / install_common_static
→ 构建 ccxt.okx(永续句柄 + options 句柄,可带代理)
→ 初始化 SQLite 核心表
→ register_trade_records_api
→ register_instance_dashboard_routes # 仪表盘缓存线程
→ install_account_ledger # 账本同步线程
→ register_instance_settings_routes
→ start_backup_scheduler # 定时备份线程
→ install_sim_trading # 模拟模式 + hooks
→ install_options_trading # 期权路由 + options-monitor
→ install_options_review
→ install_instance_data_stats # 资金采样线程
→ register_hub_bridge_routes
→ register_embed_routes # /embed + live push
→ __main__: key-monitor 后台线程 + app.run(threaded=True)
```
### 4.2 期权模块装配(要点)
`install_options_trading`(`lib/options/options_register.py`):
1. `_build_cfg(app_module)`:注入 DB、交易所、预算、报价/下单回调等。
2. `register_options_routes`:页面与 `/api/options/*`。
3. `_register_options_hub_bridge`:把 `options_snapshot_fn` 等写入 `app.config["HUB_CTX"]`。
4. `_start_monitor_thread`:若 `OKX_OPTIONS_ENABLED`,拉起 `options-monitor`。
---
## 5. 运行时架构
### 5.1 进程模型
| 单元 | 数量 | 说明 |
|------|------|------|
| PM2 应用 `crypto_okx` | 1 | `python app.py`,`PYTHONPATH` 指向仓库根 |
| Flask 请求线程 | 多 | `threaded=True` |
| 守护线程 | 多个 | 见下表(均为 daemon) |
### 5.2 守护线程一览
| 线程(逻辑名) | 启动位置 | 职责 |
|----------------|----------|------|
| `background_task` / 关键位监控 | `app.py` `__main__` | 按 `MONITOR_POLL_SECONDS` 轮询关键位规则 |
| `options-monitor` | `options_register` | 目标位平仓、翻倍出场、条件单 tick、持仓同步、卖回扫尾 |
| `okx-backup-scheduler` | `backup_lib` | 定时备份 |
| `account-ledger-okx` | `account_ledger` | 交易所资金流水同步 |
| `instance-dashboard-poll` | dashboard cache | 仪表盘数据缓存 |
| `instance-cash-sample` | data stats | 资金样本 |
| `instance-live-push` | embed live | SSE/推送类 |
短生命周期线程:日记/复盘异步出图(`journal-chart-*`、`options-review-chart-*`)。
### 5.3 配置三层
```text
① .env 文件(启动 load + env 页写入)
② os.environ(进程环境)
③ SQLite app_runtime_settings
· trading.mode = sim | live
· display.* 导航显示偏好
· env.<KEY> 热更新覆盖(runtime_config_lib)
```
读取顺序(热更场景):运行时覆盖 → 环境变量 → 代码默认(`env_ui_manifest._RUNTIME_ENV_DEFAULTS`)。
部分键改后需 **保存并重启**(见 `env_schema` 的 restart 标记)。
---
## 6. 分层架构
```text
┌──────────────────────────────────────────────────────────┐
│ 表现层 Jinja 模板 + vanilla JS(options_panel.js 等) │
├──────────────────────────────────────────────────────────┤
│ 接入层 Flask routes(options_register / hub / settings) │
├──────────────────────────────────────────────────────────┤
│ 领域编排 coin_open / close_exec / cond_order / monitor │
│ account_pnl / stats / review │
├──────────────────────────────────────────────────────────┤
│ 基础设施 okx_options_lib(ccxt) · SQLite · sim broker │
│ env_file · wechat_notify · backup │
└──────────────────────────────────────────────────────────┘
```
| 层 | 代表路径 | 职责边界 |
|----|----------|----------|
| 表现 | `lib/options/templates/*`、`lib/common/static/options_*.js` | 交互、轮询、展示口径 |
| 接入 | `options_register.py`、`hub_bridge_register.py`、`instance_settings_register.py` | HTTP、鉴权、参数归一 |
| 编排 | `options_coin_open_lib.py`、`options_close_exec_lib.py`、`options_monitor_lib.py` | 多步业务流程、状态机 |
| 领域规则 | `options_margin_mode_lib.py`、`options_close_gate_lib.py`、`options_account_pnl_lib.py` | 预算、门控、结算真源 |
| 基础设施 | `okx_options_lib.py`、`options_db.py`、`sim/*` | IO 与持久化 |
---
## 7. 核心业务技术实现
### 7.1 币本位开仓流水线
**入口:** `POST /api/options/open` → `open_coin_option_buy_full`
**尺寸归一:** `_normalize_size_mode`(币本位保留 `budget_full` / `compound_full`;USDC 遗留才落到 `sheets`)
```text
门禁(模式 / 条件单锁 / 持仓上限 / 可卖币拒开)
→ compute_coin_budget_usdt + plan_coin_open_by_budget
→ fetch_trading_usdt → trading_usdt_before
→ spot_market_buy_coin_with_usdt(× SPOT_BUY_BUFFER)
→ options_spot_bridge = bought*
→ place_option_limit_order(IOC @ 卖一)+ wait fill
失败 → 回滚卖币
成功 → bridge=holding,写入 options_trades(open, pnl_settled=0)
→ 可选 upsert 目标位 / 翻倍出场 / 企微通知
```
关键文件:
- `lib/options/options_coin_open_lib.py`
- `lib/options/options_spot_bridge_lib.py`
- `lib/options/options_margin_mode_lib.py`
- `lib/options/options_position_limit_lib.py`
- `lib/options/options_account_pnl_lib.py`
### 7.2 平仓与自动出场
| 通道 | 实现 | 门控 |
|------|------|------|
| 手动 / Hub 全平 | `close_option_by_bid1`(`require_recycle_gate=False`) | 流动性 |
| 目标位 | `run_options_target_closes` → `close_option_by_bid_depth` | `options_close_gate_lib`(倍数 + 持续秒数) |
| 翻倍出场 | `run_options_profit_exits` → `close_option_by_bid_profit_exit` | 回收 ≥ 权利金×(1+mult) |
平仓后:`settle_closed_pnl`(币/费用侧)→ `maybe_sell_spot_after_close` → `try_settle_after_sellback`:
```text
realized_pnl_usdt = trading_usdt_after − trading_usdt_before
pnl_settled = 1 # 冻结,业务路径不再改写
```
### 7.3 监控循环
`options_monitor_loop`(`options_monitor_lib.py`)周期性执行,大致包括:
- 同步交易所持仓 ↔ 本地 `options_trades`(纠偏误关仓等)
- 跑目标位 / 翻倍 / 条件单 tick
- 平仓后卖回扫尾、推动账户结算
- 历史盈亏回填(**跳过已冻结 U**)
轮询间隔受期权相关 poll env / 内部 sleep 控制;与关键位监控线程相互独立。
### 7.4 模拟盘技术实现
| 组件 | 文件 | 作用 |
|------|------|------|
| 模式 | `sim/mode_lib.py` | `trading.mode` ∈ {sim, live};启动默认 `SIM_DEFAULT_MODE` |
| 撮合 | `sim/broker_lib.py` | `SimBroker`:公开买卖一进本地钱包/仓位 |
| 注入 | `sim/hooks.py` | `apply_sim_hooks` / `patch_options_cfg`:把下单、划转等切到模拟实现 |
| 表 | `sim/db_lib.py` | `sim_wallets`、`sim_option_positions`、`sim_ledger_entries` 等 |
实盘闸门:`LIVE_TRADING_ENABLED`;模拟下即使有密钥也不应向交易所发真实期权单(由 hook 拦截)。
### 7.5 复盘与统计(只读结算真源)
```text
options_trades(closed + settled)
→ review sync → options_review_*
→ stats:compute_options_stats_auto / header_options_stats_for_window
```
- 复盘:`options_review_lib.py` + `options_review_register.py`
- 统计:`options_stats_lib.py`
- 规则:未 `pnl_settled` 不计已实现;有账户快照的新单只读冻结 U
---
## 8. 交易所集成
### 8.1 ccxt 句柄
`app.py` 构建:
- `exchange`:通用 OKX(行情/部分账户)
- `exchange_options`:`defaultType=option`
期权细节封装:`lib/exchange/okx_options_lib.py`
| 能力 | 示例 |
|------|------|
| 期权链 | `build_option_chain` |
| 报价 | `quote_option_contract` |
| 下单/撤单/等成交 | `place_option_limit_order`、`wait_option_order_full_fill` |
| 持仓/余额 | `fetch_option_positions`、`fetch_options_balances` |
| 划转 | `transfer_ccy` |
| 流动性 | `option_buy_liquidity_ok`、买一深度裁剪 |
凭证:`OKX_API_KEY` / `SECRET` / `PASSPHRASE`(遗留 `OKX_OPTIONS_API_*` 可回填)。
代理:`build_okx_ccxt_proxies()` ← `OKX_SOCKS_PROXY`。
### 8.2 账户模式约束
程序现货侧按 **合约模式 + cash** 假设编写;跨币种/组合保证金易触发 `tdMode` / `51010`。详见实盘说明。
---
## 9. 数据模型(SQLite)
单库文件,多模块 `CREATE TABLE IF NOT EXISTS`。
### 9.1 期权核心
| 表 | 用途 |
|----|------|
| `options_trades` | 开平流水;`trading_usdt_before/after`、`realized_pnl_usdt`、`pnl_settled` |
| `options_spot_bridge` | 买币/持币/待卖回/关闭 |
| `options_target_monitors` | 指数目标位 |
| `options_cond_orders` | 中控条件单状态机 |
| `options_exchange_pnl_freeze` | 实盘历史盈亏冻结辅助 |
| `options_transfer_log` / `options_convert_log` | 划转等日志 |
| `options_history_hidden` | 历史隐藏 |
### 9.2 复盘
`options_review_trades`、`options_review_entries`、`options_review_sync_state`、`options_review_hidden`
### 9.3 模拟
`sim_wallets`、`sim_option_positions`、`sim_option_orders`、`sim_ledger_entries` 等
### 9.4 实例壳层
`app_runtime_settings`、`key_monitors`、`trade_records`、`account_ledger_*`、`instance_cash_samples` 等
连接约定:业务路径多处 `sqlite3.connect(DB_PATH, timeout=…)` + `Row` factory;长事务与网络 IO 应拆分,避免「持锁等交易所」导致面板超时(历史踩坑点)。
---
## 10. 鉴权与中控 Bridge
### 10.1 站点登录
| 项 | 实现 |
|----|------|
| 账号 | `APP_USERNAME` / `APP_PASSWORD` |
| Session | `session["logged_in"]`;`APP_SESSION_DAYS`;`FLASK_SECRET_KEY` |
| 装饰器 | `login_required`;`/api/*` 未登录返回 JSON 401 |
| 可关闭 | `APP_AUTH_DISABLED`(仅受信环境) |
为支持中控 iframe:Cookie `SameSite=None` + `Secure`(按配置)。
### 10.2 Hub 鉴权(`lib/hub/hub_bridge_auth.py`)
| 机制 | 用途 |
|------|------|
| `HUB_BRIDGE_TOKEN` | M2M:`X-Hub-Token` 或 `Bearer`;`hmac.compare_digest` |
| 短时 SSO | `/hub_sso?token=` → 建站内 session(TTL ~120s) |
| 长时 embed | `embed_sso`(约 7 天)应对 iframe 第三方 Cookie 限制 |
| 自动生成 | env 页首次打开可 `ensure_hub_bridge_token` 写入 `.env` |
| CSP | `HUB_EMBED_FRAME_ANCESTORS` → `frame-ancestors` |
### 10.3 Hub API 面(`hub_bridge_register.py`)
| 方法 | 路径 | 作用 |
|------|------|------|
| GET | `/api/hub/options/snapshot` | 持仓/资金/条件单/流动性摘要 |
| GET | `/api/hub/options/stats` | 窗口统计 |
| POST | `/api/hub/options/close` | 买一限价**全平** |
| GET/POST | `/api/hub/options/cond_orders` | 条件单 |
| POST | `.../cancel` · `.../exit` | 取消 / 改出场 |
| GET | `/api/hub/version` | 在线与版本 |
| POST | `/api/hub/update` | 远程 pull + PM2 重启 |
| GET | `/api/hub/backup/*` | 备份列表/下载 |
快照构建:`options_hub_lib.build_options_hub_snapshot`。
---
## 11. 前端技术实现
### 11.1 资源加载
`install_common_static` 将 `lib/common/static/` 下白名单文件挂到 `/static/<name>`。
模板通过 `ChoiceLoader` 合并:`lib/instance/templates`、`lib/options/templates`、`lib/sim/templates` 等。
### 11.2 期权前端模块
| 文件 | 职责 |
|------|------|
| `options_panel.js` | 链、报价、下单尺寸模式、开平仓、轮询 |
| `options_position_cards.js` | 持仓卡 UI |
| `options_expiry_countdown.js` | 到期倒计时 |
| `options_settings.js` | 设置内期权相关 |
| `options_review.js` | 复盘页 |
| `options_data_stats.js` | 统计展示 |
| `hub_embed_auth.js` | 嵌入鉴权辅助 |
| `instance_settings_prefs.js` | 导航显示等偏好 |
交互模式:REST 轮询为主(链/持仓/报价);无独立 Node 构建步骤。
### 11.3 关键 API 前缀
| 前缀 | 模块 |
|------|------|
| `/api/options/*` | 交易面板 |
| `/api/options/review/*` | 复盘 |
| `/api/sim/*` | 模拟资金 |
| `/api/settings/*` | env/显示/密码等 |
| `/api/hub/*` | 中控 |
| `/api/admin/*` | 重启等 |
| `/embed`、`/hub_sso` | 嵌入与 SSO |
---
## 12. 部署与运维技术点
| 项 | 实现 |
|----|------|
| 进程 | PM2 `ecosystem.config.cjs`,`instances: 1` |
| 更新 | 本机脚本 / 中控 `POST /api/hub/update`(git pull + restart) |
| 备份 | `backup_lib` 定时 + 设置页手动;中控可下载 |
| 代理 | `OKX_SOCKS_PROXY`;SSH 动态转发不由 PM2 托管 |
| 日志 | PM2 日志 + Werkzeug;可静音 access log |
| 健康 | `deploy/lib/doctor.sh`;中控看 `/api/hub/version` |
---
## 13. 关键设计决策(实现层)
| 决策 | 原因 | 落点 |
|------|------|------|
| 单进程 + 多守护线程 | 部署简单、与 SQLite 单写者模型匹配 | PM2 instances=1 |
| 盈亏真源=交易户 USDT 差分 | 与钱包可对账、避免指数重算漂移 | `options_account_pnl_lib` |
| 一次一仓默认 | 差分对账前提 | `OKX_OPTIONS_MAX_ACTIVE_POSITIONS=1` |
| 现货桥表 | 买币/卖回与期权生命周期解耦可重试 | `options_spot_bridge` |
| Sim hook 而非第二套 UI | 同一面板切模拟/实盘 | `sim/hooks.py` |
| Hub Token + SSO 双通道 | 机器调用与 iframe 人机登录分离 | `hub_bridge_auth` |
| 前端无框架 | 运维机交付简单、无构建链 | `lib/common/static` |
| USDC 开仓下线 | 主路径币本位 | margin mode 固定 coin |
---
## 14. 扩展与修改指引
1. **新开仓入口**:必须接条件单锁、持仓上限、可卖币检查、before 快照。
2. **新统计展示**:只消费 `pnl_settled` 冻结值;勿在展示层重算账户差分。
3. **新自动平仓**:明确是否走 close_gate;与手动通道权限分开。
4. **改 env 默认**:同步代码默认、`env_ui_manifest` 文案与 `_RUNTIME_ENV_DEFAULTS`。
5. **避免在持 DB 锁时调交易所**:网络与写库分阶段,防止面板 API 超时。
6. **中控协议变更**:同步 `hub_bridge_register`、快照 `version` 与中控仓库解析逻辑。
---
## 15. 关键文件索引
| 主题 | 路径 |
|------|------|
| 入口 | `app.py` |
| 路径常量 | `lib/paths.py` |
| 期权路由/监控启动 | `lib/options/options_register.py` |
| 监控循环 | `lib/options/options_monitor_lib.py` |
| 开仓 | `lib/options/options_coin_open_lib.py` |
| 现货桥 | `lib/options/options_spot_bridge_lib.py` |
| 平仓执行 | `lib/options/options_close_exec_lib.py` |
| 账户结算 | `lib/options/options_account_pnl_lib.py` |
| 条件单 | `lib/options/options_cond_order_lib.py` |
| Hub 快照 | `lib/options/options_hub_lib.py` |
| Hub 路由/鉴权 | `lib/hub/hub_bridge_register.py`、`hub_bridge_auth.py` |
| 交易所 | `lib/exchange/okx_options_lib.py` |
| 模拟 | `lib/sim/register.py`、`hooks.py`、`broker_lib.py` |
| Env UI | `lib/env/env_ui_manifest.py`、`env_schema.py` |
| 静态资源注册 | `lib/instance/instance_static_lib.py` |
| PM2 | `ecosystem.config.cjs` |
---
## 16. 文档关系
```text
使用说明.md ← 操作员怎么用
实盘说明.md ← 交易所前置与实盘开关
规格-…盈亏结算.md ← 盈亏产品规则(真源)
系统分析-期权主链条.md ← 业务功能链与数据流
本文 ← 软件架构与技术实现
部署文档.md ← 安装运维
```