125 pairs across BTC/ETH/SOL/XRP/DOGE/BNB/HYPE/ZEC (ZEC stays Kalshi-only). The
alerts workflow regenerates docs/data/scan.json from this, so the public dashboard
rolls to July on its next ~5-min refresh.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Polymarket now publishes a HYPE monthly event
(what-price-will-hyperliquid-hit-in-{month}, no year suffix), so the
old strike-probe fallback was both unnecessary and mis-ranged -- its
strikes [24..52] predated HYPE roughly doubling to ~$72, so every
"above" market ($76-92) was invisible and all 8 above rows came back
NO POLY. Point HYPE at its event like every other asset and re-range
the probe fallback to the current band [52..92].
Regenerated June pairs.json: HYPE now 16/16 with a Poly leg (was 8/16),
total 110/126 (every non-ZEC row paired; ZEC stays Kalshi-only). Only
HYPE rows changed; the other 7 assets are byte-identical.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Regenerated from live markets via scripts/roll_month.py --month 2026-06.
126 rows across 8 assets (102 with a Polymarket leg); every Kalshi ticker
carries the 26JUN30 expiry, every Poly slug is a june-2026 slug. Full
16-strike Kalshi ladders (ETH 14) with no throttling. Also gitignore the
*.bak the roller writes on each roll.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Populate the XRP and ETH MINMON (below) pairs that were silently NO PAIR:
they were never mapped to Polymarket's "dip to" markets (and two ETH pairs
pointed at the now-resolved dip-to-2000). Map each to the nearest live Poly
strike; leave strikes with no comparable Poly market (ETH $250, below Poly's
$400 floor) as NO PAIR.
Also fix two correctness gaps surfaced while investigating:
- Settled/finalized Kalshi markets returned stale 1.0/0.0 sentinel prices and
were scored as live; now reported as NO KALSHI (timely as month-end monthly
contracts settle).
- A Kalshi ask of exactly $1.00 means "no resting offer" (real asks are 1-99c);
it was treated as a tradeable quote, producing phantom BAD BASIS rows at
-100%. Drop it at the source so no fake leg enters the arb math.
- When both venues are live but no opposite-side hedge can be built, report
NO ARB instead of the misleading NO DATA.
No real arb affected (a $1.00 leg can never be profitable); ARB count holds
at 3 and phantom BAD BASIS rows dropped 16 to 9.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Polymarket appends random hash suffixes when re-publishing markets
(e.g. will-bitcoin-dip-to-70k-in-may-2026 → ...-2026-438-356-919).
Our static pairs.json had the unsuffixed slugs from the original
spreadsheet snapshot, so every BTC 'below' pair silently fell through
to NO POLY despite both venues having liquid markets. User flagged
this looking at BTC <70k May.
- scripts/refresh_pairs.py: walks each asset's 'what-price-will-X-
hit-in-may' multi-outcome event on Gamma, rebuilds the
(asset, direction, strike) → slug map, rewrites data/pairs.json.
Probes HYPE strikes individually since there's no container event
for that asset. Has --dry-run.
- data/pairs.json: updated to current live slugs. Two BTC arbs that
were previously hidden now surface (BTC <65k and <70k both ARB).
🤖 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>