Two more visualizations + the bug building them exposed:
- Equity-curve sparkline in the P&L strip: query_equity_curve returns the day's
total_equity series + prior-close baseline (dashed); rendered as an inline SVG
(green/red vs baseline) so the day's P&L shape reads at a glance.
- Per-position R bar in Open Positions: shows current open profit/loss in R units
(-1R = the stop, 0R = breakeven), green right / red left, with a per-row ⚠ when
a position has no resting protective stop. Falls back to % when no stop known.
Also fixed the P/L column to compute from entry/last (was reading a None field).
- BUG: sync_orders dropped stop_price (kept only limit_price), so the synced
snapshot showed stop=None on real stop orders — breaking the R bar and spark
stop-line. Now captured. (The naked alarm was unaffected — it counts qty
coverage, not the level.)
Verified live: equity curve renders the -1,886 day (94,124 -> 92,238); R bars
render (fall back to % until the loop re-syncs stop_price). Tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Today's-trades reconstruction showed normally-exited positions as falsely
"open" and understated realized P&L. Two causes:
1. sync_orders recorded only TOP-LEVEL orders. A position closed by its bracket
STOP or TAKE-PROFIT leg has that exit fill as a child LEG, so every stop/TP
exit was invisible — QTEX/BBD/UWMC/etc. looked open when they were flat, and
their realized P&L was dropped. Now flatten parent + filled legs (legs inherit
the parent symbol).
2. get_orders only fetched the most-recent page; Alpaca's `limit` truncates by
recency (legs count toward the cap), so a busy day could drop the morning's
fills entirely. Unscoped get_orders now pages backwards with `until` (dedup by
id) to capture the full day; the symbol-scoped path stays single-page.
Verified live: journal open set now matches the broker exactly
(ATPC/GRAB/LNKS/NOWL/WPRT) and every reconstructed round-trip ties to a real
broker fill. NB: the realized total is FIFO-lot based, so while positions are
partially open it won't equal the broker's average-cost day P&L — the broker
figure remains the authoritative headline.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- momentum watch: replace 'open positions' with TODAY'S trade history (FIFO
round-trips from the broker orders snapshot: time/symbol/qty/entry/exit/P&L +
open lots), resets each day. Headline day P&L is broker-accurate (equity -
last_equity, now carried on AccountSummaryUpdatedEvent), shown in the header
and the panel title. sync_orders limit 50->500 so the log captures the whole
day across restarts.
- SYMBOL_WEIGHTS: optional manual per-symbol priority nudge applied to the
armed-trigger rank score (small; doesn't override gap/volume logic).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A transient WSL DNS outage made 3 consecutive equity reads fail, and the
fail-CLOSED breaker then PERMANENTLY halted new entries for the whole session
even after DNS recovered seconds later. Fixes:
- split the breaker into a permanent _halted (real daily-loss breach) and a
recoverable _data_halt (equity unreadable) that clears on the next good read;
raise the pause threshold to 5 (TRADING_EQUITY_FAIL_LIMIT).
- AlpacaPaperClient._request retries transient URLError/gaierror (not HTTP
4xx/5xx) a couple times, so brief blips don't even register as failures.
- sync logs network failures as one-line warnings, not full tracebacks (the
log was spamming stacks).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HIGH:
- Circuit breaker fails CLOSED: a repeated unreadable equity (API 401/429/5xx or
missing field) now halts new entries after 3 consecutive failures instead of
silently reporting 'no breach' and continuing to trade through a drawdown.
- execute(): map order statuses. Terminal-fail (rejected/expired/...) -> ok=False
(never armed as a resting entry); record ANY fill (partial too), not only an
exact 'filled'; require a real broker order id. approve_order only arms
genuinely OPEN statuses.
- sync: account/positions/orders failures now emit a BrokerHealthChangedEvent
(degraded) and step_sync surfaces 'DEGRADED', instead of a success-shaped None
that left risk gates reading stale snapshots as current.
MEDIUM:
- _flatten_all records a position closed only on a CONFIRMED close; the breaker
event reports 'halted_flatten_incomplete' + the unclosed symbols when a close
fails, instead of claiming the book is flat.
- submit_exit_order prefers close_position (handles short sign + fractional qty;
a plain sell of abs(qty) would double a short).
LOW:
- get_orders(nested=true) so bracket child legs aren't dropped from the snapshot.
+ tests/unit/test_execution_safety.py (4 regressions). 75/75 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Snapshot before the DuckDB->PostgreSQL migration. data/, archive/, the 232MB
rebuild zip, the Windows .venv, and .env are excluded via .gitignore.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>