feat(prompt): integra atr_pct nel system prompt LLM dell'Hypothesis Agent

Il LLM ora genera strategie sapendo distinguere quando usare atr (unità
prezzo) vs atr_pct (frazione del close) per evitare il bug protocol_unit.

agents/hypothesis.py:
- Lista indicatori: aggiunto atr_pct con annotazione unità inline
- NEW sezione "UNITÀ — REGOLA CRITICA": esempi positivi/negativi su
  literal frazionali (atr_pct > 0.02 ✓) vs literal in unità prezzo
  (atr > 0.02 ✗ sempre TRUE su asset >$1)
- PATTERN GUIDANCE: "Compressione di volatilità" ora suggerisce atr_pct(N) < 0.01
  invece di "ATR(N) < soglia bassa" generico
- "Espansione di volatilità": atr_pct(N) > 0.03 OPPURE confronto relativo

genome/mutation_prompt_llm.py:
- _VALID_KEYWORDS: aggiunti atr_pct + realized_vol (per validazione prompt mutato)

Closes open item da commit f875df3. Prima del prossimo Phase 2.x run il
modello qwen-2.5-72b ricevera' il prompt aggiornato e genera strategie
unit-aware. Vedi src/multi_swarm_core/docs/decisions/2026-05-15-atr-pct-fix.md.

Verifica: 188 test pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-05-15 18:19:46 +00:00
parent f875df31b4
commit 9c3b5ad586
3 changed files with 23 additions and 11 deletions
@@ -75,8 +75,10 @@ _ind_atr_pct(df, 14).mean() # ~0.011 (1.1% del prezzo)
## Open items ## Open items
- Aggiornare il system prompt LLM (mutation_prompt_llm) per includere - ~~Aggiornare il system prompt LLM~~ ✅ **chiuso 2026-05-15**:
`atr_pct` come indicatore raccomandato per confronti con literal `agents/hypothesis.py` ora elenca `atr_pct` con annotazione unità e
frazionali. Da fare PRIMA del prossimo Phase 2.x run. include una sezione "UNITÀ — REGOLA CRITICA" che spiega esplicitamente
al modello quando usare `atr_pct` (literal frazionali) vs `atr`
(confronti relativi). `mutation_prompt_llm._VALID_KEYWORDS` esteso.
- Considerare l'aggiunta di `sma_pct`, `macd_pct` se emergono usi - Considerare l'aggiunta di `sma_pct`, `macd_pct` se emergono usi
analoghi in future strategie. analoghi in future strategie (still open).
@@ -76,13 +76,22 @@ Crossover (eventi su 2 serie):
{{"op": "crossunder", "args": [<serie_a>, <serie_b>]}} {{"op": "crossunder", "args": [<serie_a>, <serie_b>]}}
Leaf - indicatori (calcolati su close): Leaf - indicatori (calcolati su close):
{{"kind": "indicator", "name": "sma", "params": [<length>]}} {{"kind": "indicator", "name": "sma", "params": [<length>]}} // media mobile, UNITÀ PREZZO
{{"kind": "indicator", "name": "rsi", "params": [<length>]}} {{"kind": "indicator", "name": "rsi", "params": [<length>]}} // 0-100, adimensionale
{{"kind": "indicator", "name": "atr", "params": [<length>]}} {{"kind": "indicator", "name": "atr", "params": [<length>]}} // true range, UNITÀ PREZZO
{{"kind": "indicator", "name": "realized_vol", "params": [<window>]}} {{"kind": "indicator", "name": "atr_pct", "params": [<length>]}} // atr/close, FRAZIONE 0.0-0.1
{{"kind": "indicator", "name": "realized_vol", "params": [<window>]}} // std dei returns, FRAZIONE
{{"kind": "indicator", "name": "macd", "params": [<fast>, <slow>, <signal>]}} {{"kind": "indicator", "name": "macd", "params": [<fast>, <slow>, <signal>]}}
// 0-3 numeri (tutti opzionali con default 12, 26, 9) // 0-3 numeri (tutti opzionali con default 12, 26, 9)
UNITÀ — REGOLA CRITICA per i confronti con literal numerici:
* Confronti con literal FRAZIONALI (0.01, 0.02, 0.05): usa `atr_pct`, `realized_vol`
Esempio CORRETTO: `atr_pct(14) > 0.02` significa "ATR > 2% del prezzo"
Esempio ERRATO: `atr(14) > 0.02` è sempre TRUE su asset $>1 (atr in dollari)
* Confronti RELATIVI fra indicatori in stessa unità: usa `atr`, `sma`, `macd`
Esempio: `atr(14) > sma(14)` (entrambi in dollari, confronto valido)
* RSI usa literal 0-100 (mai frazione): `rsi(14) > 70`
Leaf - feature OHLCV: Leaf - feature OHLCV:
{{"kind": "feature", "name": "open|high|low|close|volume"}} {{"kind": "feature", "name": "open|high|low|close|volume"}}
@@ -110,8 +119,8 @@ PATTERN GUIDANCE (oltre agli indicatori, considera forma delle curve e ripetibil
Forme di curva: Forme di curva:
- Trend ascendente: SMA(short) > SMA(long) E close > SMA(short) - Trend ascendente: SMA(short) > SMA(long) E close > SMA(short)
- Trend discendente: SMA(short) < SMA(long) E close < SMA(short) - Trend discendente: SMA(short) < SMA(long) E close < SMA(short)
- Compressione di volatilità (pre-breakout): ATR(N) < soglia bassa - Compressione di volatilità (pre-breakout): atr_pct(N) < 0.01 (sotto 1% del prezzo)
- Espansione di volatilità: ATR(N) > ATR(N*2) (vol corta > vol lunga) - Espansione di volatilità: atr_pct(N) > 0.03 (sopra 3%) OPPURE ATR(N) > ATR(N*2) confronto relativo
- Mean reversion strutturale: |close - SMA(long)| eccessivo → reversal atteso - Mean reversion strutturale: |close - SMA(long)| eccessivo → reversal atteso
Ripetibilità dell'andamento: Ripetibilità dell'andamento:
@@ -51,7 +51,8 @@ MUTATION_INSTRUCTIONS: dict[str, str] = {
# Keyword tecniche minime per validare che il prompt sia ancora "una strategia". # Keyword tecniche minime per validare che il prompt sia ancora "una strategia".
_VALID_KEYWORDS = ( _VALID_KEYWORDS = (
"rsi", "sma", "ema", "atr", "momentum", "breakout", "mean", "reversion", "rsi", "sma", "ema", "atr", "atr_pct", "realized_vol",
"momentum", "breakout", "mean", "reversion",
"macd", "vwap", "bb", "bollinger", "stoch", "trend", "signal", "buy", "macd", "vwap", "bb", "bollinger", "stoch", "trend", "signal", "buy",
"sell", "long", "short", "entry", "exit", "stop", "rule", "condition", "sell", "long", "short", "entry", "exit", "stop", "rule", "condition",
"if", "when", "and", "or", "gt", "lt", ">", "<", "ge", "le", "if", "when", "and", "or", "gt", "lt", ">", "<", "ge", "le",