kalshi-spread-strike-mechanics draft
How Kalshi expresses spread and total markets as a ladder of independent binary markets — and how this composes with cross-strike blended positions
- Tags
- kalshi spread total strike blended-position position
- Vocabulary
- strike_ladder
- On Kalshi, a spread or total is expressed as a series of independent binary markets at different integer thresholds — e.g. 'Patriots win by 3 or more', 'Patriots win by 7 or more', 'Patriots win by 10 or more'. Each market is its own Yes/No book.
- half_point_translation
- Sportsbook spreads typically use half-points (-3.5, -7.5) to eliminate pushes. Kalshi binary markets use integer thresholds ('win by 4 or more'). The semantic equivalence is: -3.5 sportsbook cover = 'win by 4 or more' Kalshi binary.
- independent_markets
- Each Kalshi strike-binary is its OWN market, with its OWN order book, its OWN Yes/No prices, and its OWN fee model. Different strikes do not share probability mass at the order-book level — they are correlated only through the underlying game.
- composition_with_blend
- When you hold positions across multiple Kalshi strike-binaries on the same game, you are holding a blended-spread-position whose payoff curve is computed by summing per-leg P&L over the integer-margin (or total) outcomes. Each Kalshi binary contributes one leg.
- fee_exempt_bucket
- Spread and total markets on Kalshi are fee-exempt today (game/moneyline markets are not). This affects the cents → American conversion (raw vs. fee-adjusted) and the dollar economics of holding a blend.
A sportsbook quotes a spread as a single line with a single price — "Patriots −3.5 at −110." Kalshi quotes the same economic structure differently: as a ladder of independent binary markets at integer thresholds. "Will the Patriots win by 3 or more?" is one market, with a Yes/No book. "Will the Patriots win by 7 or more?" is a separate market, with a separate Yes/No book. To take a spread position on Kalshi you pick the strike that matches the cover line you want and trade that one binary.
The two consequences for an operator coming from sportsbook conventions are: (1) different strikes on Kalshi are different markets, not different points on a single quote — your Yes-on-"win by 4+" and Yes-on-"win by 7+" share no order-book mechanics and only share the game's outcome; (2) the half-point sportsbook convention has to be translated to integer Kalshi thresholds — "Patriots −3.5" and "Patriots win by 4 or more" are the same bet, while "Patriots −3" and "Patriots win by 3 or more" differ by whether the integer 3 pushes (sportsbook push) or wins (Kalshi binary, which has no push state because it is a strict ≥ comparison against the threshold).
When you hold positions across multiple Kalshi strike-binaries on the same game, you are holding a blended-spread-position in the sense of blended-spread-position. Each Kalshi binary is one leg; the combined P&L is the per-outcome sum across legs. The hooks, key numbers, and dead zones discussed in that entry apply directly. The bucket-by-bucket aggregator described there (aggregate_spread_total_sides) sees one Kalshi binary as one bucket — not the whole "Patriots spread market" — because that's how Kalshi structures the data.
For exact field semantics (how Kalshi names strike thresholds in tickers, how event_ticker differs from ticker, the fee schedule on spread/total vs. game markets), defer to kalshi-mcp via search_gotchas(spread), search_gotchas(strike), and lookup_field(yes_price). Mimir owns the conceptual mapping; kalshi-mcp owns the API-level details.
Worked example
A Patriots-vs-Jets game. The operator believes the Patriots will win comfortably (somewhere around 7-10 points) but wants protection if the game is closer than expected. Two Kalshi positions, on two different binary markets that both reference the same game:
- Leg A: 100 contracts of YES at "Patriots win by 4 or more," bought at 47¢ each. Stake: 100 × $0.47 = $47. Win amount on Yes resolution: 100 × ($1 − $0.47) = $53.
- Leg B: 50 contracts of NO at "Patriots win by 7 or more," bought at 65¢ each. Stake: 50 × $0.65 = $32.50. Win amount on No resolution: 50 × ($1 − $0.65) = $17.50.
The legs combine to express the view: "I'm long Patriots covering −3.5 (Leg A's Yes-on-4+ resolves Yes if margin ≥ 4, equivalent to sportsbook −3.5 cover) but I'm hedged with a No on the bigger spread (Leg B pays out if margin ≤ 6, the No outcome of 'win by 7 or more')."
Build the per-outcome P&L curve over Patriots' margin of victory M. Each leg's contribution depends on whether M clears the leg's threshold:
| Margin M | Leg A (Yes on 4+) | Leg B (No on 7+) | Combined P&L |
|---|---|---|---|
| Pats win by ≥ 7 | +$53 (Yes resolves) | −$32.50 (No loses) | +$20.50 |
| Pats win by 4-6 | +$53 (Yes resolves) | +$17.50 (No resolves) | +$70.50 |
| Pats win by 0-3, tie, or Jets win | −$47 (Yes loses) | +$17.50 (No resolves) | −$29.50 |
Notice the structure:
- The 4-6 band is the hook. Both legs cash. This is the "middle" — it's the region where Leg A's lower threshold has cleared but Leg B's higher threshold hasn't. The win amounts add. Total +$70.50.
- The ≥ 7 band is the partial-hedge region. Leg A still cashes; Leg B loses. Net positive but smaller (+$20.50).
- The 0-3 / loss band is the dead zone. Leg A loses; Leg B's No resolves and partially recovers, leaving net −$29.50.
This is exactly the framework in blended-spread-position. The Kalshi-specific detail is that each leg is its own binary market with its own Yes/No book — Leg A and Leg B don't share liquidity or order-book mechanics. If the order book on the "win by 4+" market is thin, Leg A's execution doesn't benefit from depth on the "win by 7+" market, even though both reference the same game. Use kalshi-mcp__lookup_field(yes_price) to pull current quotes per binary; use position-aggregation for combining the lots into a portfolio view.
For the cents → American conversion on each leg, follow kalshi-yes-to-american-odds. Note the fee-exemption: spread/total markets on Kalshi are fee-free today, so use the raw American conversion (Kairos's is_fee_exempt_bucket("spread") returns True; american_from_kalshi_cents(47, "spread") calls no_maker_fees, not kalshi_half_maker). On the game/moneyline market the fee adjustment applies; on the spread/total binaries it doesn't. Confirm the current bucket-vs-fee mapping via kalshi-mcp__search_gotchas(fee).
Gotchas
- Kalshi spread/total markets are independent binary markets, not strikes of one shared market. Your YES at "win by 4+" and your YES at "win by 7+" don't share order-book probability mass — they are two different markets that happen to reference the same game. Order-book depth, fee accounting, and matching all happen per-binary. The cross-strike correlation only manifests at game-resolution time.
- Half-point sportsbook convention vs. integer Kalshi convention is a translation point. "Patriots −3.5" (sportsbook) = "Patriots win by 4 or more" (Kalshi). "Patriots −3" (sportsbook, with push at margin 3) does not have a clean Kalshi equivalent — Kalshi's "win by 3 or more" includes the integer 3 (no push), and "win by 4 or more" excludes it. The push behaviour is sportsbook-only; Kalshi binaries are strictly above-or-below the integer threshold. Don't translate "−3" as "win by 3 or more" without flagging that the push semantics differ.
- A Kalshi binary at a high threshold is NOT the same as a sportsbook over/under teaser. "Win by 10 or more" on Kalshi is its own binary at its own price. A sportsbook's −10 spread is a separate quote at a separate price, and the implied probabilities of the two will differ (often noticeably) due to liquidity, fee, and operator-base differences. Compare them via the cents → American conversion in
kalshi-yes-to-american-odds, not by assuming they price equivalently. - Yes designation is per-market on Kalshi, including spread markets. "Win by 4 or more" has a Yes side and a No side, and Kalshi designates which is which when the market is created. For most spread markets the Yes-side is the "favored team covers" reading — but verify via
yes_sub_title/no_sub_title(perkalshi-yes-no-semantics). Don't assume Yes = the team listed first. - Fee structure on Kalshi spread/total markets differs from binary moneyline-style markets. Spread and total are fee-exempt today; game (moneyline) is not. This means the cents → American conversion uses different formulas (raw vs. fee-adjusted), and the dollar economics of holding a blend of game + spread positions on the same matchup require per-bucket fee-aware computation. Kairos's
is_fee_exempt_bucketandamerican_from_kalshi_cents(cents, bucket)handle the dispatch; consumers writing their own should mirror the bucket dispatch. Consultkalshi-mcp__search_gotchas(fee)for the canonical schedule. - Each Kalshi binary contributes one leg to the blend; the per-outcome P&L is the sum across legs. A common error is treating two Kalshi positions on related strikes as if they were two strikes of "the same Kalshi spread market" — they aren't. They're independent legs, and the blend's payoff curve is computed by summing the per-leg P&L over each integer outcome of the game (per
blended-spread-position). - Total markets work the same way as spreads on Kalshi. "Will the total exceed 47?" and "Will the total exceed 50?" are independent binaries with independent books. Cross-strike total positions on Kalshi follow the same blend mechanics as cross-strike spread positions, with the substitution
M= combined-score instead of margin-of-victory.
Open questions
- The exact ticker convention Kalshi uses to encode the strike threshold (e.g. how "win by 4 or more" appears in the market
tickerstring vs.event_ticker) is akalshi-mcpdetail. Mimir's framing here treats strikes abstractly; consumers writing automation that selects a binary by strike should consultkalshi-mcp__search_gotchas(strike)for the ticker-encoding rules. Whether Mimir should expose a "strike_threshold" derived field is a future-entry question. - Kalshi occasionally creates spread or total markets at half-integer thresholds (e.g. on markets where the underlying outcome can be non-integer — fractional points, decimal totals). The "integer threshold" framing in this entry is the common case. Whether Mimir should add a half-integer-threshold sub-section is open; for now consumers hitting a half-integer Kalshi binary should treat the threshold the same way mathematically (the strict inequality still applies) but the half-point translation gotcha becomes irrelevant for that specific market.
- The Kairos-side mapping from a Kalshi spread binary to its bucket label (
spread_-3,spread_-7, etc., used byaggregate_spread_total_sides) is implemented in the position-extraction layer and depends on parsing the strike out of the market'syes_sub_title/no_sub_titleor its ticker. The mapping is brittle when subtitles are missing — see thews_normalize.pynotes about not substitutingcontract_tokenintoyes_sub_title. Whether Mimir should warn about this brittleness or keep it as a Kairos-internal coding concern is open; currently the entry references the boundary without diving in.
Cross-references
- mimir: kalshi-yes-no-semantics
- mimir: kalshi-yes-to-american-odds
- mimir: blended-spread-position
- mimir: position-aggregation
- mimir: american-implied-probability
- kalshi-mcp: lookup_field(yes_price)
- kalshi-mcp: lookup_field(no_price)
- kalshi-mcp: search_gotchas(fee)
- kalshi-mcp: search_gotchas(spread)
- kalshi-mcp: search_gotchas(strike)