New market_regime_service computes a benchmark (SPY) trend from its 50/200-day
SMAs, cached in a SystemSetting and refreshed by a nightly job; GET /market/regime
exposes it. Dashboard shows a regime banner; setup cards flag a counter-trend
caution when a setup fights the regime (LONG in a bearish market / SHORT in a
bullish one). Informational only — nothing is suppressed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Risk-based sizing on each setup card: shares = floor((account × risk%) /
|entry − stop|), with position value and dollars-at-risk. Account size and
per-trade risk % are editable inline and persisted in localStorage. Flags when
a position would exceed the account (needs margin). Frontend-only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes the action loop — instead of polling the dashboard, the platform pushes
actionable signals to Telegram. New hourly 'alerts' job dispatches four
toggleable triggers, deduped via a new alert_log table (cooldown-based for
qualified/S-R/digest, watermark-based for score deterioration). Admin → Settings
gains a Telegram panel (write-only bot token, chat ID, per-trigger toggles, Send
Test). Credentials follow DB > env precedence (TELEGRAM_BOT_TOKEN / _CHAT_ID).
Backend: alert_service + AlertLog model + migration 005, scheduler job, admin
endpoints/schema. Frontend: AlertSettings panel, hooks, api, types.
Deploy: run alembic upgrade (new alert_log table).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Track Record: new "Reset" action (POST /admin/track-record/reset) deletes all
trade setups so stats start fresh after material scoring/setup changes — live
setups regenerate on the next scan. Guarded by a confirm dialog.
Recommendation config: remove distance_penalty_factor, which was exposed in the
admin UI but consumed nowhere (the touch-probability model superseded it). A
knob that silently does nothing is worse than no knob. Remaining defaults are
left as-is — they're reasonable, and the honest way to tune them is backtesting
against accumulated outcomes, not invented "researched" numbers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per design decision: the watchlist is now purely user-curated (no auto-seeding
of the top-10), so the auto_populate/dismissed machinery is removed and removals
are plain deletes. Each entry is enriched with latest close + day-over-day move.
Overview now shows two clear blocks: Top Setups (what to trade) and My Watchlist
(my names with current price and today's %). Market watchlist table drops the
now-meaningless auto/manual Type column in favour of Price and Day columns.
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>
The dashboard Top Setups list showed raw fields in arbitrary order with no
indication of why a ticker was listed or which was best. Now sort by expected
value (R) — probability-weighted payoff per unit risk — so the strongest
opportunity is row 1, badged "Top pick", with a new Exp. Value column that
folds R:R and target probability into one "is this worth taking" number.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Answers "why does a too-far-progressed setup still show": setups are only
recalculated by the scheduled R:R scan and manual fetch; at creation
entry == current price (0% progress), so over-progression is a
between-scans drift effect and must be judged at read time.
- /trades now attaches current_price (latest close per ticker).
- Qualification drops setups whose R:R recomputed from the current price
falls below min_rr — i.e. price already ran toward target (reward
consumed) or through the stop. Reuses the existing min_rr threshold
instead of a separate progress %; far cleaner (a 3:1 is already ~1:1
by 33% progress). Skipped for historical setups (no current_price).
- Fix: useFetchSymbolData now invalidates the trades queries, so a fetch/
recompute actually refreshes confidence/setups in the UI (was the cause
of the stale 100% confidence lingering after recompute).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Overview Top Setups shows the primary target's probability (concrete,
distance-calibrated) instead of the overlapping confidence number. The
stale 100% confidences were leftovers from the old model and self-heal
on rescan; confidence stays in the detail view + gate.
- Each metric now has one home: composite = ranking, target probability =
actionability, confidence = direction conviction.
- Staleness message states the real basis (% of entry->target distance
already covered), not the raw % from entry, so narrow setups read
correctly ("67% of the move is gone").
Co-Authored-By: Claude Fable 5 <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>
- JWT now carries a username claim; sidebar shows "Signed in as <name>"
instead of the bare user id (sub). Re-login required for the new claim.
- Signals: Min R:R / Min Confidence inputs reflect the effective filter —
auto-filled from the activation gate when "Qualified only" is on, reset
to 0 when off (no more misleading 0 while the gate is active).
- Signals layout: Run Scanner moved to its own action row (it's a job
trigger, not a filter); qualified toggle grouped with the refinement
filters under one Filters panel.
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>
Triggered by CNC showing "LONG (High Confidence)" with SHORT reasoning
and no long setup.
- A: recommendation action + reasoning are ticker-level and identical
on both setups; reasoning always matches the shown action
- B: recommended_action only picks a direction with a tradeable setup;
strong bias with no setup (e.g. price at ATH) → NEUTRAL with an
explanatory reason instead of a fake LONG_HIGH
- C: confidence is a directional-agreement model — opposing signals push
it below 50 (SHORT on a 92-technical/99-momentum stock ~0%, not 55%)
- D: fundamental score requires >=2 real metrics (market-cap-only no
longer yields a high score)
- E: RSI score peaks at healthy momentum (~60) and penalizes
overbought/oversold extremes instead of treating RSI 90 as maximal
- F: fundamentals chain merges fields across providers (FMP market cap
+ Finnhub P/E) instead of stopping at the first with any field
- NEUTRAL label: "No Clear Setup" (covers untradeable-bias case)
Scores recompute on next scan/scoring run; C and E shift score
distributions intentionally.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xAI returned 410 — search_parameters/Live Search is retired. Route xAI
through the Responses API web_search tool instead (same path as OpenAI):
- OpenAISentimentProvider parametrized with base_url / tool_type / source
- xAI builds it against https://api.x.ai/v1 with the web_search tool
- Drop the dead Live Search code from the generic compatible provider
- Frontend label: "xAI Grok — web search"
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Providers (admin-switchable, no redeploy):
- DeepSeek and any OpenAI-compatible endpoint (OpenRouter, Together,
Groq, local Ollama) via a generic Chat Completions adapter + base_url
- xAI Grok with Live Search (search_parameters web+X, citations) —
grounded tier alongside OpenAI and Gemini
- DeepSeek / generic compatible endpoints are ungrounded (no web
search); UI shows an amber warning and labels each provider's grounding
- Optional env fallbacks DEEPSEEK_API_KEY / XAI_API_KEY
UI: replace native <select> (unstyleable white popup on Windows) with a
custom dark Dropdown component everywhere — sentiment provider, scanner
filters, market sort, indicators, admin universe, user role.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make "qualified" mean an edge candidate, not just R:R + confidence.
The gate now also requires (all admin-configurable, defaults on):
- high conviction: recommended_action LONG_HIGH / SHORT_HIGH only
- clean read: risk_level Low (no contradicting signals)
- probable primary target: best target probability >= min (default 60)
- Shared predicate: app/services/qualification.py +
frontend/src/lib/qualification.ts (mirrored)
- Activation config extended (min_target_probability,
require_high_conviction, exclude_conflicts) with bool-aware
get/update + validation
- /trades/performance switched to ?qualified_only=true, applying
the full gate server-side; confidence breakdown stays unfiltered
- Dashboard "Qualified", Signals "Qualified only" toggle, and
Track Record all use the one gate; Admin gains the new controls
Sentiment provider runtime config (prior change) included.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Admin-configurable thresholds (min R:R, default 2.0; min confidence,
default 70%) defining what counts as an actionable signal:
- Admin Settings: new Activation Thresholds panel
(GET/PUT /admin/settings/activation)
- GET /trades/activation exposes values to all users with access
- Signals/Setups: filters initialize from activation values
- Track Record: "Qualified signals only" toggle (default on) via
min_rr/min_confidence params on /trades/performance; the
confidence breakdown always covers the full population so the
thresholds can be validated against outcomes
- Dashboard: "Qualified" metric and qualified-first Top Setups
- Outcome evaluator unchanged: every setup is still evaluated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Technical dimension now uses all directional indicators:
0.30*ADX + 0.20*EMA + 0.20*RSI + 0.15*EMA_Cross (bullish=80 /
neutral=50 / bearish=20) + 0.10*Volume_Profile (POC proximity)
+ 0.05*Pivot_Points (structure confluence); weights re-normalize
when data is insufficient, as before
- ATR stays out of scoring (volatility input for scanner stops,
not a directional signal)
- IndicatorSelector uses the shared Select so the option list is
dark instead of the native white popup
- Update technical scoring tests for the six-component breakdown
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes the feedback loop on R:R scanner signals:
- Nightly outcome_evaluator job replays unresolved setups against daily
OHLCV bars: target_hit / stop_hit / ambiguous (same-bar, counted as
loss) / expired after OUTCOME_EVALUATION_MAX_BARS (default 30)
- Migration 004: evaluated_at + outcome_date on trade_setups
- GET /trades/performance: hit rate, expectancy (avg R), total R with
breakdowns by direction, recommended action, and confidence bucket
- New Performance page (stat cards, breakdown tables, Evaluate Now,
methodology disclosure) wired into sidebar and mobile nav
- 17 new unit tests for evaluation logic and stats aggregation
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>