fix: ValidationError.path optional, correct position_quantity usage in prompts
- ValidationError.path is Option<String> — the API omits it for top-level
structural errors. The required String was causing every validate call to
fail to deserialize, falling through to submission instead of catching errors.
- Log path as "(top-level)" when absent
- Prompts: add explicit CRITICAL note that {"method":"position_quantity"} is
wrong — position_quantity is an Expr (uses "kind") not a SizingMethod (uses
"method"). The new SizingMethod examples caused the model to over-apply
"method" to exits universally across the entire run.
- Prompts: note that fixed_sum has no multiplier field (additionalProperties)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -345,11 +345,11 @@ pub async fn run(cli: &Cli) -> Result<()> {
|
||||
match swym.validate_strategy(&strategy).await {
|
||||
Ok(api_errors) if !api_errors.is_empty() => {
|
||||
for e in &api_errors {
|
||||
warn!(" DSL error at {}: {}", e.path, e.message);
|
||||
warn!(" DSL error at {}: {}", e.path.as_deref().unwrap_or("(top-level)"), e.message);
|
||||
}
|
||||
let error_notes: Vec<String> = api_errors
|
||||
.iter()
|
||||
.map(|e| format!("DSL error at {}: {}", e.path, e.message))
|
||||
.map(|e| format!("DSL error at {}: {}", e.path.as_deref().unwrap_or("(top-level)"), e.message))
|
||||
.collect();
|
||||
validation_notes.extend(error_notes);
|
||||
let record = IterationRecord {
|
||||
|
||||
@@ -110,8 +110,13 @@ Buy a fixed number of base units (semantic alias for a decimal string):
|
||||
Alternatively, `"9999"` works for exits: sell quantities are automatically capped to the open
|
||||
position size, so a large fixed number is equivalent to `position_quantity`.
|
||||
|
||||
NEVER use placeholder strings like `"ATR_SIZED"`, `"FULL_BALANCE"`, `"all"`, `"dynamic"` —
|
||||
these are rejected immediately.
|
||||
CRITICAL mistakes to never make:
|
||||
- `{{"method":"position_quantity"}}` is WRONG — `position_quantity` is an Expr, not a SizingMethod.
|
||||
CORRECT: `{{"kind":"position_quantity"}}`. The `"method"` field belongs ONLY to the three
|
||||
declarative sizing objects (`fixed_sum`, `percent_of_balance`, `fixed_units`).
|
||||
- `{{"method":"fixed_sum","amount":"100","multiplier":"2.0"}}` is WRONG — `fixed_sum` has no
|
||||
`multiplier` field. Only `amount` is accepted alongside `method`.
|
||||
- NEVER add extra fields to SizingMethod objects — they use `additionalProperties: false`.
|
||||
|
||||
### Multi-timeframe
|
||||
Any expression can reference a different timeframe via "timeframe" field.
|
||||
|
||||
@@ -14,7 +14,8 @@ pub struct ValidationResponse {
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ValidationError {
|
||||
pub path: String,
|
||||
/// Dotted JSON path to the offending field. Absent for top-level structural errors.
|
||||
pub path: Option<String>,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user