feat(agent): improve LLM feedback loop and convergence detection
Three related improvements to help the model learn and explore effectively: Strategy JSON in history: include the compact strategy JSON in each IterationRecord::summary() so the LLM knows exactly what was tested in every past iteration, not just the outcome metrics. Without this the model had no record of what it tried once conversation history was trimmed. Rule comment in audit: include rule_comment from the condition audit in the formatted audit string so the LLM can correlate hit-rate data with the rule's stated purpose. Convergence detection and anti-anchoring: diagnose_history() now returns (String, bool) where the bool signals that the last 3 iterations had avg_sharpe spread < 0.03 (model stuck in local optimum). When converged: - Emit a ⚠ CONVERGENCE DETECTED note listing untried candle intervals - Suppress best_so_far JSON to break the anchoring effect that was causing the model to produce near-identical strategies for 13+ iterations - Targeted "try a different approach" instruction Also add volume-as-field clarification to the DSL mistakes section in the system prompt, fixing the "unknown variant `volume`" submit error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,8 @@ Common mistakes to NEVER make:
|
||||
- `rsi`, `adx`, `supertrend` are NOT valid inside `apply_func`. Use only `apply_func`
|
||||
with `ApplyFuncName` values: `highest`, `lowest`, `sma`, `ema`, `wma`, `std_dev`, `sum`,
|
||||
`bollinger_upper`, `bollinger_lower`.
|
||||
- `volume` is a candle FIELD, not a func name. Access it as `{{"kind":"field","field":"volume"}}`.
|
||||
To compute EMA of volume: `{{"kind":"apply_func","name":"ema","period":20,"expr":{{"kind":"field","field":"volume"}}}}`.
|
||||
|
||||
## Working examples
|
||||
|
||||
@@ -338,6 +340,7 @@ pub fn iteration_prompt(
|
||||
iteration: u32,
|
||||
results_history: &str,
|
||||
best_so_far: Option<&str>,
|
||||
diagnosis: &str,
|
||||
) -> String {
|
||||
let best_section = match best_so_far {
|
||||
Some(strat) => format!(
|
||||
@@ -351,10 +354,11 @@ pub fn iteration_prompt(
|
||||
};
|
||||
|
||||
format!(
|
||||
r#"Iteration {iteration}. Here are the results from all previous backtests:
|
||||
r#"Iteration {iteration}. Here are the results from all previous backtests
|
||||
(each iteration includes the strategy JSON that was tested):
|
||||
|
||||
{results_history}
|
||||
{best_section}
|
||||
{best_section}{diagnosis}
|
||||
|
||||
Based on these results, design the next strategy to test. Learn from what worked
|
||||
and what didn't. If a strategy family consistently fails, try a different one.
|
||||
|
||||
Reference in New Issue
Block a user