Skip to content

fix(quote): separate after-hours from the day's price; EXT extended-hours chart (depends on #43) - #52

Open
niravpatidar37 wants to merge 31 commits into
ErTasselli:mainfrom
niravpatidar37:feat/extended-hours
Open

niravpatidar37 wants to merge 31 commits into
ErTasselli:mainfrom
niravpatidar37:feat/extended-hours

Conversation

@niravpatidar37

Copy link
Copy Markdown

Depends on #43. This branch builds on #43's intraday 1D chart (nasdaq.intraday / minutePointsToCandles), so until #43 merges, GitHub also lists its commits here. The new work is only the last 2 commits: cfb1e5a and dd52ef2 (2-commit diff). Once #43 merges, this PR shrinks to just those.

Problem: after hours, the quote showed the wrong day change

Outside regular hours, Nasdaq's /info primaryData is the pre-market or after-hours trade, and its change is measured from the 16:00 close. secondaryData holds the regular close. The quote mapped primaryData as the day's price, so an after-hours move was labelled as the day's change.

SPY at 19:56 ET, Oct 29:

Nasdaq Shown before Shown now
Regular close $769.49, −0.37% not shown $769.49, −0.37%
After-hours last $764.74, −0.62% vs the close as "Last", −0.62% as the day change separate line: After hours $764.74 −0.62% · 7:56 PM ET
Previous close $772.31 (price − change) $769.66 (summary field, inconsistent) $772.31

The same mix-up fed today's live candle on 6M/1Y (it closed at the after-hours price) and the "day %" price alerts.

Changes

Server (cfb1e5a)

  • splitSessions(info) in providers/nasdaq.ts: when secondaryData is a closed regular session, it becomes price/change, and the extended trade becomes quote.extended = { session: "pre" | "post", price, change, changePercent, time }. During regular hours nothing changes.
  • yahooExtended() maps Yahoo's preMarket* / postMarket* fields the same way, for the fallback provider.
  • previousClose is derived from price − change, so it always matches the change shown.
  • GET /api/history/:symbol?range=1D&ext=1 returns 4:00–20:00 ET five-minute candles, and pre/post candles carry session: "pre" | "post". Only the literal 1 on 1D enables it, so the cache key space stays at two entries per symbol. Other ranges ignore it.

Web (dd52ef2)

  • Quote panel: the regular close stays the headline, with a separate After hours / Pre-market line showing price, change and time.
  • 1D chart: an EXT button (off by default) adds extended-hours candles, drawn faded on shaded background bands, with the full 4:00–20:00 day reserved so candles keep normal width.
  • Three new LEARN glossary entries (pre-market, after hours, EXT). The pre-market and after-hours ones warn that thin trading makes those prices less reliable.

Verification

  • npm test: 190 tests / 23 files pass with --network none. That includes 9 new tests built from the real Nasdaq after-hours payload above: session split, pre-market labelling, a blank secondary price not read as a $0 close, junk input, the extended candle window and tags, and the Yahoo mapping.
  • tsc and next build are clean.
  • Live against docker compose up --build after hours (SPY, AAPL):
    • The quote shows the regular close and change with a separate extended line.
    • ext=1 returned 66 pre + 78 regular + 48 post candles, exactly the 192 five-minute slots from 4:00 to 20:00.
    • The 6M chart's last candle equals the regular close.
    • ext=yes, and ext=1 on 6M, are ignored.
  • Headless Chromium, 6 checks: the after-hours line and its tooltip, EXT hidden on 6M, EXT fetching ext=1, the pressed state, and no page errors. Security hardening + live data, alerts, Greeks, CSV, heatmap fixes, learning features (paper trading, tooltips, replay), logo #43's 14-check UI suite still passes.

Notes

  • The extended-hours chart comes from Nasdaq only. If Nasdaq is down, 1D falls back to the regular-session chart.
  • Extended-hours data includes thin, odd prints, e.g. a spike right at 16:00 that is likely the closing cross. They are shown as reported.
  • Pre-market behaviour was verified with captured payloads and unit tests, not yet live, because the check ran after hours.

Security impact: one new query parameter, allowlisted to a single value on one range, with a bounded cache key. The new provider fields are parsed into numbers and a regex-matched time string, and rendered by React as text. No new outbound endpoints.

niravpatidar37 and others added 30 commits October 14, 2026 11:27
…ken), relay Retry-After, handle upstream errors
Tile sizes came from market cap, which tracks the live price, so every
3s poll re-ran the treemap and every tile edge shifted. Freeze tile sizes
and membership in a snapshot that polls only recolor, and re-take it on
market switch or after 5 minutes.
Prompt chevron + rising candlesticks in the app's own amber/green/red.
All assets generated by docs/brand/tools/build_brand.py (pinned, SHA-256
verified JetBrains Mono outlines; contrast and SVG-safety gates).
Wires app/icon.svg, app/apple-icon.png, theme-color, a top-bar mark, and a
light/dark README logo.
fitContent() stretched early-session 1D data (e.g. 13 five-minute bars at
10:30) across the whole panel, producing ~70 px candles. Reserve the full
9:30-16:00 session (78 slots) on 1D, and at least 60 slots elsewhere, so
the chart fills in left to right like a normal terminal.

Squash of fix/chart-bar-width (also proposed alone as ErTasselli#48).
…n price

Outside regular hours Nasdaq's primaryData is the extended-hours trade, with
its change measured from the 16:00 close; it was shown as the day's price and
change (SPY after hours: -0.62% shown, the day was -0.37%). splitSessions()
now uses the closed secondaryData as the regular price and returns the
extended trade separately as quote.extended (Yahoo: pre/postMarket* fields).
previousClose is derived from price - change, which matches the change shown.

Also adds ext=1 on 1D history: 4:00-20:00 ET five-minute candles, with
pre/post candles tagged via candle.session. Only the literal '1' on 1D enables
it, so the cache key space stays bounded.
…uote panel

1D gets an EXT button: pre-market and after-hours candles drawn faded on a
shaded background, with the full 4:00-20:00 day reserved. The quote panel
shows the regular close as the main price plus a separate 'After hours' /
'Pre-market' line with change and time, with LEARN explanations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants