spread_capture
This page covers spread_capture, one of the five built-in strategies, on Kalshi, Polymarket and Polymarket US: how it quotes, each parameter, venue differences, backtests and an example. Rules all five share, such as order sizes and how to write params, are on the Built-in Strategies page. Every number here is an illustrative example, not a suggested setting.
spread_capture quotes both sides of a market around the mid. Each loop, for each market:
- If your position is already at
risk.max_positionor more, it skips quoting. Quotes already resting stay where they are. - It reads the best YES bid and YES ask. On Kalshi the ask is 1 minus the best NO bid.
- If the book is one-sided, or the ask minus the bid is less than
spread_floor, it cancels its open quotes and posts none. - Otherwise it cancels its open quotes and posts
order_countlevels. Level i buys YES at mid − i ×spread_floor/2 and sells YES at mid + i ×spread_floor/2.
spread_capture: one loop, two books
Spread 0.08: quote
Bid 0.46, ask 0.54. The spread is at least spread_floor, so the Bot cancels its own resting quotes in this market, leaving your other orders alone, then posts 3 levels on each side.
- 0.56Sell YES · level 3
- 0.54Sell YES · level 2best ask
- 0.52Sell YES · level 1
- 0.50Mid(0.46 + 0.54) / 2
- 0.48Buy YES · level 1
- 0.46Buy YES · level 2best bid
- 0.44Buy YES · level 3
Spread 0.03: no quotes
Bid 0.49, ask 0.52. The spread is below spread_floor, so the Bot cancels the same orders and posts nothing this loop.
- 0.52Best ask
- 0.505Mid
- 0.49Best bid
The same happens when the book is one-sided. Once your position reaches max_position, the Bot stops refreshing and leaves resting quotes in place.
- Buy YES quote
- Sell YES quote
- Order book
spread_floor: 0.04, order_count: 3, price_floor: 0.10, price_ceiling: 0.90. Each level is spread_floor / 2 = 0.02 further from the mid. Quotes are 1 contract on Kalshi and Polymarket US, and the market's minimum order size (often 5 shares) on Polymarket. With an open-contract cap of 3 (the lower of max_position and Max open contracts), a Kalshi or Polymarket US ladder stops after about 2 levels. Sell quotes differ by venue: on Kalshi, a filled YES sell while you hold no YES opens a NO position; on Polymarket, sell quotes are posted only for YES you already hold.Note: Each refresh cancels only the Bot's own quotes. Your manual orders and other Bots' orders in the market stay resting. On Kalshi and Polymarket US they still count toward Max open contracts.
How the Bot knows which orders are its own:
- Kalshi: the Bot recognizes its orders by this deployment's client order id. When you redeploy a Bot in place, the deploy asks you to adopt the market's resting orders; the previous deployment's quotes you adopt are refreshed like the new ones, so its old ladder doesn't sit at stale prices. An adopted manual order is still never cancelled.
- Polymarket and Polymarket US: orders carry no client id, so the Bot remembers the id of every order the exchange accepts from it. That memory survives restarts and redeploys, but not stopping the Bot, so quotes a stopped Bot left behind stay resting until you cancel them.
| Parameter | Type | Default | Allowed values | What it does |
|---|---|---|---|---|
spread_floor | number (YES dollars) | Required | > 0 | Minimum spread before the Bot quotes. Also the quote spacing: each level sits spread_floor/2 further from the mid. |
order_count | whole number | Required | ≥ 1 | Quote levels on each side. |
post_only | boolean | false | true, false | Maker-only quotes: a quote that would trade immediately is rejected instead. |
refresh_on_fill | boolean | false | true, false | No effect. The ladder is cancelled and re-posted every loop anyway. |
spread_floor
Quotes are centered on the mid, not on the edge of the book. When the spread is wider than spread_floor, the first level sits inside the current spread. Prices are rounded to whole cents on Kalshi, to the market's tick on Polymarket (buys round down, sells round up), and to 2 decimals on Polymarket US.
A buy quote below price_floor is raised to the floor, and a sell quote above price_ceiling is lowered to the ceiling. If the floor sits above the ask, the raised buy can trade immediately unless post_only: true.
order_count
Each level is one YES buy and one YES sell. Orders go out one at a time. On Kalshi and Polymarket US, a quote refused by a deployment risk limit ends that loop's ladder.
- The open-contract cap, the lower of
max_positionand Max open contracts, counts every resting quote, so at 3 a Kalshi or Polymarket US ladder stops after about 2 levels. Raise bothmax_positionand Max open contracts to about 2 ×order_count. - On Kalshi the ladder sends up to 2 ×
order_countorders per market per loop, and the order budget is 20 per 60 seconds. Withloop.interval: 10andorder_count: 3that is 36 orders a minute, so some loops post no quotes. - On regular Polymarket each buy quote is the market's minimum size (often 5 shares), whatever
max_positionis, so a fill can take you pastmax_position.
spread_capture by venue
| Kalshi | Polymarket | Polymarket US | |
|---|---|---|---|
| Quote size | 1 contract | Market minimum (often 5 shares) | 1 contract |
| Sell quote while you hold no YES | Posted. A fill opens NO, because selling YES you don't hold is a NO buy. | Not posted. Sells only sell YES you hold. | Posted |
| Orders cancelled each loop | The Bot's own quotes, plus a previous deployment's quotes you adopted when redeploying | The Bot's own orders | The Bot's own orders |
| Deployment risk limits | Enforced | Not applied | Enforced |
| Backtest | Yes | No | No |
On Kalshi, YES sell quotes are never blocked by risk.max_entries_per_market or by the Max open contracts check, because both apply only to buys. Resting sell quotes still count toward the open-contracts total that the next buy is checked against.
spread_capture backtests
Kalshi spread_capture backtests use a resting-order replay, which differs from live in a few ways:
- Quotes are always post-only.
- Each level is modelled as a 1-contract YES bid and a 1-contract NO bid, and
max_positioncaps YES and NO holdings separately. - When the mid is outside
price_floortoprice_ceiling, the backtest skips quoting; the live Bot clamps its prices instead.
Regular Polymarket rejects spread_capture backtests, and Polymarket US has no backtests. See Backtest.
spread_capture example
Illustrative only: a one-level ladder on a single Kalshi game market. It quotes only when the spread is about 4 cents or more (an exactly 4-cent spread can miss by rounding), and stops refreshing once 3 contracts are held. With a mid of 0.50 it posts a buy at 0.48 and a sell at 0.52. The one-level ladder fits the deployment risk limits Studio pre-fills. The ticker is an example; saving a strategy doesn't check that the market exists.
version: 1
platform: kalshi
strategy: spread_capture
market:
ticker: "KXNBAGAME-26NOV04LALBOS-LAL"
risk:
max_position: 3
price_floor: 0.10
price_ceiling: 0.90
loop:
interval: 15
params:
spread_floor: 0.04
order_count: 1
post_only: true