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
@@ -1,10 +1,10 @@
<details class="tip-collapse gate-top-tips-collapse">
<summary class="tip-collapse-summary">
实时价格更新<span id="price-last-updated">--</span>北京时间 UTC+8
实时价格更新:<span id="price-last-updated">--</span>(北京时间 UTC+8)
<span class="tip-collapse-hint">· 划转规则</span>
</summary>
<div class="tip-collapse-body rule-tip gate-transfer-tip">
划转自动划转 {{ '开启' if auto_transfer_enabled else '关闭' }}每天<strong>北京时间 {{ auto_transfer_bj_hour }}:00</strong>起该整点小时内尝试账簿按 <strong>UTC 自然日</strong>去重将 {{ auto_transfer_to }} 调整至 {{ transfer_amount_fmt|default(funds_fmt(auto_transfer_amount)) }}U不足从 {{ auto_transfer_from }} 划入超出划回 {{ auto_transfer_from }}<strong>持仓中不划转</strong>并微信通知
划转:自动划转 {{ '开启' if auto_transfer_enabled else '关闭' }}(每天<strong>北京时间 {{ auto_transfer_bj_hour }}:00</strong>起该整点小时内尝试;账簿按 <strong>UTC 自然日</strong>去重;将 {{ auto_transfer_to }} 调整至 {{ transfer_amount_fmt|default(funds_fmt(auto_transfer_amount)) }}U:不足从 {{ auto_transfer_from }} 划入,超出划回 {{ auto_transfer_from }};<strong>持仓中不划转</strong>并微信通知)
</div>
</details>
<form action="/manual_transfer" method="post" class="form-row gate-transfer-form">
+33 -33
View File
@@ -1,33 +1,33 @@
{# 复盘表单首行按字段宽度比例开仓类型与离场触发同一行 #}
{% macro journal_form_fields(entry_reason_options) -%}
<div class="form-grid journal-form-row1">
<input type="datetime-local" name="open_datetime" class="journal-field-datetime" required>
<input type="datetime-local" name="close_datetime" class="journal-field-datetime" required>
<input name="coin" class="journal-field-coin" placeholder="BTC" required>
<input name="tf" class="journal-field-tf" placeholder="5m" required>
<input name="pnl" class="journal-field-num" placeholder="盈亏(U)" required>
<input name="expect_rr" class="journal-field-num" placeholder="预期RR">
<input name="real_rr" class="journal-field-num" placeholder="实际RR">
</div>
<div class="form-grid journal-form-row2">
<select name="entry_reason" id="journal-entry-reason" class="journal-field-entry-reason" required title="日内假破/结构突破/回调触价/突破触价趋势户反转/顺势/波段或策略项">
<option value="">开仓类型必选</option>
{% for er in entry_reason_options %}
<option value="{{ er }}">{{ er }}</option>
{% endfor %}
</select>
<select name="early_exit_trigger" required title="平仓如何触发">
<option value="">离场触发必选</option>
<option value="止盈">止盈</option>
<option value="保本止盈">保本止盈</option>
<option value="移动止盈">移动止盈</option>
<option value="时间平仓">时间平仓</option>
<option value="强制清仓">强制清仓</option>
<option value="手动平仓">手动平仓</option>
<option value="止损">止损</option>
<option value="其他">其他</option>
</select>
<input name="early_exit_note" id="early-exit-note" placeholder="离场补充仅手工平仓必填">
<select name="post_breakeven_stare"><option value="否">保本后盯盘:否</option><option value="是">保本后盯盘:是</option></select>
</div>
{%- endmacro %}
{# 复盘表单:首行按字段宽度比例;开仓类型与离场触发同一行 #}
{% macro journal_form_fields(entry_reason_options) -%}
<div class="form-grid journal-form-row1">
<input type="datetime-local" name="open_datetime" class="journal-field-datetime" required>
<input type="datetime-local" name="close_datetime" class="journal-field-datetime" required>
<input name="coin" class="journal-field-coin" placeholder="BTC" required>
<input name="tf" class="journal-field-tf" placeholder="5m" required>
<input name="pnl" class="journal-field-num" placeholder="盈亏(U)" required>
<input name="expect_rr" class="journal-field-num" placeholder="预期RR">
<input name="real_rr" class="journal-field-num" placeholder="实际RR">
</div>
<div class="form-grid journal-form-row2">
<select name="entry_reason" id="journal-entry-reason" class="journal-field-entry-reason" required title="日内:假破/结构突破/回调触价/突破触价;趋势户:反转/顺势/波段或策略项">
<option value="">开仓类型(必选)</option>
{% for er in entry_reason_options %}
<option value="{{ er }}">{{ er }}</option>
{% endfor %}
</select>
<select name="early_exit_trigger" required title="平仓如何触发">
<option value="">离场触发(必选)</option>
<option value="止盈">止盈</option>
<option value="保本止盈">保本止盈</option>
<option value="移动止盈">移动止盈</option>
<option value="时间平仓">时间平仓</option>
<option value="强制清仓">强制清仓</option>
<option value="手动平仓">手动平仓</option>
<option value="止损">止损</option>
<option value="其他">其他</option>
</select>
<input name="early_exit_note" id="early-exit-note" placeholder="离场补充(仅手工平仓必填)">
<select name="post_breakeven_stare"><option value="否">保本后盯盘:否</option><option value="是">保本后盯盘:是</option></select>
</div>
{%- endmacro %}
@@ -1,20 +1,20 @@
{# 复盘四周期截图槽位须加载 journal_upload_slots.js #}
{% macro journal_upload_slots() -%}
<input type="hidden" name="journal_draft_id" id="journal-draft-id" value="">
<div class="journal-upload-slots" id="journal-upload-slots">
{% for tf in ['5m', '15m', '1h', '4h'] %}
<div class="journal-upload-row" data-tf="{{ tf }}">
<span class="journal-upload-slot-label">{{ tf }}</span>
<input
type="file"
accept="image/*"
class="journal-upload-slot-input"
data-tf="{{ tf }}"
>
<input type="hidden" name="uploaded_screenshot_{{ tf }}" class="journal-upload-hidden-file" data-tf="{{ tf }}" value="">
<span class="journal-upload-status" data-tf="{{ tf }}" aria-live="polite"></span>
</div>
{% endfor %}
</div>
<p class="sub journal-upload-hint">可只传部分周期选文件后即时上传保存后详情页四宫格查看</p>
{%- endmacro %}
{# 复盘四周期截图槽位(须加载 journal_upload_slots.js) #}
{% macro journal_upload_slots() -%}
<input type="hidden" name="journal_draft_id" id="journal-draft-id" value="">
<div class="journal-upload-slots" id="journal-upload-slots">
{% for tf in ['5m', '15m', '1h', '4h'] %}
<div class="journal-upload-row" data-tf="{{ tf }}">
<span class="journal-upload-slot-label">{{ tf }}</span>
<input
type="file"
accept="image/*"
class="journal-upload-slot-input"
data-tf="{{ tf }}"
>
<input type="hidden" name="uploaded_screenshot_{{ tf }}" class="journal-upload-hidden-file" data-tf="{{ tf }}" value="">
<span class="journal-upload-status" data-tf="{{ tf }}" aria-live="polite"></span>
</div>
{% endfor %}
</div>
<p class="sub journal-upload-hint">可只传部分周期;选文件后即时上传,保存后详情页四宫格查看</p>
{%- endmacro %}
+3 -3
View File
@@ -29,9 +29,9 @@
</div>
<div class="row">
<a class="btn" href="/">返回首页</a>
<strong class="focus-title">关键位放大{% if trade_policy.symbol_restrict_enabled %}选择币种{% else %}可输入币种{% endif %}</strong><span class="exchange-tag">{{ exchange_display }}</span>
<strong class="focus-title">关键位放大{% if trade_policy.symbol_restrict_enabled %}(选择币种){% else %}(可输入币种){% endif %}</strong><span class="exchange-tag">{{ exchange_display }}</span>
</div>
<div class="status">最近刷新<span id="updated-at">--</span></div>
<div class="status">最近刷新:<span id="updated-at">--</span></div>
</div>
<div class="row" style="margin-top:10px">
<label>币种</label>
@@ -41,7 +41,7 @@
{{ symbol_live_price_hint('key-focus-symbol-live-price', 'symbol-input') }}
<label>关键位</label>
<select id="key-id">
<option value="">仅看K线</option>
<option value="">(仅看K线)</option>
{% for k in key_list %}
<option value="{{ k.id }}" {% if selected_key and k.id == selected_key.id %}selected{% endif %}>#{{ k.id }} {{ k.symbol }} {{ k.monitor_type }} {{ '做多' if k.direction == 'long' else '做空' }}</option>
{% endfor %}
@@ -150,7 +150,7 @@
<option value="收敛突破">收敛突破</option>
<option value="斐波回调0.618">斐波回调0.618</option>
<option value="斐波回调0.786">斐波回调0.786</option>
<option value="假突破">假突破BTC/ETH</option>
<option value="假突破">假突破(BTC/ETH)</option>
{% endif %}
{% if key_auto_order_enabled|default(false) %}
<option value="回调触价开仓">回调触价开仓</option>
@@ -13,47 +13,47 @@
<tbody>
<tr>
<td class="key-rule-type">箱体突破<br><span class="key-rule-sub">收敛突破</span></td>
<td class="key-rule-cell">方向必选填 H/L<br>方案标准 / 1R·1.5H / 趋势<br>可勾移动保本</td>
<td class="key-rule-cell">{{ r.tf }} 两根闭合 K{{ r.breakout_bar }}/{{ r.confirm_bar }}<br>突破 &gt;{{ r.amp_min_pct }}%确认在箱外<br>&gt;前{{ r.vol_ma_bars }}均×{{ r.vol_ratio_min }}<br>成交 Top{{ r.vol_rank_max }}RR &gt;{{ r.min_rr }}<br>标记价先破反向边界→失效</td>
<td class="key-rule-cell">标准SL 极值外{{ r.stop_outside_pct }}%TP=E±H<br>1RSL=E∓HTP=E∓1.5H<br>趋势SL 极值外{{ r.trend_stop_outside_pct }}%TP 自填</td>
<td class="key-rule-cell">方向必选;填 H/L<br>方案:标准 / 1R·1.5H / 趋势<br>可勾移动保本</td>
<td class="key-rule-cell">{{ r.tf }} 两根闭合 K({{ r.breakout_bar }}/{{ r.confirm_bar }})<br>突破 &gt;{{ r.amp_min_pct }}%;确认在箱外<br>&gt;前{{ r.vol_ma_bars }}均×{{ r.vol_ratio_min }}<br>成交 Top{{ r.vol_rank_max }};RR &gt;{{ r.min_rr }}<br>标记价先破反向边界→失效</td>
<td class="key-rule-cell">标准:SL 极值外{{ r.stop_outside_pct }}%,TP=E±H<br>1R:SL=E∓H,TP=E∓1.5H<br>趋势:SL 极值外{{ r.trend_stop_outside_pct }}%,TP 自填</td>
<td class="key-rule-cell">门控过→市价开仓→下单监控<br>满仓不可再加</td>
</tr>
<tr>
<td class="key-rule-type">斐波回调<br><span class="key-rule-sub">0.618 / 0.786</span></td>
<td class="key-rule-cell">方向 + H/L 波段<br>系统算 E/SL/TP</td>
<td class="key-rule-cell">E=HSL=LTP=H<br>E=L+rΔSL=HTP=L<br>RR &gt;{{ r.min_rr }}先触 TP 侧失效</td>
<td class="key-rule-cell">:E=H,SL=L,TP=H<br>:E=L+rΔ,SL=H,TP=L<br>RR &gt;{{ r.min_rr }};先触 TP 侧失效</td>
<td class="key-rule-cell">公式固定 SL/TP<br>成交后挂所</td>
<td class="key-rule-cell">挂限价等成交<br>成交→下单监控</td>
</tr>
<tr>
<td class="key-rule-type">假突破<br><span class="key-rule-sub">BTC / ETH</span></td>
<td class="key-rule-cell">空填高点 / 多填低点<br>同币仅 1 条</td>
<td class="key-rule-cell">外侧 {{ r.fb_offset_pct }}% 限价<br>SL {{ r.fb_sl_pct }}%RR {{ r.fb_rr }}<br>有效 {{ r.fb_valid_hours }}h</td>
<td class="key-rule-cell">外侧 {{ r.fb_offset_pct }}% 限价<br>SL {{ r.fb_sl_pct }}%;RR {{ r.fb_rr }}<br>有效 {{ r.fb_valid_hours }}h</td>
<td class="key-rule-cell">自动 E/SL/TP<br>可保本</td>
<td class="key-rule-cell">即挂限价<br>成交/过期→历史</td>
</tr>
<tr>
<td class="key-rule-type">回调触价开仓</td>
<td class="key-rule-cell">方向 + 入场 E / 止损 SL / 止盈 TP<br>可勾移动保本时间平仓</td>
<td class="key-rule-cell">RR &gt;{{ r.min_rr }}做多 SL&lt;E&lt;TP<br>标记价回调触 E多≤E / 空≥E后下一轮询市价开<br>先触 TP 侧失效有效 {{ r.trigger_entry_validity_hours }}h</td>
<td class="key-rule-cell">程序盯价无交易所挂单<br>成交后挂所 TP/SL → 下单监控</td>
<td class="key-rule-cell">方向 + 入场 E / 止损 SL / 止盈 TP<br>可勾移动保本,时间平仓</td>
<td class="key-rule-cell">RR &gt;{{ r.min_rr }};做多 SL&lt;E&lt;TP<br>标记价回调触 E(多≤E / 空≥E)后下一轮询市价开<br>先触 TP 侧失效;有效 {{ r.trigger_entry_validity_hours }}h</td>
<td class="key-rule-cell">程序盯价,无交易所挂单<br>成交后挂所 TP/SL → 下单监控</td>
<td class="key-rule-cell">占当日开仓意图<br>全仓模式可用</td>
</tr>
<tr>
<td class="key-rule-type">突破触价开仓</td>
<td class="key-rule-cell">方向 + 突破价 E / 止损 SL / 止盈 TP<br>可勾移动保本时间平仓</td>
<td class="key-rule-cell">RR &gt;{{ r.min_rr }}做多 SL&lt;E&lt;TP<br>标记价<strong>穿越</strong> E 立即市价开多向上 / 空向下<br>先触 TP 或 SL 侧失效有效 {{ r.trigger_entry_validity_hours }}h</td>
<td class="key-rule-cell">程序盯价无交易所挂单<br>成交后挂所 TP/SL → 下单监控</td>
<td class="key-rule-cell">方向 + 突破价 E / 止损 SL / 止盈 TP<br>可勾移动保本,时间平仓</td>
<td class="key-rule-cell">RR &gt;{{ r.min_rr }};做多 SL&lt;E&lt;TP<br>标记价<strong>穿越</strong> E 立即市价开(多向上 / 空向下)<br>先触 TP 或 SL 侧失效;有效 {{ r.trigger_entry_validity_hours }}h</td>
<td class="key-rule-cell">程序盯价,无交易所挂单<br>成交后挂所 TP/SL → 下单监控</td>
<td class="key-rule-cell">占当日开仓意图<br>全仓模式可用</td>
</tr>
<tr>
<td class="key-rule-type">关键支撑阻力</td>
<td class="key-rule-cell">双向填上/下沿</td>
<td class="key-rule-cell">双向;填上/下沿</td>
<td class="key-rule-cell">{{ r.tf }} 收盘破上沿或下沿<br>上沿优先</td>
<td class="key-rule-cell">仅提醒</td>
<td class="key-rule-cell">(仅提醒)</td>
<td class="key-rule-cell">微信 ≤{{ r.alert_max }} 次<br>间隔 ≥{{ r.alert_interval_min }} 分</td>
</tr>
</tbody>
</table>
</div>
<p class="key-rule-foot">阈值来自 <code>.env</code>修改后重启实例</p>
<p class="key-rule-foot">阈值来自 <code>.env</code>,修改后重启实例.</p>
+3 -3
View File
@@ -25,9 +25,9 @@
</div>
<div class="row">
<a class="btn" href="/">返回首页</a>
<strong class="focus-title">实盘下单放大100根K线</strong><span class="exchange-tag">{{ exchange_display }}</span>
<strong class="focus-title">实盘下单放大(100根K线)</strong><span class="exchange-tag">{{ exchange_display }}</span>
</div>
<div class="status">最近刷新<span id="updated-at">--</span></div>
<div class="status">最近刷新:<span id="updated-at">--</span></div>
</div>
{% if orders %}
<div class="row" style="margin-top:10px">
@@ -49,7 +49,7 @@
<span id="load-status" class="status"></span>
</div>
{% else %}
<div class="empty">当前没有激活订单无法展示放大K线</div>
<div class="empty">当前没有激活订单,无法展示放大K线.</div>
{% endif %}
</div>
@@ -1,21 +1,21 @@
<details class="tip-collapse order-rule-collapse">
<summary class="tip-collapse-summary">开仓规则说明</summary>
<div class="tip-collapse-body rule-tip" id="order-rule-tip">
规则最多 {{ max_active_positions }} 仓BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓持仓已满单日开仓达上限或未到北京时间 {{ reset_hour }}:00{% endif %}
规则:最多 {{ max_active_positions }} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x;
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}(AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓(持仓已满,单日开仓达上限,或未到北京时间 {{ reset_hour }}:00){% endif %};
人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1
</div>
</details>
<details class="tip-collapse order-sizing-collapse">
<summary class="tip-collapse-summary">计仓与保本说明</summary>
<div class="tip-collapse-body rule-tip">
计仓模式<strong>{{ position_sizing_mode_label }}</strong>仅 .env <code>POSITION_SIZING_MODE</code>须无仓后重启
计仓模式:<strong>{{ position_sizing_mode_label }}</strong>(仅 .env <code>POSITION_SIZING_MODE</code>,须无仓后重启)
{% if position_sizing_mode == 'full_margin' %}
|全仓合约可用×{{ full_margin_buffer_ratio }}BTC/ETH {{ btc_leverage }}x其它 {{ alt_leverage }}x单仓张数按交易所精度
|全仓:合约可用×{{ full_margin_buffer_ratio }},BTC/ETH {{ btc_leverage }}x,其它 {{ alt_leverage }}x,单仓;张数按交易所精度
{% else %}
|以损定仓风险 {{ risk_percent }}%
|以损定仓:风险 {{ risk_percent }}%
{% endif %}
|移动保本下单可勾选关闭开启时 {{ breakeven_rr_trigger }}R 触发每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
|移动保本:下单可勾选关闭;开启时 {{ breakeven_rr_trigger }}R 触发(每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
</div>
</details>
@@ -1,21 +1,21 @@
<details class="tip-collapse order-rule-collapse">
<summary class="tip-collapse-summary">开仓规则说明</summary>
<div class="tip-collapse-body rule-tip" id="order-rule-tip">
规则最多 {{ max_active_positions }} 仓BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓持仓已满单日开仓达上限或未到北京时间 {{ reset_hour }}:00{% endif %}
规则:最多 {{ max_active_positions }} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x;
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}(AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓(持仓已满,单日开仓达上限,或未到北京时间 {{ reset_hour }}:00){% endif %};
人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1
</div>
</details>
<details class="tip-collapse order-sizing-collapse">
<summary class="tip-collapse-summary">计仓与保本说明</summary>
<div class="tip-collapse-body rule-tip">
计仓模式<strong>{{ position_sizing_mode_label }}</strong>仅 .env <code>POSITION_SIZING_MODE</code>须无仓后重启
计仓模式:<strong>{{ position_sizing_mode_label }}</strong>(仅 .env <code>POSITION_SIZING_MODE</code>,须无仓后重启)
{% if position_sizing_mode == 'full_margin' %}
|全仓合约可用×{{ full_margin_buffer_ratio }}BTC/ETH {{ btc_leverage }}x其它 {{ alt_leverage }}x单仓张数按交易所精度
|全仓:合约可用×{{ full_margin_buffer_ratio }},BTC/ETH {{ btc_leverage }}x,其它 {{ alt_leverage }}x,单仓;张数按交易所精度
{% else %}
|以损定仓风险 {{ risk_percent }}%
|以损定仓:风险 {{ risk_percent }}%
{% endif %}
|移动保本下单可勾选关闭开启时 {{ breakeven_rr_trigger }}R 触发每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
|移动保本:下单可勾选关闭;开启时 {{ breakeven_rr_trigger }}R 触发(每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
</div>
</details>
@@ -1,21 +1,21 @@
<details class="tip-collapse order-rule-collapse">
<summary class="tip-collapse-summary">开仓规则说明</summary>
<div class="tip-collapse-body rule-tip" id="order-rule-tip">
规则最大同时持仓 {{ max_active_positions }}当前 active {{ active_count }});与「趋势回调」计划互斥BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓持仓达上限单日开仓达上限有趋势回调计划或未到北京时间 {{ reset_hour }}:00{% endif %}
规则:最大同时持仓 {{ max_active_positions }}(当前 active {{ active_count }});与「趋势回调」计划互斥;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x;
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}(AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓(持仓达上限,单日开仓达上限,有趋势回调计划,或未到北京时间 {{ reset_hour }}:00){% endif %};
人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1
</div>
</details>
<details class="tip-collapse order-sizing-collapse">
<summary class="tip-collapse-summary">计仓与保本说明</summary>
<div class="tip-collapse-body rule-tip">
计仓模式<strong>{{ position_sizing_mode_label }}</strong>仅 .env <code>POSITION_SIZING_MODE</code>须无仓后重启
计仓模式:<strong>{{ position_sizing_mode_label }}</strong>(仅 .env <code>POSITION_SIZING_MODE</code>,须无仓后重启)
{% if position_sizing_mode == 'full_margin' %}
|全仓合约可用×{{ full_margin_buffer_ratio }}BTC/ETH {{ btc_leverage }}x其它 {{ alt_leverage }}x单仓张数按交易所精度
|全仓:合约可用×{{ full_margin_buffer_ratio }},BTC/ETH {{ btc_leverage }}x,其它 {{ alt_leverage }}x,单仓;张数按交易所精度
{% else %}
|以损定仓风险 {{ risk_percent }}%
|以损定仓:风险 {{ risk_percent }}%
{% endif %}
|移动保本下单可勾选关闭开启时 {{ breakeven_rr_trigger }}R 触发每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
|移动保本:下单可勾选关闭;开启时 {{ breakeven_rr_trigger }}R 触发(每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
</div>
</details>
@@ -1,21 +1,21 @@
<details class="tip-collapse order-rule-collapse">
<summary class="tip-collapse-summary">开仓规则说明</summary>
<div class="tip-collapse-body rule-tip" id="order-rule-tip">
规则最多 {{ max_active_positions }} 仓BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓{% if active_count >= max_active_positions %}持仓 {{ active_count }}/{{ max_active_positions }}{% endif %}{% if daily_open_hard_limit > 0 and opens_today >= daily_open_hard_limit %}单日开仓达上限{% endif %}{% if open_guard_blocks_now %}未到北京时间 {{ reset_hour }}:00{% endif %}{% endif %}
规则:最多 {{ max_active_positions }} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x;
本交易日开仓 {{ opens_today }}{% if daily_open_hard_limit > 0 %} / 硬上限 {{ daily_open_hard_limit }}{% endif %}(AI 提醒 {{ daily_open_alert_threshold }});
{% if can_trade %}可开仓{% else %}不可开仓{% if active_count >= max_active_positions %}(持仓 {{ active_count }}/{{ max_active_positions }}){% endif %}{% if daily_open_hard_limit > 0 and opens_today >= daily_open_hard_limit %}(单日开仓达上限){% endif %}{% if open_guard_blocks_now %}(未到北京时间 {{ reset_hour }}:00){% endif %}{% endif %};
人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1
</div>
</details>
<details class="tip-collapse order-sizing-collapse">
<summary class="tip-collapse-summary">计仓与保本说明</summary>
<div class="tip-collapse-body rule-tip">
计仓模式<strong>{{ position_sizing_mode_label }}</strong>仅 .env <code>POSITION_SIZING_MODE</code>须无仓后重启
计仓模式:<strong>{{ position_sizing_mode_label }}</strong>(仅 .env <code>POSITION_SIZING_MODE</code>,须无仓后重启)
{% if position_sizing_mode == 'full_margin' %}
|全仓合约可用×{{ full_margin_buffer_ratio }}BTC/ETH {{ btc_leverage }}x其它 {{ alt_leverage }}x单仓张数按交易所精度
|全仓:合约可用×{{ full_margin_buffer_ratio }},BTC/ETH {{ btc_leverage }}x,其它 {{ alt_leverage }}x,单仓;张数按交易所精度
{% else %}
|以损定仓风险 {{ risk_percent }}%
|以损定仓:风险 {{ risk_percent }}%
{% endif %}
|移动保本下单可勾选关闭开启时 {{ breakeven_rr_trigger }}R 触发每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
|移动保本:下单可勾选关闭;开启时 {{ breakeven_rr_trigger }}R 触发(每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
</div>
</details>
@@ -1,5 +1,5 @@
<div id="order-plan-preview" class="order-plan-preview">
<span id="order-risk-preview" class="order-preview-risk">预估风险<strong></strong></span>
<span id="order-profit-preview" class="order-preview-profit">预估盈利<strong></strong></span>
<span id="order-rr-preview" class="order-preview-rr">预估盈亏比<strong></strong></span>
<span id="order-risk-preview" class="order-preview-risk">预估风险:<strong></strong></span>
<span id="order-profit-preview" class="order-preview-profit">预估盈利:<strong></strong></span>
<span id="order-rr-preview" class="order-preview-rr">预估盈亏比:<strong></strong></span>
</div>
@@ -51,8 +51,8 @@
<div class="strategy-records-page card full">
<h2>策略交易记录</h2>
<p class="strategy-records-tip">
数据库保留最近 <strong>{{ strategy_records_limit|default(100) }}</strong> 条结束快照按结束时间排序)。
趋势回调与顺势加仓分栏展示点击行展开详情结束计划保本移交止盈止损会自动写入
数据库保留最近 <strong>{{ strategy_records_limit|default(100) }}</strong> 条结束快照(按结束时间排序).
趋势回调与顺势加仓分栏展示;点击行展开详情.结束计划,保本移交,止盈止损会自动写入.
</p>
<div class="sr-filters" id="sr-filters">
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="zh-CN" data-theme="dark">
<head>
<meta charset="UTF-8">
@@ -3,18 +3,18 @@
<details class="tip-collapse strategy-roll-rule-collapse" open>
<summary class="tip-collapse-summary">顺势加仓规则说明{% if roll_trend_active %} · 当前有趋势回调计划{% endif %}</summary>
<div class="tip-collapse-body rule-tip">
<strong>仅人工提交</strong>须先在「实盘下单」有同向持仓<strong>以损定仓</strong>模式可用<br>
做多/做空各最多滚仓 <strong>3</strong>仅计已成交腿);止盈<strong>锁定首仓</strong>不变<br>
风险比例读取所选监控单<strong>不可手改</strong>打到新止损时合并持仓亏损 ≈ 1 个风险单位当前基数 × 监控 risk%)。<br>
斐波/突破为<strong>程序监控</strong>交易所 mark 价),触价后市价加仓填写后直接点「执行滚仓」无需预览)。同时仅允许 <strong>1</strong> 条监控中腿提交后<strong>不可修改</strong>可删除<br>
手动平仓后滚仓监控自动结束<strong>已成交腿历史保留</strong>供复盘<br>
<strong>仅人工提交</strong>;须先在「实盘下单」有同向持仓.<strong>以损定仓</strong>模式可用.<br>
做多/做空各最多滚仓 <strong>3</strong>(仅计已成交腿);止盈<strong>锁定首仓</strong>不变.<br>
风险比例读取所选监控单,<strong>不可手改</strong>;打到新止损时合并持仓亏损 ≈ 1 个风险单位(当前基数 × 监控 risk%).<br>
斐波/突破为<strong>程序监控</strong>(交易所 mark 价),触价后市价加仓;填写后直接点「执行滚仓」(无需预览).同时仅允许 <strong>1</strong> 条监控中腿,提交后<strong>不可修改</strong>,可删除.<br>
手动平仓后滚仓监控自动结束;<strong>已成交腿历史保留</strong>供复盘.<br>
<a href="/strategy/roll/docs" target="_blank" rel="noopener" class="roll-doc-link">→ 顺势加仓完整逻辑说明</a><br>
{% if roll_trend_active %}<span style="color:#ff8f8f">当前有运行中的趋势回调计划请先结束后再滚仓</span>{% endif %}
{% if roll_trend_active %}<span style="color:#ff8f8f">当前有运行中的趋势回调计划,请先结束后再滚仓.</span>{% endif %}
</div>
</details>
<div id="roll-risk-banner" class="rule-tip roll-risk-banner">
当前风险请选择持仓币种
当前风险:请选择持仓币种
</div>
<form id="roll-form" action="{{ url_for('strategy_roll_execute') }}" method="post" class="form-row" data-add-mode="market">
@@ -92,7 +92,7 @@
<td>{{ leg.status_label or leg.status }}</td>
<td>
{% if leg.status == 'pending' %}
<form action="{{ url_for('strategy_roll_cancel_leg', leg_id=leg.id) }}" method="post" style="margin:0" onsubmit="return confirm('确认删除本条滚仓监控')">
<form action="{{ url_for('strategy_roll_cancel_leg', leg_id=leg.id) }}" method="post" style="margin:0" onsubmit="return confirm('确认删除本条滚仓监控?')">
<button type="submit" style="padding:2px 8px;font-size:.75rem">删除</button>
</form>
{% else %}—{% endif %}
@@ -14,7 +14,7 @@
<div class="box">
<h1>趋势回调</h1>
<p>{{ trend_note }}</p>
<p style="color:#8892b0;font-size:.9rem">趋势回调含自动补仓档位在三所实例Binance / Gate / OKX中均可启用须配置 LIVE_TRADING_ENABLED=true</p>
<p style="color:#8892b0;font-size:.9rem">趋势回调含自动补仓档位,在三所实例(Binance / Gate / OKX)中均可启用,须配置 LIVE_TRADING_ENABLED=true.</p>
</div>
</body>
</html>
@@ -2,15 +2,15 @@
<div class="card trend-card" style="grid-column:1/-1">
<h2 style="margin-bottom:8px">趋势回调</h2>
<details class="tip-collapse strategy-trend-disabled-collapse">
<summary class="tip-collapse-summary">趋势回调说明本实例未启用</summary>
<summary class="tip-collapse-summary">趋势回调说明(本实例未启用)</summary>
<div class="tip-collapse-body rule-tip">
{{ trend_disabled_note }}<br><br>
趋势回调含自动补仓档位与预览执行<strong>Binance / Gate / OKX</strong> 各实例的「策略交易 → 趋势回调」中运行
请访问对应实例同一菜单或常用地址如 Gate <code>:5000/strategy/trend</code>
趋势回调含自动补仓档位与预览执行,<strong>Binance / Gate / OKX</strong> 各实例的「策略交易 → 趋势回调」中运行.
请访问对应实例同一菜单,或常用地址如 Gate <code>:5000/strategy/trend</code>.
</div>
</details>
<p style="margin-top:12px;font-size:.85rem">
<a href="/trade" style="color:#8fc8ff">返回实盘下单</a>
<a href="/strategy/roll" style="color:#8fc8ff">顺势加仓本实例可用</a>
<a href="/strategy/roll" style="color:#8fc8ff">顺势加仓(本实例可用)</a>
</p>
</div>
@@ -5,19 +5,19 @@
<details class="tip-collapse strategy-trend-rule-collapse">
<summary class="tip-collapse-summary">趋势回调规则说明</summary>
<div class="tip-collapse-body rule-tip">
<strong>生成预览</strong>读取合约 USDT <strong>可用余额快照</strong>并计算计划不下单)。预览有效期 <strong>{{ trend_pullback_preview_ttl }} 秒</strong><br>
<strong>确认执行</strong>市价首仓 50% + 挂交易所止损首仓后可<strong>手动保本</strong>默认均价+{{ trend_manual_breakeven_offset_pct }}%);剩余 50% 在止损与补仓区间之间共 {{ trend_pullback_dca_legs }} 档做多为<strong>上沿</strong>做空为<strong>下沿</strong>程序可能因最小张数自动减档市价补仓<strong>止盈由程序监控</strong><br>
确认执行时若当前可用余额与预览快照相对偏差 &gt; <strong>{{ trend_preview_max_drift_pct }}%</strong> 会拒绝并要求重新预览
<strong>生成预览</strong>:读取合约 USDT <strong>可用余额快照</strong>并计算计划(不下单).预览有效期 <strong>{{ trend_pullback_preview_ttl }} 秒</strong>.<br>
<strong>确认执行</strong>:市价首仓 50% + 挂交易所止损;首仓后可<strong>手动保本</strong>(默认均价+{{ trend_manual_breakeven_offset_pct }}%);剩余 50% 在止损与补仓区间之间共 {{ trend_pullback_dca_legs }} 档(做多为<strong>上沿</strong>,做空为<strong>下沿</strong>;程序可能因最小张数自动减档)市价补仓;<strong>止盈由程序监控</strong>.<br>
确认执行时若当前可用余额与预览快照相对偏差 &gt; <strong>{{ trend_preview_max_drift_pct }}%</strong> 会拒绝并要求重新预览.
</div>
</details>
{% if trend_dca_probes %}
{% for p in trend_dca_probes %}
{% if p.trigger_reached and p.block_reason %}
<div class="rule-tip" style="margin-bottom:10px;border-color:#a55;background:#2a1818;color:#ffb4b4">
<strong>计划 #{{ p.plan_id }}</strong> 标记价 {{ p.mark_price }} 已触达补仓触发价 {{ p.next_trigger }}但未自动补仓
{{ p.block_reason }}
<strong>计划 #{{ p.plan_id }}</strong> 标记价 {{ p.mark_price }} 已触达补仓触发价 {{ p.next_trigger }},但未自动补仓:
{{ p.block_reason }}.
{% if not live_trading_enabled %}
请在当前实例 <code>.env</code> 设置 <code>LIVE_TRADING_ENABLED=true</code> 后重启对应 PM2 进程<strong>crypto_gate</strong><strong>crypto_okx</strong><strong>crypto_binance</strong>)。
请在当前实例 <code>.env</code> 设置 <code>LIVE_TRADING_ENABLED=true</code> 后重启对应 PM2 进程(<strong>crypto_gate</strong>,<strong>crypto_okx</strong>,<strong>crypto_binance</strong>).
{% endif %}
</div>
{% endif %}
@@ -30,7 +30,7 @@
{% from 'symbol_live_price_snippet.html' import symbol_live_price_hint %}
{{ symbol_live_price_hint('trend-symbol-live-price', 'trend-symbol', 'trend-direction') }}
<input name="leverage" type="number" min="1" step="1" placeholder="杠杆(必填)" required>
<input name="risk_percent" type="number" min="0.1" step="0.1" value="5" placeholder="风险%相对可用快照" title="默认5最坏亏损约≤可用余额×5%">
<input name="risk_percent" type="number" min="0.1" step="0.1" value="5" placeholder="风险%相对可用快照" title="默认5:最坏亏损约≤可用余额×5%">
<input name="sl" step="any" placeholder="止损价" required>
<input name="add_upper" id="trend-add-upper" step="any" placeholder="补仓上沿价" required>
<input name="take_profit" step="any" placeholder="止盈价(固定)" required>
@@ -55,14 +55,14 @@
{% if trend_preview %}
<div style="margin-top:14px;padding:12px;background:#141a2e;border:1px solid #2a3150;border-radius:8px">
<div style="display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;margin-bottom:8px">
<strong style="color:#dbe4ff">当前预览剩余 <span id="trend-preview-ttl">{{ trend_pullback_preview_ttl }}</span>s</strong>
<strong style="color:#dbe4ff">当前预览(剩余 <span id="trend-preview-ttl">{{ trend_pullback_preview_ttl }}</span>s)</strong>
<span style="font-size:.8rem;color:#9aa" data-expires-ms="{{ preview_expires_ms }}">倒计时加载中…</span>
</div>
<div style="font-size:.82rem;color:#cfd3ef;line-height:1.55;margin-bottom:10px">
{{ trend_preview.symbol }} {{ '做多' if trend_preview.direction == 'long' else '做空' }} {{ trend_preview.leverage }}x
预览可用快照 <strong>{{ mf(trend_preview.snapshot_available_usdt) }}</strong> U 参考价 {{ price_fmt(trend_preview.symbol, trend_preview.live_price_ref) }}
计划保证金≈{{ mf(trend_preview.plan_margin_capital) }} U 总张≈{{ amt_disp(trend_preview.symbol, trend_preview.target_order_amount) }}首仓 {{ amt_disp(trend_preview.symbol, trend_preview.first_order_amount) }} + 补仓 {{ amt_disp(trend_preview.symbol, trend_preview.remainder_total) }}<br>
止损价 {{ price_fmt(trend_preview.symbol, trend_preview.preview_unified_stop_loss or trend_preview.stop_loss) }} 止损金额 {% if trend_preview.preview_risk_amount_u is not none %}{{ mf(trend_preview.preview_risk_amount_u) }}U{% else %}—{% endif %}快照×风险{{ trend_preview.risk_percent }}% {{ trend_add_zone_label(trend_preview.direction) }} {{ price_fmt(trend_preview.symbol, trend_preview.add_upper) }} 止盈价 {{ price_fmt(trend_preview.symbol, trend_preview.take_profit) }} 首仓盈亏比 {% if trend_preview.preview_target_rr is not none %}{{ '%.2f'|format(trend_preview.preview_target_rr) }}{% else %}—{% endif %}
计划保证金≈{{ mf(trend_preview.plan_margin_capital) }} U 总张≈{{ amt_disp(trend_preview.symbol, trend_preview.target_order_amount) }}(首仓 {{ amt_disp(trend_preview.symbol, trend_preview.first_order_amount) }} + 补仓 {{ amt_disp(trend_preview.symbol, trend_preview.remainder_total) }})<br>
止损价 {{ price_fmt(trend_preview.symbol, trend_preview.preview_unified_stop_loss or trend_preview.stop_loss) }} 止损金额 {% if trend_preview.preview_risk_amount_u is not none %}{{ mf(trend_preview.preview_risk_amount_u) }}U{% else %}—{% endif %}(快照×风险{{ trend_preview.risk_percent }}%) {{ trend_add_zone_label(trend_preview.direction) }} {{ price_fmt(trend_preview.symbol, trend_preview.add_upper) }} 止盈价 {{ price_fmt(trend_preview.symbol, trend_preview.take_profit) }} 首仓盈亏比 {% if trend_preview.preview_target_rr is not none %}{{ '%.2f'|format(trend_preview.preview_target_rr) }}{% else %}—{% endif %}
</div>
<div class="table-wrap" style="margin-bottom:10px">
<table>
@@ -83,7 +83,7 @@
<div class="form-row" style="gap:10px;align-items:center">
<form action="{{ url_for('execute_trend_pullback') }}" method="post" style="display:inline">
<input type="hidden" name="preview_id" value="{{ trend_preview.id }}">
<button type="submit" onclick="return confirm('确认按预览参数实盘下单')">确认执行实盘</button>
<button type="submit" onclick="return confirm('确认按预览参数实盘下单?')">确认执行(实盘)</button>
</form>
<form action="{{ url_for('cancel_trend_pullback_preview') }}" method="post" style="display:inline">
<input type="hidden" name="preview_id" value="{{ trend_preview.id }}">
@@ -98,7 +98,7 @@
const exp = parseInt(el.getAttribute("data-expires-ms")||"0",10);
function tick(){
const left = Math.max(0, Math.floor((exp - Date.now()) / 1000));
el.innerText = left > 0 ? ("剩余 " + left + " 秒") : "已过期请重新生成预览";
el.innerText = left > 0 ? ("剩余 " + left + " 秒") : "已过期,请重新生成预览";
const span = document.getElementById("trend-preview-ttl");
if(span) span.innerText = String(left);
if(left <= 0) return;
@@ -108,7 +108,7 @@
})();
</script>
{% elif trend_preview_expired %}
<div class="rule-tip" style="margin-top:12px;color:#ff8f8f">该预览已过期超过 {{ trend_pullback_preview_ttl }} 秒),请重新点击「生成预览」</div>
<div class="rule-tip" style="margin-top:12px;color:#ff8f8f">该预览已过期(超过 {{ trend_pullback_preview_ttl }} 秒),请重新点击「生成预览」.</div>
{% endif %}
<div class="trend-running-plans">
@@ -126,7 +126,7 @@
<span>#{{ t.id }} {{ sym }}</span>
<span class="badge {{ 'direction-long' if t.direction == 'long' else 'direction-short' }}">{{ '做多' if t.direction == 'long' else '做空' }}</span>
</div>
<a href="/stop_trend_pullback/{{ t.id }}" class="btn-close-plan" onclick="return confirm('结束计划市价平仓并撤掉该合约全部挂单确定')">结束计划</a>
<a href="/stop_trend_pullback/{{ t.id }}" class="btn-close-plan" onclick="return confirm('结束计划:市价平仓并撤掉该合约全部挂单,确定?')">结束计划</a>
</div>
<div class="plan-card-meta">
来源: 趋势回调计划 风险: {% if t.risk_percent is not none %}{{ t.risk_percent }}%{% else %}—{% endif %}
@@ -184,7 +184,7 @@
</div>
{% endif %}
<div class="plan-card-meta" style="margin-top:8px">
<form action="{{ url_for('trend_pullback_breakeven', pid=t.id) }}" method="post" class="form-row" style="margin:0;align-items:center" onsubmit="return confirm('确认保本将结束本趋势计划持仓移交「下单监控」备注趋势回调计划),并在交易所同时挂保本止损与计划止盈后续平仓会写入交易记录');">
<form action="{{ url_for('trend_pullback_breakeven', pid=t.id) }}" method="post" class="form-row" style="margin:0;align-items:center" onsubmit="return confirm('确认保本?将结束本趋势计划,持仓移交「下单监控」(备注趋势回调计划),并在交易所同时挂保本止损与计划止盈;后续平仓会写入交易记录.');">
<label style="font-size:.78rem;color:#cfd3ef;display:flex;align-items:center;gap:6px">
保本移交 偏移%
<input name="breakeven_offset_pct" type="number" min="0" step="0.01" value="{{ trend_manual_breakeven_offset_pct }}" style="width:72px;padding:4px 8px">
@@ -1,10 +1,10 @@
{# 币种输入旁实时现价须加载 symbol_live_price.js #}
{% macro symbol_live_price_hint(price_id, symbol_input_id, direction_input_id='') -%}
<span
id="{{ price_id }}"
class="symbol-live-price"
data-symbol-input="{{ symbol_input_id }}"
{% if direction_input_id %}data-direction-input="{{ direction_input_id }}"{% endif %}
aria-live="polite"
>现价</span>
{%- endmacro %}
{# 币种输入旁实时现价(须加载 symbol_live_price.js) #}
{% macro symbol_live_price_hint(price_id, symbol_input_id, direction_input_id='') -%}
<span
id="{{ price_id }}"
class="symbol-live-price"
data-symbol-input="{{ symbol_input_id }}"
{% if direction_input_id %}data-direction-input="{{ direction_input_id }}"{% endif %}
aria-live="polite"
>现价:</span>
{%- endmacro %}
+32 -32
View File
@@ -1,32 +1,32 @@
{# 方向 / 币种env 账户级限制三所共用宏);调用方须 with context #}
{% if trade_policy is not defined %}
{% set trade_policy = {'symbol_restrict_enabled': false, 'direction_restrict_enabled': false, 'symbol_whitelist': [], 'allows_long': true, 'allows_short': true, 'direction_mode': 'both', 'badge_text': ''} %}
{% endif %}
{% macro trade_policy_symbol(name, id, value='', required=true, placeholder='BTC 或 BTC/USDT') -%}
{% if trade_policy.symbol_restrict_enabled and trade_policy.symbol_whitelist %}
<select name="{{ name }}" id="{{ id }}" {% if required %}required{% endif %} class="trade-policy-symbol-select">
<option value="">选择币种</option>
{% for sym in trade_policy.symbol_whitelist %}
<option value="{{ sym }}" {% if value and (value|upper == sym or value|upper.startswith(sym ~ '/')) %}selected{% endif %}>{{ sym }}/USDT</option>
{% endfor %}
</select>
{% else %}
<input id="{{ id }}" name="{{ name }}" placeholder="{{ placeholder }}" {% if required %}required{% endif %} value="{{ value }}">
{% endif %}
{%- endmacro %}
{% macro trade_policy_direction(name, id, required=true, include_empty=true) -%}
{% if trade_policy.direction_restrict_enabled and trade_policy.direction_mode == 'long_only' %}
<span class="trade-policy-dir-lock" title="账户配置仅做多">做多</span>
<input type="hidden" name="{{ name }}" id="{{ id }}" value="long">
{% elif trade_policy.direction_restrict_enabled and trade_policy.direction_mode == 'short_only' %}
<span class="trade-policy-dir-lock" title="账户配置仅做空">做空</span>
<input type="hidden" name="{{ name }}" id="{{ id }}" value="short">
{% else %}
<select name="{{ name }}" id="{{ id }}" {% if required %}required{% endif %}>
{% if include_empty %}<option value="">方向</option>{% endif %}
{% if trade_policy.allows_long %}<option value="long">做多</option>{% endif %}
{% if trade_policy.allows_short %}<option value="short">做空</option>{% endif %}
</select>
{% endif %}
{%- endmacro %}
{# 方向 / 币种:env 账户级限制(三所共用宏);调用方须 with context #}
{% if trade_policy is not defined %}
{% set trade_policy = {'symbol_restrict_enabled': false, 'direction_restrict_enabled': false, 'symbol_whitelist': [], 'allows_long': true, 'allows_short': true, 'direction_mode': 'both', 'badge_text': ''} %}
{% endif %}
{% macro trade_policy_symbol(name, id, value='', required=true, placeholder='BTC 或 BTC/USDT') -%}
{% if trade_policy.symbol_restrict_enabled and trade_policy.symbol_whitelist %}
<select name="{{ name }}" id="{{ id }}" {% if required %}required{% endif %} class="trade-policy-symbol-select">
<option value="">选择币种</option>
{% for sym in trade_policy.symbol_whitelist %}
<option value="{{ sym }}" {% if value and (value|upper == sym or value|upper.startswith(sym ~ '/')) %}selected{% endif %}>{{ sym }}/USDT</option>
{% endfor %}
</select>
{% else %}
<input id="{{ id }}" name="{{ name }}" placeholder="{{ placeholder }}" {% if required %}required{% endif %} value="{{ value }}">
{% endif %}
{%- endmacro %}
{% macro trade_policy_direction(name, id, required=true, include_empty=true) -%}
{% if trade_policy.direction_restrict_enabled and trade_policy.direction_mode == 'long_only' %}
<span class="trade-policy-dir-lock" title="账户配置:仅做多">做多</span>
<input type="hidden" name="{{ name }}" id="{{ id }}" value="long">
{% elif trade_policy.direction_restrict_enabled and trade_policy.direction_mode == 'short_only' %}
<span class="trade-policy-dir-lock" title="账户配置:仅做空">做空</span>
<input type="hidden" name="{{ name }}" id="{{ id }}" value="short">
{% else %}
<select name="{{ name }}" id="{{ id }}" {% if required %}required{% endif %}>
{% if include_empty %}<option value="">方向</option>{% endif %}
{% if trade_policy.allows_long %}<option value="long">做多</option>{% endif %}
{% if trade_policy.allows_short %}<option value="short">做空</option>{% endif %}
</select>
{% endif %}
{%- endmacro %}