← back to Zero Code Trading Bot
references/strategy-dsl.md
79 lines
# Strategy DSL — plain English → `strategy.json`
The "zero code" part: the user describes a strategy in plain English, and Claude
compiles it to a declarative `strategy.json`. The bot never runs arbitrary code —
rules are sandboxed expressions over a fixed set of market variables.
## The shape
```jsonc
{
"name": "longshot-fade",
"venue": "polymarket", // polymarket | kalshi
"mode": "paper", // ALWAYS scaffold as paper; live is gated
"poll_seconds": 300,
"universe": { // which markets are even considered
"query": "", // substring match on market title ("" = all)
"min_volume_usd": 100000,
"max_spread": 0.05,
"resolves_within_days": 45,
"limit": 200
},
"entry": [ // OR-list: first matching rule fires
{ "when": "price <= 0.08 and volume_usd >= 100000", "side": "YES",
"reason": "deep longshot with liquidity" }
],
"exit": [ // evaluated on each open position
{ "when": "price >= 0.15", "action": "close", "reason": "take profit" },
{ "when": "price <= 0.03", "action": "close", "reason": "stop loss" }
],
"sizing": {
"type": "fixed_usd",
"amount": 25, // $ per new position
"max_position_usd": 50,
"max_open_positions": 10
},
"risk": {
"max_daily_loss_usd": 100, // circuit breaker: halt new entries for the day
"max_total_exposure_usd": 250, // hard cap on summed open size
"kill_switch": true // honor a data/KILL file
}
}
```
## Rule variables (the ONLY names a `when` may use)
| variable | meaning |
|-------------------|-------------------------------------------|
| `price` | current YES price, 0..1 |
| `volume_usd` | lifetime USD volume |
| `liquidity_usd` | order-book liquidity |
| `spread` | best ask − best bid, 0..1 |
| `days_to_resolve` | days until the market resolves |
Operators allowed: `and or not == != < <= > >= + - * / % **` and numeric
constants. **No function calls, no attribute access, no other names** — enforced
by `safe_eval.py` and re-checked by `scripts/validate_strategy.py`.
## Translating plain English (examples)
| user says | compiles to |
|-----------|-------------|
| "buy longshots under 8 cents with real volume, take profit at 15c, stop at 3c" | entry `price <= 0.08 and volume_usd >= 100000`; exits `price >= 0.15` / `price <= 0.03` |
| "fade near-certain YES over 92c, close if it drops below 85c" | entry `price >= 0.92`, side `NO`; exit `price <= 0.85` |
| "only tight markets resolving this month" | universe `max_spread: 0.03, resolves_within_days: 31` |
| "never risk more than $200 total, $20 a bet, 8 positions max" | sizing `amount:20, max_open_positions:8`; risk `max_total_exposure_usd:200` |
## Workflow
1. Draft `strategy.json` from the user's words.
2. `scripts/validate_strategy.py strategy.json` — must pass.
3. `scripts/new_bot.py <name> --strategy strategy.json` — scaffold the project (paper).
4. `python bot.py --once --dry-run` inside it — confirm the rules fire as intended.
5. Iterate on the rules, re-validate, re-dry-run. Only Steve flips it toward live.