feat: client-side validation, cycling detection, quantity prompt fix

- validate_strategy(): hard error if quantity is not a parseable decimal
  (catches "ATR_SIZED" etc. before sending to swym API); soft warning if
  a sell rule has no entry_price stop-loss or no bars_since_entry time exit
- Hard validation errors skip the backtest and feed errors back to the LLM
  via IterationRecord.validation_notes included in summary()
- json_contains_kind(): recursive helper to search strategy JSON tree
- diagnose_history(): add cycling detection — triggers is_converged when
  any avg_sharpe value appears 3+ times in history (not just last 3 streak),
  catching the alternating RSI<30 / RSI<25 pattern seen in the latest run
- prompts: clarify that quantity must parse as a float; list invalid
  placeholder strings ("ATR_SIZED", "FULL_BALANCE", "dynamic", etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 17:56:59 +02:00
parent e27aabae34
commit b947f48b01
2 changed files with 162 additions and 37 deletions

View File

@@ -51,8 +51,11 @@ bars_since_entry — complete bars elapsed since position was opened
balance — free balance of a named asset (e.g. "usdt", "usdc")
### Quantity
Action quantity MUST be a fixed decimal string, e.g. `"quantity": "0.001"`.
Action quantity MUST be a fixed decimal string that parses as a floating-point number,
e.g. `"quantity": "0.001"`.
NEVER use an expression object for quantity — only plain decimal strings are accepted.
NEVER use placeholder strings like `"ATR_SIZED"`, `"FULL_BALANCE"`, `"percent_of_balance"`,
`"dynamic"`, or any non-numeric string — these will be rejected immediately.
### Multi-timeframe
Any expression can reference a different timeframe via "timeframe" field.
@@ -314,6 +317,7 @@ Common mistakes to NEVER make:
- 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
- Never use an expression object for `quantity` — it must always be a plain decimal string like `"0.001"`
- Never use a placeholder string for `quantity` — `"ATR_SIZED"`, `"FULL_BALANCE"`, `"dynamic"`, etc. are all invalid and will be rejected. Use `"0.001"` or similar.
"##
)
}