{% extends "base.html" %} {% block title %}Markets{% endblock %} {% block description %}A live market overview — the major indexes, gold, crude, and bitcoin, each its own day chart — plus your personal watchlist.{% endblock %} {% block extra_css %}{% endblock %} {% block main %}
{# Market-hours banner: makes the current session unmistakable. The dot colour keys off data-session; hero.js keeps it live as the session flips. #}
{{ session_label }} {% if session == 'closed' %}Prices update during market hours · ET{% else %}US equities · all times ET{% endif %}
{# The market overview: one chart per instrument (the major indexes + gold, crude and bitcoin), each on its own axis showing the day's actual values (points or dollars) with its live value + % change from the open. Cash indexes during the regular session, the E-mini futures off-hours. hero.js builds the cards into the grid from /api/dashboard; this is its mount point. #}

Market overview

value & % change vs prev close
{# Until /api/dashboard answers, the grid shows one shimmer-skeleton card per overview slot — same shape as the real sparkline cards, so the page doesn't jump when they land. hero.js hides this wrapper (display: contents, so the skeletons are real grid items) on the first draw. #}
{# Overview symbols as hidden data-ticker nodes: the live stream registers them with the interest registry so the demand-driven intraday poll keeps their bars fresh while the dashboard is open. The graph itself is drawn from /api/dashboard; these carry no fields, so quote events no-op on them. #} {# Sector heatmap: the 11 SPDR sector ETFs, coloured by today's move, so the dashboard answers "what part of the market is driving it". hero.js fills the grid from /api/dashboard; the hidden interest nodes keep the ETFs polled. #}

What’s moving

sectors · latest-session % move
{# Headline market reads (context the graph doesn't carry). VIX and SPY carry data-ticker only (to keep them polled) and are patched by hero.js, which also fills volume + the S&P trend. The S&P price itself lives on the graph now. #}
{% if reads.asof %}Prices as of {{ reads.asof|asof }}{% else %}Awaiting first quotes…{% endif %}
S&P from high
{{ reads.drawdown_pct|pct if reads.drawdown_pct is not none else "—" }}
{{ reads.drawdown_label or "Drawdown from record close" }}
Volatility · VIX
{{ reads.vix_level|round(2) if reads.vix_level is not none else "—" }}
{{ reads.vix_tone|capitalize if reads.vix_tone else "—" }}
Credit · high yield
{{ reads.credit_pct|pct if reads.credit_pct is not none else "—" }}
{{ reads.credit_label or "HYG vs prev close" }}
Market volume
{{ reads.volume|compact if reads.volume is not none else "—" }}
{% if reads.volume_label %}{{ reads.volume_label }} vs avg{% else %}—{% endif %}
S&P trend
{{ reads.sma_read or "—" }}
50 & 200-day average
{# The editable, session-scoped watchlist. #}

Watchlist

{% if cards %} {# Same chart-card shell as the overview. data-ticker registers the symbol with the live stream (so its intraday bars stay polled); hero.js draws the Schwab-day chart + refreshes the value/% from /api/dashboard. The remove button sits outside the link so the whole card stays navigable. #} {% else %}

Your watchlist is empty. Add a stock or ETF above, or browse the universe to find one.

{% endif %}
{# Market movers: top gainers / losers / most active, the "what specific names moved and why" detail. hero.js fills the three lists from /api/movers (an 8-minute server-side cache), after first paint so it never blocks the page. #}

Market movers S&P 500

Gainers

Losers

Most active

{% endblock %} {% block extra_js %}{% endblock %}