diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index f0f866e..ce6e2a4 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -7452,44 +7452,70 @@ body.funds-fullscreen-open { margin: 0; font-size: 0.72rem; } +.archive-cum-wrap { + display: flex; + flex-direction: column; + gap: 6px; +} .archive-cum-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; - margin-bottom: 4px; } .archive-cum-end { font-size: 0.78rem; font-weight: 700; font-variant-numeric: tabular-nums; } +.archive-cum-body { + display: grid; + grid-template-columns: 3.2em 1fr; + gap: 6px; + align-items: stretch; +} +.archive-cum-yaxis { + display: flex; + flex-direction: column; + justify-content: space-between; + font-size: 0.58rem; + color: rgba(255, 255, 255, 0.42); + font-variant-numeric: tabular-nums; + padding: 2px 0 14px; + text-align: right; +} +.archive-cum-plot { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; +} .archive-cum-chart { width: 100%; - height: 110px; + height: 96px; display: block; border-radius: 8px; - background: rgba(0, 0, 0, 0.15); + background: rgba(0, 0, 0, 0.12); } -.archive-cum-ylabel, -.archive-cum-xlabel { - fill: rgba(255, 255, 255, 0.45); - font-size: 9px; - font-family: inherit; +.archive-cum-xaxis { + display: flex; + justify-content: space-between; + font-size: 0.58rem; + color: rgba(255, 255, 255, 0.42); + font-variant-numeric: tabular-nums; + padding: 0 2px; } -.archive-cum-zero { - stroke: rgba(255, 255, 255, 0.15); +.archive-cum-foot { + font-size: 0.62rem; + line-height: 1.35; +} +.archive-cum-grid { + stroke: rgba(255, 255, 255, 0.06); stroke-width: 1; - stroke-dasharray: 3 3; } -.archive-cum-area { - opacity: 0.18; -} -.archive-cum-area.archive-cum-line--up { - fill: #4cd97f; -} -.archive-cum-area.archive-cum-line--down { - fill: #ff6b6b; +.archive-cum-grid--zero { + stroke: rgba(255, 255, 255, 0.16); + stroke-dasharray: 4 4; } .archive-cum-line { fill: none; @@ -7507,12 +7533,16 @@ body.funds-fullscreen-open { stroke: rgba(0, 0, 0, 0.35); stroke-width: 1; } -.archive-cum-dot.archive-cum-line--up { +.archive-cum-dot--up { fill: #4cd97f; } -.archive-cum-dot.archive-cum-line--down { +.archive-cum-dot--down { fill: #ff6b6b; } +.archive-cum-dot--last { + stroke: rgba(255, 255, 255, 0.35); + stroke-width: 1.5; +} @media (max-width: 520px) { .archive-viz-kpis { grid-template-columns: 1fr; diff --git a/manual_trading_hub/static/archive.js b/manual_trading_hub/static/archive.js index 624ef92..78a9824 100644 --- a/manual_trading_hub/static/archive.js +++ b/manual_trading_hub/static/archive.js @@ -661,15 +661,21 @@ if (!series.length) { return '
当前区间暂无平仓数据
'; } - const w = 400; - const h = 110; - const padL = 36; - const padR = 8; - const padT = 8; - const padB = 22; + const w = 320; + const h = 96; + const padL = 6; + const padR = 6; + const padT = 10; + const padB = 10; const vals = series.map(function (s) { return s.cum; }); - const minV = Math.min(0, ...vals); - const maxV = Math.max(0, ...vals); + const rawMin = Math.min.apply(null, vals); + const rawMax = Math.max.apply(null, vals); + let minV = Math.min(0, rawMin); + let maxV = Math.max(0, rawMax); + const span = maxV - minV || Math.max(Math.abs(rawMax), Math.abs(rawMin), 1); + const yPad = span * 0.14; + minV -= yPad; + maxV += yPad; const range = maxV - minV || 1; const innerW = w - padL - padR; const innerH = h - padT - padB; @@ -677,78 +683,83 @@ return padT + innerH - ((v - minV) / range) * innerH; }; const zeroY = yOf(0); + const showZero = rawMin < -0.0001 || rawMax > 0.0001; const pts = series.map(function (s, i) { const x = padL + (i / Math.max(series.length - 1, 1)) * innerW; const y = yOf(s.cum); - return { x: x, y: y }; + return { x: x, y: y, day: s.day, pnl: s.pnl, cum: s.cum }; }); const linePts = pts.map(function (p) { return p.x.toFixed(1) + "," + p.y.toFixed(1); }).join(" "); - const areaPts = - linePts + - " " + - pts[pts.length - 1].x.toFixed(1) + - "," + - zeroY.toFixed(1) + - " " + - pts[0].x.toFixed(1) + - "," + - zeroY.toFixed(1); const last = series[series.length - 1]; const lastCls = last.cum >= 0 ? "pnl-pos" : "pnl-neg"; const lineCls = last.cum >= 0 ? "archive-cum-line--up" : "archive-cum-line--down"; const sign = last.cum > 0 ? "+" : ""; const fmtAxis = function (v) { const a = Math.abs(v); - if (a >= 100) return (v > 0 ? "+" : "") + v.toFixed(0); - if (a >= 10) return (v > 0 ? "+" : "") + v.toFixed(1); - return (v > 0 ? "+" : "") + v.toFixed(2); + if (a >= 100) return (v > 0 ? "+" : "") + v.toFixed(0) + "U"; + if (a >= 10) return (v > 0 ? "+" : "") + v.toFixed(1) + "U"; + return (v > 0 ? "+" : "") + v.toFixed(2) + "U"; }; - const yTicks = [maxV, 0, minV].filter(function (v, i, arr) { - return arr.indexOf(v) === i; - }); - const yLabels = yTicks + const yTop = fmtAxis(maxV); + const yMid = showZero ? "0" : fmtAxis((maxV + minV) / 2); + const yBot = fmtAxis(minV); + const gridLines = [maxV, showZero ? 0 : null, minV] + .filter(function (v, i, arr) { + return v != null && arr.indexOf(v) === i; + }) .map(function (v) { + const y = yOf(v).toFixed(1); + const cls = v === 0 ? "archive-cum-grid archive-cum-grid--zero" : "archive-cum-grid"; + return '