calc.evaluate now reports NO POLY when the Kalshi side has data but the
Polymarket slug doesn't resolve (the common case: Polymarket renamed/
dropped a market while Kalshi still trades it). NO KALSHI is the reverse,
NO DATA only when both are missing. User caught this looking at BTC <70k
May: 20 of 118 pairs were silently NO-DATA when the real cause was Poly-
side absence — now visible as a dedicated NO POLY chip + filter button.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- arb/ibkr.py: Client Portal Gateway client (localhost:5000 over self-
signed SSL; auth_status, tickle, snapshot, secdef/search). Distinct
NotConnected vs NotAuthed exceptions for graceful UI fallbacks.
- arb/daily.py: pairs each user-configured IBKR ForecastEx daily-BTC
contract against the Kalshi KXBTCD market closing at the same UTC
instant with nearest strike. Reuses arb.calc.evaluate for the worst-
case arb math; IBKR slots into the 'pq' position. NO KALSHI status
when no matching Kalshi market exists.
- data/ibkr_contracts.example.json: template (real file gitignored).
- /api/scan/daily route + 'IBKR × Kalshi' tab in the local UI. Tab
shows a setup banner explaining what to do when Gateway/contracts
aren't configured (vs crashing).
- Public Pages dashboard unchanged (positions + IBKR are local-only).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Monthly + hourly Kalshi/Polymarket arb scanner (stdlib-only Python).
- Live positions tab w/ realized P&L history.
- GitHub Actions cron workflow texts SMS via Apps Script webhook on
newly-detected arbs. State persisted in alerts_state.json.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>