Problem
PriceChart paints 240 synthetic candles via seedCandles(anchor, 240) on mount. Only the right-most candle is live (oracle ticks update its OHLC). Anything left of "now" is decorative — refresh the page and the entire history changes.
Proposal
Persist OHLC buckets inside the edge per market per timeframe.
- New
BucketStore in AppState: RwLock<HashMap<(MarketId, Tf), VecDeque<Candle>>>.
- On every
record_fill, find the active bucket for each supported Tf (1m, 5m, 15m, 1h, 4h, 1d) and update high/low/close + volume.
- Roll the bucket forward when wall clock crosses the next boundary.
- New REST endpoint:
GET /v1/candles/:marketId?tf=1m&limit=240
Returns Candle[] with { time, open, high, low, close, volume }.
- FE:
PriceChart.useEffect swaps seedCandles(...) for an initial fetch of /v1/candles.
Acceptance
Notes
Unblocks #3 (real chart volume bars) and #4 (real 24h change %).
Problem
PriceChart paints 240 synthetic candles via
seedCandles(anchor, 240)on mount. Only the right-most candle is live (oracle ticks update its OHLC). Anything left of "now" is decorative — refresh the page and the entire history changes.Proposal
Persist OHLC buckets inside the edge per market per timeframe.
BucketStoreinAppState:RwLock<HashMap<(MarketId, Tf), VecDeque<Candle>>>.record_fill, find the active bucket for each supportedTf(1m,5m,15m,1h,4h,1d) and update high/low/close + volume.Candle[]with{ time, open, high, low, close, volume }.PriceChart.useEffectswapsseedCandles(...)for an initial fetch of/v1/candles.Acceptance
Notes
Unblocks #3 (real chart volume bars) and #4 (real 24h change %).