Map XRP/ETH below-pairs + harden Kalshi quote handling

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>
This commit is contained in:
Casey Judice
2026-05-29 17:44:20 -04:00
parent 9fba884cf4
commit 36dd29b549
3 changed files with 51 additions and 33 deletions
+12 -2
View File
@@ -22,6 +22,12 @@ all resolution regions and key off the guaranteed worst case, NOT (1 - cost).
"""
from datetime import date
# Kalshi market statuses that mean the market is no longer live/tradeable.
# A settled/finalized market still returns prices, but they are stale 1.0/0.0
# sentinels (e.g. a month-end MINMON whose strike already resolved) and must
# not be treated as a real quote.
_DEAD_KALSHI = {"finalized", "settled", "closed", "determined"}
def direction(ticker):
return "Below" if "MINMON" in (ticker or "").upper() else "Above"
@@ -125,7 +131,8 @@ def evaluate(pair, kq, pq, settings, today=None):
if not pq:
row["status"] = "NO POLY"
return row
if not kq:
if not kq or (kq.get("status") in _DEAD_KALSHI):
# Settled/finalized Kalshi leg: prices are stale sentinels, not a quote.
row["status"] = "NO KALSHI"
return row
@@ -149,7 +156,10 @@ def evaluate(pair, kq, pq, settings, today=None):
cands.append(("NO+YES", "NO", kq["no_ask"], k_nsz,
"YES", pq["yes_ask"], pq.get("yes_ask_size")))
if not cands:
row["status"] = "NO DATA"
# Both venues returned live quotes, but the opposite-side asks needed to
# build a hedge aren't both offered (e.g. deep-OTM 'below' markets where
# each venue only quotes the cheap YES side). There's data, just no arb.
row["status"] = "NO ARB"
return row
best = None # (worst_pnl, ...)
+10 -2
View File
@@ -31,6 +31,14 @@ def _f(v):
return None
def _ask(v):
"""Like _f, but also drops the '1.0000' sentinel Kalshi returns when there
is no resting offer on that side. Real Kalshi asks are 1-99c, so a $1.00
ask is never executable and must not be treated as a tradeable quote."""
x = _f(v)
return x if (x is not None and x < 1.0) else None
def parse_expiry(ticker):
"""KX...-26MAY31-7000 -> '2026-05-31', else None."""
m = re.search(r"-(\d{2})([A-Z]{3})(\d{2})-", ticker)
@@ -49,9 +57,9 @@ def _quote(mkt):
return {
"ticker": t,
"yes_bid": _f(mkt.get("yes_bid_dollars")),
"yes_ask": _f(mkt.get("yes_ask_dollars")),
"yes_ask": _ask(mkt.get("yes_ask_dollars")),
"no_bid": _f(mkt.get("no_bid_dollars")),
"no_ask": _f(mkt.get("no_ask_dollars")),
"no_ask": _ask(mkt.get("no_ask_dollars")),
"yes_ask_size": None,
"no_ask_size": None,
"open_interest": _f(mkt.get("open_interest_fp")) or 0.0,
+29 -29
View File
@@ -316,16 +316,16 @@
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-75000",
"kalshi_strike": 750.0,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-ethereum-dip-to-800-in-may-2026",
"poly_strike": 800.0
},
{
"active": true,
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-50000",
"kalshi_strike": 500.0,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-ethereum-dip-to-400-in-may-2026",
"poly_strike": 400.0
},
{
"active": true,
@@ -340,32 +340,32 @@
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-200000",
"kalshi_strike": 2000.0,
"poly_slug": "will-ethereum-dip-to-2000-in-may-2026",
"poly_strike": 2000.0
"poly_slug": "will-ethereum-dip-to-1800-in-may-2026",
"poly_strike": 1800.0
},
{
"active": true,
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-175000",
"kalshi_strike": 1750.0,
"poly_slug": "will-ethereum-dip-to-2000-in-may-2026",
"poly_strike": 2000.0
"poly_slug": "will-ethereum-dip-to-1800-in-may-2026",
"poly_strike": 1800.0
},
{
"active": true,
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-150000",
"kalshi_strike": 1500.0,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-ethereum-dip-to-1400-in-may-2026",
"poly_strike": 1400.0
},
{
"active": true,
"asset": "ETH",
"kalshi_ticker": "KXETHMINMON-ETH-26MAY31-125000",
"kalshi_strike": 1250.0,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-ethereum-dip-to-1200-in-may-2026",
"poly_strike": 1200.0
},
{
"active": true,
@@ -564,64 +564,64 @@
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-130",
"kalshi_strike": 1.3,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-1pt2-in-may-2026",
"poly_strike": 1.2
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-120",
"kalshi_strike": 1.2,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-1pt2-in-may-2026",
"poly_strike": 1.2
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-110",
"kalshi_strike": 1.1,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-1-in-may-2026",
"poly_strike": 1.0
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-100",
"kalshi_strike": 1.0,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-1-in-may-2026",
"poly_strike": 1.0
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-090",
"kalshi_strike": 0.9,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-0pt8-in-may-2026",
"poly_strike": 0.8
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-080",
"kalshi_strike": 0.8,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-0pt8-in-may-2026",
"poly_strike": 0.8
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-070",
"kalshi_strike": 0.7,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-0pt6-in-may-2026",
"poly_strike": 0.6
},
{
"active": true,
"asset": "XRP",
"kalshi_ticker": "KXXRPMINMON-XRP-26MAY31-060",
"kalshi_strike": 0.6,
"poly_slug": null,
"poly_strike": null
"poly_slug": "will-xrp-dip-to-0pt6-in-may-2026",
"poly_strike": 0.6
},
{
"active": true,
@@ -943,4 +943,4 @@
"poly_slug": "will-bnb-dip-to-500-in-may",
"poly_strike": 500.0
}
]
]