Normalize fullwidth punctuation to ASCII across codebase.

Add scripts/normalize_ambiguous_unicode.py; fix corrupted patch_instance_theme_templates.py. Preserves curly quotes in string literals; removes Git homoglyph warnings on .env.example.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-08 23:42:26 +08:00
parent aaa72c7961
commit b733e551a0
392 changed files with 71522 additions and 71369 deletions
+67 -67
View File
@@ -1,17 +1,17 @@
# 趋势回调策略说明
本文描述 **「趋势回调」** 自动交易计划的业务规则与实现口径
本文描述 **「趋势回调」** 自动交易计划的业务规则与实现口径.
**三所主站**Binance / Gate / OKX均在顶栏 **策略交易 → `/strategy`** 左栏提供同一套逻辑共用 `strategy_trend_register.py`);各所使用各自 API 与 `crypto.db`
**三所主站**(Binance / Gate / OKX)均在顶栏 **策略交易 → `/strategy`** 左栏提供同一套逻辑(共用 `strategy_trend_register.py`);各所使用各自 API 与 `crypto.db`.
**检阅备忘**中控平仓交易记录补仓展示漏记补录):[trend-hub-close-and-trade-records.md](./trend-hub-close-and-trade-records.md)
**检阅备忘**(中控平仓,交易记录,补仓展示,漏记补录):[trend-hub-close-and-trade-records.md](./trend-hub-close-and-trade-records.md)
---
## 1. 适用场景
-**USDT 永续** 实例独立部署使用各自 API 与 `crypto.db`
- 你已明确**方向止损价补仓区间边界价止盈价杠杆**并接受程序按风险预算拆分 **首仓 50% + 多档补仓 50%**
-**USDT 永续** 实例独立部署,使用各自 API 与 `crypto.db`.
- 你已明确:**方向,止损价,补仓区间边界价,止盈价,杠杆**,并接受程序按风险预算拆分 **首仓 50% + 多档补仓 50%**.
---
@@ -19,67 +19,67 @@
| 名称 | 含义 |
|------|------|
| **合约 USDT 可用余额** | **生成预览**时通过 API 读取的 **swap 账户 USDT `free`** 快照**确认执行**时再次读取并与快照比对偏差 |
| **风险比例** | 默认 **5%**指「若整笔计划在 **补仓区间远侧边界**做多=上沿做空=下沿这一侧的最坏价格结构下触及止损」目标亏损上限约为 **可用余额快照 × 风险比例**实现上用 `calc_risk_fraction``prepare_order_amount` 反推总张数受交易所最小张数与精度约束)。 |
| **止损价** | 用户填写开仓后挂 **交易所仓位类止损触发单**全平)。 |
| **补仓区间边界**库字段 `add_upper` | 用户填写**仅在该价位与止损价构成的区间内** 才允许程序触发剩余 50% 的市价补仓**界面文案**做多显示「补仓上沿」做空显示「补仓下沿」校验做多 `止损 < 边界价`做空 `止损 > 边界价` |
| **止盈价** | 用户填写的 **固定价格****不由交易所条件止盈单触发**由应用后台 **按标记价/行情价轮询**达到后 **市价全平** |
| **杠杆** | 计划内固定写入用于 `set_leverage` 与名义换算 |
| **补仓档位数** | 默认 **5**环境变量 `TREND_PULLBACK_DCA_LEGS` 可调);程序在满足最小张数前提下可能 **自动减少档数** |
| **合约 USDT 可用余额** | **生成预览**时通过 API 读取的 **swap 账户 USDT `free`** 快照;**确认执行**时再次读取并与快照比对偏差. |
| **风险比例** | 默认 **5%**:指「若整笔计划在 **补仓区间远侧边界**(做多=上沿,做空=下沿)这一侧的最坏价格结构下触及止损」,目标亏损上限约为 **可用余额快照 × 风险比例**(实现上用 `calc_risk_fraction``prepare_order_amount` 反推总张数,受交易所最小张数与精度约束). |
| **止损价** | 用户填写;开仓后挂 **交易所仓位类止损触发单**(全平). |
| **补仓区间边界**(库字段 `add_upper`) | 用户填写;**仅在该价位与止损价构成的区间内** 才允许程序触发剩余 50% 的市价补仓.**界面文案**:做多显示「补仓上沿」,做空显示「补仓下沿」.校验:做多 `止损 < 边界价`;做空 `止损 > 边界价`. |
| **止盈价** | 用户填写的 **固定价格**;**不由交易所条件止盈单触发**,由应用后台 **按标记价/行情价轮询**,达到后 **市价全平**. |
| **杠杆** | 计划内固定写入;用于 `set_leverage` 与名义换算. |
| **补仓档位数** | 默认 **5**(环境变量 `TREND_PULLBACK_DCA_LEGS` 可调);程序在满足最小张数前提下可能 **自动减少档数**. |
---
## 3. 执行流程时间顺序
## 3. 执行流程(时间顺序)
### 3.0 列表时间窗交易记录 / 计划历史
### 3.0 列表时间窗(交易记录 / 计划历史)
- **交易记录****计划历史**含预览快照列表与 **交易记录 CSV 导出** 支持 **UTC** 时间筛选默认 UTC 当日可选近 24h近 7d自定义起止)。
- 查询参数`win_preset``utc_today` / `utc_last24h` / `utc_last7d` / `custom`)、自定义时另传 `from_utc``to_utc`
- **统计分析**页仍按北京时间 `TRADING_DAY_RESET_HOUR` 切日不受列表窗影响
- **交易记录**,**计划历史**(含预览快照)列表与 **交易记录 CSV 导出** 支持 **UTC** 时间筛选(默认 UTC 当日;可选近 24h,近 7d,自定义起止).
- 查询参数:`win_preset`(`utc_today` / `utc_last24h` / `utc_last7d` / `custom`),自定义时另传 `from_utc`,`to_utc`.
- **统计分析**页仍按北京时间 `TRADING_DAY_RESET_HOUR` 切日,不受列表窗影响.
### 3.1 预览阶段不下单
### 3.1 预览阶段(不下单)
1. **风控**与「机器人下单监控」**互斥**——存在活跃机器人持仓或运行中趋势计划时不可生成预览
2. **读取可用余额快照** `get_available_trading_usdt()`失败则拒绝
3. **计算**写入表 `trend_pullback_previews`并跳转带 `preview_id`):
-**补仓区间边界 ↔ 止损** 区间内生成 `N` 个补仓触发价做多从上沿向止损做空从下沿向止损);
-**剩余 50% 计划张数** 拆成 `N` 份写入 `leg_amounts_json`
4. **预览有效期**默认 **120 秒**`TREND_PULLBACK_PREVIEW_TTL_SECONDS`),超时须重新点「生成预览」
1. **风控**:与「机器人下单监控」**互斥**——存在活跃机器人持仓或运行中趋势计划时,不可生成预览.
2. **读取可用余额快照** `get_available_trading_usdt()`,失败则拒绝.
3. **计算**(写入表 `trend_pullback_previews`,并跳转带 `preview_id`):
-**补仓区间边界 ↔ 止损** 区间内生成 `N` 个补仓触发价(做多从上沿向止损,做空从下沿向止损);
-**剩余 50% 计划张数** 拆成 `N` 份写入 `leg_amounts_json`.
4. **预览有效期**:默认 **120 秒**(`TREND_PULLBACK_PREVIEW_TTL_SECONDS`),超时须重新点「生成预览」.
### 3.2 确认执行实盘
### 3.2 确认执行(实盘)
5. 再次校验预览未过期**当前可用余额**与预览快照相对偏差 ≤ `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT`默认 **5%**),否则拒绝执行并要求重新预览
6. **首仓****立即市价** 开立 **总计划张数 × 50%**不附带交易所止盈单)。
7. **止损**撤销旧条件单后**仅止损** 的仓位触发单之后每次补仓成交会 **刷新** 止损挂单
7b. **保本移交下单监控**可选):首仓完成且交易所有持仓后可点击「保本移交下单监控」——将止损移至 **持仓均价 ± 偏移%**默认 **+0.3%** 多 / **0.3%** 空),仅当新止损 **优于** 当前止损时生效**本次趋势计划随即结束**持仓写入 **下单监控**备注 **趋势回调计划**),交易所在 **同一时刻挂保本止损 + 计划止盈**后续无论中控平仓或交易所手动平仓均经下单监控轮询 **`reconcile_external_closes` / `check_order_monitors`** 写入 **交易记录**`trend_plan_id`开仓类型「趋势回调」),供人工核对
8. **补仓**当价格 **穿越** 下一档触发价做多为自上向下穿越做空为自下向上穿越)时,按该档张数 **市价加仓**直至 `N` 档执行完毕或计划结束
9. **止盈监控**后台线程若发现价格触及止盈**市价全平**
10. **止损触发**若仓位被交易所止损打光本地检测到 **持仓为 0** 后记账为 **止损** 并结束计划
11. **计划结束**任一结束路径止盈 / 止损 / 用户手动结束均会 **撤单**条件单 + 普通挂单尽力而为)。
5. 再次校验:预览未过期;**当前可用余额**与预览快照相对偏差 ≤ `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT`(默认 **5%**),否则拒绝执行并要求重新预览.
6. **首仓**:**立即市价** 开立 **总计划张数 × 50%**(不附带交易所止盈单).
7. **止损**:撤销旧条件单后,**仅止损** 的仓位触发单;之后每次补仓成交会 **刷新** 止损挂单.
7b. **保本移交下单监控**(可选):首仓完成且交易所有持仓后,可点击「保本移交下单监控」——将止损移至 **持仓均价 ± 偏移%**(默认 **+0.3%** 多 / **0.3%** 空),仅当新止损 **优于** 当前止损时生效;**本次趋势计划随即结束**,持仓写入 **下单监控**(备注 **趋势回调计划**),交易所在 **同一时刻挂保本止损 + 计划止盈**;后续无论中控平仓或交易所手动平仓,均经下单监控轮询 **`reconcile_external_closes` / `check_order_monitors`** 写入 **交易记录**(`trend_plan_id`,开仓类型「趋势回调」),供人工核对.
8. **补仓**:当价格 **穿越** 下一档触发价(做多为自上向下穿越,做空为自下向上穿越)时,按该档张数 **市价加仓**;直至 `N` 档执行完毕或计划结束.
9. **止盈监控**:后台线程若发现价格触及止盈,**市价全平**.
10. **止损触发**:若仓位被交易所止损打光,本地检测到 **持仓为 0** 后记账为 **止损** 并结束计划.
11. **计划结束**:任一结束路径(止盈 / 止损 / 用户手动结束)均会 **撤单**(条件单 + 普通挂单,尽力而为).
### 3.3 取消预览
用户可「取消预览」删除 `trend_pullback_previews` 中对应记录过期记录会在新预览或页面加载时清理
用户可「取消预览」删除 `trend_pullback_previews` 中对应记录;过期记录会在新预览或页面加载时清理.
### 3.4 界面计划历史与运行中浮动盈亏
### 3.4 界面:计划历史与运行中浮动盈亏
- **计划历史页顶卡片**
- 仅展示 **`trend_pullback_plans` 中已结束的计划**`status != 'active'`如止盈结束止损结束手动结束)。
- **不包含**仅存在于 `trend_pullback_previews`从未「确认执行」的预览
- 每行提供 **删除**删除该计划行并删除 `trade_records`**`trend_plan_id` 与之相同** 且类型为「趋势回调」的记录用于与计划一一对应的新数据历史旧行若无 `trend_plan_id` 则不会随删)。
- **运行中的计划交易执行页**
- 在计划摘要下方展示 **浮盈亏交易所**来自 Gate 当前持仓接口的 **未实现盈亏**及标记价若可得);与本地按均价估算可能略有差异以交易所为准便于对照
- **补仓边界**按方向显示「补仓上沿」或「补仓下沿」数值仍为 `add_upper` 字段)。
- **手动保本**表单可改偏移 %默认见 `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT`);成功后显示「已保本」时间与原止损若与当前不同)。
- **计划历史(页顶卡片)**
- 仅展示 **`trend_pullback_plans` 中已结束的计划**(`status != 'active'`,如止盈结束,止损结束,手动结束).
- **不包含**仅存在于 `trend_pullback_previews`,从未「确认执行」的预览.
- 每行提供 **删除**:删除该计划行,并删除 `trade_records`**`trend_plan_id` 与之相同** 且类型为「趋势回调」的记录(用于与计划一一对应的新数据;历史旧行若无 `trend_plan_id` 则不会随删).
- **运行中的计划(交易执行页)**
- 在计划摘要下方展示 **浮盈亏(交易所)**:来自 Gate 当前持仓接口的 **未实现盈亏**(及标记价,若可得);与本地按均价估算可能略有差异,以交易所为准便于对照.
- **补仓边界**按方向显示「补仓上沿」或「补仓下沿」(数值仍为 `add_upper` 字段).
- **手动保本**:表单可改偏移 %(默认见 `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT`);成功后显示「已保本」时间与原止损(若与当前不同).
### 3.5 交易记录与交易所「已实现盈亏」对齐
- 平仓时仍会写入一条 **`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` 的趋势回调记录 **匹配一条平仓记录**并回填
- **`exchange_realized_pnl`**交易所口径已实现盈亏与 App「历史仓位」更接近);
- **`exchange_opened_at` / `exchange_closed_at`**换算为应用时区默认北京下的开平时间字符串
- **交易记录表**展示列「开仓(展示) / 平仓(展示) / 盈亏U(展示)」对「趋势回调」行若已同步则优先显示交易所字段界面小字 **「所」**);未同步前仍显示本地复盘字段小字 **「估」**)。
- 匹配规则概要同品种同方向平仓时间与本地 `closed_at` 接近并结合 **`trend_plan_id`** 对应计划的 `opened_at` 收窄时间窗极端情况下若短时间多笔同向同品种仍存在错配可能可对照 `exchange_sync_key` 与交易所记录
- 平仓时仍会写入一条 **`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` 的趋势回调记录 **匹配一条平仓记录**,并回填:
- **`exchange_realized_pnl`**:交易所口径已实现盈亏(与 App「历史仓位」更接近);
- **`exchange_opened_at` / `exchange_closed_at`**:换算为应用时区(默认北京)下的开,平时间字符串.
- **交易记录表**展示列「开仓(展示) / 平仓(展示) / 盈亏U(展示)」:对「趋势回调」行,若已同步则优先显示交易所字段(界面小字 **「所」**);未同步前仍显示本地复盘字段(小字 **「估」**).
- 匹配规则概要:同品种,同方向,平仓时间与本地 `closed_at` 接近,并结合 **`trend_plan_id`** 对应计划的 `opened_at` 收窄时间窗;极端情况下若短时间多笔同向同品种,仍存在错配可能,可对照 `exchange_sync_key` 与交易所记录.
---
@@ -89,17 +89,17 @@
|------|------------------|----------|
| 开仓 | 单次市价 + 条件止盈+止损 | 首仓 50% 市价 + 多档补仓 + **仅止损在交易所** |
| 止盈 | 条件单 + 本地监控 | **仅本地监控市价止盈** |
| 仓位基数 | 以损定仓表单/会话基数 | **可用余额快照 × 风险比例** 推导 |
| 移动保本 | 支持按 R 自动上移 | **保本移交**结束计划→下单监控交易所 TP+SL**无**自动 R 保本 |
| 仓位基数 | 以损定仓(表单/会话基数) | **可用余额快照 × 风险比例** 推导 |
| 移动保本 | 支持(按 R 自动上移) | **保本移交**(结束计划→下单监控;交易所 TP+SL;**无**自动 R 保本) |
---
## 5. 风险声明必读
## 5. 风险声明(必读)
- 市价单存在 **滑点**极端行情下实际亏损可能 **大于** 理论 5%
- 补仓触发依赖应用 **轮询间隔**`MONITOR_POLL_SECONDS`),非毫秒级高频
- 交易所 **最小张数 / 精度** 可能导致计划张数被截断实际风险略低于或偏离纸面计算
- 请使用 **单独 API Key / 子账户**并先在 `LIVE_TRADING_ENABLED=false` 环境验证流程若需沙盒请自行对接测试网本仓库默认实盘接口)。
- 市价单存在 **滑点**;极端行情下实际亏损可能 **大于** 理论 5%.
- 补仓触发依赖应用 **轮询间隔**(`MONITOR_POLL_SECONDS`),非毫秒级高频.
- 交易所 **最小张数 / 精度** 可能导致计划张数被截断,实际风险略低于或偏离纸面计算.
- 请使用 **单独 API Key / 子账户**,并先在 `LIVE_TRADING_ENABLED=false` 环境验证流程(若需沙盒请自行对接测试网,本仓库默认实盘接口).
---
@@ -107,23 +107,23 @@
| 变量 | 说明 | 默认 |
|------|------|------|
| `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT` | 手动保本默认偏移相对持仓均价% | `0.3` |
| `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT` | 手动保本默认偏移(相对持仓均价,%) | `0.3` |
| `TREND_PULLBACK_DCA_LEGS` | 剩余 50% 拆档数量上限 | `5` |
| `TREND_PULLBACK_PREVIEW_TTL_SECONDS` | 预览有效时间(秒) | `120` |
| `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT` | 确认执行时允许「当前可用 / 预览快照」最大相对偏差% | `5` |
| `MONITOR_POLL_SECONDS` | 监控轮询间隔(秒) | `3` |
| `TREND_PULLBACK_PREVIEW_TTL_SECONDS` | 预览有效时间(秒) | `120` |
| `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT` | 确认执行时允许「当前可用 / 预览快照」最大相对偏差(%) | `5` |
| `MONITOR_POLL_SECONDS` | 监控轮询间隔(秒) | `3` |
| `LIVE_TRADING_ENABLED` | 是否允许真实下单 | `false` |
| `FULL_MARGIN_BUFFER_RATIO` | 计划保证金相对可用余额上限比例 | `0.98` |
| `APP_TIMEZONE` | 应用墙钟与「北京日期」同步起点时区`Asia/Shanghai` | `Asia/Shanghai` |
| `EXCHANGE_POSITION_SYNC_FROM_BJ` | 拉取 Gate **平仓历史** 的最早日期`YYYY-MM-DD``APP_TIMEZONE` 当日 **00:00** 起算)。**留空**则从近 **90 天** 起拉取 | 空 |
| `EXCHANGE_POSITION_HISTORY_LIMIT` | 单次拉取平仓历史条数上限501000 | `200` |
| `APP_TIMEZONE` | 应用墙钟与「北京日期」同步起点时区(`Asia/Shanghai`) | `Asia/Shanghai` |
| `EXCHANGE_POSITION_SYNC_FROM_BJ` | 拉取 Gate **平仓历史** 的最早日期(`YYYY-MM-DD`,`APP_TIMEZONE` 当日 **00:00** 起算).**留空**则从近 **90 天** 起拉取 | 空 |
| `EXCHANGE_POSITION_HISTORY_LIMIT` | 单次拉取平仓历史条数上限(501000) | `200` |
---
## 7. 数据库
- **`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`** 存补仓区间远侧边界价做多=上沿做空=下沿)。
- **`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)。
- **`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`** 存补仓区间远侧边界价(做多=上沿,做空=下沿).
- **`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`.