Strategy grammar

Every tinycorp.ai strategy is a JSON config. The Builder lets you assemble it visually, but the raw shape is documented here so power users can fork-and-edit. The engine runs your config against live market data every 5 minutes and logs simulated fills.

Reference

Overall shape

A strategy config is a JSON object with five top-level keys:

{
  "platforms": ["kalshi", "poly", "manifold"],
  "categories": ["weather", "sports", "crypto", ...],
  "entry": { /* all filter fields below go here */ },
  "exit":  { "at": "expiry" },
  "sizing": { "type": "flat", "amount_cents": 500 },
  "side":   "YES"
}

Every cycle (every 5 minutes), the engine fetches markets matching platforms + categories, then applies the entry filter rules in order. Matching markets get a simulated fill at the current ask.

platforms + categories

FieldTypeNotes
platformslist<str>Subset of kalshi, poly, manifold. Defaults to ["kalshi"] if omitted.
categorieslist<str>Optional. Empty list = all categories. Kalshi has weather. Poly has crypto, sports, politics, economics, commodities, stocks, other, world-events, entertainment.

Price filters

FieldTypeNotes
entry.yes_ask_minfloat 0-1Minimum YES ask (e.g., 0.85 = 85¢).
entry.yes_ask_maxfloat 0-1Maximum YES ask. Use both for a band.
entry.yes_bid_minfloat 0-1Minimum YES bid.
entry.yes_bid_maxfloat 0-1Maximum YES bid.

Liquidity filters

FieldTypeNotes
entry.vol_24h_minintMinimum 24h volume in USD (or MANA on Manifold).
entry.open_interest_minintMinimum open interest contracts.
Kalshi quirk: volume_24h is NULL on most weather brackets. If you set vol_24h_min on a kalshi+weather strategy, you'll exclude most candidates. Leave it off for weather; use it for poly markets.

Timing filters

FieldTypeNotes
entry.hours_to_close_minfloatMin hours until market close. 0.5 = at least 30 min out.
entry.hours_to_close_maxfloatMax hours until close. 8 = within 8 hours of close.
entry.title_containslist<str>Market title must contain each substring (case-insensitive). E.g., ["minimum"] for LOW brackets.

Momentum signals

Price-delta filters that require a lookback window. Engine reads from market_price_snapshots (cached every 1-3 min per platform).

FieldTypeNotes
entry.ya_change_window_minint (minutes)Required when using ya_change filters. Defines the lookback. E.g., 30 = look 30 min back.
entry.ya_change_min_centsintYES ask must have RISEN by at least this many cents in the window. Positive value.
entry.ya_change_max_centsintYES ask must have DROPPED by at least this many cents (use negative). E.g., -5 = dropped 5+ cents.
// "Buy when ya dropped 5+¢ in the last 30 min"
{
  "yes_ask_min": 0.40,
  "yes_ask_max": 0.85,
  "ya_change_max_cents": -5,
  "ya_change_window_min": 30
}

Volume-spike signals

FieldTypeNotes
entry.vol_spike_ratio_minfloatCurrent 24h volume / lookback-ago volume. 2.0 = doubled. Requires ya_change_window_min.

Calendar gates

Short-circuit filters that fire before any market query. Use for strategies that should only run during specific times.

FieldTypeNotes
entry.hour_of_day_minint 0-23UTC hour. Strategy skips entire cycle outside the range.
entry.hour_of_day_maxint 0-23UTC hour.
entry.day_of_week_inlist<int>Mon=0..Sun=6. [0,1,2,3,4] = weekdays only.

External anchors

Signals that reference external data sources we poll.

FieldTypeNotes
entry.crypto_anchorobject {"symbol": "bitcoin", "usd_above": 70000} or "usd_below". Spot price from CoinGecko (free, polled every 5 min). Supported symbols: bitcoin, ethereum, solana, ripple, dogecoin. Fails closed if no fresh data in 30 min.
entry.nws_anchorobject {"value_above": 50} or {"value_below": 60} — degrees F. Per-candidate filter: parses the Kalshi weather ticker (e.g. KXLOWTSFO-26MAY24-B49.5 → SFO low for May 24), fetches the latest NWS forecast for that station/date, applies the threshold. Supported stations: KSFO, KAUS, KATL, KBOS, KDCA, KDEN, KDAL, KHOU, KLAS, KLAX, KMDW, KMIA, KMSP, KNYC, KOKC, KPHL, KPHX, KSAT, KSEA. NWS forecasts updated hourly. Fails closed when no forecast available.
Combining anchors: a strategy can use any/all of these in the same entry block. E.g., a weather-fade strategy can require both nws_anchor.value_above AND a price band — both must pass.

Exit + sizing

FieldTypeNotes
exit.atstr"expiry" is the only supported value in v1. Strategies hold to market close; engine settles based on official result (Kalshi) or last_price (Poly/Manifold).
sizing.typestr"flat" only in v1.
sizing.amount_centsintDollars-per-trade in cents. 500 = $5/trade. House strategies use $5.
sizing.max_fills_per_dayintOptional cap on total fills per UTC day. Useful for broad-match strategies (cheap-price lottery, vol-spike on Poly's "other" category) that would otherwise fire on dozens of markets per cycle. Once the cap is reached, the engine stops opening new positions for the strategy until tomorrow.
sidestr"YES" or "NO". Most strategies are YES.

Full examples

Fade weather brackets in the late window:

{
  "platforms": ["kalshi"],
  "categories": ["weather"],
  "entry": {
    "yes_ask_min": 0.85,
    "yes_ask_max": 0.95,
    "hours_to_close_max": 18
  },
  "exit": { "at": "expiry" },
  "sizing": { "type": "flat", "amount_cents": 500 },
  "side": "YES"
}

Multi-signal: weekday US morning Poly mover with vol spike:

{
  "platforms": ["poly"],
  "categories": ["other", "politics", "economics"],
  "entry": {
    "yes_ask_min": 0.25,
    "yes_ask_max": 0.75,
    "vol_24h_min": 10000,
    "vol_spike_ratio_min": 1.3,
    "ya_change_window_min": 60,
    "hour_of_day_min": 13,
    "hour_of_day_max": 17,
    "day_of_week_in": [0,1,2,3,4]
  },
  "exit": { "at": "expiry" },
  "sizing": { "type": "flat", "amount_cents": 500 },
  "side": "YES"
}
Live preview: drop any config into the Builder — the "Markets matching now" panel re-evaluates against live data on every chip click via POST /api/quants/preview.

API reference

EndpointMethodNotes
/api/quants/strategiesGETList public strategies. Params: category, status, sort (sharpe/pnl/win_rate/newest), limit.
/api/quants/strategies/<slug>GETSingle strategy preview + config (when entitled).
/api/quants/strategies/<slug>/pnlGETCumulative realized P&L points for the chart.
/api/quants/strategies/<slug>/tradesGETSimulated trade log (5 for preview, 50 for unlocked).
/api/quants/strategies/<slug>/candidatesGETMarkets currently matching all entry rules.
/api/quants/strategies/<slug>/versionsGETEdit history snapshots.
/api/quants/previewPOSTEvaluate an ad-hoc config (used by the Builder). Body: {"config": <config>}.
/api/quants/leaderboardGETSortable list. Params: sort, limit.
/api/quants/activityGETRecent fills + publishes + unlocks platform-wide.
/api/quants/statsGETTopline platform numbers.

House strategies using each signal

Live snapshot from /api/quants/strategies. Click any strategy name to see its full config + live performance.

Loading…