# Current recommendations Last reviewed: 2026-08-11 03:19 CDT. This file is the short list of work worth considering next. Verified history, measurements and completed work remain in `docs/IMPLEMENTATION_PLAN.md`. ## Fix next ### Keep snapping out of the price axes `ConfluenceChart.withinPlot()` currently checks plot-relative coordinates against `chartEl.clientWidth` and `clientHeight`. The element also contains the price and time axes, so hovering the right price axis can leave the snap dot visible at the plot edge. Recommended fix: 1. Compare against the measured plot canvas width and height. 2. Add a Playwright page-pixel test that moves from a bar into the actual right axis rectangle and expects the snap dot to disappear, then return over the plot and expect it to reappear. 3. Reuse the same plot-relative conversion for selection and anchor dragging; do not add another coordinate frame. This was discovered by test research but deliberately not committed as a failing test because it requires production code to correct. ### Show unambiguous market freshness The best location is the status strip directly below the chart. Keep the header for coarse transport state (`LIVE · SCHWAB`, `DELAYED · YAHOO 10m`) and replace the ambiguous `LAST BAR` age with browser-observed receipt time: ```text UPDATED 3s AGO ``` On mobile use a compact form: ```text Updated 3s ago · Live ``` No additional request is needed. Record `Date.now()` when an existing WebSocket `bar` message arrives. A snapshot should initially say `LOADED JUST NOW`; level, alert and preference messages are not market updates and must not refresh it. Do not derive update age from `bar.t`: it is the bucket start, and selected timeframe bar messages currently overwrite `status.last_bar_t`, making an hourly bar appear stale even when just received. A later, more complete implementation can add these fields to the existing WebSocket rather than add polling: - exact `last_trade_t` where the source supplies it; - `last_settled_m1_t`, measured from the end of the minute; - `last_source_received_at`; - an application heartbeat for transport health. Stale warnings must distinguish market closure from transport failure and must subtract Yahoo's declared delay before calling delayed data overdue. ## Mobile authoring The detailed plan is in `docs/mobile_enhance.md`. Recommended first tranche: 1. Use one plot-relative pointer path for placement, selection and anchor drag. 2. Add touch-sized invisible hit regions without enlarging the visual marks. 3. Keep the first tap's trendline anchor visible with price/time, Cancel and Undo anchor. 4. Add a compact sticky mobile tool rail next to the chart. 5. Add a selected-drawing action bar so End here and Delete do not require right-click or a hardware keyboard. Prefer tap-tap trendlines on touch devices. Reserve one-finger vertical movement for page scrolling, retain horizontal chart panning and pinch zoom, and offer a chart-focused landscape/fullscreen mode. ## Market-data alternatives No durable unauthenticated source of free real-time CME `/ES` data has been identified. CME real-time access is normally broker-subsidized and tied to an authenticated exchange entitlement, not a public free API. Practical ranking: 1. Keep Schwab for verified entitled real-time streaming and Yahoo for delayed development/history seeding. 2. Pilot Tastytrade/dxLink on a live futures-approved account. Confirm actual delay, candle retention, continuous/root symbol behavior and server-side-use terms before integrating it. 3. Consider IBKR as the strongest low-cost fallback if literal zero cost is not required; resolve and roll the active contract explicitly for live data. 4. Consider TradeStation only if its account-funding/API-access requirements are already acceptable. 5. Evaluate Nasdaq Data Link CHRIS only for continuous daily seeding after confirming current freshness and free-key availability. Do not build a backend around scraped TradingView, CME, Barchart, Investing.com, MarketWatch or Stooq pages. Public display access is not a supported market-data API or a CME redistribution license. References: - Tastytrade streaming: https://developer.tastytrade.com/streaming-market-data/ - IBKR market data: https://www.interactivebrokers.com/en/pricing/research-news-marketdata.php - TradeStation API: https://www.tradestation.com/platforms-and-tools/trading-api/ - Nasdaq Data Link API: https://docs.data.nasdaq.com/ ## Deferred test tied to production work When startup seeding is changed to bulk-load bars, add an integration test that asserts expensive level rebuilding happens once and that final stores/levels match incremental ingestion. Do not assert a wall-clock duration and do not add a test that merely codifies today's slow startup. ## Test and deployment commands README is authoritative for local pytest, local Playwright E2E, pre-deploy and production smoke-test commands. Browser E2E creates and deletes drawings, so it must remain pointed at the local stack rather than production.