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 {
|
match swym.validate_strategy(&strategy).await {
|
||||||
Ok(api_errors) if !api_errors.is_empty() => {
|
Ok(api_errors) if !api_errors.is_empty() => {
|
||||||
for e in &api_errors {
|
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
|
let error_notes: Vec<String> = api_errors
|
||||||
.iter()
|
.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();
|
.collect();
|
||||||
validation_notes.extend(error_notes);
|
validation_notes.extend(error_notes);
|
||||||
let record = IterationRecord {
|
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
|
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`.
|
position size, so a large fixed number is equivalent to `position_quantity`.
|
||||||
|
|
||||||
NEVER use placeholder strings like `"ATR_SIZED"`, `"FULL_BALANCE"`, `"all"`, `"dynamic"` —
|
CRITICAL mistakes to never make:
|
||||||
these are rejected immediately.
|
- `{{"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
|
### Multi-timeframe
|
||||||
Any expression can reference a different timeframe via "timeframe" field.
|
Any expression can reference a different timeframe via "timeframe" field.
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ pub struct ValidationResponse {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct ValidationError {
|
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,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user