(function () { var posTimer = null; function fmtNum(v, digits) { if (v === null || v === undefined) return '--'; return Number(v).toFixed(digits === undefined ? 2 : digits); } function buildPosCard(row) { var pnlClass = ''; if (row.float_pnl > 0) pnlClass = 'pnl-pos'; if (row.float_pnl < 0) pnlClass = 'pnl-neg'; var pnlText = '--'; if (row.float_pnl != null) { var sign = row.float_pnl >= 0 ? '+' : ''; pnlText = sign + fmtNum(row.float_pnl) + '元'; if (row.float_pct != null) { pnlText += ' (' + sign + fmtNum(row.float_pct) + '%)'; } } var rr = row.rr_ratio != null ? row.rr_ratio + ':1' : '--'; var openT = (row.open_time || '').replace('T', ' ').slice(0, 16); return ( '
' + '
' + '
' + row.symbol + ' ' + row.direction + '
' + '
' + '
' + '
' + '
来源 手动输入 · 风险 ' + fmtNum(row.risk_pct) + '%≈' + fmtNum(row.risk_amount) + '元
' + '
' + '
' + fmtNum(row.entry_price) + '
' + '
' + fmtNum(row.stop_loss) + '
' + '
' + fmtNum(row.take_profit) + '
' + '
' + rr + '
' + '
' + (row.mark_price != null ? fmtNum(row.mark_price) : '--') + '
' + '
' + pnlText + '
' + '
' + fmtNum(row.est_fee) + '元
' + '
' + '
' + (row.est_pnl_net != null ? fmtNum(row.est_pnl_net) + '元' : '--') + '
' + '
' + '
' ); } function pollPositions() { var list = document.getElementById('position-live-list'); if (!list) return; fetch('/api/position_live') .then(function (r) { return r.json(); }) .then(function (rows) { if (!rows.length) { list.innerHTML = '
暂无持仓,左侧录入后显示
'; return; } list.innerHTML = rows.map(buildPosCard).join(''); }) .catch(function () { /* ignore */ }); } document.addEventListener('DOMContentLoaded', function () { pollPositions(); posTimer = setInterval(pollPositions, 1000); }); })();