Fix mark/PnL display fallback and intraday entry labels
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7224,6 +7224,15 @@ def api_price_snapshot():
|
|||||||
except Exception:
|
except Exception:
|
||||||
all_swap_positions = []
|
all_swap_positions = []
|
||||||
|
|
||||||
|
from lib.hub.price_snapshot_lib import resolve_order_snapshot_price, seed_prices_from_positions
|
||||||
|
|
||||||
|
seed_prices_from_positions(
|
||||||
|
prices,
|
||||||
|
order_rows,
|
||||||
|
all_swap_positions,
|
||||||
|
resolve_ex_sym_fn=resolve_monitor_exchange_symbol,
|
||||||
|
)
|
||||||
|
|
||||||
key_prices = []
|
key_prices = []
|
||||||
for r in key_rows:
|
for r in key_rows:
|
||||||
is_fib = is_fib_key_monitor_type(r["monitor_type"])
|
is_fib = is_fib_key_monitor_type(r["monitor_type"])
|
||||||
@@ -7364,8 +7373,6 @@ def api_price_snapshot():
|
|||||||
})
|
})
|
||||||
|
|
||||||
order_prices = []
|
order_prices = []
|
||||||
from lib.hub.price_snapshot_lib import resolve_order_snapshot_price
|
|
||||||
|
|
||||||
for r in order_rows:
|
for r in order_rows:
|
||||||
margin = float(r["margin_capital"] or 0)
|
margin = float(r["margin_capital"] or 0)
|
||||||
leverage = float(r["leverage"] or 0)
|
leverage = float(r["leverage"] or 0)
|
||||||
@@ -7403,7 +7410,11 @@ def api_price_snapshot():
|
|||||||
if ex_metrics.get("notional") is not None:
|
if ex_metrics.get("notional") is not None:
|
||||||
payload["exchange_notional"] = ex_metrics["notional"]
|
payload["exchange_notional"] = ex_metrics["notional"]
|
||||||
if ex_metrics.get("mark_price") is not None:
|
if ex_metrics.get("mark_price") is not None:
|
||||||
payload["exchange_mark_price"] = ex_metrics["mark_price"]
|
mp = ex_metrics["mark_price"]
|
||||||
|
payload["exchange_mark_price"] = mp
|
||||||
|
payload["exchange_mark_price_display"] = format_price_for_symbol(
|
||||||
|
r["symbol"], mp
|
||||||
|
)
|
||||||
if ex_metrics.get("unrealized_pnl") is not None:
|
if ex_metrics.get("unrealized_pnl") is not None:
|
||||||
payload["float_pnl"] = round(float(ex_metrics["unrealized_pnl"]), 2)
|
payload["float_pnl"] = round(float(ex_metrics["unrealized_pnl"]), 2)
|
||||||
payload["pnl_source"] = "exchange"
|
payload["pnl_source"] = "exchange"
|
||||||
@@ -7429,6 +7440,9 @@ def api_price_snapshot():
|
|||||||
except Exception:
|
except Exception:
|
||||||
payload["price"] = px_for_fmt
|
payload["price"] = px_for_fmt
|
||||||
payload["price_display"] = px_disp
|
payload["price_display"] = px_disp
|
||||||
|
if payload.get("exchange_mark_price") is None:
|
||||||
|
payload["exchange_mark_price"] = px_for_fmt
|
||||||
|
payload["exchange_mark_price_display"] = px_disp
|
||||||
else:
|
else:
|
||||||
payload["price"] = None
|
payload["price"] = None
|
||||||
payload["price_display"] = "-"
|
payload["price_display"] = "-"
|
||||||
@@ -8288,6 +8302,8 @@ def add_order():
|
|||||||
conn.close()
|
conn.close()
|
||||||
flash(style_err)
|
flash(style_err)
|
||||||
return redirect("/trade")
|
return redirect("/trade")
|
||||||
|
if entry_model:
|
||||||
|
trade_style = "trend"
|
||||||
available_usdt = get_available_trading_usdt()
|
available_usdt = get_available_trading_usdt()
|
||||||
live_price = get_price(symbol)
|
live_price = get_price(symbol)
|
||||||
if live_price is None:
|
if live_price is None:
|
||||||
|
|||||||
@@ -527,6 +527,12 @@ def register_hub_routes(app):
|
|||||||
od = apply_order_monitor_source_labels(od)
|
od = apply_order_monitor_source_labels(od)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
from lib.trade.entry_model_lib import enrich_entry_model_display
|
||||||
|
|
||||||
|
enrich_entry_model_display(od)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
orders.append(od)
|
orders.append(od)
|
||||||
trends = []
|
trends = []
|
||||||
if c.get("has_trend"):
|
if c.get("has_trend"):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""price_snapshot 共用:订单行情价兜底,避免 get_price 失败时整单不入 order_prices。"""
|
"""price_snapshot 共用:订单行情价兜底,避免 get_price 失败时整单不入 order_prices。"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable, Mapping, Optional
|
from typing import Any, Callable, Mapping, Optional, Sequence
|
||||||
|
|
||||||
from lib.hub.hub_position_metrics import parse_position_mark_price
|
from lib.hub.hub_position_metrics import parse_position_mark_price
|
||||||
|
|
||||||
@@ -73,3 +73,52 @@ def resolve_order_snapshot_price(
|
|||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def seed_prices_from_positions(
|
||||||
|
prices: dict[str, float],
|
||||||
|
order_rows: Sequence[Any],
|
||||||
|
all_positions: Sequence[dict[str, Any]],
|
||||||
|
*,
|
||||||
|
resolve_ex_sym_fn: Callable[[Any], str],
|
||||||
|
) -> None:
|
||||||
|
"""用持仓标记价补全 prices 字典(symbol 与 order_monitors 行对齐)。"""
|
||||||
|
if not all_positions or not order_rows:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
from lib.hub.hub_symbol_lib import symbols_match
|
||||||
|
except Exception:
|
||||||
|
symbols_match = None
|
||||||
|
for r in order_rows:
|
||||||
|
try:
|
||||||
|
sym = str(r["symbol"] or "").strip()
|
||||||
|
except (KeyError, TypeError, IndexError):
|
||||||
|
sym = ""
|
||||||
|
if not sym or sym in prices:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
ex_sym = resolve_ex_sym_fn(r)
|
||||||
|
except Exception:
|
||||||
|
ex_sym = sym
|
||||||
|
try:
|
||||||
|
direction = str(r["direction"] or "long").lower()
|
||||||
|
except (KeyError, TypeError, IndexError):
|
||||||
|
direction = "long"
|
||||||
|
for p in all_positions:
|
||||||
|
if not isinstance(p, dict):
|
||||||
|
continue
|
||||||
|
ps = p.get("symbol") or ""
|
||||||
|
if not ps:
|
||||||
|
continue
|
||||||
|
matched = ps == sym or ps == ex_sym
|
||||||
|
if not matched and symbols_match is not None:
|
||||||
|
matched = symbols_match(sym, ps) or symbols_match(ex_sym, ps)
|
||||||
|
if not matched:
|
||||||
|
continue
|
||||||
|
side = (p.get("side") or "").lower()
|
||||||
|
if side and side != direction:
|
||||||
|
continue
|
||||||
|
mp = parse_position_mark_price(p)
|
||||||
|
if mp is not None and mp > 0:
|
||||||
|
prices[sym] = float(mp)
|
||||||
|
break
|
||||||
|
|||||||
@@ -891,6 +891,38 @@ function paintPriceTrend(el, key, value){
|
|||||||
lastPriceMap[key] = value;
|
lastPriceMap[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatOrderMarkDisplay(o){
|
||||||
|
const row = o || {};
|
||||||
|
const markRaw = row.exchange_mark_price;
|
||||||
|
const markNum = Number(markRaw);
|
||||||
|
const hasMark = markRaw !== null && markRaw !== undefined && markRaw !== "" && Number.isFinite(markNum) && markNum > 0;
|
||||||
|
if(hasMark){
|
||||||
|
if(row.exchange_mark_price_display && row.exchange_mark_price_display !== "-") return row.exchange_mark_price_display;
|
||||||
|
return markNum.toFixed(6);
|
||||||
|
}
|
||||||
|
if(row.price_display && row.price_display !== "-") return row.price_display;
|
||||||
|
const px = Number(row.price);
|
||||||
|
return Number.isFinite(px) && px > 0 ? px.toFixed(6) : "-";
|
||||||
|
}
|
||||||
|
function paintOrderMarkAndPnl(orderId, o){
|
||||||
|
const pEl = document.getElementById(`order-price-${orderId}`);
|
||||||
|
if(pEl){
|
||||||
|
const disp = formatOrderMarkDisplay(o);
|
||||||
|
pEl.innerText = disp;
|
||||||
|
const markNum = Number(o && o.exchange_mark_price);
|
||||||
|
const pxNum = Number.isFinite(markNum) && markNum > 0 ? markNum : Number(o && o.price);
|
||||||
|
paintPriceTrend(pEl, `o-${orderId}`, Number.isFinite(pxNum) ? pxNum : null);
|
||||||
|
}
|
||||||
|
const pnlEl = document.getElementById(`order-pnl-${orderId}`);
|
||||||
|
if(pnlEl){
|
||||||
|
pnlEl.innerText = `${formatSigned(o.float_pnl, 2)}U (${formatSigned(o.float_pct, 2)}%)`;
|
||||||
|
pnlEl.classList.remove("price-up","price-down","price-flat");
|
||||||
|
if(Number(o.float_pnl) > 0) pnlEl.classList.add("price-up");
|
||||||
|
else if(Number(o.float_pnl) < 0) pnlEl.classList.add("price-down");
|
||||||
|
else pnlEl.classList.add("price-flat");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function refreshPriceSnapshot(){
|
function refreshPriceSnapshot(){
|
||||||
fetch("/api/price_snapshot").then(r=>r.json()).then(data=>{
|
fetch("/api/price_snapshot").then(r=>r.json()).then(data=>{
|
||||||
const updatedEl = document.getElementById("price-last-updated");
|
const updatedEl = document.getElementById("price-last-updated");
|
||||||
@@ -925,22 +957,7 @@ function refreshPriceSnapshot(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
(data.order_prices || []).forEach(o=>{
|
(data.order_prices || []).forEach(o=>{
|
||||||
const pEl = document.getElementById(`order-price-${o.id}`);
|
paintOrderMarkAndPnl(o.id, o);
|
||||||
if(pEl){
|
|
||||||
const hasMark = (()=>{ const x = o.exchange_mark_price; if(x===null||x===undefined||x==="")return false; const n=Number(x); return !Number.isNaN(n); })();
|
|
||||||
let disp = "";
|
|
||||||
if(hasMark && o.exchange_mark_price_display){
|
|
||||||
disp = o.exchange_mark_price_display;
|
|
||||||
} else if(o.price_display){
|
|
||||||
disp = o.price_display;
|
|
||||||
} else {
|
|
||||||
const px = hasMark ? Number(o.exchange_mark_price) : Number(o.price);
|
|
||||||
disp = Number.isFinite(px) ? px.toFixed(6) : "-";
|
|
||||||
}
|
|
||||||
pEl.innerText = disp;
|
|
||||||
const pxNum = hasMark ? Number(o.exchange_mark_price) : Number(o.price);
|
|
||||||
paintPriceTrend(pEl, `o-${o.id}`, Number.isFinite(pxNum) ? pxNum : px);
|
|
||||||
}
|
|
||||||
const exM = document.getElementById(`order-ex-margin-${o.id}`);
|
const exM = document.getElementById(`order-ex-margin-${o.id}`);
|
||||||
if(exM){
|
if(exM){
|
||||||
const mv = o.exchange_initial_margin;
|
const mv = o.exchange_initial_margin;
|
||||||
@@ -952,14 +969,6 @@ function refreshPriceSnapshot(){
|
|||||||
exM.innerText = (prc === 0) ? "无仓数据" : "-";
|
exM.innerText = (prc === 0) ? "无仓数据" : "-";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const pnlEl = document.getElementById(`order-pnl-${o.id}`);
|
|
||||||
if(pnlEl){
|
|
||||||
pnlEl.innerText = `${formatSigned(o.float_pnl, 2)}U (${formatSigned(o.float_pct, 2)}%)`;
|
|
||||||
pnlEl.classList.remove("price-up","price-down","price-flat");
|
|
||||||
if(Number(o.float_pnl) > 0) pnlEl.classList.add("price-up");
|
|
||||||
else if(Number(o.float_pnl) < 0) pnlEl.classList.add("price-down");
|
|
||||||
else pnlEl.classList.add("price-flat");
|
|
||||||
}
|
|
||||||
const rrEl = document.getElementById(`order-rr-${o.id}`);
|
const rrEl = document.getElementById(`order-rr-${o.id}`);
|
||||||
if(rrEl){
|
if(rrEl){
|
||||||
const rr = o.display_rr_ratio != null && o.display_rr_ratio !== "" ? o.display_rr_ratio : o.rr_ratio;
|
const rr = o.display_rr_ratio != null && o.display_rr_ratio !== "" ? o.display_rr_ratio : o.rr_ratio;
|
||||||
@@ -1225,19 +1234,10 @@ function refreshPriceSnapshotConditional(){
|
|||||||
if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k);
|
if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(page === "trade"){
|
const tradePage = page === "trade" || !!document.querySelector("[id^='order-price-']");
|
||||||
|
if(tradePage){
|
||||||
(data.order_prices || []).forEach(o=>{
|
(data.order_prices || []).forEach(o=>{
|
||||||
const pEl = document.getElementById(`order-price-${o.id}`);
|
paintOrderMarkAndPnl(o.id, o);
|
||||||
if(pEl){
|
|
||||||
const hasMark = (()=>{ const x = o.exchange_mark_price; if(x===null||x===undefined||x==="")return false; const n=Number(x); return !Number.isNaN(n); })();
|
|
||||||
let disp = "";
|
|
||||||
if(hasMark && o.exchange_mark_price_display) disp = o.exchange_mark_price_display;
|
|
||||||
else if(o.price_display) disp = o.price_display;
|
|
||||||
else { const px = hasMark ? Number(o.exchange_mark_price) : Number(o.price); disp = Number.isFinite(px) ? px.toFixed(6) : "-"; }
|
|
||||||
pEl.innerText = disp;
|
|
||||||
const pxNum = hasMark ? Number(o.exchange_mark_price) : Number(o.price);
|
|
||||||
paintPriceTrend(pEl, `o-${o.id}`, Number.isFinite(pxNum) ? pxNum : px);
|
|
||||||
}
|
|
||||||
const exM = document.getElementById(`order-ex-margin-${o.id}`);
|
const exM = document.getElementById(`order-ex-margin-${o.id}`);
|
||||||
if(exM){
|
if(exM){
|
||||||
const mv = o.exchange_initial_margin;
|
const mv = o.exchange_initial_margin;
|
||||||
@@ -1245,14 +1245,6 @@ function refreshPriceSnapshotConditional(){
|
|||||||
if(!Number.isNaN(mn)) exM.innerText = `${mn.toFixed(2)}U`;
|
if(!Number.isNaN(mn)) exM.innerText = `${mn.toFixed(2)}U`;
|
||||||
else { const prc = (typeof data.positions_raw_count === "number") ? data.positions_raw_count : null; exM.innerText = (prc === 0) ? "无仓数据" : "-"; }
|
else { const prc = (typeof data.positions_raw_count === "number") ? data.positions_raw_count : null; exM.innerText = (prc === 0) ? "无仓数据" : "-"; }
|
||||||
}
|
}
|
||||||
const pnlEl = document.getElementById(`order-pnl-${o.id}`);
|
|
||||||
if(pnlEl){
|
|
||||||
pnlEl.innerText = `${formatSigned(o.float_pnl, 2)}U (${formatSigned(o.float_pct, 2)}%)`;
|
|
||||||
pnlEl.classList.remove("price-up","price-down","price-flat");
|
|
||||||
if(Number(o.float_pnl) > 0) pnlEl.classList.add("price-up");
|
|
||||||
else if(Number(o.float_pnl) < 0) pnlEl.classList.add("price-down");
|
|
||||||
else pnlEl.classList.add("price-flat");
|
|
||||||
}
|
|
||||||
const rrEl = document.getElementById(`order-rr-${o.id}`);
|
const rrEl = document.getElementById(`order-rr-${o.id}`);
|
||||||
if(rrEl) rrEl.innerText = formatRrRatio(o.rr_ratio);
|
if(rrEl) rrEl.innerText = formatRrRatio(o.rr_ratio);
|
||||||
paintBreakevenBadge(o.id, o.sl_breakeven_secured);
|
paintBreakevenBadge(o.id, o.sl_breakeven_secured);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pos-meta">
|
<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.monitor_type|default('下单监控', true) }}{% if o.key_signal_type %} · {{ o.key_signal_type }}{% endif %}</span>
|
||||||
<span class="pos-meta-item">{% if o.entry_model_label %}开仓: {{ o.entry_model_label }}{% else %}风格: {{ '波段单' if o.trade_style == 'swing' else '趋势单' }}{% endif %}</span>
|
<span class="pos-meta-item">{% if o.entry_model_label %}开仓: {{ o.entry_model_label }}{% elif intraday_discipline %}开仓: —{% else %}风格: {{ '波段单' if o.trade_style == 'swing' else '趋势单' }}{% endif %}</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 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" id="order-latest-risk-wrap-{{ o.id }}" style="display:none">最新风险: —</span>
|
<span class="pos-meta-item" id="order-latest-risk-wrap-{{ o.id }}" style="display:none">最新风险: —</span>
|
||||||
<span class="pos-meta-item {% if not intraday_discipline %}{% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}{% endif %}">
|
<span class="pos-meta-item {% if not intraday_discipline %}{% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}{% endif %}">
|
||||||
|
|||||||
@@ -224,7 +224,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pos-meta">
|
<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.monitor_type|default('下单监控', true) }}{% if o.key_signal_type %} · {{ o.key_signal_type }}{% endif %}</span>
|
||||||
<span class="pos-meta-item">{% if o.entry_model_label %}开仓: {{ o.entry_model_label }}{% else %}风格: {{ '波段单' if o.trade_style == 'swing' else '趋势单' }}{% endif %}</span>
|
<span class="pos-meta-item">{% if o.entry_model_label %}开仓: {{ o.entry_model_label }}{% elif intraday_discipline %}开仓: —{% else %}风格: {{ '波段单' if o.trade_style == 'swing' else '趋势单' }}{% endif %}</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 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" id="order-latest-risk-wrap-{{ o.id }}" style="display:none">最新风险: —</span>
|
<span class="pos-meta-item" id="order-latest-risk-wrap-{{ o.id }}" style="display:none">最新风险: —</span>
|
||||||
<span class="pos-meta-item {% if not intraday_discipline %}{% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}{% endif %}">
|
<span class="pos-meta-item {% if not intraday_discipline %}{% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}{% endif %}">
|
||||||
|
|||||||
@@ -1112,6 +1112,17 @@
|
|||||||
return mt || "下单监控";
|
return mt || "下单监控";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function monitorEntryStyleHtml(mo, intradayDiscipline) {
|
||||||
|
const o = mo || {};
|
||||||
|
if (o.entry_model_label) return `开仓: ${esc(o.entry_model_label)}`;
|
||||||
|
if (intradayDiscipline) return "开仓: —";
|
||||||
|
const ts = String(o.trade_style || "").toLowerCase();
|
||||||
|
if (ts === "swing") return "风格: 波段单";
|
||||||
|
if (ts === "trend") return "风格: 趋势单";
|
||||||
|
if (o.trade_style) return `风格: ${esc(o.trade_style)}`;
|
||||||
|
return "风格: —";
|
||||||
|
}
|
||||||
|
|
||||||
function monitorOrderSourceHtml(mo, trendPlan) {
|
function monitorOrderSourceHtml(mo, trendPlan) {
|
||||||
if (isTrendContext(mo, trendPlan)) {
|
if (isTrendContext(mo, trendPlan)) {
|
||||||
return `来源: ${esc(monitorOrderSourceLabel(mo, trendPlan))}`;
|
return `来源: ${esc(monitorOrderSourceLabel(mo, trendPlan))}`;
|
||||||
@@ -3073,8 +3084,7 @@
|
|||||||
meta.push(`<span class="pos-meta-off">移动保本:关</span>`);
|
meta.push(`<span class="pos-meta-off">移动保本:关</span>`);
|
||||||
} else if (mo.monitor_type || mo.key_signal_type || mo.trend_plan_id) {
|
} else if (mo.monitor_type || mo.key_signal_type || mo.trend_plan_id) {
|
||||||
meta.push(monitorOrderSourceHtml(mo, trendPlan));
|
meta.push(monitorOrderSourceHtml(mo, trendPlan));
|
||||||
if (mo.trade_style) meta.push(`风格: ${esc(mo.trade_style)}`);
|
meta.push(monitorEntryStyleHtml(mo, intraday));
|
||||||
else meta.push("风格: —");
|
|
||||||
const riskLine = formatMonitorRiskMeta(mo, trendPlan);
|
const riskLine = formatMonitorRiskMeta(mo, trendPlan);
|
||||||
if (riskLine) meta.push(riskLine);
|
if (riskLine) meta.push(riskLine);
|
||||||
const latestRiskLine = formatLatestRiskMeta(mo, trendPlan, pos, tpsl);
|
const latestRiskLine = formatLatestRiskMeta(mo, trendPlan, pos, tpsl);
|
||||||
@@ -3188,7 +3198,7 @@
|
|||||||
const fcBadge = o.force_close_enabled ? forceCloseSymbolBadgeHtml(o) : "";
|
const fcBadge = o.force_close_enabled ? forceCloseSymbolBadgeHtml(o) : "";
|
||||||
return `<div class="hub-mini-card">
|
return `<div class="hub-mini-card">
|
||||||
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} ${tcBadge}${fcBadge} · ${renderDirectionHtml(o.direction)}</div>
|
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} ${tcBadge}${fcBadge} · ${renderDirectionHtml(o.direction)}</div>
|
||||||
<div class="hub-mini-line">触发 ${fmtSymbolPrice(o.trigger_price, sym, tickMap)} · SL ${fmtSymbolPrice(o.stop_loss, sym, tickMap)} · TP ${fmtSymbolPrice(o.take_profit, sym, tickMap)} · ${esc(o.trade_style || o.monitor_type || "下单监控")}</div>
|
<div class="hub-mini-line">触发 ${fmtSymbolPrice(o.trigger_price, sym, tickMap)} · SL ${fmtSymbolPrice(o.stop_loss, sym, tickMap)} · TP ${fmtSymbolPrice(o.take_profit, sym, tickMap)} · ${esc(o.entry_model_label || o.trade_style || o.monitor_type || "下单监控")}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
|
|||||||
Reference in New Issue
Block a user