feat: add reverse flag and symmetric short support to DSL
Update scout's schema and system prompt to reflect two upstream swym changes from 2026-03-10: - b535207: symmetric short quantity fix — buy-to-cover now correctly uses position_qty (executor was broken; scout's DSL patterns were already correct and will now work as intended) - 6f58949: reverse flag on Action — new optional "reverse": true field that submits position_qty + configured_qty when an opposite position is open, closing it and opening a new one in the opposite direction in a single order (flip-through-zero) Changes: - dsl-schema.json: add "reverse" boolean to Action definition - prompts.rs: add "Reverse / flip-through-zero" capability section and Example 6 (2-rule EMA flip strategy) to FUTURES_SHORT_EXAMPLES Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,11 @@
|
|||||||
{ "$ref": "#/definitions/SizingFixedUnits" },
|
{ "$ref": "#/definitions/SizingFixedUnits" },
|
||||||
{ "$ref": "#/definitions/Expr" }
|
{ "$ref": "#/definitions/Expr" }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Flip-through-zero flag (futures only). When true and an opposite position is currently open, the submitted order quantity becomes position_qty + configured_qty, closing the existing position and immediately opening a new one in the opposite direction in a single order. When flat the flag has no effect and configured_qty is used as normal. Omit or set false for standard close-only behaviour."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -121,6 +121,24 @@ CRITICAL — the `"method"` vs `"kind"` distinction:
|
|||||||
`multiplier` field. Only `amount` is accepted alongside `method`.
|
`multiplier` field. Only `amount` is accepted alongside `method`.
|
||||||
- NEVER add extra fields to SizingMethod objects — they use `additionalProperties: false`.
|
- NEVER add extra fields to SizingMethod objects — they use `additionalProperties: false`.
|
||||||
|
|
||||||
|
### Reverse / flip-through-zero (futures only)
|
||||||
|
|
||||||
|
Setting `"reverse": true` on a rule action enables a single-order position flip on futures.
|
||||||
|
When an opposite position is open, quantity = `position_qty + configured_qty`, which closes
|
||||||
|
the existing position and opens a new one in the opposite direction in one order (fees split
|
||||||
|
proportionally). When flat the flag has no effect — `configured_qty` is used normally.
|
||||||
|
|
||||||
|
This lets you collapse a 4-rule long+short strategy (separate open/close for each leg) into
|
||||||
|
2 rules, reducing round-trip fees and keeping logic compact:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{{"side": "sell", "quantity": {{"method": "percent_of_balance", "percent": "10", "asset": "usdc"}}, "reverse": true}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `reverse` when you always want to be in a position — the signal flips you from long to
|
||||||
|
short (or vice versa) rather than first exiting and then re-entering separately. Do NOT use
|
||||||
|
`reverse` on spot markets (short selling is not supported there).
|
||||||
|
|
||||||
### Multi-timeframe
|
### Multi-timeframe
|
||||||
Any expression can reference a different timeframe via "timeframe" field.
|
Any expression can reference a different timeframe via "timeframe" field.
|
||||||
Use higher timeframes as trend filters, lower timeframes for entry precision.
|
Use higher timeframes as trend filters, lower timeframes for entry precision.
|
||||||
@@ -557,7 +575,58 @@ Key short-specific notes:
|
|||||||
- Stop-loss for short = close > entry_price * (1 + stop_pct), e.g. `* 1.02` for 2% stop
|
- Stop-loss for short = close > entry_price * (1 + stop_pct), e.g. `* 1.02` for 2% stop
|
||||||
- Take-profit for short = close < entry_price * (1 - target_pct), e.g. `* 0.97` for 3% target
|
- Take-profit for short = close < entry_price * (1 - target_pct), e.g. `* 0.97` for 3% target
|
||||||
- Short exit uses `"side": "buy"` with `{"kind": "position_quantity"}` (same as long exit uses sell)
|
- Short exit uses `"side": "buy"` with `{"kind": "position_quantity"}` (same as long exit uses sell)
|
||||||
- `percent_of_balance` for short entry uses `"usdc"` as the asset (the collateral currency)"##;
|
- `percent_of_balance` for short entry uses `"usdc"` as the asset (the collateral currency)
|
||||||
|
|
||||||
|
### Example 6 — Futures flip-through-zero: 2-rule EMA trend-follower using `reverse`
|
||||||
|
|
||||||
|
When you always want to be in a position (long during uptrends, short during downtrends),
|
||||||
|
use `"reverse": true` to flip from one side to the other in a single order. This uses half
|
||||||
|
the round-trip fee count compared to a 4-rule separate-entry/exit approach.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "rule_based",
|
||||||
|
"candle_interval": "4h",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"comment": "Go long (or flip short→long): EMA9 crosses above EMA21 while above EMA50",
|
||||||
|
"when": {
|
||||||
|
"kind": "all_of",
|
||||||
|
"conditions": [
|
||||||
|
{"kind": "any_of", "conditions": [
|
||||||
|
{"kind": "position", "state": "flat"},
|
||||||
|
{"kind": "position", "state": "short"}
|
||||||
|
]},
|
||||||
|
{"kind": "ema_crossover", "fast_period": 9, "slow_period": 21, "direction": "above"},
|
||||||
|
{"kind": "ema_trend", "period": 50, "direction": "above"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {"side": "buy", "quantity": {"method": "percent_of_balance", "percent": "10", "asset": "usdc"}, "reverse": true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Go short (or flip long→short): EMA9 crosses below EMA21 while below EMA50",
|
||||||
|
"when": {
|
||||||
|
"kind": "all_of",
|
||||||
|
"conditions": [
|
||||||
|
{"kind": "any_of", "conditions": [
|
||||||
|
{"kind": "position", "state": "flat"},
|
||||||
|
{"kind": "position", "state": "long"}
|
||||||
|
]},
|
||||||
|
{"kind": "ema_crossover", "fast_period": 9, "slow_period": 21, "direction": "below"},
|
||||||
|
{"kind": "ema_trend", "period": 50, "direction": "below"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {"side": "sell", "quantity": {"method": "percent_of_balance", "percent": "10", "asset": "usdc"}, "reverse": true}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Key flip-strategy notes:
|
||||||
|
- Gate each rule on `flat OR opposite` (using `any_of`) so it fires both on initial entry and on flip
|
||||||
|
- `reverse: true` handles the flip math automatically — no need to size for `position_qty + new_qty`
|
||||||
|
- This pattern works best for trend-following where you want continuous market exposure
|
||||||
|
- Still add a time-based or ATR stop if you want a safety exit when the trend stalls"##;
|
||||||
|
|
||||||
/// Build the user message for the first iteration (no prior results).
|
/// Build the user message for the first iteration (no prior results).
|
||||||
/// `prior_summary` contains a formatted summary of results from previous runs, if any.
|
/// `prior_summary` contains a formatted summary of results from previous runs, if any.
|
||||||
|
|||||||
Reference in New Issue
Block a user