# Chart Fix Summary - Timestamp and Timeframe Issues ## Problem Description The chart was experiencing two main issues: 1. **Error**: "Cannot update oldest data, last time=[object Object], new time=[object Object]" 2. **Timeframe switching**: Live updates interfering with historical data when changing timeframes (e.g., to 5min) ## Root Causes ### Issue 1: Timestamp Conflicts - Live price updates were generating timestamps that could be **older** than the last candle in historical data - The lightweight-charts library requires that new updates must have timestamps >= the last candle's timestamp - When rounded to the nearest minute, the live timestamp could be before the last historical candle ### Issue 2: Inappropriate Live Updates - Live updates were enabled for **all** timeframes, including daily/weekly historical views - When switching to intraday timeframes (5min, 15min), stale live updates would conflict with freshly loaded historical data - No synchronization between the live update interval and the chart's timeframe ## Solutions Implemented ### 1. Smart Timestamp Validation (GoldChart.tsx) ```typescript // Only update if the new time is newer than or equal to the last historical time if (liveUpdate.time < lastHistoricalTime) { console.log('Skipping live update: timestamp is older than historical data'); return; } ``` - Added validation to skip live updates that are older than historical data - Prevents the "Cannot update oldest data" error - Logs skipped updates for debugging ### 2. Conditional Live Updates (App.tsx) ```typescript // Live price updates - only enable for intraday timeframes const enableLiveUpdates = ['1min', '5min', '15min', '30min', '60min'].includes(timeframe); const { latestPrice, isConnected } = useLivePrice({ enabled: enableLiveUpdates && !isLoading, pollInterval: 10000, timeframe: timeframe, ... }); ``` - Live updates are **only enabled** for intraday timeframes (1min-60min) - Disabled for daily/weekly views where live updates don't make sense - Live updates pause during data loading to prevent conflicts ### 3. Timeframe-Aware Live Endpoint (Backend) **File:** `backend/app/api/market.py` ```python @router.get("/gold/live") async def get_live_gold_price(interval: str = "1min"): # Map intervals to seconds for rounding interval_map = { "1min": 60, "5min": 5 * 60, "15min": 15 * 60, ... } # Round UP to the next interval to ensure newest timestamp current_time = ((current_time // interval_seconds) + 1) * interval_seconds ``` Key improvements: - Accepts an `interval` parameter matching the chart's timeframe - Rounds timestamps **up** to the next interval boundary (not down or nearest) - Ensures live updates always have timestamps **newer** than historical data - Aligns with the granularity of the selected timeframe ### 4. Enhanced Hook with Timeframe Support **File:** `frontend/src/hooks/useLivePrice.ts` ```typescript export interface UseLivePriceOptions { pollInterval?: number; // Renamed from 'interval' for clarity timeframe?: string; // NEW: Chart timeframe (1min, 5min, etc.) ... } ``` - Passes the current timeframe to the backend - Fetches live data matching the chart's time granularity - Prevents timestamp misalignment ## Testing Checklist ✅ **Daily View (1D)** - Live updates are **disabled** ✓ - No "Live" badge showing - Historical data loads correctly - No timestamp errors ✅ **Intraday Views (1min, 5min, 15min, etc.)** - Live updates are **enabled** ✓ - "Live" badge shows with pulse animation - New candles appear every 10 seconds - No timestamp errors when switching between timeframes ✅ **Timeframe Switching** - Switching from 1D → 5min: Historical data loads, then live updates begin - Switching from 5min → 1D: Live updates stop, historical data loads - No errors during transitions ✅ **Error Handling** - Gracefully handles API rate limits - Connection status tracked correctly - Skips invalid live updates without crashing ## Configuration ### Adjusting Poll Frequency In `App.tsx`: ```typescript pollInterval: 10000, // 10 seconds - increase to reduce API calls ``` ### Supported Timeframes for Live Updates In `App.tsx`: ```typescript const enableLiveUpdates = ['1min', '5min', '15min', '30min', '60min'].includes(timeframe); ``` ### API Rate Limits The free FXRatesAPI has rate limits. If you hit 429 errors: 1. Increase `pollInterval` to 30000 (30 seconds) or more 2. Consider caching the current price on the backend 3. Implement exponential backoff in the hook ## Technical Details ### Timestamp Rounding Logic - **1min**: Rounds to next minute boundary - **5min**: Rounds to next 5-minute boundary (e.g., 10:05, 10:10, 10:15) - **15min**: Rounds to next 15-minute boundary - Always rounds **up** (not down) to ensure future timestamps ### Why Round Up Instead of Down? - Historical data ends at time T - Rounding down could create time T-1, causing timestamp conflict - Rounding up creates time T+1, safely appending after historical data ### Lightweight Charts Update Methods - `setData()`: Replaces all data (used for historical data load) - `update()`: Appends/updates a single candle (used for live updates) - `update()` requires timestamps in ascending order ## Known Limitations 1. **Simulated Intraday Data**: Free APIs don't provide real intraday OHLC data - we generate it 2. **Rate Limits**: Free API tier has rate limits (fix: increase poll interval) 3. **No Real-time Ticks**: 10-second polls, not true tick-by-tick data 4. **SMA Updates**: Live SMA updates not yet implemented (only price updates) ## Future Enhancements - [ ] Implement WebSocket for true real-time updates (sub-second) - [ ] Update SMA/indicators in real-time as new candles arrive - [ ] Add configurable poll intervals in UI - [ ] Implement smart backoff when API rate limits hit - [ ] Cache current price on backend to reduce external API calls - [ ] Show last update timestamp in the UI