get_latest_price queried TradingClient.get_asset (asset metadata — no price fields) so it ALWAYS returned Decimal('0'). Every Kevin signal was priced 0, so the executor skipped them ("No current price") even after the Phase 1 sizing fix; the market-closed deferral masked it until the market-open drain.
Use StockHistoricalDataClient.get_stock_latest_trade with a daily-bar close fallback — both return the last session's data, so they work when the market is closed (Kevin posts at all hours). Validated live: MRVL 263.16, AVGO 385.10 with the market closed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bracket stop-loss/take-profit legs fill at Alpaca without passing through the executor, so those closes (and their P&L) were invisible locally.
- broker: add get_order(nested) + list_orders to BaseBroker/AlpacaBroker (+ SimulatedBroker); BrokerOrder carries child legs
- Trade gains broker_order_id (migration f6a7b8c9d0e1); executor stamps the entry order id
- new api_gateway trade-reconcile loop: books a closing SELL + realized P&L when a bracket leg fills (idempotent on the leg order id), syncs PENDING->terminal status, logs drift; runs alongside portfolio_sync
[ci skip]
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wires the dependency-injected KevinBridge to concrete Redis cursor +
DB session factory + AlpacaBroker (or stub when creds missing). Includes
TradeSignalPublisher (Pydantic -> dict for the redis stream) and
SIGINT/SIGTERM graceful shutdown. Adds is_asset_tradable + get_latest_price
to AlpacaBroker so the bridge can query asset metadata.