Custom Rule Actions
The action is what a custom rule does when it is the first rule to match on a tick (see How rules are evaluated). This page covers what each action does on Kalshi, Polymarket and Polymarket US and in backtests, then how size and price bounds apply. Kalshi's composite orders, which a rule can use instead of action, are covered in Advanced Kalshi Rules.
Action reference
| Action | Kalshi | Polymarket | Polymarket US | Backtest |
|---|---|---|---|---|
buy_yes | Limit buy at the YES ask | Limit buy at the YES midpoint | Limit buy at the last trade price | Fills at the next candle's YES ask |
buy_no | Limit buy at the NO ask | Limit buy at the NO midpoint | Limit buy at 1 minus the last trade price | Fills at the next candle's NO ask |
sell_yes | Sells this Bot's available YES at the YES bid, immediate-or-cancel | Limit sell of size (or all) YES at the YES bid | Not allowed | Sells all YES at the next candle's bid |
sell_no | Sells this Bot's available NO at the NO bid, immediate-or-cancel | Limit sell of size (or all) NO at the NO bid | Not allowed | Sells all NO at the next candle's bid |
sell_all | Sells this Bot's available holdings, immediate-or-cancel at the bid | Limit sell of each token you hold at its bid | Market orders for the whole position, split to fit Max contracts per order | Closes everything at the next candle |
cancel_all | Cancels this Bot's resting orders on the market | Cancels all your open orders in the market | Cancels all your open orders on the market | No effect in ordinary backtests |
skip | Nothing; stops checking rules this tick | Same | Same | Same |
Action names are lowercase. buy, sell, close or BUY_YES give unknown action. On Polymarket US, sell_yes and sell_no are rejected with use sell_all on Polymarket US.
Buying: buy_yes and buy_no
Kalshi. A good-till-canceled limit buy for size contracts at the current ask, clamped into risk.price_floor to risk.price_ceiling. Because it is priced at the ask it usually fills at once; any remainder rests on the book. If the ask is above your ceiling, the order is posted at the ceiling and rests. Every buy must also pass your Studio deployment risk limits (Max contracts per order, Max open contracts, which never allows more than risk.max_position, Max dollars per order, Max daily notional traded) and your balance. A buy that would break one of them is refused with an error, not resized. Once Max daily loss is reached, a matching buy rule is skipped instead, and the rules below it still run. risk.max_notional trims the quantity to the remaining budget, and risk.max_entries_per_market can skip the buy.
Kalshi entries also wait while the account holds contracts in this market that are not attributed to this Bot. Its existing holdings can still exit.
Both sides of a Kalshi book must have orders when the buy is sent; otherwise the buy errors for that tick. Because price falls back to the last trade (or 0.00) when there is no YES bid, a price-only entry can match on an empty book and then error. Gate Kalshi entries on spread or on the order book fields, which fail safe when a side is empty.
Polymarket. A good-till-canceled limit buy at the token's midpoint, rounded down to the market's tick and clamped to your price bounds, so it can rest instead of filling. The buy is skipped while any of your orders rest in the market, unless risk.max_entries_per_market is set. The quantity is size shares, trimmed to risk.max_position minus what you hold and to the remaining risk.max_notional budget. If the result is below the market's minimum order size (commonly 5 shares), the entry is blocked. Polymarket holds YES and NO tokens separately, so buying NO does not reduce a YES holding.
Polymarket US. A good-till-canceled limit buy at the last trade price (buy_yes) or 1 minus the last trade price (buy_no), clamped to your price bounds. It is skipped while any of your orders rest on the market, and it needs buying power, a two-sided book and your Studio deployment risk limits.
Backtest. A fill at the next candle's opening ask. A buy whose price is outside your price bounds is skipped, not clamped. If you hold the opposite side, it is sold first. On Polymarket this differs from live trading, where YES and NO tokens are held separately.
A buy rule without a position_size == 0 gate (or a similar cap) matches on every tick and keeps adding until a risk limit stops it.
Selling: sell_yes, sell_no and sell_all
Kalshi. Sells this Bot's available holding of the side (or, for sell_all, whichever side it holds) with reduce-only, immediate-or-cancel limit orders at the best bid. Every exit, including composite orders, is capped at the Bot's attributed inventory and the account's remaining holdings. Pending or unconfirmed exits reserve inventory so it cannot be submitted again. These checks apply with or without a trading schedule. Large positions go out in chunks of up to 40 contracts, or your Max contracts per order if that is lower. Whatever does not fill is canceled, and the rule tries again on the next tick if it still matches. size is ignored. With no bid on that side, the sell errors for that tick. Sells are not clamped to your price bounds. Kalshi also refuses any order, sells included, when the market's most recent trade is more than 120 seconds old, so on a quiet market an exit can be refused until a fresh trade prints (see Kalshi units and execution).
Polymarket. sell_yes and sell_no place a good-till-canceled limit sell of size tokens (all of them if size is omitted) at that token's best bid, rounded up to the tick. This is how you scale out. Sells are not clamped to your price bounds, so a stop-loss with the bid below risk.price_floor sells at the bid. If the token has no bid, the sell is priced from that token's ask or last trade and may rest unfilled. Do not rely on selling into an empty book. Unlike buys, Polymarket sells are not held back while your orders rest: if a sell rests unfilled and the rule still matches on the next tick, it places another sell. Add order_count == 0 to scale-out rules. sell_all places a limit sell of the full balance of each token you hold, at its best bid, or its best ask when there is no bid; a token with no book price is skipped.
Polymarket US. Only sell_all is allowed. It sells your whole position with market orders, split into orders of at most min(40, Max contracts per order) contracts. It needs a bid to sell into, and it is refused if the side you hold cannot be determined.
Backtest. Every sell closes the whole side at the next candle's opening bid, including a Polymarket sell_yes with a size.
A sell that matches while you are flat does nothing, but it still ends evaluation for that tick. Selling does not cancel your resting orders; add a cancel_all rule if they should come down too.
cancel_all
Cancels resting orders on the current market. It does not sell anything.
- Kalshi: cancels only this Bot deployment's own resting orders. Manual orders and other Bots are untouched.
- Polymarket and Polymarket US: cancels only the orders this Bot placed, which it recognizes by the order ids the exchange accepted from it. Manual orders and other Bots are untouched.
- Backtest: no effect in ordinary backtests (orders never rest); it cancels simulated resting orders in Kalshi composite-order backtests.
cancel_all satisfies the required exit rule, but it never reduces a position.
skip
Places no order and stops checking rules for this market until the next tick. Use it as a guard above your entries, for example to stand aside when the spread is wide or cash is low. It does not count as an exit, and a skip above your exits blocks them. Its conditions still count when the validator looks for unreachable rules, so a skip that matches every state is rejected.
Size rules
size is a whole number of contracts (Kalshi, Polymarket US) or shares (Polymarket). It is a quantity, not dollars: 12 contracts at $0.39 cost $4.68 before fees.
- Buys: omitted or 0 means 1. Negative sizes are rejected.
- Save-time limits: a buy's
sizemust be at mostrisk.max_position, andsize × risk.price_floormust fit insiderisk.max_notionalwhen that is set. - Whole numbers only.
size: 1.9fails withrules[0].size: must be a whole number, got 1.9, and so does a fractionalorders[].size. A quoted size (size: "2") is a YAML error. - Kalshi and Polymarket US: your Studio deployment risk limits apply at runtime. Studio pre-fills Max contracts per order from the largest buy
sizeacross your rules (an omitted size counts as 1). A buy larger than the limit you deploy with is refused, not shrunk. On Polymarket US asell_alllarger than it is split to fit. - Polymarket: a buy below the market's minimum order size is blocked, so an omitted size (1 share) usually never trades. The quantity is also trimmed by
risk.max_positionandrisk.max_notional. - Sells:
sizeis ignored, except by Polymarketsell_yes/sell_no, where it caps how many tokens are sold. - Backtests: buys are trimmed to
risk.max_positionminus your position, and sells close the whole side. In a multi-market backtest withrisk.max_notionalset, a buy with nosizebuys as many contracts as the remaining budget allows, which differs from live. Writesizeon every buy rule so live and backtest agree.
Price bounds
risk.price_floor and risk.price_ceiling bound order prices differently by venue: Kalshi clamps buy prices only, Polymarket clamps buys and tick-rounds every order, and Polymarket US clamps buys. Backtests skip buys whose fill price falls outside the band. To avoid resting bids when the market is above your limit, put the limit in the rule itself, for example yes_best_ask <= 0.60.