SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%

web: charts — légende alimentée par les clés tracées du moteur (sma, upper/middle/lower, macd/signal/hist)

Simon-Pierre Boucher committed 18 days ago (Sep 7, 2026) parent 9784272

2 changed files +5 −2

modified hfmarketdata/web/src/pages/charts/ChartsPage.jsx +4 −1
@@ -131,7 +131,10 @@ export default function ChartsPage() {
131 131 const vals = {}
132 132 for (const ind of chart.getIndicators()) {
133 133 vals[ind.id] = {}
134 − for (const [k, arr] of Object.entries(ind.values || {})) {
134 + // only the plotted keys (engine names: sma, upper/middle/lower, macd/signal/hist…), not helper arrays
135 + const keys = ind.plotColors && Object.keys(ind.plotColors).length ? Object.keys(ind.plotColors) : Object.keys(ind.values || {})
136 + for (const k of keys) {
137 + const arr = ind.values?.[k]
135 138 // the engine stores plots as typed arrays (Float64Array): not Array.isArray, NaN = no value yet
136 139 const v = arr && typeof arr.length === 'number' && arr.length ? arr[arr.length - 1] : null
137 140 vals[ind.id][k] = v == null || Number.isNaN(v) ? null : v
modified hfmarketdata/web/src/pages/charts/Legend.jsx +1 −1
@@ -91,7 +91,7 @@ export default function Legend({ state, name, hover, lastBar, prevBar, indValues
91 91 <span className="ch-swatch" style={{ background: color }} aria-hidden="true" />
92 92 <button type="button" className="ch-legend-btn" onClick={() => setEditing(editing === ind.id ? null : ind.id)} aria-expanded={editing === ind.id} title="Edit parameters">{indicatorShortLabel(ind)}</button>
93 93 <span className="ch-legend-vals mono">
94 − {(def?.outputs || ['value']).map(k => <span key={k}>{def?.outputs.length > 1 && <i>{k} </i>}{fmtVal(vals[k], decimals)}</span>)}
94 + {(() => { const keys = Object.keys(vals).length ? Object.keys(vals) : (def?.outputs || ['value']); return keys.map(k => <span key={k}>{keys.length > 1 && <i>{k} </i>}{fmtVal(vals[k], decimals)}</span>) })()}
95 95 </span>
96 96 <button type="button" className="ch-legend-x" aria-label={`Remove ${indicatorShortLabel(ind)}`} onClick={() => onRemoveIndicator(ind.id)}><CloseIcon /></button>
97 97 {editing === ind.id && <IndicatorEditor ind={ind} onChange={p => onUpdateIndicator(ind.id, p)} onClose={() => setEditing(null)} />}
98 98