docs(prompts): add DSL expression kind reference and three working examples

Shows correct usage of rsi/bollinger/ema_trend condition shortcuts, entry_price
and bars_since_entry ExprKind values, and func/cross_over/bin_op expressions.
Also calls out common model mistakes (rsi as ExprKind, bars_since_entry as
FuncName, expr_field) and adds a note that spot strategies are long-only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 13:09:01 +02:00
parent fc9b7e094a
commit 292c101859

View File

@@ -119,6 +119,188 @@ When I share results from previous iterations, use them to guide your next strat
- **Condition audit shows one condition always true/false**: That condition is - **Condition audit shows one condition always true/false**: That condition is
redundant or broken. Remove it or adjust its parameters. redundant or broken. Remove it or adjust its parameters.
## Critical: expression kinds (common mistakes)
These are the ONLY valid values for `"kind"` inside an `Expr` object:
`literal`, `field`, `func`, `bin_op`, `apply_func`, `unary_op`, `bars_since`,
`entry_price`, `position_quantity`, `unrealised_pnl`, `bars_since_entry`, `balance`
Common mistakes to NEVER make:
- `"kind": "rsi"` inside an Expr is WRONG. `rsi` is a *Condition* kind, not an Expr.
To use RSI value in a `compare` expression use: `{{"kind":"func","name":"rsi","period":14}}`
- `"kind": "bars_since_entry"` is a valid standalone Expr (no extra fields needed).
Do NOT put `"bars_since_entry"` as a `"name"` inside `{{"kind":"func",...}}` — that is WRONG.
- `"kind": "expr_field"` does NOT exist. Use `{{"kind":"field","field":"close"}}`.
- `rsi`, `adx`, `supertrend` are NOT valid inside `apply_func`. Use only `apply_func`
with `ApplyFuncName` values: `highest`, `lowest`, `sma`, `ema`, `wma`, `std_dev`, `sum`,
`bollinger_upper`, `bollinger_lower`.
## Working examples
### Example 1 — EMA crossover with trend filter and position exits
```json
{{
"type": "rule_based",
"candle_interval": "1h",
"rules": [
{{
"comment": "Buy: EMA9 crosses above EMA21 while price is above EMA50",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "flat"}},
{{"kind": "ema_crossover", "fast_period": 9, "slow_period": 21, "direction": "above"}},
{{"kind": "ema_trend", "period": 50, "direction": "above"}}
]
}},
"then": {{"side": "buy", "quantity": "0.001"}}
}},
{{
"comment": "Sell: EMA9 crosses below EMA21, OR 2% stop-loss, OR 72-bar time exit",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "long"}},
{{
"kind": "any_of",
"conditions": [
{{"kind": "ema_crossover", "fast_period": 9, "slow_period": 21, "direction": "below"}},
{{
"kind": "compare",
"left": {{"kind": "field", "field": "close"}},
"op": "<",
"right": {{"kind": "bin_op", "op": "mul", "left": {{"kind": "entry_price"}}, "right": {{"kind": "literal", "value": "0.98"}}}}
}},
{{
"kind": "compare",
"left": {{"kind": "bars_since_entry"}},
"op": ">=",
"right": {{"kind": "literal", "value": "72"}}
}}
]
}}
]
}},
"then": {{"side": "sell", "quantity": "0.001"}}
}}
]
}}
```
### Example 2 — RSI mean-reversion with Bollinger band confirmation
```json
{{
"type": "rule_based",
"candle_interval": "4h",
"rules": [
{{
"comment": "Buy: RSI below 35 AND price below lower Bollinger band",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "flat"}},
{{"kind": "rsi", "period": 14, "threshold": "35", "comparison": "below"}},
{{"kind": "bollinger", "period": 20, "band": "below_lower"}}
]
}},
"then": {{"side": "buy", "quantity": "0.001"}}
}},
{{
"comment": "Sell: RSI recovers above 55, OR 3% stop-loss, OR 48-bar time exit",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "long"}},
{{
"kind": "any_of",
"conditions": [
{{"kind": "rsi", "period": 14, "threshold": "55", "comparison": "above"}},
{{
"kind": "compare",
"left": {{"kind": "field", "field": "close"}},
"op": "<",
"right": {{"kind": "bin_op", "op": "mul", "left": {{"kind": "entry_price"}}, "right": {{"kind": "literal", "value": "0.97"}}}}
}},
{{
"kind": "compare",
"left": {{"kind": "bars_since_entry"}},
"op": ">=",
"right": {{"kind": "literal", "value": "48"}}
}}
]
}}
]
}},
"then": {{"side": "sell", "quantity": "0.001"}}
}}
]
}}
```
### Example 3 — ATR breakout with ATR-based stop-loss
```json
{{
"type": "rule_based",
"candle_interval": "1h",
"rules": [
{{
"comment": "Buy: close crosses above 20-bar high while EMA50 confirms uptrend",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "flat"}},
{{"kind": "ema_trend", "period": 50, "direction": "above"}},
{{
"kind": "cross_over",
"left": {{"kind": "field", "field": "close"}},
"right": {{"kind": "func", "name": "highest", "field": "high", "period": 20, "offset": 1}}
}}
]
}},
"then": {{"side": "buy", "quantity": "0.001"}}
}},
{{
"comment": "Sell: 2-ATR stop-loss below entry price, OR 48-bar time exit",
"when": {{
"kind": "all_of",
"conditions": [
{{"kind": "position", "state": "long"}},
{{
"kind": "any_of",
"conditions": [
{{
"kind": "compare",
"left": {{"kind": "field", "field": "close"}},
"op": "<",
"right": {{
"kind": "bin_op", "op": "sub",
"left": {{"kind": "entry_price"}},
"right": {{
"kind": "bin_op", "op": "mul",
"left": {{"kind": "func", "name": "atr", "period": 14}},
"right": {{"kind": "literal", "value": "2.0"}}
}}
}}
}},
{{
"kind": "compare",
"left": {{"kind": "bars_since_entry"}},
"op": ">=",
"right": {{"kind": "literal", "value": "48"}}
}}
]
}}
]
}},
"then": {{"side": "sell", "quantity": "0.001"}}
}}
]
}}
```
## Anti-patterns to avoid ## Anti-patterns to avoid
- Don't use the same indicator for both entry and exit (circular logic) - Don't use the same indicator for both entry and exit (circular logic)
@@ -128,6 +310,7 @@ When I share results from previous iterations, use them to guide your next strat
- Don't create strategies with more than 5-6 conditions — overfitting risk - Don't create strategies with more than 5-6 conditions — overfitting risk
- Don't ignore fees — a strategy needs to overcome 0.1% per round trip - Don't ignore fees — a strategy needs to overcome 0.1% per round trip
- Always gate buy rules with position state "flat" and sell rules with "long" - Always gate buy rules with position state "flat" and sell rules with "long"
- Never add a short-entry (sell when flat) rule — spot markets are long-only
"## "##
) )
} }