The A5 cutover has been on and observed in production, so SEC Company Facts +
DoltHub earnings are already the live source for `fundamental_data`. This
removes everything the legacy path still occupied.
Gone: the three providers and their config/env keys; the weekly
`fundamental_collector` job; the cutover toggle (SEC + Dolt is now the
unconditional path, so `off` can no longer silently freeze scoring inputs); the
A5 parity report, whose deltas became structurally zero once the candidate
builder started writing the table it compared against; and the FMP tier of
universe bootstrap.
Two behavioral notes:
- Disabling **SEC Fundamentals Import** now stops the SEC network fetch only.
The local cache refresh moved outside the job-enable check, because candidates
also derive from daily closes and earnings events — freezing those on an
ingestion pause would stale scoring with no fallback left to recover from.
- `/ingestion/fetch?sources=fundamentals` still accepts the key and reports
`skipped`; there is no per-ticker fetch any more.
Migration 029 does not blanket-delete the leftover settings rows. Migrations run
before the service restart, and pre-A6 code reads an absent `job_*_enabled` row
as *enabled* — so the two behavior-bearing keys become tombstones pinned to safe
values (hidden in Admin) and only the inert three are deleted. Removing the
provider keys from the production `.env` is the matching rollout step.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Persist job and ingestion warnings/errors for 7 days, surface a dismissible top-nav badge, treat stale OHLCV as a warning (e.g. ticker renames), and show market bar age on the ticker freshness chip.
De-clutter setup labels (left roles, right prices; hide Entry near Now; S/R in-plot), and draw green/red arrows for paper trade entry and exit on the matching sessions.
Single-ticker fetch now attaches residual-momentum ranks so setups do not silently fail the activation gate. Exit plan is a timeline, chart labels move left of the price scale, and missing ranks surface explicitly.
The dashboard fingerprints sorted score dimensions alphabetically
while the ticker page rendered them in API order, so the same ticker
drew a differently-shaped polygon on each page.
New shared helper radarAxesFromDimensions() pins the axis order to the
backend's DIMENSIONS list (technical, sr_quality, sentiment,
fundamental, momentum; unknown dimensions append alphabetically) and
centralizes the label truncation. Used by the dashboard fingerprint
strip, the ticker header radar, and ScoreCard.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The ladder target choice is lifted to the ticker page (per
direction), so selecting a target updates the candlestick overlay's
target line and zone too, with the R:R for the tooltip taken from
the ladder row.
- Price rail: the scale now always spans the entire target ladder, so
stop / entry / now hold their positions and only the target marker
moves when a different target is selected. The furthest target sits
at the right edge.
- Setup card layout: position sizing (shares / value / max loss,
details in the tooltip) and the Mark-as-taken button move to the top
right of the card header row, next to the stats they belong with -
the dangling bottom row is gone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
selectable targets drive the rail
- Data freshness is now the very first row of the ticker panel, above
the symbol - data age is the first thing to check.
- Indicator cards: long price-level lists (pivot swing highs/lows,
volume-profile HVN/LVN) no longer clip or overwhelm. Numeric lists
are clustered into ranges (values within ~0.75% of price merge),
sorted nearest-to-price first, capped at 4 chips with a "+n more"
note; scalar values wrap instead of overflowing the card.
- Recommendation verdict: the action ("LONG (high confidence)") is set
in the display face in accent cyan with the risk level beside it;
the signal breakdown (technical/momentum/sentiment) drops to a small
muted subtitle line.
- Target ladder is open by default and selectable: clicking a row
previews that target on the price rail and updates the R:R and
probability chips, the low-probability warning, and the prefilled
target in Mark-as-taken (still overridable there). The scanner's
primary stays the default; a non-primary choice is chipped as
"custom target".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
verdict de-dup, target picker on take
Five fixes from prod review:
1. Data freshness row moves from the panel foot to directly under the
header - data age is a first-look concern.
2. Radar fingerprint labels were clipped left ("Momentum") and right
(value digits): label padding widened to fit "momentum 100" on both
anchored sides.
3. Indicators tab: the one-at-a-time dropdown (which also clipped) is
gone; all indicators load in parallel as quiet outlined cards - EMA
cross with its colored signal, RSI/ADX with a one-line human read
(overbought / trending / ...), values formatted to 2 decimals
instead of 4, normalized score demoted to a corner note.
4. Recommendation verdict line de-duplicated: the backend reasoning
already starts with the action label, so it now replaces the
headline instead of repeating under it.
5. Mark-as-taken: the take form gains a target selector listing every
detected target with price / probability / classification (primary
preselected), and the card warns when the primary target sits below
15% probability. Why the scanner promotes such a target to primary
is a separate (backend) question.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RecommendationPanel redesigned to match the rest of the redesign:
- Setup cards use the spatial price rail (stop -> entry -> now ->
target with live R-multiples) instead of the label/value text grid.
- One quiet chip row per card (direction, preferred marker, confidence,
R:R, target probability) replaces scattered header text.
- Position sizing is a single mono line (shares / position / max loss)
instead of a boxed 3-column mini-table; Mark-as-taken flow kept, in
the standard cyan button style.
- Full target ladder moves behind a disclosure (the primary target is
already on the rail); warnings (counter-trend, stale/invalidated
drift, earnings window, conflict flags) all kept.
- Cards are quiet outlined blocks, no glass-in-glass; the module
renders frameless inside the unified ticker panel's Analysis tab,
under the chart.
Ticker panel tabs now: Analysis, Standing, Dimensions, Indicators,
S/R Levels, Sentiment, Fundamentals - Standing and Dimensions were the
last below-the-fold sections; the whole page is now the single panel.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The previous pass kept a stack of independent glass cards (header,
recommendation, chart section, tab pills, per-tab sections), which read
as clutter. Now the page is a single casting, like the mockup:
One glass panel containing:
- header (identity, price, chips | actions + score fingerprint)
- inline hairline tab row (Analysis / Indicators / S/R Levels /
Sentiment / Fundamentals) with the chart-overlay pills riding on the
right of the row during Analysis
- tab body: Analysis = the candlestick chart; other tabs render their
panel inside via .hz-frameless, which strips the nested card chrome
(no card-in-card)
- panel foot: data freshness row (frameless now) with per-source
refresh
Below the panel, only on Analysis: the recommendation module and a
two-column Standing | Dimensions grid. Nothing removed; the standalone
Tabs bar, the separate chart card, and the duplicated section stack are
gone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restructures TickerDetailPage to match the Horizon mockup's ticker
drill-down while keeping every existing feature:
- Glass header card: eyebrow + big symbol/company, price with change
and freshness, chips (composite score, next earnings, top-pick /
open-trade pills) on the left; watchlist + Fetch All actions and the
score fingerprint radar on the right (hover a corner for values).
- Data freshness bar (per-source age + refresh buttons) moves to the
foot of the chart card, like the mockup's panel footer.
- Tabs extended to five: Analysis, Indicators, S/R Levels, Sentiment,
Fundamentals - sentiment and fundamentals no longer stack below the
analysis content, they are one tab away.
- ScoreCard gains showRadar prop so the fingerprint is not duplicated
in the Dimensions section.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Store an optional company name on Ticker (migration 014) and backfill it from
Alpaca's asset list in a single Trading-API call for the whole universe — no
per-ticker fetch. Runs automatically at the end of universe bootstrap and via a
manual "Backfill Names" button (admin) / POST /admin/tickers/backfill-names.
The name ships on /tickers; a shared symbol→name map (useTickerNames) lets any view
show it without its own request. Displayed subtly next to the symbol — in the global
search, the ticker header, and as a small muted line under the symbol in Top Setups
and Open Trades (no extra column, truncated so it never widens the table).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ticker page renders the composite via the Standing matrix (ScoreCard runs with
showComposite=false), so the "Base X · sentiment +Y" line in the ScoreCard header
was never visible there. Add a compact caption beneath the matrix — "Composite 83 =
Base 78 + Sentiment 5.0" — shown only when sentiment actually moves the score, so
the composition of the number has a visible home where the number lives.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the scattered score readouts with one hero: a quality (composite) x
momentum-percentile scatter that plots this ticker against the whole field and
reads out a verdict by quadrant — Strong Buy / Momentum / Accumulate / Pass. The
dashed divider is the activation gate's momentum percentile, so "above the line =
qualifies" is visible at a glance; peers are clickable. Reuses the regime-quadrant
visual language and is lazy-loaded so recharts stays out of the main ticker chunk.
- New StandingMatrix component (composite x momentum, field cloud, verdict).
- ScoreCard gains showComposite (default true); the ticker page now renders it
without the composite ring (composite lives in the matrix) under "Dimensions".
- Confidence + target probability stay in the recommendation panel (the trade).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two read-only pills in the ticker header, beside the watchlist toggle:
- "Top Pick" when the ticker is the current #1 — the same ranking the dashboard
highlights, via a shared topPickSymbol() helper so the two stay in sync.
- "Open Trade" when an open paper trade exists on the ticker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Finnhub's earnings calendar now supplies next_earnings_date through the
fundamentals chain; persisted on fundamental_data (migration 006) and exposed in
the fundamentals API. The recommendation panel warns when earnings fall within
the ~30-day target horizon (a report can gap price through stop/target) and
otherwise shows the next date. Informational only.
Deploy: run alembic upgrade (new fundamental_data.next_earnings_date column).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removing a ticker did nothing because get_watchlist re-runs auto_populate on
every read, instantly re-adding any top-ranked ticker the user had just removed.
Removals are now tombstoned as a "dismissed" entry_type: auto-population skips
them, the list hides them, and a later manual add revives the row. Also exposes
an Add/Remove-watchlist toggle in the ticker detail header.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scores never updated ("101d ago"): get_score only recomputes stale/
missing dimensions, but nothing marked them stale on new data, and there
was no scheduled scoring job.
- Fetch endpoint force-recomputes dimensions + composite.
- Scheduled scan (scan_all_tickers) refreshes scores per ticker, so
scores stay current globally, not just on manual fetch.
Granular fetch: /ingestion/fetch accepts a sources filter; the freshness
bar gets a per-row refresh button (OHLCV/Sentiment/Fundamentals fetch
that provider only — marked paid; S/R/Scores recompute for free). Header
button is now "Fetch All".
Job visibility: GET /jobs/running (any user) + sidebar live indicator
showing running scheduled jobs with progress, polled every 10s.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Triggered by MRK: entry 113 shown with no current price (actually ~119).
- Ticker header shows last close + day change % + "last close · Nd ago"
(the age reveals OHLCV collection lag — why entry looked off)
- Setup cards show Current price and entry drift; flag setups as
stale (price moved >1/3 toward target) or invalidated (past stop)
- Chart: draw only nearest support below + nearest resistance above
current price, plus a prominent "Now" price line (full S/R stays in
the S/R tab)
- Chart overlay is selectable (Auto/Long/Short/None) — only the chosen
setup's entry/stop/target render, instead of everything at once
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add shared UI primitives: Button, Field/Input/Select, PageHeader,
Section, Callout, Tabs, Disclosure
- Replace gradient buttons with single blue-accent btn-primary
- Reserve gradient text for the brand wordmark only
- Rework Scanner page onto the glass system; collapse explainer and
glossary into a disclosure, move filters into a glass toolbar
- Restructure Ticker Detail into tabs (Analysis / Indicators / S/R)
with chart and recommendation always visible
- Align Watchlist, Rankings, Admin, Login/Register to shared primitives
- Unify stray indigo/violet/gray accents into the blue family
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>