Commit Graph
154 Commits
Author SHA1 Message Date
dennisthiessen 4c0c0579f5 fix: make SEC quality gating terminal-safe 2026-08-04 07:58:18 +02:00
dennisthiessen d1caac86b5 fix: preserve OHLCV stale detection 2026-08-04 07:39:40 +02:00
dennisthiessen d431ee283d feat: show max-hold session countdown 2026-08-03 23:55:30 +02:00
dennisthiessen 7d703ea524 fix: refresh same-day OHLCV bars 2026-08-03 23:13:17 +02:00
dennisthiessen c8c660e63d fix(sec): warn when deferred imports stay stale 2026-07-31 13:27:31 +02:00
dennisthiessenandClaude Opus 5 83c0555e52 Event study: report its own statistical limits
Deploy / lint (push) Failing after 8s
Deploy / test (push) Skipped
Deploy / deploy (push) Skipped
The v3 cutover run scored 2/4 corrections warned against v2's 3/4, which reads
like a regression and is not one. Only 4 of the 11 detected corrections fall in
the holdout, so recall is one event from a different headline -- and the event
that flips is decided by threshold placement, not by what the score saw. "v3
without the credit sensor" catches 2025-02-21 at a *higher* threshold (35.5)
than shipped v3 misses it at (32.3), because the alarm rule needs a rising edge
and a lower threshold can fire outside the horizon then never reset below.

Two caveats are now computed and surfaced rather than left for the reader to
infer:

- Holdout event count against MIN_EVENTS_FOR_CONFIDENCE. The summary sentence
  states how many of the detected corrections actually fall in the test period.
- Warning-sensor coverage across the split. The score renormalises over what is
  available, so a training window predating a sensor's history freezes the
  threshold on a different construct than the holdout is measured against. At
  the cutover that is 39% of training sessions with all three sensors versus
  100% of the test period, credit history beginning 2023-07-25.

Restricting the threshold to sensor-matched training sessions was tested and
rejected: those sessions are a calm recent stretch, so the threshold falls from
32.3 to 22.5 and false alarms rise from 3.3 to 8.6/yr. It swaps a coverage bias
for a regime-selection bias. The report states its limits instead.

_warning_series now returns per-session sensor counts alongside the scores.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 15:12:53 +02:00
dennisthiessenandClaude Opus 5 019ca1342a Rewrite Regime Monitor as v3: fundamentals off the score, desaturate P3
Deploy / lint (push) Successful in 11s
Deploy / test (push) Successful in 1m43s
Deploy / deploy (push) Successful in 38s
The LLM-sourced capex/earnings observations carried 12+8 of 100 Warning points,
so both pegged at 100 produced a Warning of 20.0 -- below the event study's 25.3
alarm threshold and still inside the "stable" band. The reading was
arithmetically incapable of changing anything on screen, which is why refreshing
it appeared to do nothing. They are now a qualitative overlay reported beside
the scores rather than diluted into them.

Calibrated against the 408 v2 sessions to 2026-07-24, reproduced offline from
Alpaca + FRED; the harness matched the stored prod distribution exactly before
any parameter was changed.

State:
- P3 used dd_pct * 5, reaching 100 at a 20% drawdown -- the 90th percentile of
  the observed distribution -- so 39/408 sessions sat at exactly 100 with no
  resolution left during the part of a selloff that matters most. Replaced with
  anchored breakpoints keeping headroom past the observed 36% maximum, blended
  2:1 like P1/P2 instead of max(). P3's realized share of State falls from 65%
  to 40%, matching its nominal weight.
- Credit level is now anchors-only. ICE capped FRED's BAMLH0A0HYM2 at a rolling
  3-year window in April 2026, silently turning the 10-year percentile leg into
  a 3-year one that scored 20 points of stress at an OAS of 3.5 -- the level its
  own anchors call "mild". The anchors already encode the long-run distribution.

Warning:
- Added HY OAS 20-session widening (25%). The level is pinned at zero below the
  3.5 anchor; its rate of change is not.
- Divergence tapers to a 0.35 floor instead of a hard price_ret >= 0 gate, which
  zeroed the sensor through every decline: on 2026-07-24 the basket shed 10
  points of participation in 20 sessions and Warning printed exactly 0.
- The event study and the live monitor now share one sensor definition, so they
  cannot silently drift apart.

Bands are per axis (State 20/50/80, Warning 20/40/60) with quadrant dividers at
50/40; v2 Warning never exceeded 64.9 against a shared 60, leaving that half of
the quadrant unreachable. Realized shares: State 73/15/8/3%, Warning 69/20/8/3%.

Snapshots now record credit_history_days and vix_history_days -- the percentile
defect went unnoticed for months because nothing asserted the window the code
claimed.

Cutover: the first run rebuilds 400 sessions automatically; the Event Study job
must be re-run, as its cached report self-invalidates on the methodology check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 14:36:57 +02:00
dennisthiessen 49bf3b140e Add Admin control for fundamentals cutover
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m48s
Deploy / deploy (push) Successful in 40s
2026-07-24 16:15:51 +02:00
dennisthiessen ce8c60d957 feat: add fundamentals parity reporting 2026-07-23 21:17:58 +02:00
dennisthiessen 88fc90cc6f feat(deploy): schedule fundamentals shadow imports 2026-07-23 12:41:27 +02:00
dennisthiessen 71d21a45b6 feat(frontend): finish fundamentals reference rails 2026-07-23 10:59:50 +02:00
dennisthiessenandClaude Opus 4.8 480baf762f chore(frontend): harness at desktop width (768px) for two-column preview
max-w-md (448px) under-sized the panel vs its real full-width tab placement and
never triggered the desktop two-column layout. Widen to max-w-3xl; note to
resize to ~390px for the mobile (single-column) check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 09:34:09 +02:00
dennisthiessenandClaude Opus 4.8 103b182598 feat(frontend): FundamentalsPanel — Reference Rails redesign
Replace the four-cell quarter tape (too many equally-weighted numbers) with one
comparison rail per metric, so the panel answers "improving? sound? fairly
valued?" instead of asking the reader to decode it.

- Operating trend (revenue/EPS growth, operating/FCF margin, share count): a rail
  centered on a truthful reference — prior quarter (growth), prior-period average
  (margins), or zero (share count) — with a dot at the current delta and a bar
  back to the reference, plus a shaded neutral band (backend's +-2pp / +-1pp /
  +-1% rules). Value, read, reference label, and signed delta stay visible;
  per-quarter history drops out of the default view.
- Valuation & balance (net debt/EBITDA, P/E, FCF yield): a 0-100 favorable-
  percentile rail with the peer median fixed at 50; right is always more
  favorable (percentile is polarity-aware). median + peer_count shown.
- Not a progress bar: reference line, not a 100% target.
- Horizon tokens: cyan #6EC9DB favorable / coral #EF9182 adverse / #5D6373 track,
  replacing emerald/rose. Two columns on desktop, single column (rows stack) on
  mobile. Null -> n/a with no rail; insufficient peers -> "peers n/a", no track.
- Kept: compact earnings line, provenance footer, local-date parsing, aria-labels
  on every rail. tsc -b passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 09:28:38 +02:00
dennisthiessenandClaude Opus 4.8 bd23f41a1d fix(frontend): FundamentalsPanel review — mobile, local dates, peer a11y
Addresses the static review + adds a dev-only visual harness:

1. Tape no longer overflows narrow mobile: each row stacks (label + read on one
   line, cells below) under sm, keeping the single-line grid on desktop.
2. Date-only strings (earnings, price_date) are parsed as LOCAL calendar dates,
   so a viewer west of UTC no longer sees the previous day.
3. Peer context is visible ("med X · Np") on every width and the percentile
   strip carries a full aria-label — no longer hover-only / desktop-only.
4. Per-metric provenance + freshness surfaced (SEC filings · latest quarter,
   filed date) replacing the removed panel-wide FMP label.
5. Same-day earnings render "today", not "in 0d".

Harness: frontend/harness.html + src/dev/harness.tsx (dev-only, served at
/harness.html by vite, not in the production build) render full /
partial-insufficient-peer / empty fixtures for desktop + ~390px review.

tsc -b passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:56:45 +02:00
dennisthiessenandClaude Opus 4.8 9172c1a699 feat(frontend): A4 — FundamentalsPanel v1 (quarter tape + earnings + peers)
Reshapes FundamentalsPanel to consume the additive API v1, within the app's
existing dark-glass language.

- types.ts updated to the exact v1 shape (metrics/earnings/valuation/reads +
  legacy fields preserved).
- The quarter tape is the single distinctive device: per-metric 4-cell tape
  (revenue/EPS growth, operating + FCF margin, share count) with the latest cell
  toned by the deterministic read; color is always paired with the read text.
- Restrained peer strips for Net debt/EBITDA, P/E, FCF yield: value + a
  polarity-aware percentile bar with a median marker + the read; hidden ("peers
  n/a") when industry is null (< 5 peers).
- Earnings: next date/session/countdown + last-N beat/miss arrows (▲/▼/·) with
  text aria-labels; explicit "no date" state.
- Explicit n/a, insufficient-peer, and no-earnings states; header shows the
  deterministic sentence. Removed the hard-coded "FMP" source label.

Frontend tsc -b passes; backend suite 778 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 22:05:17 +02:00
dennisthiessen aaca82d9d7 fix: synchronize shadow book save state
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m18s
Deploy / deploy (push) Successful in 38s
2026-07-21 14:16:11 +02:00
dennisthiessenandClaude Fable 5 1e072346a9 ui: explicit Save button for shadow book settings
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m17s
Deploy / deploy (push) Successful in 37s
The shadow book toggle saved on change and the numeric fields on blur,
inconsistent with every other admin panel (which stages edits behind a
Save button). Stage all four fields in local state and commit them
together on Save, with an unsaved-changes hint. This also makes enabling
the live-trade toggle a deliberate two-step action rather than an
unguarded single click.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:50:00 +02:00
dennisthiessenandClaude Fable 5 ba2df8b9fd feat: shadow book + shadow-vs-manual performance comparison
The manual paper book only contains trades taken by hand, inside a 20
minute window, on days someone was available. The backtest that validated
this strategy auto-takes the top-ranked qualified setups up to capacity
every session. The forward record was therefore measuring strategy plus
discretion plus availability -- and degrading silently on busy days.

The shadow book closes that gap: it mirrors the backtest's selection rule
(top strategy_rank qualified, up to capacity, 1% fixed-fractional risk)
and shares the manual book's exit policy, so the only difference between
the two books is which setups get taken. Selection ordering reuses the
strategy_rank the scanner already stores rather than recomputing it, so
the two cannot drift apart. It runs as a near-close pipeline step right
after the scan, marking entries at the same prices a human would see.

Gate-reset re-entry state is now scoped per book -- the books diverge as
soon as their entries differ, and each must see only its own stops.

Performance view rewritten around the comparison:
  - three series (shadow, manual, SPY) from a new endpoint
  - SPY changes from a per-trade cost-basis counterfactual to plain
    buy-and-hold %, since one line has to serve two books
  - headline stats are R-multiples, not currency: the books size
    differently, so only R compares across them
  - configurable start date, because the strategy has been revised
    repeatedly and pre-cutover trades ran under rules that no longer
    exist

Migration 024 also repairs the numeric weekday crons written by 023,
rewriting only rows still holding the broken form so hand-corrected
settings survive. Its literals are inlined because bound parameters
render as NULL under 'alembic upgrade --sql'.

The shadow book is opt-in and writes nothing until enabled. Verify its
first selections match a backtest of that day's cross-section before
trusting any point on the curve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 23:44:41 +02:00
dennisthiessen dc08a805a8 fix: recalibrate FIP path labels to live equity scale
Deploy / lint (push) Successful in 9s
Deploy / test (push) Canceled after 0s
Deploy / deploy (push) Canceled after 0s
Replace inert ±0.25 bands with ~p25/p75 cutoffs from the prod snapshot
(−0.08 / 0.00). Document zero-return dilution and left-skewed distribution.
2026-07-18 19:27:45 +02:00
dennisthiessen 19d674ed62 feat: show FIP path-smoothness in ticker technicals
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m20s
Deploy / deploy (push) Successful in 41s
Display-only Da/Gurun/Warachka information discreteness on the ticker
indicator panel. Shared compute with the backtest harness; not wired into
gate or rank.
2026-07-18 19:22:02 +02:00
dennisthiessen a71dd4adb7 fix: chain morning alerts for regime Telegram delivery
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m14s
Deploy / deploy (push) Successful in 37s
Regime is computed at 02:00 ET; without a morning alert pass, quadrant
changes waited until 15:30. Dispatcher is change-driven so quiet days stay
quiet. Drop unused alerts_frequency config.
2026-07-18 18:00:00 +02:00
dennisthiessen 736451e26f feat: near-close scan schedule and distinct-day gate reset
Move the only qualifying R:R scan to 15:30 ET with chained Telegram alerts,
put outcome eval after a final-bar OHLCV fetch, enforce NY trading-day
requalify semantics, stamp paper trades fill_mode=near_close, and migrate
stored schedule_* keys to America/New_York.
2026-07-18 17:55:39 +02:00
dennisthiessen cad4b49e7c fix: harden Structural S/R after OHLCV writes and surface cleanup failures
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m18s
Deploy / deploy (push) Successful in 40s
Honor custom S/R tolerance as a transient detect, refresh levels after OHLCV
mutations without failing committed price writes, report per-ticker S/R
rebuild failures from admin cleanup, and warn in the admin UI when refresh is partial.
2026-07-18 13:44:34 +02:00
dennisthiessen b0e33e1606 fix: align production defaults and close review parity gaps
Ship greenfield min_rr=2.0 and conf=0, read-only Structural S/R, indicator
cache invalidation, and UI/gate language that treats GTL as screening not exit.
Align strategy_rank missing-vol fallback live vs backtest, single-source
PRIMARY_TARGET_MIN_RR, expand prod parity tests, and drop dead FE clients.
2026-07-18 13:03:22 +02:00
dennisthiessen e07da0f8f0 feat: add Signal favicon (ember pulse with cyan rim)
Deploy / lint (push) Successful in 10s
Deploy / test (push) Successful in 1m17s
Deploy / deploy (push) Successful in 38s
Wire the chosen brand mark as an SVG favicon and set theme-color to the void background.
2026-07-18 11:51:44 +02:00
dennisthiessen 5155d00d9e feat: require gate reset before post-stop reentry 2026-07-17 19:30:40 +02:00
dennisthiessen 65a462271c feat: add selectable daily backtest cadence 2026-07-17 14:41:24 +02:00
dennisthiessen bc50ba9136 fix: harden post-stop reentry lockdown 2026-07-17 14:17:57 +02:00
dennisthiessen 1e9f2dc4fb feat: add five-session post-stop reentry lockdown 2026-07-17 13:21:06 +02:00
dennisthiessen f714782fa4 fix: use categorical regime fundamentals
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m13s
Deploy / deploy (push) Successful in 37s
2026-07-15 10:13:22 +02:00
dennisthiessen 81c6f5fe2f fix: refresh latest regime trading session
Deploy / lint (push) Successful in 10s
Deploy / test (push) Successful in 1m14s
Deploy / deploy (push) Successful in 39s
2026-07-15 09:13:42 +02:00
dennisthiessen 1d5b1489be feat: replace regime monitor with v2 methodology 2026-07-15 09:02:56 +02:00
dennisthiessen fd21067a40 Fix S&P 500 universe parse so renames like BNY are discovered.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m6s
Deploy / deploy (push) Successful in 37s
Wikipedia no longer uses plain symbol table cells; parse exchange links and NyseSymbol templates, surface the list source in bootstrap results, and keep legacy cell parsing as a fallback.
2026-07-14 14:14:58 +02:00
dennisthiessen 644e81d1a3 Fix TypeScript type for system-events acknowledge mutation.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m13s
Deploy / deploy (push) Successful in 38s
2026-07-14 13:40:27 +02:00
dennisthiessen f59c0c3484 Add system alerts log with nav badge and Admin Alerts tab.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Failing after 1m4s
Deploy / deploy (push) Has been skipped
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.
2026-07-14 13:38:04 +02:00
dennisthiessen ed82d0a665 Improve open-position mini chart readability.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m3s
Deploy / deploy (push) Successful in 37s
Center young-trade entry, draw full-width stop/now/gate, color the path vs entry, and show the trail only after it ratchets.
2026-07-14 13:14:52 +02:00
dennisthiessen 751d103f4e Draw moving trailing stops on open-position charts.
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m9s
Deploy / deploy (push) Successful in 37s
Reconstruct the ATR/% trail bar-by-bar so the mini chart shows a ratchet path instead of a flat current level, and de-emphasize screening targets under trailing exit modes.
2026-07-14 13:02:23 +02:00
dennisthiessen ac0bcf9012 Explain fundamentals score with good/bad status labels.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m13s
Deploy / deploy (push) Successful in 39s
Add overall and per-metric reads for P/E, growth, and surprise using the same scoring rules as the backend, plus a short how-it-works note.
2026-07-14 12:02:33 +02:00
dennisthiessen cad1be96da Add human status labels to all indicators and small UI tweaks.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m13s
Deploy / deploy (push) Successful in 40s
Interpret RSI, ADX, EMA, ATR, volume profile, and pivots like EMA cross; tighten exit timeline spacing; risk presets are 1/2/3/5%.
2026-07-14 11:24:08 +02:00
dennisthiessen f309bd5691 Polish exit timeline and always show S/R levels.
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m8s
Deploy / deploy (push) Successful in 36s
Keep support/resistance visible even near trade lines, tighten the how-this-exits spine so steps connect, unify step styling, and add space above the panel.
2026-07-14 10:55:27 +02:00
dennisthiessen d5b0ebf895 Improve chart trade overlays and paper fill markers.
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m12s
Deploy / deploy (push) Successful in 39s
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.
2026-07-14 10:44:56 +02:00
dennisthiessen 8db535b889 Fix manual refresh dropping qualified ranks and clarify trade UI.
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m20s
Deploy / deploy (push) Successful in 39s
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.
2026-07-14 10:10:30 +02:00
dennisthiessen bddaeb9110 Cleanup retired S/R research scaffolding
- Remove unused _gate_eligible_levels filtering logic and its tests (research-only)
- Add prominent RESEARCH/DIAGNOSTIC markers and docs to clear-air/ATR fallback helpers
- Document production vs research BACKTEST_* environment variables in backtest_service
- Minor cleanups: update legacy report text, improve outdated function docstring
2026-07-13 18:52:24 +02:00
dennisthiessen bee5a5ce89 Finalize GTL and retire S/R research harness 2026-07-13 17:58:04 +02:00
dennisthiessen 0873176f64 Show production rank below ticker chart 2026-07-13 12:35:16 +02:00
dennisthiessen 4730d19694 Add GTL price-traffic chart diagnostic 2026-07-13 12:08:10 +02:00
dennisthiessenandClaude Opus 4.8 9789e3d762 UI: frame the setup as what it is — a momentum signal with a trailing exit
The UI told a swing-trade story (entry -> target -> stop) while the engine runs
a momentum portfolio (buy strength, trail out, re-rank). The selection was
honest; everything around it was borrowed from a strategy we don't run.

The target is never an exit under `atr_trailing`: `_atr_trailing_close()` does
not even take it as a parameter. It exists only to compute the R:R and touch
odds that admit a setup through the activation gate. Backtested exit reasons for
the production strategy: 144 initial stop, 98 trailing stop, 78 max hold —
target 0. See docs/research/sr-levels-and-exits.md.

What changed:

- New ExitPlanPanel on every setup card states the rules that actually close the
  trade: initial stop (1R), the price at which the 3x ATR trail takes over from
  it, the trail width in R, and the max hold. Derived in lib/exitPlan.ts from the
  live exit policy, so it follows Admin rather than hardcoding the default.
- New BaseRatesPanel replaces per-target "probability" as the answer to "what
  usually happens": win rate, average hold, best/worst R, and how trades actually
  ended — measured under the real exit, from the backtest report.
- "Target"/"target probability" relabelled to "level"/"touch odds" and grouped as
  gate metrics, with the R:R. On the dashboard focus card, residual momentum
  (the actual signal) takes the headline stat those two used to occupy.
- The take-trade dialog no longer offers a target dropdown whose value the exit
  ignores; it states the trailing plan instead. The picker returns only when the
  live policy is mode='target', where the choice is real. The stored target is
  now the setup's own, not whichever row was last clicked while exploring.
- "Played out" is gone. A setup was declared dead once price reached the target —
  backwards under a trailing exit, where reaching a level is the good case and
  the trade keeps running. Only the stop invalidates a setup now; running past
  the entry is an "extended" warning, measured in R (you'd be chasing).

The levels ladder, the price rail and the chart overlay all stay fully
explorable — clicking a level still drives them. It is framed as overhead
structure, which is what it is, rather than a menu of exits.

Adds a parity guard: the UI recovers ATR as |entry - stop| / 1.5, so the test
fails if the scanner's stop width ever moves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 15:29:21 +02:00
dennisthiessenandClaude Fable 5 fdc49d0e28 Setup views: primary-target column, floor-target prune, liveness cutoff
Three follow-ups to the gate probability floor (8f41143):

- Signals table shows the starred primary target (shared primaryTarget
  helper) instead of an independently computed max-probability best,
  so Overview, Signals and ticker details agree by construction.
- Targets pinned at the 3% probability clamp floor collapse to the
  nearest one (enhance_trade_setup + backtest candidates in parity):
  floor-pinned levels are indistinguishable to the model, so farther
  ones were duplicate 3% rows inviting lottery headlines.
- get_trade_setups only returns setups re-emitted within
  LIVE_SETUP_MAX_AGE_DAYS (3): an older latest row means the daily
  scan no longer confirms the setup, and such rows otherwise surface
  forever on Overview/Signals/ticker/alerts. History endpoints keep
  full history.

Backtest on the Jul-3 snapshot is metric-identical to the gate-floor
run on all qualified stats (1089 qualified, Sharpe 2.02, CAGR +49.6%,
DD -15.8%): the prune only removes noise the gate already rejected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 10:06:34 +02:00
dennisthiessenandClaude Fable 5 8f411435ee Activation gate: primary target probability floor (>= 20%)
A qualified setup's primary target must now clear MIN_TARGET_PROBABILITY
(20%), shared with the primary-selection floor in recommendation_service
and mirrored in the frontend gate. Closes the read-time hole where a
stale pre-c7a198b row starring a far lottery target (probability pinned
at the 3% clamp floor, R:R inflated by the same distance) qualified
forever: the scanner emits no replacement row and live R:R never decays.

A/B backtest vs c7a198b baseline (same July-3 snapshot): 7 of 1096
qualified setups removed; qualified net avg R 0.202 -> 0.207, hold
Sharpe 2.00 -> 2.02, CAGR +48.8% -> +49.6%, max DD unchanged at -15.8%.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:31:28 +02:00
dennisthiessenandClaude Fable 5 924c474624 Track Record: Strategy/Lookback selects use the shared Dropdown
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 1m3s
Deploy / deploy (push) Successful in 34s
The portfolio-monitor filters were native <select> elements with a
hardcoded bg-slate-950 - a look from before the design system. They
now use the shared Dropdown (same as the Setups filters), which also
gives them the dark themed menu and the portal fix from 6464fdd.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:23:09 +02:00