read.markets/app/templates/dashboard.html
Giorgio Gilestro 1edf9cad41 add Eurostat + UK ONS sources; valuation/bubble/economy/bonds groups; aggregate read; market-open header
Three new data sources hooked into the existing SOURCES registry. All
open APIs, no keys:

  - EUROSTAT: prefix EUROSTAT:dataset?dim=val&... — current EU bond
    yields (Bund/OAT/BTP/EZ) and Eurozone economic indicators that
    FRED's OECD-mirror series stopped updating in 2022-2023.
  - ONS: prefix ONS:topic/cdid/dataset — current UK CPI, unemployment,
    GDP, industrial production. Replaces the 5+ month-stale FRED
    LRHUTTTTGBM156S mirror.

New indicator groups in default.toml feed the strategic/fundamental
lens we converged on: valuation (CAPE/Buffett anchors), bubble_watch
(SKEW/VVIX/RSP vs SPY/HYG vs TLT/IPO/crypto), economy (multi-region,
ALL current-or-stale-flagged), bonds (UK/EU/US/JPN sovereign yields).

Indicator panel now opens with an AI "read" interpretation per group
(generated hourly at :07 UTC alongside an aggregate cross-group read
shown in the dashboard header). The aggregate is grounded by a markets
strip — NYSE/LSE/Frankfurt/Tokyo/HK/Shanghai with open/closed LEDs and
next-open countdown, computed locally from each exchange's tz.

Other UX bits: indicator-row tooltips populated from TOML notes;
rows whose last observation is >90 days old get a 'stale' chip;
ghost symbols (in DB but no longer in TOML) filtered out of the
panel; Eurostat/ONS symbols display as short codes rather than the
full API path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 23:07:42 +01:00

85 lines
2.7 KiB
HTML

{% extends "base.html" %}
{% block title %}Cassandra · Dashboard{% endblock %}
{% block main %}
<div id="dash-header-container"
style="grid-column: 1 / -1;"
hx-get="/api/summary/aggregate?as=html"
hx-trigger="load, every 300s"
hx-swap="innerHTML">
<div class="empty">loading aggregate read…</div>
</div>
<section id="indicators-panel" class="panel">
<div class="panel-header">
<span class="title">Indicators</span>
<span class="meta">{% if anchor %}anchor {{ anchor }} · {% endif %}ingest hourly @ :05 UTC</span>
</div>
<div class="group-tabs" id="group-tabs">
{% for g in groups %}
<button
class="{% if loop.first %}active{% endif %}"
hx-get="/api/indicators/{{ g }}?as=html"
hx-target="#indicators-body"
hx-trigger="click"
onclick="document.querySelectorAll('#group-tabs button').forEach(b=>b.classList.remove('active'));this.classList.add('active')"
>{{ g }}</button>
{% endfor %}
</div>
<div id="indicators-body"
class="panel-body panel-body--scroll"
hx-get="/api/indicators/{{ groups[0] }}?as=html"
hx-trigger="load"
hx-swap="innerHTML">
<div class="empty">loading…</div>
</div>
</section>
<script>
// Auto-refresh the *currently selected* group every 60s by simulating a
// click on the active tab. Replaces the hard-coded `every 60s` on
// #indicators-body which always re-fetched groups[0].
setInterval(function () {
var active = document.querySelector('#group-tabs button.active');
if (active) active.click();
}, 60000);
</script>
<section id="portfolio-panel" class="panel">
<div class="panel-header">
<span class="title">Portfolio</span>
<span class="meta">ingest hourly @ :15 UTC</span>
</div>
<div class="panel-body"
hx-get="/api/portfolios?as=html"
hx-trigger="load, every 60s"
hx-swap="innerHTML">
<div class="empty">loading…</div>
</div>
</section>
<section id="log-panel" class="panel">
<div class="panel-header">
<span class="title">Strategic Log</span>
<span class="meta">generated hourly @ :20 UTC</span>
</div>
<div class="panel-body"
hx-get="/api/log/latest?as=html"
hx-trigger="load, every 300s"
hx-swap="innerHTML">
<div class="empty">awaiting first log…</div>
</div>
</section>
<section id="news-panel" class="panel">
<div class="panel-header">
<span class="title">Flash News</span>
<span class="meta">last 24h · ingest hourly @ :10 UTC</span>
</div>
<div class="panel-body panel-body--scroll"
hx-get="/api/news?as=html&limit=40"
hx-trigger="load, every 60s"
hx-swap="innerHTML">
<div class="empty">loading…</div>
</div>
</section>
{% endblock %}