entry,
take_profit, stop_loss — plus an execution_params block. The
same shape powers the visual Strategy Builder, the backtest engine,
and the paper trader.
Top-level shape
Condition tree
A tree node is either a group (AND / OR over children) or a leaf (a typed primitive condition).Group node
op is "AND" or "OR". Children can themselves be groups, so trees
nest arbitrarily.
Leaf node primitives
| Field | Notes |
|---|---|
type | Required. One of the eight primitives above. |
side | "yes" or "no" — only for token-side primitives. |
op | ">=", "<=", ">", "<", "==", "!=", "crosses_above", "crosses_below" |
value | Comparison RHS. Number. |
window_sec | Only for volatility primitives. Lookback. |
crosses_above / crosses_below use the immediately-preceding
snapshot — true if the threshold was crossed in this step.
Empty trees
An empty tree is equivalent to a constant:entry: {op: "AND", children: []}→ always fires on first fillable snapshot.take_profit / stop_loss: {op: "AND", children: []}→ never fires via that path; trade exits only at resolution.
Resolution risk modeling
If a market resolves to an outcome other thanUp / Down (UMA
dispute, N/A), the position can resolve to a refund rather than 1. The engine models this via the resolution_risk block in the
backtest response — each trade’s pnl is the engine’s best estimate
given Polymarket’s actual outcome.
Worked example — endgame
The “endgame sniper” strategy our public audit tracks looks like:/v1/backtest; the engine
replays it across the most-recent N markets and returns realised PnL.