32079bb4c2
日历数据改为安全 JSON 内嵌,仅统计页构建;构建失败时降级为空,避免拖垮其他页面。 Co-authored-by: Cursor <cursoragent@cursor.com>
476 lines
34 KiB
HTML
476 lines
34 KiB
HTML
{# Hub iframe tab fragment — shared via embed_templates #}
|
||
{% macro period_stats(title, s) %}
|
||
<div class="stats-period-block">
|
||
<h3>{{ title }}</h3>
|
||
<div class="sub">{{ s.range_label }}</div>
|
||
<div class="stats-detail">
|
||
<div class="stat-item"><div class="label">开单次数</div><div class="value">{{ s.opens_count }}</div></div>
|
||
<div class="stat-item"><div class="label">平仓笔数</div><div class="value">{{ s.closed_count }}</div></div>
|
||
<div class="stat-item"><div class="label">胜率</div><div class="value">{% if s.win_rate_pct is not none %}{{ s.win_rate_pct }}%{% else %}-{% endif %}</div></div>
|
||
<div class="stat-item"><div class="label">净盈亏(U)</div><div class="value">{{ funds_fmt(s.net_pnl_u) }}</div></div>
|
||
<div class="stat-item"><div class="label">亏损额合计(U)</div><div class="value">{{ funds_fmt(s.loss_sum_u) }}</div></div>
|
||
<div class="stat-item"><div class="label">单笔最大亏损(U)</div><div class="value">{% if s.max_single_loss is not none %}{{ funds_fmt(s.max_single_loss) }}{% else %}-{% endif %}</div></div>
|
||
<div class="stat-item"><div class="label">单笔最大盈利(U)</div><div class="value">{% if s.max_single_profit is not none %}{{ funds_fmt(s.max_single_profit) }}{% else %}-{% endif %}</div></div>
|
||
<div class="stat-item"><div class="label">最大回撤(U)</div><div class="value">{{ funds_fmt(s.max_drawdown_u) }}</div></div>
|
||
<div class="stat-item"><div class="label">当前连续亏损笔数</div><div class="value">{{ s.consecutive_losses }}</div></div>
|
||
<div class="stat-item"><div class="label">最长连续亏损(交易日)</div><div class="value">{{ s.max_loss_streak_days }} 天</div></div>
|
||
<div class="stat-item"><div class="label">期内最大亏损日</div><div class="value">{% if s.worst_day %}{{ s.worst_day }}({{ funds_fmt(s.worst_day_pnl) }}U){% else %}-{% endif %}</div></div>
|
||
</div>
|
||
</div>
|
||
{% endmacro %}
|
||
<div class="grid">
|
||
{% if page == 'key_monitor' %}
|
||
{% include 'key_monitor_panel.html' %}
|
||
{% elif page == 'trade' %}
|
||
<div class="dual-panel-grid" style="grid-column:1/-1">
|
||
<div class="card">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;margin-bottom:8px">
|
||
<h2 style="margin-bottom:0">实盘下单监控</h2>
|
||
{% if focus_order_id %}
|
||
<a href="/order_focus?order_id={{ focus_order_id }}" class="btn-del" style="text-decoration:none;background:#1f3a5a;color:#8fc8ff">放大查看K线(100根)</a>
|
||
{% else %}
|
||
<span class="btn-del" style="background:#2f2f44;color:#9aa;cursor:not-allowed">暂无持仓可放大</span>
|
||
{% endif %}
|
||
</div>
|
||
{% include order_rule_tips_tpl %}
|
||
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||
<select id="order-direction" name="direction" required>
|
||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||
</select>
|
||
<select id="sltp-mode" name="sltp_mode">
|
||
<option value="fixed_rr" selected>止盈止损:固定盈亏比</option>
|
||
<option value="price">止盈止损:价格模式</option>
|
||
<option value="pct">止盈止损:百分比模式</option>
|
||
</select>
|
||
<select name="trade_style" required>
|
||
<option value="trend">趋势单</option>
|
||
<option value="swing">波段单</option>
|
||
</select>
|
||
{% if position_sizing_mode != 'full_margin' %}
|
||
<input id="order-leverage" name="leverage" type="number" min="1" step="1" placeholder="杠杆(可选)">
|
||
{% endif %}
|
||
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
||
<input type="checkbox" name="breakeven_enabled" value="1" checked> 启用移动保本(关闭则仅保留初始止损与交易所挂单)
|
||
</label>
|
||
<span id="order-time-close-wrap" class="order-time-close-wrap" style="display:inline-flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
||
<label style="display:inline-flex;align-items:center;gap:4px;margin:0;cursor:pointer">
|
||
<input type="checkbox" name="time_close_enabled" value="1" id="order-time-close-cb"> 时间平仓
|
||
</label>
|
||
<select name="time_close_hours" id="order-time-close-hours" title="持仓满该时长后自动平仓">
|
||
<option value="1">1h</option>
|
||
<option value="2">2h</option>
|
||
<option value="4" selected>4h</option>
|
||
</select>
|
||
</span>
|
||
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
||
<input type="checkbox" name="order_chart" value="true"> 开仓后生成多周期K线图(各周期100根,含开平仓标记)
|
||
</label>
|
||
<span style="display:flex;align-items:center;padding:0 10px;font-size:.8rem;color:#8fc8ff">成交价自动取交易所实时+成交回报</span>
|
||
<input id="order-sl" name="sl" step="any" placeholder="止损价格" required>
|
||
<input id="order-fixed-rr" name="fixed_rr" type="number" min="0.01" step="0.01" placeholder="盈亏比(默认1.5)" value="1.5" title="止盈距离=止损距离×盈亏比">
|
||
<span id="order-tp-preview" style="display:none;font-size:.8rem;color:#8fc8ff;align-self:center">预估止盈:—</span>
|
||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
||
<input id="order-sl-pct" name="sl_pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
|
||
<input id="order-tp-pct" name="tp_pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
|
||
<button type="submit">{{ open_position_button_label }}</button>
|
||
</form>
|
||
{% include 'order_plan_preview_bar.html' %}
|
||
</div>
|
||
<div class="card">
|
||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||
<div class="panel-scroll pos-list pos-list-live">
|
||
{% for o in order %}
|
||
<div class="pos-card" id="order-row-{{ o.id }}"
|
||
data-monitor-id="{{ o.id }}"
|
||
data-symbol="{{ o.symbol }}"
|
||
data-direction="{{ o.direction }}"
|
||
data-plan-sl="{% if o.stop_loss %}{{ price_fmt(o.symbol, o.stop_loss) }}{% endif %}"
|
||
data-plan-tp="{% if o.take_profit %}{{ price_fmt(o.symbol, o.take_profit) }}{% endif %}"
|
||
data-entry="{% if o.trigger_price %}{{ price_fmt(o.symbol, o.trigger_price) }}{% endif %}">
|
||
<div class="pos-card-head">
|
||
<div class="pos-card-symbol">
|
||
<strong>{{ o.exchange_symbol or o.symbol }}</strong>
|
||
{% if o.time_close_enabled %}
|
||
<span class="pos-symbol-time-close pos-meta-on pos-time-close-meta" id="order-time-close-wrap-{{ o.id }}"
|
||
data-close-at-ms="{{ o.time_close_at_ms or '' }}">
|
||
<span class="pos-time-close-label">时间平仓 {{ o.time_close_hours or '' }}h</span>
|
||
· <span class="pos-time-close-cd" id="order-time-close-cd-{{ o.id }}">--:--:--</span>
|
||
</span>
|
||
{% endif %}
|
||
<span class="pos-side-badge {{ 'pos-side-long' if o.direction == 'long' else 'pos-side-short' }}">{{ '做多' if o.direction == 'long' else '做空' }}</span>
|
||
</div>
|
||
<div class="pos-head-actions">
|
||
<button type="button" class="pos-entrust-btn" onclick="openTpslEntrustModal({{ o.id }})">委托</button>
|
||
<a href="/del_order/{{ o.id }}" class="pos-close-btn" onclick="return confirm('删除会触发手动平仓,继续?')">平仓</a>
|
||
</div>
|
||
</div>
|
||
<div class="pos-meta">
|
||
<span class="pos-meta-item">来源: {{ o.monitor_type|default('下单监控', true) }}{% if o.key_signal_type %} · {{ o.key_signal_type }}{% endif %}</span>
|
||
<span class="pos-meta-item">风格: {{ o.trade_style or 'trend' }}</span>
|
||
<span class="pos-meta-item">风险: {% if position_sizing_mode == 'full_margin' %}{{ funds_fmt(o.risk_amount) if o.risk_amount is not none else '-' }}U{% else %}{{ o.risk_percent or '-' }}%≈{{ funds_fmt(o.risk_amount) if o.risk_amount is not none else '-' }}U{% endif %}</span>
|
||
<span class="pos-meta-item {% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}">
|
||
{% if o.breakeven_enabled %}移动保本:开 {{ o.breakeven_rr_trigger or '-' }}R→{{ price_fmt(o.symbol, o.breakeven_price) }}{% else %}移动保本:关{% endif %}
|
||
</span>
|
||
<span class="pos-meta-item" id="order-be-wrap-{{ o.id }}" style="display:none"><span class="pos-breakeven-badge">已保本</span></span>
|
||
</div>
|
||
<div class="pos-grid">
|
||
<div class="pos-cell">
|
||
<span class="pos-label">成交价</span>
|
||
<span class="pos-value">{{ price_fmt(o.symbol, o.trigger_price) }}</span>
|
||
</div>
|
||
<div class="pos-cell">
|
||
<span class="pos-label">止损</span>
|
||
<span class="pos-value" id="order-plan-sl-{{ o.id }}">{{ price_fmt(o.symbol, o.stop_loss) if o.stop_loss else '—' }}</span>
|
||
</div>
|
||
<div class="pos-cell">
|
||
<span class="pos-label">止盈</span>
|
||
<span class="pos-value" id="order-plan-tp-{{ o.id }}">{{ price_fmt(o.symbol, o.take_profit) if o.take_profit else '—' }}</span>
|
||
</div>
|
||
<div class="pos-cell">
|
||
<span class="pos-label">盈亏比</span>
|
||
<span class="pos-value" id="order-rr-{{ o.id }}">{% if o.rr_ratio is not none %}{{ '%g'|format(o.rr_ratio) }}:1{% else %}-:1{% endif %}</span>
|
||
</div>
|
||
<div class="pos-cell">
|
||
<span class="pos-label">标记价</span>
|
||
<span class="pos-value" id="order-price-{{ o.id }}">-</span>
|
||
</div>
|
||
<div class="pos-cell">
|
||
<span class="pos-label">浮盈亏</span>
|
||
<span class="pos-value" id="order-pnl-{{ o.id }}">-</span>
|
||
</div>
|
||
</div>
|
||
<div class="pos-footer">
|
||
<span>保证金: <span id="order-ex-margin-{{ o.id }}">-</span></span>
|
||
<span>计划基数: {{ funds_fmt(o.margin_capital) if o.margin_capital is not none else '-' }}U</span>
|
||
<span>杠杆: {{ o.leverage or '-' }}x</span>
|
||
<span>仓位占比: {{ o.position_ratio if o.position_ratio is not none else '-' }}%</span>
|
||
<span>开仓时间: {{ (o.opened_at or '-')[:16] }}</span>
|
||
<span>持仓时长: <span class="order-hold-duration" id="order-hold-duration-{{ o.id }}" data-order-opened-ms="{{ o.opened_at_ms or '' }}">—</span></span>
|
||
</div>
|
||
<div class="pos-ex-orders">
|
||
<div class="pos-ex-orders-title">交易所止盈止损</div>
|
||
<div class="pos-ex-order-row">
|
||
<span class="pos-ex-order-main" id="ex-sl-text-{{ o.id }}">止损:加载中…</span>
|
||
<button type="button" class="pos-ex-cancel-btn" id="ex-sl-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'sl')">撤单</button>
|
||
</div>
|
||
<div class="pos-ex-order-row">
|
||
<span class="pos-ex-order-main" id="ex-tp-text-{{ o.id }}">止盈:加载中…</span>
|
||
<button type="button" class="pos-ex-cancel-btn" id="ex-tp-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'tp')">撤单</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% else %}
|
||
<div class="pos-empty">暂无持仓</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<div id="tpsl-modal" class="tpsl-modal-backdrop" onclick="if(event.target===this)closeTpslEntrustModal()">
|
||
<div class="tpsl-modal" onclick="event.stopPropagation()">
|
||
<h3 id="tpsl-modal-title">挂止盈止损</h3>
|
||
<p style="font-size:.78rem;color:#8892b0;margin:0 0 10px">将先撤销该合约已有 TP/SL,再按下列价格重挂。</p>
|
||
<div class="form-row">
|
||
<select id="tpsl-modal-mode" onchange="toggleTpslModalMode()">
|
||
<option value="price">价格模式</option>
|
||
<option value="pct">百分比模式</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-row">
|
||
<input id="tpsl-modal-sl" step="any" placeholder="止损价格">
|
||
<input id="tpsl-modal-tp" step="any" placeholder="止盈价格">
|
||
</div>
|
||
<div class="form-row">
|
||
<input id="tpsl-modal-sl-pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
|
||
<input id="tpsl-modal-tp-pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
|
||
</div>
|
||
<div class="tpsl-modal-actions">
|
||
<button type="button" class="tpsl-modal-cancel" onclick="closeTpslEntrustModal()">取消</button>
|
||
<button type="button" class="tpsl-modal-submit" onclick="submitTpslEntrust()">先撤后挂</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
{% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %}
|
||
{% include 'strategy_trading_page.html' %}
|
||
{% elif page == 'strategy_records' %}
|
||
{% include 'strategy_records_page.html' %}
|
||
{% endif %}
|
||
|
||
|
||
|
||
{% if page == 'records' %}
|
||
<div class="card full records-card">
|
||
<h2>交易记录 & 错过机会</h2>
|
||
<div class="form-row" style="margin-bottom:10px;gap:8px">
|
||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||
<input id="review-mode-toggle" type="checkbox">
|
||
修改/核对开关(开启后可编辑关键字段)
|
||
</label>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<tr><th>品种</th><th>类型</th><th>方向</th><th>成交</th><th>止损(开仓)</th><th>止盈</th><th>基数</th><th>杠杆</th><th>持仓分钟</th><th>开仓时间(北京)</th><th>平仓时间(北京)</th><th>盈亏U</th><th>结果</th><th>操作</th></tr>
|
||
{% for r in record %}
|
||
<tr id="trade-row-{{ r.id }}">
|
||
{% set pnl_val = (r.pnl_amount or 0)|float %}
|
||
<td>{{ r.symbol }}</td>
|
||
<td>{{ r.monitor_type }}{% if r.key_signal_type %} · {{ r.key_signal_type }}{% endif %}</td>
|
||
<td><span class="badge {{ 'direction-long' if r.direction == 'long' else 'direction-short' }}">{{ '做多' if r.direction == 'long' else '做空' }}</span></td>
|
||
<td>{{ price_fmt(r.symbol, r.trigger_price) }}</td>
|
||
{% set stop_show = r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss %}
|
||
{% set tp_show = r.effective_take_profit or r.take_profit %}
|
||
<td>{{ price_fmt(r.symbol, stop_show) }}</td>
|
||
<td>{{ price_fmt(r.symbol, tp_show) }}</td>
|
||
<td>{% if r.margin_capital is not none and r.margin_capital != '' %}{{ funds_fmt(r.margin_capital) }}{% else %}-{% endif %}</td>
|
||
<td>{{ r.leverage or '-' }}</td>
|
||
<td>{{ r.effective_hold_minutes or 0 }}</td>
|
||
<td>{{ (r.effective_opened_at or '-')[:16] }}</td>
|
||
<td>{{ (r.effective_closed_at or r.created_at or '-')[:16] }}</td>
|
||
{% set pnl_val = (r.effective_pnl_amount or 0)|float %}
|
||
<td><span class="{{ 'pnl-profit' if pnl_val > 0 else ('pnl-loss' if pnl_val < 0 else '') }}">{{ funds_fmt(r.effective_pnl_amount or 0) }}</span>{% if r.display_pnl_source == 'exchange' %}<span style="font-size:.68rem;color:#6ab88a">所</span>{% elif r.display_pnl_source != 'reviewed' %}<span style="font-size:.68rem;color:#8892b0">估</span>{% endif %}</td>
|
||
<td>
|
||
{% set effective_result = r.effective_result %}
|
||
{% if effective_result in ["止盈","保本止盈","移动止盈"] %}<span class="badge profit">{{ effective_result }}</span>
|
||
{% elif effective_result in ["止损","强制清仓","手动平仓"] %}<span class="badge loss">{{ effective_result }}</span>
|
||
{% elif effective_result == "时间平仓" %}<span class="badge miss">{{ effective_result }}</span>
|
||
{% else %}<span class="badge miss">{{ effective_result }}</span>{% endif %}
|
||
</td>
|
||
<td>
|
||
<button
|
||
type="button"
|
||
class="table-del"
|
||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||
onclick='fillJournalFromTrade({{ {
|
||
"symbol": r.symbol,
|
||
"monitor_type": r.monitor_type,
|
||
"key_signal_type": r.key_signal_type or "",
|
||
"direction": r.direction,
|
||
"trigger_price": r.trigger_price,
|
||
"stop_loss": r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||
"take_profit": r.effective_take_profit or r.take_profit,
|
||
"opened_at": r.effective_opened_at,
|
||
"closed_at": r.effective_closed_at,
|
||
"pnl_amount": r.effective_pnl_amount,
|
||
"result": r.effective_result,
|
||
"risk_amount": r.risk_amount
|
||
}|tojson|safe }})'
|
||
>填入复盘</button>
|
||
<button
|
||
type="button"
|
||
class="table-del review-edit-btn"
|
||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||
onclick='editTradeRecordReview({{ {
|
||
"id": r.id,
|
||
"opened_at": r.effective_opened_at,
|
||
"closed_at": r.effective_closed_at,
|
||
"stop_loss": r.effective_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||
"take_profit": r.effective_take_profit or r.take_profit,
|
||
"pnl_amount": r.effective_pnl_amount,
|
||
"result": r.effective_result,
|
||
"miss_reason": r.effective_miss_reason,
|
||
"effective_entry_reason": r.effective_entry_reason or ""
|
||
}|tojson|safe }})'
|
||
disabled
|
||
>核对修改</button>
|
||
<button type="button" class="table-del" onclick="deleteTradeRecord({{ r.id }})">删除</button>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card miss-card" style="opacity:.78">
|
||
<h2>记录错过机会</h2>
|
||
<form action="/add_miss" method="post" class="form-row">
|
||
<input name="symbol" placeholder="品种" required>
|
||
<select name="type" required>
|
||
<option value="箱体突破">箱体突破</option>
|
||
<option value="收敛突破">收敛突破</option>
|
||
<option value="关键支撑阻力">关键支撑阻力</option>
|
||
</select>
|
||
<select name="direction" required>
|
||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||
</select>
|
||
<input name="tp" step="0.0001" placeholder="入场价" required>
|
||
<input name="sl" step="any" placeholder="止损" required>
|
||
<input name="tgt" step="any" placeholder="止盈" required>
|
||
<input name="reason" placeholder="错过原因" required>
|
||
<button type="submit">记录</button>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card journal-card">
|
||
<h2>交易复盘记录上传(含截图)</h2>
|
||
<form id="journal-form" action="/add_journal" method="post" enctype="multipart/form-data">
|
||
<input type="hidden" name="risk_amount_hint" id="risk-amount-hint">
|
||
<input type="hidden" name="entry_price_hint" id="entry-price-hint">
|
||
<input type="hidden" name="stop_loss_hint" id="stop-loss-hint">
|
||
<input type="hidden" name="exit_price_hint" id="exit-price-hint">
|
||
<input type="hidden" name="direction_hint" id="direction-hint">
|
||
<div class="form-grid">
|
||
<input type="datetime-local" name="open_datetime" required>
|
||
<input type="datetime-local" name="close_datetime" required>
|
||
<input name="coin" placeholder="BTC" required>
|
||
<input name="tf" placeholder="5m" required>
|
||
<input name="pnl" placeholder="盈亏(U)" required>
|
||
<select name="entry_reason" id="journal-entry-reason" required title="固定五种或选其他手写">
|
||
<option value="">开仓类型(必选)</option>
|
||
{% for er in entry_reason_options %}
|
||
<option value="{{ er }}">{{ er }}</option>
|
||
{% endfor %}
|
||
<option value="{{ entry_reason_other_value }}">其他(自定义,见下方说明框)</option>
|
||
</select>
|
||
<input type="text" name="entry_reason_custom" id="journal-entry-reason-custom" maxlength="2000" placeholder="选「其他」时在此填写开仓类型说明" autocomplete="off" style="display:none">
|
||
<input name="expect_rr" placeholder="预期RR">
|
||
<input name="real_rr" placeholder="实际RR">
|
||
<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>
|
||
</select>
|
||
<input name="early_exit_note" id="early-exit-note" placeholder="离场补充(仅手工平仓必填)">
|
||
<select name="post_breakeven_stare"><option value="否">保本后盯盘:否</option><option value="是">保本后盯盘:是</option></select>
|
||
<select name="new_trade_while_occupied"><option value="否">占用时新开仓:否</option><option value="是">占用时新开仓:是</option></select>
|
||
<input id="journal-screenshot" type="file" name="screenshot" accept="image/*">
|
||
</div>
|
||
<div class="form-row" style="margin-top:8px;flex-wrap:wrap;gap:10px;align-items:center">
|
||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||
<input type="checkbox" name="journal_exchange_chart" value="true" checked>
|
||
保存时自动生成 K 线图并作为截图
|
||
</label>
|
||
<label style="font-size:.82rem;color:#9aa">周期1</label>
|
||
<select name="journal_chart_tf1" style="min-width:72px">
|
||
{% for tf in journal_chart_tf_choices %}
|
||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf1 %}selected{% endif %}>{{ tf }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<label style="font-size:.82rem;color:#9aa">周期2</label>
|
||
<select name="journal_chart_tf2" style="min-width:72px">
|
||
{% for tf in journal_chart_tf_choices %}
|
||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf2 %}selected{% endif %}>{{ tf }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<label style="font-size:.82rem;color:#9aa">K线数</label>
|
||
<select name="journal_chart_limit" style="min-width:72px">
|
||
{% for n in [100, 150, 200, 250, 300, 400, 500] %}
|
||
<option value="{{ n }}" {% if n == journal_chart_default_limit %}selected{% endif %}>{{ n }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<label style="font-size:.82rem;color:#9aa">K线截止</label>
|
||
<select name="journal_chart_anchor" id="journal-chart-anchor" style="min-width:96px" title="K线窗口右端对齐的时间">
|
||
<option value="close" {% if journal_chart_default_anchor == 'close' %}selected{% endif %}>平仓时间</option>
|
||
<option value="now" {% if journal_chart_default_anchor == 'now' %}selected{% endif %}>当前时间</option>
|
||
</select>
|
||
</div>
|
||
<div class="sub" id="journal-chart-anchor-hint" style="font-size:.72rem;color:#8892b0;margin-top:4px">双周期上下排列;截止=平仓时间:开仓前背景至平仓;截止=当前时间:最近 N 根至此刻(可看平仓后走势);标注开仓、平仓与止损位</div>
|
||
<div class="form-row" style="margin-top:8px">
|
||
<button type="button" style="background:#1f3a5a" onclick="prefillJournalByImage()">AI识别预填(你再手动改原因)</button>
|
||
</div>
|
||
<div class="mood-grid" style="margin-top:8px">
|
||
<label><input type="checkbox" name="mood_issues" value="怕踏空">怕踏空</label>
|
||
<label><input type="checkbox" name="mood_issues" value="报复开仓">报复开仓</label>
|
||
<label><input type="checkbox" name="mood_issues" value="盈利飘了">盈利飘了</label>
|
||
<label><input type="checkbox" name="mood_issues" value="拿不住单">拿不住单</label>
|
||
<label><input type="checkbox" name="mood_issues" value="扛单">扛单</label>
|
||
<label><input type="checkbox" name="mood_issues" value="重仓违规">重仓违规</label>
|
||
</div>
|
||
<textarea name="note" rows="2" style="width:100%;margin-top:8px" placeholder="备注"></textarea>
|
||
<button type="submit" style="margin-top:8px">保存复盘记录</button>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card full review-card" id="review-card">
|
||
<div class="review-card-head">
|
||
<h2>AI复盘(按交易记录)</h2>
|
||
<button type="button" class="review-card-fs-btn" id="review-card-fs-btn" onclick="toggleReviewCardFullscreen()">全屏</button>
|
||
</div>
|
||
<div class="form-row">
|
||
<input type="date" id="day_date">
|
||
<button type="button" id="gen-daily-btn" onclick="genDaily()">生成日复盘</button>
|
||
<button type="button" onclick="exportDailyBundleMd()" style="background:#1f3a5a">导出当日日复盘MD</button>
|
||
<input type="date" id="week_start">
|
||
<input type="date" id="week_end">
|
||
<button type="button" id="gen-weekly-btn" onclick="genWeekly()">生成周复盘</button>
|
||
<button type="button" onclick="exportWeeklyBundleMd()" style="background:#1f3a5a">导出当周复盘MD</button>
|
||
</div>
|
||
<div class="ai-result-wrap" id="daily_result_wrap" style="display:none">
|
||
<div id="daily_result" class="ai-result"></div>
|
||
<div class="ai-result-toolbar">
|
||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('日复盘结果', 'daily_result')">全屏查看</button>
|
||
</div>
|
||
</div>
|
||
<div class="ai-result-wrap" id="weekly_result_wrap" style="display:none">
|
||
<div id="weekly_result" class="ai-result"></div>
|
||
<div class="ai-result-toolbar">
|
||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('周复盘结果', 'weekly_result')">全屏查看</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-list" style="margin-top:10px">
|
||
<div class="panel-item">
|
||
<strong>交易复盘记录</strong>
|
||
<div id="journal-list"></div>
|
||
</div>
|
||
<div class="panel-item">
|
||
<strong>AI历史复盘</strong>
|
||
<div id="review-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% if page == 'stats' %}
|
||
<div class="card stats-card full" id="stats-card">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap">
|
||
<h2 style="margin-bottom:0">数据统计</h2>
|
||
<button type="button" class="stats-toggle" id="stats-toggle-btn" onclick="toggleStatsCard()">折叠</button>
|
||
</div>
|
||
<div class="stats-content" id="stats-content">
|
||
<div class="stat-box" style="margin-bottom:10px">
|
||
<div class="stat-item"><div class="label">持仓占用导致错过(累计)</div><div class="value">{{ occupied_miss_total }}</div></div>
|
||
</div>
|
||
<div class="sub" style="margin-bottom:12px;color:#8892b0;font-size:.82rem">
|
||
统计分析按<strong>北京时间 {{ stats_bundle.stats_reset_hour }}:00</strong>切日计入(与顶栏 UTC 列表窗无关)。历史总开仓(累计):
|
||
<strong style="color:#cfd3ef">{{ stats_bundle.total_opens_all }}</strong> 次
|
||
</div>
|
||
<div class="form-row" style="margin-bottom:14px;align-items:center">
|
||
<label style="display:flex;align-items:center;gap:8px;font-size:.88rem;color:#cfd3ef">
|
||
统计品类
|
||
<select id="stats-segment-select" onchange="switchStatsSegment()" style="min-width:200px">
|
||
{% for seg in stats_bundle.segments %}
|
||
<option value="{{ seg.key }}">{{ seg.title }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</label>
|
||
</div>
|
||
{% if stats_bundle.calendar_bootstrap_json %}
|
||
<script type="application/json" id="stats-calendar-bootstrap">{{ stats_bundle.calendar_bootstrap_json | safe }}</script>
|
||
{% endif %}
|
||
<div id="stats-calendar-wrap" class="trade-cal-wrap stats-calendar-wrap">
|
||
<div class="trade-cal-head">
|
||
<button type="button" id="stats-cal-prev" class="btn" title="上一月">‹</button>
|
||
<span id="stats-cal-title" class="trade-cal-title"></span>
|
||
<button type="button" id="stats-cal-next" class="btn" title="下一月">›</button>
|
||
</div>
|
||
<div id="stats-calendar" class="trade-cal-grid-host" role="grid" aria-label="交易日历"></div>
|
||
</div>
|
||
{% for seg in stats_bundle.segments %}
|
||
<div class="stats-segment-block stats-segment-panel" data-stats-segment="{{ seg.key }}"{% if not loop.first %} style="display:none"{% endif %}>
|
||
{{ period_stats("日统计", seg.day) }}
|
||
{{ period_stats("周统计", seg.week) }}
|
||
{{ period_stats("月统计", seg.month) }}
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|