Add hub TP profit field, 2-decimal options PnL, and exchange mark price display.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-08 17:22:26 +08:00
parent e3e53ff7f5
commit 279648de56
8 changed files with 58 additions and 7 deletions
+1 -1
View File
@@ -455,7 +455,7 @@
'<div class="pos-cell"><span class="pos-label">指数价</span><span class="pos-value">' + fmt(p.idx_px, 0) + "</span></div>" +
'<div class="pos-cell"><span class="pos-label">到期平衡</span><span class="pos-value">' + fmt(p.expiry_be_px, 0) + "</span></div>" +
'<div class="pos-cell"><span class="pos-label">平掉回本</span><span class="pos-value">' + fmt(p.close_be_px, 0) + "</span></div>" +
'<div class="pos-cell"><span class="pos-label">浮盈亏</span><span class="pos-value ' + uplCls + '">' + fmt(p.upl, 4) + "</span></div>" +
'<div class="pos-cell"><span class="pos-label">浮盈亏</span><span class="pos-value ' + uplCls + '">' + fmt(p.upl, 2) + "</span></div>" +
'<div class="pos-cell"><span class="pos-label">收益率</span><span class="pos-value ' + uplCls + '">' +
(p.upl_ratio_pct != null ? p.upl_ratio_pct + "%" : "—") + "</span></div>" +
"</div></div>"
@@ -920,6 +920,7 @@ function formatOrderMarkDisplay(o){
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;
if(row.price_display && row.price_display !== "-") return row.price_display;
return markNum.toFixed(6);
}
if(row.price_display && row.price_display !== "-") return row.price_display;
+1 -1
View File
@@ -137,4 +137,4 @@
</div>
</div>
<script src="/static/options_expiry_countdown.js?v=1"></script>
<script src="/static/options_panel.js?v=13"></script>
<script src="/static/options_panel.js?v=14"></script>
+6
View File
@@ -355,6 +355,12 @@ def apply_order_price_display_fields(
payload["take_profit_display"] = (
format_price_fn(symbol, disp_tp) if disp_tp is not None else ""
)
mark_raw = mark_price if mark_price is not None else None
if mark_raw is not None and format_price_fn is not None and symbol is not None:
try:
payload["exchange_mark_price_display"] = format_price_fn(symbol, float(mark_raw))
except (TypeError, ValueError):
payload["exchange_mark_price_display"] = None
return payload
+12
View File
@@ -1989,6 +1989,7 @@ _ORDER_PRICE_MERGE_KEYS = (
"display_rr_ratio",
"latest_risk_amount",
"contracts",
"reward_at_tp_usdt",
"exchange_initial_margin",
"plan_margin",
"time_close_enabled",
@@ -2120,6 +2121,17 @@ def _merge_flask_position_breakeven(agent_row: dict, snap: dict | None, hub_mon:
break
if isinstance(matched, dict):
_apply_order_price_op_fields(p, matched)
disp = matched.get("exchange_mark_price_display")
if disp is not None and str(disp).strip() not in ("", "-"):
p["mark_price_fmt"] = str(disp)
mp = matched.get("exchange_mark_price")
if mp is not None:
try:
mpf = float(mp)
if mpf > 0:
p["mark_price"] = mpf
except (TypeError, ValueError):
pass
def _agent_position_has_mark(p: dict) -> bool:
+9
View File
@@ -1968,6 +1968,15 @@ body.market-chart-fs-open {
font-weight: 600;
}
.hub-pos-card .pos-tp-profit {
color: #4cd97f;
font-weight: 600;
}
html[data-theme="light"] .hub-pos-card .pos-tp-profit {
color: #1a8f4a;
}
.hub-pos-card .pos-footer {
display: flex;
flex-wrap: wrap;
+27 -4
View File
@@ -116,7 +116,7 @@
function positionTableHeadHtml(compact) {
const pnlTh = showAccountPnlPref() ? "<th>浮盈</th>" : "";
const cls = compact ? " data-table data-table-positions" : "";
return `<table class="data-table${cls}"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th>${pnlTh}<th>操作</th></tr></thead><tbody>`;
return `<table class="data-table${cls}"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>盈利金额</th>${pnlTh}<th>操作</th></tr></thead><tbody>`;
}
let tpslPending = null;
let lastMonitorRows = [];
@@ -864,6 +864,26 @@
return null;
}
function resolveTpProfitUsdt(mo, pos) {
const m = mo || {};
const p = pos || {};
const raw =
m.reward_at_tp_usdt != null && m.reward_at_tp_usdt !== ""
? m.reward_at_tp_usdt
: p.reward_at_tp_usdt != null && p.reward_at_tp_usdt !== ""
? p.reward_at_tp_usdt
: null;
if (raw == null || raw === "") return null;
const n = Number(raw);
return Number.isFinite(n) ? n : null;
}
function formatTpProfitCell(mo, pos) {
const n = resolveTpProfitUsdt(mo, pos);
if (n == null) return "—";
return `<span class="pos-tp-profit">${fmt(n, 2)}U</span>`;
}
function formatMonitorRiskMeta(mo, trendPlan) {
const m = mo || {};
const t = trendPlan || {};
@@ -3155,7 +3175,8 @@
<div class="pos-cell"><span class="pos-label">止损</span><span class="pos-value">${sl != null && sl !== "" ? fmtSymbolPrice(sl, symbol, tickMap) : ""}</span></div>
<div class="pos-cell"><span class="pos-label">止盈</span><span class="pos-value${tpMonitored ? " pos-tp-program" : ""}">${formatTpCellValue(tp, tpMonitored, symbol, tickMap)}</span></div>
<div class="pos-cell"><span class="pos-label">盈亏比</span><span class="pos-value">${rr != null ? fmt(rr, 2) + ":1" : ""}</span></div>
<div class="pos-cell"><span class="pos-label">张数</span><span class="pos-value">${fmt(pos.contracts, 4)}</span></div>
<div class="pos-cell"><span class="pos-label">张数</span><span class="pos-value">${fmt(pos.contracts, 2)}</span></div>
<div class="pos-cell"><span class="pos-label">盈利金额</span><span class="pos-value">${formatTpProfitCell(mo, pos)}</span></div>
${
showAccountPnlPref()
? `<div class="pos-cell"><span class="pos-label">浮盈亏</span><span class="pos-value ${pnlFmt.cls}">${pnlText}</span></div>`
@@ -3308,12 +3329,14 @@
const pnlTd = showAccountPnlPref()
? `<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 2)}</td>`
: "";
const tpProfitTd = `<td>${formatTpProfitCell(monitorOrder, x)}</td>`;
return `<tr>
<td class="td-symbol"><button type="button" class="btn-open-market sym-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)">${esc(x.symbol)}</button>${tcBadge}${fcBadge}${symBeBadge}</td>
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
<td class="td-entry">${fmtEntryPrice(x, tickMap)}</td>
<td>${fmtMarkPrice(x, tickMap)}</td>
<td>${fmt(x.contracts, 4)}</td>
<td>${fmt(x.contracts, 2)}</td>
${tpProfitTd}
${pnlTd}
<td class="td-actions">${actionCell}</td>
</tr>`;
@@ -3499,7 +3522,7 @@
<td>${p.idx_px != null ? fmt(p.idx_px, 0) : "—"}</td>
<td>${p.expiry_be_px != null ? fmt(p.expiry_be_px, 0) : "—"}</td>
<td>${p.close_be_px != null ? fmt(p.close_be_px, 0) : "—"}</td>
<td class="${pnlCls(p.upl)}">${fmt(p.upl, 4)}</td>
<td class="${pnlCls(p.upl)}">${fmt(p.upl, 2)}</td>
<td class="${pnlCls(p.upl)}">${p.upl_ratio_pct != null ? esc(p.upl_ratio_pct) + "%" : "—"}</td>
</tr>`;
});
+1 -1
View File
@@ -1152,6 +1152,6 @@
<script src="/assets/time_close_ui.js?v=3"></script>
<script src="/assets/options_expiry_countdown.js?v=1"></script>
<script src="/assets/backup.js?v=1"></script>
<script src="/assets/app.js?v=20260708-options-expiry-cd"></script>
<script src="/assets/app.js?v=20260708-hub-tp-profit"></script>
</body>
</html>