This commit is contained in:
dekun
2026-05-23 11:20:45 +08:00
parent 4b185133c4
commit fc8f9b70da
14 changed files with 294 additions and 79 deletions
+20
View File
@@ -5682,6 +5682,13 @@ def render_main_page(page="trade"):
f"箱体/收敛可选 SL/TP 方案(标准 / 箱体1R·止盈1.5H / 趋势单+自填止盈)|移动保本默认关|"
f"斐波:限价 @ E(SL/TP 为 H/L),可选移动保本|趋势止损外侧 {KEY_TREND_STOP_OUTSIDE_PCT}%"
)
strategy_extra = {}
if page in ("strategy_trend", "strategy_roll"):
from strategy_ui import strategy_page_template_vars
strategy_extra = strategy_page_template_vars(
conn, page, default_risk_percent=float(RISK_PERCENT)
)
conn.close()
return render_template(
"index.html",
@@ -5737,6 +5744,7 @@ def render_main_page(page="trade"):
key_auto_min_planned_rr=KEY_AUTO_MIN_PLANNED_RR,
key_gate_rule_text=key_gate_rule_text,
kline_timeframe=KLINE_TIMEFRAME,
**strategy_extra,
)
@@ -7674,6 +7682,18 @@ except Exception as _hub_err:
print(f"[hub_bridge] binance: {_hub_err}")
@app.route("/strategy/trend")
@login_required
def strategy_trend_page():
return render_main_page("strategy_trend")
@app.route("/strategy/roll")
@login_required
def strategy_roll_page():
return render_main_page("strategy_roll")
from strategy_register import install_strategy_trading
install_strategy_trading(app, _REPO_ROOT, app_module=sys.modules[__name__])
+5 -2
View File
@@ -218,8 +218,7 @@
<div class="top-nav">
<a href="/key_monitor" class="{% if page == 'key_monitor' %}active{% endif %}">关键位监控</a>
<a href="/trade" class="{% if page == 'trade' %}active{% endif %}">实盘下单</a>
<a href="/strategy/trend" class="{% if page == 'strategy_trend' %}active{% endif %}">策略·趋势回调</a>
<a href="/strategy/roll" class="{% if page == 'strategy_roll' %}active{% endif %}">策略·顺势加仓</a>
<a href="/strategy/trend" class="{% if page in ('strategy_trend', 'strategy_roll') %}active{% endif %}">策略交易</a>
<a href="/records" class="{% if page == 'records' %}active{% endif %}">交易记录与复盘</a>
<a href="/stats" class="{% if page == 'stats' %}active{% endif %}">统计分析</a>
</div>
@@ -540,6 +539,10 @@
</div>
</div>
{% elif page == 'strategy_trend' %}
{% include 'strategy_trend_disabled_panel.html' %}
{% elif page == 'strategy_roll' %}
{% include 'strategy_roll_panel.html' %}
{% endif %}
+20
View File
@@ -5661,6 +5661,13 @@ def render_main_page(page="trade"):
f"箱体/收敛可选 SL/TP 方案(标准 / 箱体1R·止盈1.5H / 趋势单+自填止盈)|移动保本默认关|"
f"斐波:限价 @ E(SL/TP 为 H/L),可选移动保本|趋势止损外侧 {KEY_TREND_STOP_OUTSIDE_PCT}%"
)
strategy_extra = {}
if page in ("strategy_trend", "strategy_roll"):
from strategy_ui import strategy_page_template_vars
strategy_extra = strategy_page_template_vars(
conn, page, default_risk_percent=float(RISK_PERCENT)
)
conn.close()
return render_template(
"index.html",
@@ -5718,6 +5725,7 @@ def render_main_page(page="trade"):
key_gate_rule_text=key_gate_rule_text,
kline_timeframe=KLINE_TIMEFRAME,
exchange_pnl_sync=exchange_pnl_sync,
**strategy_extra,
)
@@ -7735,6 +7743,18 @@ except Exception as _hub_err:
print(f"[hub_bridge] gate: {_hub_err}")
@app.route("/strategy/trend")
@login_required
def strategy_trend_page():
return render_main_page("strategy_trend")
@app.route("/strategy/roll")
@login_required
def strategy_roll_page():
return render_main_page("strategy_roll")
from strategy_register import install_strategy_trading
install_strategy_trading(app, _REPO_ROOT, app_module=sys.modules[__name__])
+5 -2
View File
@@ -218,8 +218,7 @@
<div class="top-nav">
<a href="/key_monitor" class="{% if page == 'key_monitor' %}active{% endif %}">关键位监控</a>
<a href="/trade" class="{% if page == 'trade' %}active{% endif %}">实盘下单</a>
<a href="/strategy/trend" class="{% if page == 'strategy_trend' %}active{% endif %}">策略·趋势回调</a>
<a href="/strategy/roll" class="{% if page == 'strategy_roll' %}active{% endif %}">策略·顺势加仓</a>
<a href="/strategy/trend" class="{% if page in ('strategy_trend', 'strategy_roll') %}active{% endif %}">策略交易</a>
<a href="/records" class="{% if page == 'records' %}active{% endif %}">交易记录与复盘</a>
<a href="/stats" class="{% if page == 'stats' %}active{% endif %}">统计分析</a>
</div>
@@ -540,6 +539,10 @@
</div>
</div>
{% elif page == 'strategy_trend' %}
{% include 'strategy_trend_disabled_panel.html' %}
{% elif page == 'strategy_roll' %}
{% include 'strategy_roll_panel.html' %}
{% endif %}
+18 -1
View File
@@ -5312,6 +5312,15 @@ def render_main_page(page="trade"):
trend_preview_levels.append({"i": i, "price": pair[0], "contracts": pair[1]})
elif pr:
trend_preview_expired = True
strategy_extra = {}
if page == "strategy_roll":
from strategy_ui import fetch_roll_page_data
strategy_extra = fetch_roll_page_data(
conn,
default_risk_percent=float(RISK_PERCENT),
count_active_trends=lambda c, ta=trend_active: int(ta or 0),
)
conn.close()
return render_template(
"index.html",
@@ -5376,6 +5385,7 @@ def render_main_page(page="trade"):
entry_reason_options=list(ENTRY_REASON_OPTIONS),
entry_reason_other_value=ENTRY_REASON_OTHER,
exchange_display=EXCHANGE_DISPLAY_NAME,
**strategy_extra,
)
@@ -7371,10 +7381,18 @@ except Exception as _hub_err:
print(f"[hub_bridge] gate_bot: {_hub_err}")
@app.route("/strategy/trend")
@login_required
def strategy_trend_page():
return render_main_page("strategy_trend")
@app.route("/strategy/roll")
@login_required
def strategy_roll_page():
return render_main_page("strategy_roll")
from strategy_register import install_strategy_trading
install_strategy_trading(
@@ -7382,7 +7400,6 @@ install_strategy_trading(
_REPO_ROOT,
app_module=sys.modules[__name__],
trend_enabled=True,
render_trend_page=login_required(strategy_trend_page),
)
+4 -2
View File
@@ -205,8 +205,7 @@
</div>
<div class="top-nav">
<a href="/trade" class="{% if page == 'trade' %}active{% endif %}">交易执行</a>
<a href="/strategy/trend" class="{% if page == 'strategy_trend' %}active{% endif %}">策略·趋势回调</a>
<a href="/strategy/roll" class="{% if page == 'strategy_roll' %}active{% endif %}">策略·顺势加仓</a>
<a href="/strategy/trend" class="{% if page in ('strategy_trend', 'strategy_roll') %}active{% endif %}">策略交易</a>
<a href="/records" class="{% if page == 'records' %}active{% endif %}">交易记录与复盘</a>
<a href="/stats" class="{% if page == 'stats' %}active{% endif %}">统计分析</a>
</div>
@@ -372,6 +371,7 @@
</div>
</div>
{% elif page == 'strategy_trend' %}
{% include 'strategy_subnav.html' %}
<div class="card trend-card">
<h2 style="margin-bottom:8px">趋势回调策略</h2>
<div class="rule-tip">
@@ -553,6 +553,8 @@
</div>
</div>
</div>
{% elif page == 'strategy_roll' %}
{% include 'strategy_roll_panel.html' %}
{% endif %}
{% if page == 'records' %}
+20
View File
@@ -4192,6 +4192,13 @@ def render_main_page(page="trade"):
f"自动开仓盈亏比 > {KEY_AUTO_MIN_PLANNED_RR}:1|日成交量排名前 {KEY_DAILY_VOLUME_RANK_MAX}"
f"斐波:添加后立即挂限价 @ E,失效按标记价触达 H/L(未成交撤单)"
)
strategy_extra = {}
if page in ("strategy_trend", "strategy_roll"):
from strategy_ui import strategy_page_template_vars
strategy_extra = strategy_page_template_vars(
conn, page, default_risk_percent=float(RISK_PERCENT)
)
conn.close()
return render_template(
"index.html",
@@ -4242,6 +4249,7 @@ def render_main_page(page="trade"):
entry_reason_other_value=ENTRY_REASON_OTHER,
key_gate_rule_text=key_gate_rule_text,
key_auto_min_planned_rr=KEY_AUTO_MIN_PLANNED_RR,
**strategy_extra,
)
@@ -5950,6 +5958,18 @@ except Exception as _hub_err:
print(f"[hub_bridge] okx: {_hub_err}")
@app.route("/strategy/trend")
@login_required
def strategy_trend_page():
return render_main_page("strategy_trend")
@app.route("/strategy/roll")
@login_required
def strategy_roll_page():
return render_main_page("strategy_roll")
from strategy_register import install_strategy_trading
install_strategy_trading(app, _REPO_ROOT, app_module=sys.modules[__name__])
+5 -2
View File
@@ -154,8 +154,7 @@
<div class="header"><h1>加密货币|交易监控 + AI复盘一体化</h1></div>
<div class="top-nav">
<a href="/trade" class="{% if page == 'trade' %}active{% endif %}">交易执行</a>
<a href="/strategy/trend" class="{% if page == 'strategy_trend' %}active{% endif %}">策略·趋势回调</a>
<a href="/strategy/roll" class="{% if page == 'strategy_roll' %}active{% endif %}">策略·顺势加仓</a>
<a href="/strategy/trend" class="{% if page in ('strategy_trend', 'strategy_roll') %}active{% endif %}">策略交易</a>
<a href="/records" class="{% if page == 'records' %}active{% endif %}">交易记录与复盘</a>
<a href="/stats" class="{% if page == 'stats' %}active{% endif %}">统计分析</a>
</div>
@@ -353,6 +352,10 @@
{% endfor %}
</div>
</div>
{% elif page == 'strategy_trend' %}
{% include 'strategy_trend_disabled_panel.html' %}
{% elif page == 'strategy_roll' %}
{% include 'strategy_roll_panel.html' %}
{% endif %}
{% if page == 'records' %}
+3 -61
View File
@@ -5,7 +5,7 @@ import os
from functools import wraps
from typing import Any, Callable, Optional
from flask import Flask, flash, jsonify, redirect, render_template, request, url_for
from flask import Flask, flash, jsonify, redirect, request, url_for
from jinja2 import ChoiceLoader, FileSystemLoader
from strategy_db import init_strategy_tables
@@ -13,14 +13,12 @@ from strategy_roll_lib import preview_roll
def install_strategy_trading(app: Flask, repo_root: str, app_module: Any = None, **build_kw) -> None:
"""在 app.py 末尾调用(login_required 已定义后)。build_kw 传给 build_strategy_config"""
"""在 app.py 末尾调用(login_required 已定义后)。仅注册 POST API;页面由各 app 的 render_main_page 渲染"""
from strategy_config import build_strategy_config
render_trend_page = build_kw.pop("render_trend_page", None)
build_kw.pop("render_trend_page", None)
attach_strategy_templates(app, repo_root)
cfg = build_strategy_config(app_module, **build_kw)
if render_trend_page is not None:
cfg["render_trend_page"] = render_trend_page
register_strategy_trading(app, cfg)
@@ -43,66 +41,10 @@ def register_strategy_trading(app: Flask, cfg: dict[str, Any]) -> None:
login_required = cfg["login_required"]
get_db = cfg["get_db"]
trend_enabled = bool(cfg.get("trend_enabled"))
render_trend_page = cfg.get("render_trend_page")
def _lr(f):
return login_required(f)
if trend_enabled and callable(render_trend_page):
app.add_url_rule(
"/strategy/trend",
endpoint="strategy_trend_page",
view_func=_lr(render_trend_page),
)
else:
@_lr
@app.route("/strategy/trend")
def strategy_trend_disabled_page():
return render_template(
"strategy_trend_disabled.html",
exchange_display=cfg.get("exchange_display", ""),
trend_note=cfg.get(
"trend_disabled_note",
"趋势回调(自动补仓)当前仅在 Gate 趋势机器人实例中启用。",
),
)
@_lr
@app.route("/strategy/roll")
def strategy_roll_page():
conn = get_db()
init_strategy_tables(conn)
monitors = []
for row in conn.execute(
"SELECT * FROM order_monitors WHERE status='active' ORDER BY id DESC"
).fetchall():
monitors.append(_row_to_dict(row))
roll_groups = []
for row in conn.execute(
"SELECT * FROM roll_groups WHERE status='active' ORDER BY id DESC"
).fetchall():
roll_groups.append(_row_to_dict(row))
legs = []
for row in conn.execute(
"SELECT * FROM roll_legs ORDER BY id DESC LIMIT 50"
).fetchall():
legs.append(_row_to_dict(row))
trend_n = _count_active_trends(conn, cfg)
conn.close()
return render_template(
"strategy_roll.html",
page="strategy_roll",
exchange_display=cfg.get("exchange_display", ""),
monitors=monitors,
roll_groups=roll_groups,
roll_legs=legs,
trend_active=trend_n,
default_risk_percent=cfg.get("default_risk_percent", 2),
price_fmt=cfg.get("price_fmt"),
)
@_lr
@app.route("/strategy/roll/preview", methods=["POST"])
def strategy_roll_preview():
@@ -0,0 +1,75 @@
{% include 'strategy_subnav.html' %}
<div class="card" style="grid-column:1/-1">
<h2 style="margin:0 0 8px">顺势加仓(滚仓)</h2>
<div class="rule-tip">
<strong>仅人工加仓</strong>,程序不会自动触发。须先在「实盘下单」有同向持仓。<br>
做多最多滚仓 <strong>3</strong> 次;止盈<strong>锁定首仓</strong>不变;每次填写<strong>新统一止损</strong>,总风险%按「合并持仓打到新止损≈账户风险」反推张数。<br>
斐波限价:上沿 H、下沿 L 仅用于算 0.618/0.786 加仓价(多:下沿=止损侧;空:上沿=止损侧)。<br>
{% if roll_trend_active %}<span style="color:#ff8f8f">当前有运行中的趋势回调计划,请先结束后再滚仓。</span>{% endif %}
</div>
<form action="{{ url_for('strategy_roll_execute') }}" method="post" class="form-row">
<select name="symbol" required>
<option value="">选择持仓币种</option>
{% for o in roll_monitors %}
<option value="{{ o.symbol }}">{{ o.symbol }} {{ '多' if o.direction=='long' else '空' }} #{{ o.id }}</option>
{% endfor %}
</select>
<select name="direction">
<option value="long">做多</option>
<option value="short">做空</option>
</select>
<select name="add_mode">
<option value="market">市价加仓</option>
<option value="fib_618">限价 斐波0.618</option>
<option value="fib_786">限价 斐波0.786</option>
</select>
<input name="fib_upper" step="any" placeholder="上沿 H">
<input name="fib_lower" step="any" placeholder="下沿 L">
<input name="new_stop_loss" step="any" placeholder="新统一止损" required>
<input name="risk_percent" type="number" min="0.1" step="0.1" value="{{ default_risk_percent }}" placeholder="总风险%">
<button type="submit" {% if roll_trend_active %}disabled style="opacity:.5"{% endif %} onclick="return confirm('确认按预览逻辑实盘加仓并更新止损?')">执行滚仓</button>
</form>
<p class="rule-tip" style="margin-top:8px">执行前可用开发者工具 POST <code>/strategy/roll/preview</code> 查看 JSON 预览。</p>
</div>
<div class="card" style="grid-column:1/-1">
<h3 style="margin:0 0 8px">活跃滚仓组</h3>
<div class="table-wrap">
<table>
<tr><th>ID</th><th>币种</th><th>方向</th><th>腿数</th><th>首仓TP</th><th>当前SL</th></tr>
{% for g in roll_groups %}
<tr>
<td>{{ g.id }}</td>
<td>{{ g.symbol }}</td>
<td>{{ g.direction }}</td>
<td>{{ g.leg_count }}</td>
<td>{% if price_fmt %}{{ price_fmt(g.symbol, g.initial_take_profit) }}{% else %}{{ g.initial_take_profit }}{% endif %}</td>
<td>{% if price_fmt %}{{ price_fmt(g.symbol, g.current_stop_loss) }}{% else %}{{ g.current_stop_loss }}{% endif %}</td>
</tr>
{% else %}
<tr><td colspan="6" style="color:#8892b0">暂无</td></tr>
{% endfor %}
</table>
</div>
</div>
<div class="card" style="grid-column:1/-1">
<h3 style="margin:0 0 8px">最近滚仓腿</h3>
<div class="table-wrap">
<table>
<tr><th>#</th><th></th><th>方式</th><th>张数</th><th>新SL</th><th>状态</th></tr>
{% for leg in roll_legs %}
<tr>
<td>{{ leg.leg_index }}</td>
<td>{{ leg.roll_group_id }}</td>
<td>{{ leg.add_mode }}</td>
<td>{{ leg.amount }}</td>
<td>{{ leg.new_stop_loss }}</td>
<td>{{ leg.status }}</td>
</tr>
{% else %}
<tr><td colspan="6" style="color:#8892b0">暂无</td></tr>
{% endfor %}
</table>
</div>
</div>
+4
View File
@@ -0,0 +1,4 @@
<div class="strategy-subnav" style="display:flex;gap:8px;flex-wrap:wrap;margin:0 0 12px;padding-bottom:8px;border-bottom:1px solid #2a3150">
<a href="/strategy/trend" class="{% if page == 'strategy_trend' %}active{% endif %}" style="padding:6px 12px;border-radius:8px;text-decoration:none;font-size:.85rem;{% if page == 'strategy_trend' %}background:#2a3f6c;color:#dbe4ff;border:1px solid #4a6a9a{% else %}background:#151a2a;color:#8fc8ff;border:1px solid #304164{% endif %}">趋势回调</a>
<a href="/strategy/roll" class="{% if page == 'strategy_roll' %}active{% endif %}" style="padding:6px 12px;border-radius:8px;text-decoration:none;font-size:.85rem;{% if page == 'strategy_roll' %}background:#2a3f6c;color:#dbe4ff;border:1px solid #4a6a9a{% else %}background:#151a2a;color:#8fc8ff;border:1px solid #304164{% endif %}">顺势加仓</a>
</div>
@@ -0,0 +1,13 @@
{% include 'strategy_subnav.html' %}
<div class="card trend-card" style="grid-column:1/-1">
<h2 style="margin-bottom:8px">趋势回调</h2>
<div class="rule-tip">{{ trend_disabled_note }}</div>
<div class="rule-tip" style="margin-top:10px;color:#8892b0">
趋势回调含自动补仓档位与预览执行,仅在 <strong>Gate 趋势机器人</strong><code>crypto_monitor_gate_bot</code>)实例中运行。
请访问该实例同一菜单「策略交易 → 趋势回调」,或常用地址 <code>:5002/strategy/trend</code>
</div>
<p style="margin-top:12px;font-size:.85rem">
<a href="/trade" style="color:#8fc8ff">返回实盘下单</a>
<a href="/strategy/roll" style="color:#8fc8ff">顺势加仓(本实例可用)</a>
</p>
</div>
+88
View File
@@ -0,0 +1,88 @@
"""策略交易页:主站 index.html 所需数据(顺势加仓等)。"""
from __future__ import annotations
from typing import Any, Callable, Optional
from strategy_db import init_strategy_tables
def _row_to_dict(row) -> dict:
if row is None:
return {}
try:
return dict(row)
except Exception:
return {}
def count_active_trend_plans(conn, count_fn: Optional[Callable] = None) -> int:
if callable(count_fn):
return int(count_fn(conn) or 0)
try:
return int(
conn.execute(
"SELECT COUNT(*) FROM trend_pullback_plans WHERE status='active'"
).fetchone()[0]
)
except Exception:
return 0
def fetch_roll_page_data(
conn,
*,
default_risk_percent: float = 2.0,
count_active_trends: Optional[Callable] = None,
) -> dict[str, Any]:
init_strategy_tables(conn)
monitors = []
for row in conn.execute(
"SELECT * FROM order_monitors WHERE status='active' ORDER BY id DESC"
).fetchall():
monitors.append(_row_to_dict(row))
roll_groups = []
for row in conn.execute(
"SELECT * FROM roll_groups WHERE status='active' ORDER BY id DESC"
).fetchall():
roll_groups.append(_row_to_dict(row))
roll_legs = []
for row in conn.execute(
"SELECT * FROM roll_legs ORDER BY id DESC LIMIT 50"
).fetchall():
roll_legs.append(_row_to_dict(row))
return {
"roll_monitors": monitors,
"roll_groups": roll_groups,
"roll_legs": roll_legs,
"roll_trend_active": count_active_trend_plans(conn, count_active_trends),
"default_risk_percent": default_risk_percent,
}
DEFAULT_TREND_DISABLED_NOTE = (
"趋势回调(预览、自动补仓、程序止盈)仅在 Gate 趋势机器人实例 "
"crypto_monitor_gate_bot,常见端口 5002)中启用。"
"币安 / Gate 主站 / OKX 可使用本页「顺势加仓」;完整趋势回调请打开该实例。"
)
def strategy_page_template_vars(
conn,
page: str,
*,
default_risk_percent: float = 2.0,
count_active_trends: Optional[Callable] = None,
trend_disabled_note: str = "",
) -> dict[str, Any]:
"""render_main_page 在 conn.close() 前合并进 render_template 的变量。"""
if page == "strategy_roll":
return fetch_roll_page_data(
conn,
default_risk_percent=default_risk_percent,
count_active_trends=count_active_trends,
)
if page == "strategy_trend":
return {
"trend_disabled_note": trend_disabled_note or DEFAULT_TREND_DISABLED_NOTE,
}
return {}
+14 -9
View File
@@ -1,6 +1,6 @@
# 策略交易说明
本文档说明仓库根目录 **共用策略逻辑** 与四个 `crypto_monitor_*` 实例中的 **策略交易** 入口(导航栏「策略·趋势回调」「策略·顺势加仓)。
本文档说明仓库根目录 **共用策略逻辑** 与四个 `crypto_monitor_*` 实例中的 **策略交易** 入口(栏「策略交易」,页内子 Tab:趋势回调 / 顺势加仓)。
---
@@ -11,9 +11,10 @@ strategy_trend_lib.py # 趋势回调:网格价、补仓拆分、边界校
strategy_roll_lib.py # 顺势加仓:总风险反推、斐波限价、最多 3 腿(纯计算)
strategy_db.py # roll_groups / roll_legs 表结构
strategy_config.py # 各所 app → 统一回调配置(交易所 API)
strategy_register.py # Flask 路由/strategy/trend、/strategy/roll
strategy_register.py # Flask POST/strategy/roll/preview、/strategy/roll/execute
strategy_ui.py # 主站 index 页数据(滚仓组、持仓列表等)
strategy_exchange_*.py # 适配器说明(实际下单仍走各所 app 的 ccxt)
strategy_templates/ # 顺势加仓页、趋势禁用提示页
strategy_templates/ # 主站内嵌 panelsubnav、roll、trend 禁用说明)
```
| 层级 | 职责 |
@@ -28,22 +29,26 @@ strategy_templates/ # 顺势加仓页、趋势禁用提示页
## 二、导航与页面
| 路由 | 名称 | 说明 |
|------|------|------|
| `/strategy/trend` | 趋势回调 | **完整功能仅在 `crypto_monitor_gate_bot`**;其它所显示说明 |
| `/strategy/roll` | 顺势加仓 | **四所均可用**(须已有同向持仓) |
顶栏一项 **「策略交易」**(高亮含 `/strategy/trend``/strategy/roll`),页内子导航切换:
| 路由 | 子 Tab | 说明 |
|------|--------|------|
| `/strategy/trend` | 趋势回调 | **完整功能仅在 `crypto_monitor_gate_bot`**;其它所在主站 `index.html` 内嵌说明(不再跳转独立 HTML) |
| `/strategy/roll` | 顺势加仓 | **四所均可用**(须已有同向持仓),与实盘页同一布局 |
| `/trade` | 实盘下单 | 首仓、以损定仓、移动保本(不变) |
各所 `app.py` 注册 `@app.route("/strategy/trend|roll")``render_main_page(...)``install_strategy_trading` 仅注册滚仓 POST API。
---
## 三、趋势回调(延续 Gate 趋势机器人逻辑)
- **位置**`crypto_monitor_gate_bot`**策略·趋势回调**原「交易执行」页内区块已迁出)。
- **位置**`crypto_monitor_gate_bot`**策略交易 → 趋势回调**与 Gate 主站同一顶栏风格,非独立站点)。
- **行为**:与《[crypto_monitor_gate_bot/趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md)》一致——预览 → 确认执行 → 首仓 50% + 交易所止损 + 多档 **自动** 市价补仓 + 程序监控止盈。
- **共用代码**`parse_and_compute_trend_pullback_plan` 中网格/拆档已改为调用 `strategy_trend_lib`
- **互斥**:与「机器人下单监控」持仓上限、运行中趋势计划互斥(逻辑未改)。
其它三所打开 `/strategy/trend` 会提示:请使用 Gate 趋势机器人实例。
其它三所打开 **策略交易 → 趋势回调** 会在主站内嵌说明:完整功能请使用 Gate 趋势机器人实例(常见 `:5002`
---