feat: add declarative SizingMethod types from upstream schema

Upstream added three new quantity sizing objects alongside DecimalString and Expr:
- fixed_sum: buy N quote-currency worth at current price
- percent_of_balance: buy N% of named asset's free balance
- fixed_units: buy exactly N base units (semantic alias for decimal string)

Update dsl-schema.json to include the three definitions and expand
Action.quantity.oneOf to reference all five valid forms.

Update prompts.rs Quantity section to present the declarative methods
as the preferred approach — they're cleaner, more readable, and
instrument-agnostic compared to raw Expr composition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 09:33:43 +02:00
parent 7e1ff51ae0
commit 3f8d4de7fb
2 changed files with 55 additions and 15 deletions

View File

@@ -66,14 +66,48 @@
"properties": { "properties": {
"side": { "type": "string", "enum": ["buy", "sell"] }, "side": { "type": "string", "enum": ["buy", "sell"] },
"quantity": { "quantity": {
"description": "Per-order size in base asset units. Either a fixed decimal string (e.g. \"0.001\") or a dynamic Expr evaluated at candle close. When an Expr returns None the order is skipped; negative values are clamped to zero.", "description": "Per-order size in base asset units. Fixed decimal string (e.g. \"0.001\"), a declarative SizingMethod object, or a dynamic Expr object. When a method or Expr returns None the order is skipped; negative values are clamped to zero.",
"oneOf": [ "oneOf": [
{ "$ref": "#/definitions/DecimalString" }, { "$ref": "#/definitions/DecimalString" },
{ "$ref": "#/definitions/SizingFixedSum" },
{ "$ref": "#/definitions/SizingPercentOfBalance" },
{ "$ref": "#/definitions/SizingFixedUnits" },
{ "$ref": "#/definitions/Expr" } { "$ref": "#/definitions/Expr" }
] ]
} }
} }
}, },
"SizingFixedSum": {
"description": "Buy `amount` worth of quote currency at the current price. qty = amount / current_price.",
"type": "object",
"required": ["method", "amount"],
"additionalProperties": false,
"properties": {
"method": { "const": "fixed_sum" },
"amount": { "$ref": "#/definitions/DecimalString", "description": "Quote-currency amount, e.g. \"500\" means buy $500 worth." }
}
},
"SizingPercentOfBalance": {
"description": "Buy percent% of the named asset's free balance worth of base asset. qty = balance(asset) * percent/100 / current_price.",
"type": "object",
"required": ["method", "percent", "asset"],
"additionalProperties": false,
"properties": {
"method": { "const": "percent_of_balance" },
"percent": { "$ref": "#/definitions/DecimalString", "description": "Percentage, e.g. \"2\" means 2% of the free balance." },
"asset": { "type": "string", "description": "Asset name to look up, e.g. \"usdc\". Matched case-insensitively." }
}
},
"SizingFixedUnits": {
"description": "Buy exactly `units` of base asset. Semantic alias for a fixed decimal quantity.",
"type": "object",
"required": ["method", "units"],
"additionalProperties": false,
"properties": {
"method": { "const": "fixed_units" },
"units": { "$ref": "#/definitions/DecimalString", "description": "Base asset quantity, e.g. \"0.01\" means 0.01 BTC." }
}
},
"Rule": { "Rule": {
"type": "object", "type": "object",
"required": ["when", "then"], "required": ["when", "then"],

View File

@@ -74,36 +74,42 @@ bars_since_entry — complete bars elapsed since position was opened
balance — free balance of a named asset (e.g. "usdt", "usdc") balance — free balance of a named asset (e.g. "usdt", "usdc")
### Quantity ### Quantity
Action quantity is either a fixed decimal string **or** an Expr that evaluates to a number Action quantity accepts four forms — pick the simplest one for your intent:
at candle close. If the Expr returns None the order is skipped; negative values are clamped
to zero.
**Preferred: expression-based sizing** — instrument-agnostic, scales automatically: **1. Declarative sizing methods (preferred — instrument-agnostic, readable):**
Fixed fraction of quote balance (5% of USDC balance, converted to base units at current price): Spend a fixed quote amount (e.g. $500 worth of base at current price):
```json ```json
{{"kind":"bin_op","op":"div", {{"method":"fixed_sum","amount":"500"}}
"left":{{"kind":"bin_op","op":"mul",
"left":{{"kind":"balance","asset":"usdc"}},
"right":{{"kind":"literal","value":"0.05"}}}},
"right":{{"kind":"field","field":"close"}}}}
``` ```
ATR-based risk sizing (risk $200 per trade, sized by volatility): Spend a percentage of free quote balance (e.g. 5% of USDC):
```json
{{"method":"percent_of_balance","percent":"5","asset":"usdc"}}
```
Buy a fixed number of base units (semantic alias for a decimal string):
```json
{{"method":"fixed_units","units":"0.01"}}
```
**2. Plain decimal string** — use only when you have a specific reason:
`"0.01"` (0.01 BTC, 3.0 ETH, 50.0 SOL — instrument-specific, not portable)
**3. Expr** — for dynamic sizing not covered by the methods above, e.g. ATR-based:
```json ```json
{{"kind":"bin_op","op":"div", {{"kind":"bin_op","op":"div",
"left":{{"kind":"literal","value":"200"}}, "left":{{"kind":"literal","value":"200"}},
"right":{{"kind":"func","name":"atr","period":14}}}} "right":{{"kind":"func","name":"atr","period":14}}}}
``` ```
For exit rules, use `position_quantity` to close the exact open position: **4. Exit rules** — use `position_quantity` to close the exact open size:
```json ```json
{{"kind":"position_quantity"}} {{"kind":"position_quantity"}}
``` ```
**Fixed strings are also valid** when you want a specific size, e.g. `"0.01"`.
NEVER use placeholder strings like `"ATR_SIZED"`, `"FULL_BALANCE"`, `"all"`, `"dynamic"` — NEVER use placeholder strings like `"ATR_SIZED"`, `"FULL_BALANCE"`, `"all"`, `"dynamic"` —
these are rejected immediately. Use an Expr or a plain decimal string. these are rejected immediately.
### Multi-timeframe ### Multi-timeframe
Any expression can reference a different timeframe via "timeframe" field. Any expression can reference a different timeframe via "timeframe" field.