Files
TR_Agent/MQL5/Experts/MultiAgentTest/DOCUMENTAZIONE_COMPLETA.md
T

836 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentazione Completa — MultiAgent TR_Agent EA
## Indice
1. [MultiAgentTest.mq5](#1-multiagenttestmq5)
2. [Core/Orchestrator.mqh](#2-coreorchestratormqh)
3. [Core/NeuralNet.mqh](#3-coreneuralnetmqh)
4. [Core/Statistics.mqh](#4-corestatisticsmqh)
5. [Core/Signal.mqh](#5-coresignalmqh)
6. [Core/MarketData.mqh](#6-coremarketdatamqh)
7. [Core/PeriodCalculator.mqh](#7-coreperiodcalculatormqh)
8. [Agents/AgentBase.mqh](#8-agentsagentbasemqh)
9. [Agents/MAAgent.mqh](#9-agentsmaagentmqh)
10. [Agents/MomentumAgent.mqh](#10-agentsmomentumagentmqh)
11. [Agents/PatternHunter.mqh](#11-agentspatternhuntermqh)
12. [Agents/RegimeADX.mqh](#12-agentsregimeadxmqh)
13. [Agents/RegimeConsensus.mqh](#13-agentsregimeconsensusmqh)
14. [Agents/RegimeDetector.mqh](#14-agentsregimedetectormqh)
---
## 1. MultiAgentTest.mq5
### Scopo
Main EA file: punto d'ingresso di MetaTrader 5. Gestisce OnInit (setup), OnTick (per-barra), OnTrade (chiusure), e OnDeinit (salvataggio e report).
### Input Parameters
- **Inp_Symbol**: Simbolo da tradare (vuoto = simbolo corrente)
- **Inp_TF**: Timeframe di esecuzione (default = CURRENT = timeframe del chart)
- Funziona su QUALSIASI timeframe (M1, M5, M15, M30, H1, H4, D1, W1, MN1)
- I periodi degli agenti (Hurst, MA, Momentum, ADX) si adattano automaticamente
- Il buffer dati scala con la barra: 300+ barre sono sempre sufficienti
- L'unica differenza tra timeframes è la granularità degli ingressi
- **Inp_Lot**: Lotto fisso (sostituito da AdaptiveBaseLot se >0)
- **Inp_MinZ**: Soglia minima z-score per entrata (0=adattiva)
- **Inp_WMin**: Peso minimo per agente (0=auto)
- **Inp_BufferBars**: Barre nel buffer (0=auto)
- **Inp_SLRiskATR**: SL fisso in ATR (0=adattivo)
- **Inp_TPRiskATR**: TP fisso in ATR (0=adattivo)
- **Inp_HurstPeriod, Inp_ADXPeriod**: Periodi fissi (0=auto)
- **Inp_UseNeural**: True = neural orchestrator, False = softmax classico
- **Inp_TrainMode**: Colleziona campioni e allena NN in backtest
- **Inp_NNHidden**: Neuroni hidden layer
- **Inp_RiskFraction**: Frazione di capitale da rischiare per trade (default 0.20 = 20%)
- **Inp_UseReversalClose**: Se true, chiude posizioni quando il segnale si inverte. Se false, long e short coesistono
### OnInit
1. Legge parametri di mercato (spread, digits, punto)
2. Crea Orchestrator con gli input
3. Crea e registra 6 agenti: RegimeDetector (Hurst), RegimeADX, RegimeConsensus, MAAgent, MomentumAgent, PatternHunter
4. Verifica buffer dati sufficiente
5. Carica modello NN esistente (se Inp_UseNeural)
### OnTick
- Lavora su **new bar** (compare i tempi)
- Prepara MarketData (prezzi, indicatori)
- Chiama `orchestrator.Analyze(data)` per z-score combinato
- Ottiene FinalSignal da GetFinalSignal()
- Chiama `ManagePositions(data, fs)` per apertura/chiusura
- Trailing stop su tutte le posizioni
### OnTrade
- Rileva trade chiusi da SL/TP (non da reversal)
- Calcola il ritorno in ATR
- Chiama `orchestrator.OnTradeClose()` che:
- Aggiorna MAE/MFE stats
- Colleziona campione NN con peso = |return| + 1
- Chiama agente Learn() con ritorno normalizzato
- Aggiorna health (Sharpe rolling)
- Salva stato ogni saveInterval trade
### ManagePositions
1. Update MAE/MFE per tutti gli aperti (intra-barra high/low)
2. TrailStops: muove SL su tutte le posizioni
3. Chiudi posizioni con segnale invertito (reversal)
4. Aggiorna SL sul terminale via PositionModify
5. Apri nuova posizione OGNI BARRA con |z| > minZ (aggressivo multi-position)
- SL width da AdaptiveSLWidth (MAE-based con EVT fallback)
- Lotto = AdaptiveBaseLot × |z| (scalato dal segnale)
- Nessun TP fisso: uscita via trailing stop o reversal
### OnDeinit
- Salva: stato agenti, correlazioni, RunningStats, NN (inline)
- Stampa report: PrintAgentStats, PrintNeuralStats, loss history CSV
- Aggiorna summary
### Principi Chiave
- **Multi-position**: ogni barra con segnale apre UNA NUOVA posizione
- **Nessun TP fisso**: uscita via reversal o trailing stop
- **SL adattivo**: da distribuzione MAE dei trade vincenti
- **Training online**: campioni collezionati in backtest, NN allenata in OnDeinit
---
## 2. Core/Orchestrator.mqh
### Scopo
Cervello del sistema: orchestrazione agenti, combinazione z-score, gestione multi-position, trailing stop, training NN, stato persistente.
### Strutture Dati
**TrackedTrade**: traccia ogni posizione aperta:
- ticket, entryPrice, entryATR, entryZ, slPrice, isBuy
- highestPrice, lowestPrice (per MAE/MFE tracking)
- maeATR, mfeATR (massimo movimento avverso/favorevole in ATR)
- barsHeld, active
- entryFeatures[NN_FEATURES] (per training NN)
- entryZScores[MAX_AGENTS] (per agent learning)
**BarSnapshot**: cache storica per autocorrelazione:
- combinedZ, timestamp
### Membri Principali
- `agents[MAX_AGENTS]`: array di IAgent*
- `combinedZ`: z-score combinato pesato
- `agentWeights[MAX_AGENTS]`: pesi EWMA basati su correlazione
- `corrMeanX/Y, corrCov, corrVarX/Y`: RunningCorrelation per coppia agente-combinedZ
- `returnStats, combinedZStats, maeStats, mfeStats, maeWinStats`: distribuzioni empiriche
- `openTrades[maxOpenTrades]`: tutte le posizioni aperte
- `m_neuralNet, m_trainBuffer`: rete neurale e buffer training
- `m_riskFraction`: frazione di capitale da rischiare (default 20%)
- `rollingReturns[ROLLING_TRADES]`: per Sharpe rolling
### Metodi Principali
**AddAgent**: registra agente, inizializza correlazioni, ri-inizializza RunningStats con alpha/min derivati da agentCount.
**Analyze** (fase 1-3):
1. **Aggrega**: raccoglie z-score da tutti gli agenti
2. **Interact**: agenti leggono z-score altrui (via SHARED_)
3. **Combina**: pesi EWMA basati su correlazione agente-combinedZ, softmax con temperatura adattiva (o NN)
**OnTradeOpen**: registra nuova posizione in openTracks[], copia entryZScores ed entryFeatures
**OnTradeClose**:
- Calcola ritorno in ATR
- Aggiorna MAE/MFE stats
- Colleziona training sample NN con peso = |return| + 1
- Chiama agent.Learn() per auto-calibrazione
- Aggiorna rolling Sharpe
- Salva stato ogni saveInterval
**UpdateOpenTrades**: per ogni barra, aggiorna MAE/MFE da high/low
**TrailStops**: implementa trailing stop:
- Calcola trail trigger da MFE mean (o EVT fallback)
- Calcola trail offset da MAE win mean (o EVT fallback)
- Se profitto > trigger, muove SL a entry ± (profitto - offset)
**AdaptiveSLWidth**: SL width da MAE distribuzione:
- Fallback: combinedZStats.Std() × sqrt(N) o EVT_SL
- Con dati: max(fallback, maeWinStats.Mean() + maeWinStats.Std())
**AdaptiveTrailTrigger**: da MFE mean (o EVT)
**AdaptiveTrailOffset**: da MAE win mean (o EVT)
**AdaptiveMinZ**: soglia entrata = StdErr(combinedZ) = Std/sqrt(N) — bassa per trading frequente
**AdaptiveBaseLot**: lotto = balance × riskFraction / 100000 — chiamante scala per |z|
**GetTradesToClose**: reversal detection: buy chiusi se currentZ < -minZ, sell se > minZ
**SaveState / LoadState (v6)**:
- Salva: versione, agenti (pesi, bias, predError, predCorr, lastZScore), correlazioni, RunningStats, NN
- NN salvato inline (handle file embedded)
- Carica: stessi campi, ripristino buffer NN
**TrainNN**: allena CNeuralNet con buffer campioni, pesi per sample importance
**InitNeuralNet**: configura architettura NN, inizializza He con iperparametri derivati:
- dropout = 1/sqrt(hidden)
- L2 = 1/max(totalParams, 100)
- β₁ = 1 1/max(hidden, 10)
- β₂ = 1 1/max(hidden×100, 1000)
- BN momentum = 1 1/max(hidden×5, 50)
- BN ε = DATA_EPS(1.0)
### Principi Chiave
- **Zero magic constants**: ogni soglia derivata da distribuzioni empiriche o EVT
- **Multi-position aggressivo**: ogni barra con segnale apre posizione
- **Trailing stop adattivo**: MAE/MFE guidano trigger e offset
- **NN opzionale**: cade a softmax se non inizializzata
- **Persistenza**: tutto (incluso NN) salvato inline in file stato
---
## 3. Core/NeuralNet.mqh
### Scopo
Rete neurale feed-forward: 1 hidden layer ReLU, dropout, BatchNorm, Softmax output, Adam optimizer. Training online con batch_size=1 per compatibilità MT5.
### Architettura
- Input → W1 (fanIn×hidden) + b1 → ReLU → Dropout → BatchNorm → W2 (hidden×3) + b2 → Softmax
- Output: [P(Buy), P(Flat), P(Sell)]
- Hidden size: input Inp_NNHidden (default 6)
### CNeuralNet
**Inizializzazione**: He Init `sqrt(6/fanIn)` per ReLU.
**Forward**:
1. z1 = W1×x + b1 → ReLU(z1) → h1
2. Dropout: mask binaria con probabilità 1-dropoutRate
3. BatchNorm (train): EMA runningMean/runningVar, gamma/beta learnable
4. z2 = W2×h1_norm + b2 → Softmax → output [0,1]³
**Loss**: CCE (Cross-Entropy) pesata + L2:
- L = -Σ weight × target_i × log(p_i) + 0.5×L2×(∥W1∥² + ∥W2∥²)
**Backward (Adam)**:
- dL/dz2 = weight × (output target) (CCE+Softmax combinata)
- dL/dW2 = h1_normᵀ × dL/dz2
- dL/dh1_norm = W2 × dL/dz2
- BNBackward: dL/dh1_drop = gamma/sqrt(var) × dL/dh1_norm
- Dropout backward: passa gradiente solo dove mask=1
- dL/dz1 = dL/dh1_raw ⊙ ReLU'(z1)
- dL/dW1 = xᵀ × dL/dz1
- Adam update per W1, b1, W2, b2, bnGamma, bnBeta
**Iperparametri architettura-derivati** (zero magic constants):
- dropout = 1/sqrt(hidden)
- L2 = 1/max(totalParams, 100)
- β₁ = 1 1/max(hidden, 10)
- β₂ = 1 1/max(hidden×100, 1000)
- ε = DATA_EPS(1.0)
- BN momentum = 1 1/max(hidden×5, 50)
- BN ε = DATA_EPS(1.0)
**Save/Load v3**: pesi salvati in formato binario compatto, inline nello stato.
**LossHistory**: array epoch-loss, dump CSV.
### NNTrainBuffer
Buffer circolare di campioni per training NN.
**Struttura**: NNTrainSample { features[8], target[3], weight }.
**Metodi**:
- Add(features, target, weight): aggiunge campione
- Trim(maxSamples): rimuove i più vecchi
- ToMatrices(features, targets): esporta per training
- GetWeights(): vettore dei pesi campione
- SaveCsv(filename): dump per debug
- PrintStats/PrintFeatureStats: diagnostica dataset
### Principi Chiave
- **Batch size = 1**: forzato da MT5, BN usa running stats non batch stats
- **Loss pesata**: trade con grande impatto pesano di più nel training
- **Inline nel file stato**: NN salvato dentro .model per portabilità tester→live
- **Zero magic**: dropout, L2, β₁, β₂, ε, BN momentum/ε tutti derivati
---
## 4. Core/Statistics.mqh
### Scopo
Statistiche in tempo reale: EWMA, RunningStats (media/variance online), RunningCorrelation, DATA_EPS.
### DATA_EPS(x)
- `MathMax(MathSqrt(DBL_EPS), MathAbs(x) * MathSqrt(DBL_EPS))`
- Soglia floating-point di qualità: scala con la magnitudine dei dati
- Radice quadrata del DBL_EPS standard (≈1.49e-8), non epsilon assoluto 1e-15
### EWMA
EWMA univariato con fattore α:
- mean += α × (x mean)
- var = (1−α) × (var + α × (xmean)²) (metodo di Finch)
### RunningStats
Media e varianza online con EWMA:
- alpha = 1/(N_agenti × 10), minSamples = N_agenti × 5
- Count(), Mean(), Std(), Var(), Skew()
- Ready(): count >= minSamples
- Save/Load: formato binario
### RunningCorrelation
Correlazione online tra due variabili:
- Stessa logica EWMA di RunningStats
- Update(x, y), Correlation(), Count(), Ready()
- Utilizzata per: correlazione agente-combinedZ, weight update
### Funzioni EVT
- `EVT_MaxAbsZ(N) = sqrt(2 × log(2 × N))`: expected maximum |z| di N gaussiane
- `RStatsAlpha() = 1.0 / max(agentCount × 10, 10)`
- `RStatsMinSamp() = max(agentCount × 5, 10)`
### Principi Chiave
- **Online**: tutte le statistiche sono incrementali, nessun buffer storico
- **EWMA**: pesa più i dati recenti
- **DATA_EPS**: soglia scalabile, non epsilon assoluto
- **EVT**: Extreme Value Theory per fallback senza dati
---
## 5. Core/Signal.mqh
### Scopo
Strutture dati di segnale e stato.
### FinalSignal
Rappresenta il segnale finale dopo orchestrazione:
- direction: +1 (Buy), -1 (Sell), 0 (Flat)
- zScore: z-score combinato (firmato)
- totalAgents: numero agenti attivi
- agreeingCount: quanti agenti concordano con direzione
- contributingAgents: stringa nomi agenti concordanti
### TrackedTrade
Rappresenta una posizione aperta tracciata:
- ticket, entryPrice, entryATR, entryZ, slPrice, isBuy
- highestPrice, lowestPrice: per MAE/MFE intra-barra
- maeATR, mfeATR: massimo movimento avverso/favorevole in ATR
- barsHeld: barre da apertura
- active: true se posizione ancora aperta
- entryFeatures[8]: feature snapshot all'apertura (per NN)
- entryZScores[MAX_AGENTS]: z-score agenti all'apertura (per learning)
### BarSnapshot
- combinedZ, timestamp: per calcolo autocorrelazione
### Principi Chiave
- **TrackedTrade è auto-contenuta**: porta tutto ciò che serve per learning e training
- **Multi-position**: array di TrackedTrade fino a maxOpenTrades
---
## 6. Core/MarketData.mqh
### Scopo
Fornitore dati di mercato: prezzi, spread, indicatori nativi MT5.
### MarketData
- Symbol() / Timeframe()
- High(shift), Low(shift), Close(shift), Open(shift)
- Spread(): spread corrente in punti
- ATR(period): iATR nativo
- ATR(period, shift): iATR con shift
- Ma(period, shift, method, applied): iMA nativo
- Momentum(period, shift): iMomentum nativo
- ADX(period, shift): iADX nativo (Main, PlusDI, MinusDI)
### Principi Chiave
- **Indicatori nativi MT5**: iMA, iATR, iMomentum, iADX — nessuna implementazione custom
- **Cache**: i valori sono calcolati su richiesta con handle MT5
- **ATR period derivato**: max(N+1, min(buffer/15, 50)) — scala con agenti e buffer
---
## 7. Core/PeriodCalculator.mqh
### Scopo
Calcolo dei periodi adattivi per ogni agente.
### Funzioni
- `HurstPeriod(bufferBars, hurstPeriodInput)`: periodo per calcolo Hurst
- `ADXPeriod(bufferBars, adxPeriodInput)`: periodo per ADX
- `MAPeriod(bufferBars, ...)`: periodo per MA
- `MomentumPeriod(bufferBars, ...)`: periodo per Momentum
Ogni funzione:
- Se input > 0: usa input fisso
- Se input = 0: calcola da bufferBars usando formula adattiva
---
## 8. Agents/AgentBase.mqh
### Scopo
Classe base astratta per tutti gli agenti. Definisce interfaccia, stato persistente, meccanismi di calibrazione.
### IAgent (interfaccia)
```
virtual void Analyze(MarketData&) = 0;
virtual void Learn(double actualReturn) = 0;
virtual double GetZScore() = 0;
```
### Membro
- name, enabled, weight, lastZScore
- predictionError: RunningStats dell'errore di predizione (bias)
- predCorr: RunningCorrelation tra predetto e reale
- combinedZStats: RunningStats locale per normalizzare z-score
### AgentBase (implementazione parziale)
**CalibrateZ(z)**: normalizza z-score usando combinedZStats locale:
- Se ha dati: z_score = (z mean) / std
- Se non ha dati: z_score = z / EVT_MaxAbsZ(max(2N, 2))
**Learn(actualReturn, subSignals)**:
- Calcola predictionError: differenza tra lastZScore e actualReturn normalizzato
- Aggiorna predCorr: correla lastZScore con actualReturn
- Tutti gli agenti ereditano questo comportamento
**Save/Load v3**: salva nome, peso, lastZScore, predictionError, predCorr, combinedZStats.
### Principi Chiave
- **Auto-calibrazione**: ogni agente normalizza i propri z-score
- **Autovalutazione**: predictionError (bias) + predCorr (allineamento direzionale)
- **Zero magic**: fallback EVT per normalizzazione
---
## 9. Agents/MAAgent.mqh
### Scopo
Agente Moving Average: confronta prezzo corrente con MA per generare z-score.
### Funzionamento
1. Calcola MA a periodo adattivo (iMA nativo)
2. Prezzo relativo: (close MA) / ATR
3. Normalizza via CalibrateZ() per produrre z-score ~N(0,1)
4. Learn(): traccia sub-signals priceToMaCorr e slopeCorr
### Sub-signals
- priceToMaCorr: RunningCorrelation tra (close-MA)/ATR e ritorno
- slopeCorr: RunningCorrelation tra pendenza MA e ritorno
### Output
- Z-score positivo: prezzo sopra MA (trend rialzista)
- Z-score negativo: prezzo sotto MA (trend ribassista)
- Segnale tanto più forte quanto più il prezzo è lontano dalla MA (in ATR)
### Principi Chiave
- **MA period adattivo**: da PeriodCalculator
- **Unità ATR**: normalizza la distanza prezzo-MA in termini di volatilità
- **Auto-calibrazione**: CalibrateZ mantiene output ~N(0,1)
- **Apprendimento**: traccia correlazione sub-signals per miglioramento
---
## 10. Agents/MomentumAgent.mqh
### Scopo
Agente Momentum: cattura accelerazione del prezzo via iMomentum nativo.
### Funzionamento
1. Calcola Momentum = iMomentum(period) = close close[period-1]
2. Momento normalizzato: momentum / ATR (in unità di volatilità)
3. Seconde differenze per accelerazione: momentum momentum[shift]
4. Combina momentum + accel con RunningStats pesato
5. CalibrateZ() per z-score finale
### Sub-signals
- momCorr: RunningCorrelation tra momentum e ritorno
- accelCorr: RunningCorrelation tra accelerazione e ritorno
### Output
- Z-score positivo: momentum positivo (trend in accelerazione)
- Z-score negativo: momentum negativo
- Pesa accelerazione quando ha alta correlazione col ritorno
### Principi Chiave
- **iMomentum nativo MT5**: no implementazione custom
- **Doppio segnale**: momentum + accelerazione
- **Adattivo**: peso accelerazione basato su correlazione storica
---
## 11. Agents/PatternHunter.mqh
### Scopo
Agente di pattern recognition cross-agente: identifica pattern negli z-score degli altri agenti.
### Funzionamento
1. Analizza z-score di tutti gli agenti (da SHARED_ variabili)
2. Classifica pattern in codici -10..+10:
- Pattern di accordo: tutti concordi (z-std basso)
- Pattern di divergenza: agenti divisi (z-std alto)
- Pattern di reversal: cambio direzione rispetto a barra precedente
- Pattern di momentum: accelerazione/decelerazione
3. Ogni pattern code ha RunningStats locale (patternStats[code+10])
4. Z-score = winRate del pattern corrente (CalibrateZ normalizza)
### Learn()
- patternStats[patternCode+10] aggiornato con esito trade
- Traccia win rate per ogni pattern
### Output
- Timeframe lungo: convergenza/dominanza di certi pattern
- Z-score positivo: pattern storicamente vincente per Buy
- Z-score negativo: pattern storicamente vincente per Sell
### Principi Chiave
- **Cross-agente**: non guarda il prezzo ma il comportamento degli altri agenti
- **Pattern statistics**: ogni pattern ha RunningStats di performance
- **Auto-apprendimento**: più trade → migliori stime win rate per pattern
---
## 12. Agents/RegimeADX.mqh
### Scopo
Agente di regime basato su ADX: rileva trend vs range tramite iADX nativo.
### Funzionamento
1. iADX(period, shift): ADX Main, +DI, -DI
2. Regime score = (+DI -DI) / ADX_Main (direzione normalizzata per forza trend)
3. CalibrateZ() per output ~N(0,1)
### Output
- Z-score positivo: +DI > -DI → trend rialzista
- Z-score negativo: -DI > +DI → trend ribassista
- Magnitudo: forza del trend (ADX alto) + direzionalità
### Principi Chiave
- **iADX nativo MT5**: no implementazione custom
- **Unità di forza trend**: regime score normalizzato da ADX
- **Risposta rapida**: reagisce a cambiamenti di regime DI
---
## 13. Agents/RegimeConsensus.mqh
### Scopo
Agente di consenso: combina Hurst + ADX per determinazione robusta del regime.
### Funzionamento
1. Legge Hurst da RegimeDetector (via SHARED_)
2. Legge ADX da RegimeADX (via SHARED_)
3. Consensus score = peso × Hurst + (1-peso) × ADX
4. Peso da RunningStats della correlazione di ciascuno col ritorno
5. CalibrateZ() per output finale
### Learn()
- Sub-signals: hurstCorr (corr Hurst-ritorno), adxCorr (corr ADX-ritorno)
- Aggiorna pesi basati su correlazione storica
### Output
- Z-score positivo: regime identificato come trend rialzista
- Z-score negativo: regime trend ribassista
- Zero: regime incerto (Hurst range-bound + ADX basso)
### Principi Chiave
- **Consenso multi-regime**: Hurst + ADX complementari
- **Pesi adattivi**: aggiornati via Learn() basato su performance
- **Stabilità**: consenso filtra falsi segnali di un singolo regime detector
---
## 14. Agents/RegimeDetector.mqh
### Scopo
Agente di detection basato su Hurst Exponent: misura tendenza al trend/mean-reversion del mercato.
### Funzionamento
1. Hurst via DFA (Detrended Fluctuation Analysis) con fallback R/S
2. Hurst = 0.5 → random walk
3. Hurst > 0.5 → trending (buy quando close sopra MA, sell sotto)
4. Hurst < 0.5 → mean-reverting (buy quando close sotto MA, sell sopra)
5. Z-score = (Hurst - 0.5) × factor × (close-MA)/ATR
6. CalibrateZ() per output finale
### DFA Algorithm
1. Prezzo logaritmico: y_i = log(close_i)
2. Trend locale: sottrai media su finestra mobile
3. Fluttuazione: RMS dei residui
4. Hurst = log(F(n) / F(n/2)) / log(2)
### Fallback R/S
- Se DFA fallisce (dati insufficienti): R/S classico
- Range = max(cumsum) min(cumsum)
- R/S = range / std dei log-returns
### Output
- Z-score positivo: mercato trending rialzista
- Z-score negativo: mercato trending ribassista
- Magnitudo: forza del fenomeno (quanto Hurst si discosta da 0.5 × forza trend)
### Principi Chiave
- **Implementazione manuale**: nessun indicatore nativo (Hurst non esiste in MT5)
- **DFA primario, R/S fallback**: robustezza
- **Direzionalità**: combina Hurst con posizione prezzo-MA
- **Lento ma fondamentale**: identifica regime macro, non trading frequency
---
## Filosofia Generale del Sistema
### Multi-Agente con Orchestrazione Neurale
6 agenti specializzati producono z-score normalizzati ~N(0,1). L'orchestratore combina:
- Classic: pesi EWMA basati su correlazione storica + softmax con temperatura adattiva
- Neural: CNeuralNet che impara la combinazione non-lineare ottimale
### Zero Magic Constants
Ogni numero nel sistema è derivato da:
- **Distribuzioni empiriche**: RunningStats di MAE/MFE/ritorni
- **EVT (Extreme Value Theory)**: fallback senza dati per SL, trigger, offset
- **Architettura NN**: dropout, L2, β₁, β₂, ε da hidden size
- **Floating-point standard**: sqrt(DBL_EPS) per soglie numeriche
- **Statistica classica**: StdErr, correlazioni, Student-t
### Multi-Position Aggressivo
- Ogni barra con segnale apre nuova posizione
- 20% di capitale per trade (configurabile)
- Nessun TP fisso: trailing stop adattivo da MFE/MAE
- SL width da MAE dei trade vincenti
### Apprendimento Continuo
- Agenti: CalibrateZ() + Learn() con bias/correlation tracking
- NN: training supervisionato con campioni pesati per importanza
- Stato: tutto salvato inline (incluso NN) per portabilità tester→live
---
## 15. Trade Entry / Exit Logic
### Come Entra a Mercato
L'entry avviene in `ManagePositions()` in MultiAgentTest.mq5, **ogni barra** con segnale actionable:
1. **Nuova barra rilevata** in OnTick → chiama `orchestrator.Analyze(data)` per produrre `combinedZ`
2. **GetFinalSignal()** produce `FinalSignal { direction, zScore, ... }`
3. **Controllo soglia**: se `|zScore| > minZ` (dove `minZ = AdaptiveMinZ()`), si procede
4. **Calcolo SL**: `SL = price ± atr × slWidth` dove `slWidth = AdaptiveSLWidth()`
5. **Calcolo lotto**: `lot = AdaptiveBaseLot() × |zScore|`
- `AdaptiveBaseLot() = balance × riskFraction / 100000`
- Con riskFraction = 0.20 (20%): per $10k → lotto base 0.20 × z
6. **Chiamata MT5**: `trade.Buy(lot, sym, ask, sl, 0)` o `trade.Sell(lot, sym, bid, sl, 0)`
- TP = 0: nessun take profit fisso, l'uscita è gestita da trailing stop o reversal
7. **Tracciamento**: `orchestrator.OnTradeOpen(ticket, price, atr)` salva la posizione in `openTrades[]`
### Frequenza di Entry (Multi-Position)
- **Ogni barra** con segnale apre UNA NUOVA posizione, indipendentemente da quante sono già aperte
- **Solo il margine libero** limita il numero di posizioni: se `marginReq ≥ freeMargin`, il trade è saltato
- Nessun limite artificiale: l'array `openTrades[]` cresce dinamicamente (`EnsureTradeCapacity`)
- Con `AdaptiveMinZ = Std/sqrt(N)` (~0.16 con 6 agenti), la soglia è molto bassa → molte entrate
- Il sistema può gestire centinaia di posizioni contemporanee se il margine lo permette
### Come Esce a Mercato
Ci sono **tre modi** per chiudere una posizione:
**A) Reversal (chiusura attiva) — OPZIONALE**
- Controllato da `Inp_UseReversalClose` (default: true)
- Se **true**: in `ManagePositions()`, dopo aver calcolato il nuovo segnale:
- `GetTradesToClose()` ritorna i ticket delle posizioni con direzione opposta al segnale corrente
- BUY chiusi se `currentZ < -minZ`, SELL chiusi se `currentZ > minZ`
- Chiamata: `OnTradeClose(tkt, closePrice)` + `trade.PositionClose(tkt)`
- Se **false**: le posizioni NON vengono mai chiuse per reversal. Ogni barra apre UNA NUOVA posizione nella direzione del segnale, e le posizioni esistenti rimangono aperte. Questo permette:
- **Long e short simultanei**: il sistema può tenere posizioni in entrambe le direzioni
- **Massimizzazione del profitto**: non taglia le posizioni che potrebbero ancora essere redditizie
- **Uscita solo via trailing stop o SL**: nessuna chiusura "forzata" dal segnale
- Attenzione: il rischio aumenta perché le posizioni opposte si compensano parzialmente
**B) Trailing Stop (chiusura automatica)**
- In `TrailStops()`, chiamato ogni barra:
1. Calcola **trail trigger**: da `AdaptiveTrailTrigger()` = MFE medio o EVT fallback
2. Calcola **trail offset**: da `AdaptiveTrailOffset()` = MAE medio dei vincenti o EVT fallback
3. Se il profitto corrente > trail trigger (in ATR):
- BUY: `newSL = entryPrice + (highestPrice - entryPrice) - offset`
- SELL: `newSL = entryPrice - (entryPrice - lowestPrice) + offset`
4. Se il nuovo SL è più stretto del precedente, viene aggiornato via `PositionModify(tkt, newSL, curTP)`
- Il trailing stop si attiva SOLO dopo che il prezzo ha superato il tipico MFE
**C) SL/TP iniziale (broker-side)**
- All'apertura, ogni posizione ha uno stop loss (SL = price ± atr × slWidth)
- Se il mercato va contro la posizione, lo SL iniziale ferma la perdita
- La chiusura da SL/TP è rilevata in `OnTrade()`: se un ticket tracciato non è più in `PositionsTotal()`, viene chiamato `OnTradeClose()`
- Il trailing stop può spostare lo SL per proteggere i profitti, ma non lo allarga mai
### Numero di Ordini
- **Entrate**: 1 posizione per barra con segnale (potenzialmente centinaia al giorno su M1)
- **Uscite**: 1 chiusura per posizione (via reversal, trailing, o SL)
- **Modifiche**: 1 modifica per barra per posizione (trailing SL via PositionModify)
- **Totale ordini**: dipende dalla frequenza dei segnali × numero posizioni aperte
- In backtest su H1 con 6 agenti: tipicamente 50-200 trade/mese, ma con entry aggressive può essere molto di più
---
## 16. Risk Management
### Dimensionamento Posizione
Il rischio per trade è controllato da due livelli:
**Livello 1: Frazione di Capitale (`Inp_RiskFraction`)**
- Default: 0.20 (20% del capitale per trade)
- `lotto = balance × riskFraction / 100000 × |z|`
- Esempio: $10,000 × 0.20 / 100000 × |z=1.0| = 0.02 lotti (= 2,000 unità EURUSD)
- Il `|z|` scala il lotto in base alla forza del segnale (|z|=2 → lotto doppio)
**Livello 2: Stop Loss Iniziale**
- `SL = prezzo ± atr × slWidth`
- `slWidth = AdaptiveSLWidth()`: usa MAE dei trade vincenti (o EVT fallback)
- Maggiore slWidth → stop più largo → maggiore rischio per trade
- Il trailing stop protegge ulteriormente spostando lo SL in profitto
**Livello 3: Margine**
- Controllo esplicito: `if(marginReq ≥ freeMargin) return`
- Se non c'è abbastanza margine per il lotto calcolato, il trade è saltato
- Questo è l'UNICO limite reale al numero di posizioni
### Distribuzione del Rischio (Multi-Position)
Con multi-position:
- Ogni posizione ha rischio individuale = `balance × riskFraction × |z| / 100000`
- Con 10 posizioni contemporanee: rischio totale = 10 × 0.20 × |z_medio| / 100000 × balance
- Il rischio totale è proporzionale a: `Σ|z_i| × riskFraction × balance / 100000`
- La diversificazione tra N posizioni riduce il rischio specifico di ogni entry
### Drawdown Control
Il sistema non ha un hard stop sul drawdown (per scelta: l'utente vuole trading aggressivo). Tuttavia:
- Il trailing stop limita le perdite di ogni singola posizione
- La distribuzione MAE dei vincenti guida la larghezza dello SL
- Il `rollingSharpe` negativo è segnalato ma non blocca il trading
---
## 17. Manual Override System
Anche se il sistema è progettato per essere "zero magic constants" con tutti i valori derivati dai dati, puoi **sovrascrivere manualmente** qualsiasi parametro tramite gli **input dell'EA**:
### Cosa si può sovrascrivere
| Input | Default | Descrizione |
|-------|---------|-------------|
| `Inp_MinZ` | 0.0 (auto) | Soglia minima z-score. Se >0, ignora `AdaptiveMinZ()` |
| `Inp_WMin` | 0.0 (auto) | Peso minimo per agente. Se >0, ignora `1/(N×sqrt(N))` |
| `Inp_SLRiskATR` | 0.0 (auto) | SL fisso in ATR. Se >0, ignora `AdaptiveSLWidth()` |
| `Inp_TPRiskATR` | 0.0 (auto) | TP fisso in ATR. (TP=0 = trailing stop puro) |
| `Inp_HurstPeriod` | 0 (auto) | Periodo Hurst fisso. Se >0, ignora calcolo adattivo |
| `Inp_ADXPeriod` | 0 (auto) | Periodo ADX fisso. Se >0, ignora calcolo adattivo |
| `Inp_Lot` | 0.01 | Lotto fisso. Sostituisce `AdaptiveBaseLot()` se >0 |
| `Inp_BufferBars` | 0 (auto) | Numero barre buffer. Se 0: `max(300, HurstPeriod×10)` |
| `Inp_RiskFraction` | 0.20 | Frazione di capitale per trade. Puoi abbassare (0.05=5%) o alzare (0.50=50%) |
| `Inp_UseNeural` | false | True = neural orchestrator, False = softmax classico |
| `Inp_TrainMode` | false | Colleziona campioni e allena NN in backtest |
| `Inp_NNHidden` | 6 | Neuroni hidden layer della NN |
| `Inp_UseReversalClose` | true | true=chiudi su segnale opposto, false=long+short coesistono |
### Come funziona l'override
Nel codice, ogni input segue il pattern:
```mql
// Se input > 0, usa input. Se = 0, usa valore adattivo
double minZ = (Inp_MinZ > 0) ? Inp_MinZ : orchestrator.AdaptiveMinZ();
```
Oppure per parametri non-zero:
```mql
// NN: se passato >= 0, override
if(l2 >= 0) m_l2 = l2;
if(dropoutRate >= 0) m_dropoutRate = dropoutRate;
```
### Esempi Pratici
**Scenario conservativo**: `Inp_RiskFraction=0.05, Inp_MinZ=1.0`
- Rischia 5% per trade, soglia alta → pochi trade selezionati
**Scenario aggressivo**: `Inp_RiskFraction=0.50, Inp_MinZ=0`
- Rischia 50% per trade, soglia adattiva bassa → trade frequenti e grandi
**Scenario fisso**: `Inp_SLRiskATR=2.0, Inp_Lot=0.10`
- SL sempre a 2 ATR, lotto fisso 0.10 — nessun adattamento
### Cosa NON si può sovrascrivere (rimane data-driven)
- RunningStats alpha/min: derivati da N agenti
- NN iperparametri: dropout, L2, β₁, β₂, ε — derivati dall'architettura
- MAE/MFE distribuzioni: sempre empiriche
- EVT fallback: solo quando non ci sono dati
- Correlazioni e pesi: sempre empirici
---
## 18. Dati Salvati per Analisi Periodica
Alla fine del backtest (`OnDeinit`), il sistema salva MOLTEPLICI file per analisi approfondita:
### File Salvati
| File | Contenuto | Cartella |
|------|-----------|----------|
| `TR_Agent_Analysis_SYMBOL_TF.csv` | **TUTTI** i parametri derivati, soglie, periodi, stats | `Common` |
| `TR_Agent_NN_v1.dat` | Modello NN con pesi inline | `Common` |
| `NN_TrainingSamples_SYMBOL_TF.csv` | Campioni di training (8 feature + target) | `Common` |
| `NN_LossHistory_SYMBOL_TF.csv` | Loss per epoca di training | `Common` |
| `AgentLearning_SYMBOL_TF.csv` | Bias, correlazioni, errori per ogni agente | `Common` |
### Contenuto del CSV di Analisi (`SaveAnalysisCSV`)
Il file `TR_Agent_Analysis_SYMBOL_TF.csv` contiene TUTTO:
**Sezione 1: Trade Statistics**
- TotalTrades, WinCount, WinRate, MaxDrawdown, RollingSharpe
- ReturnMean, ReturnStd, ReturnCount
- CombinedZMean, CombinedZStd, CombinedZCount
**Sezione 2: MAE/MFE Distributions**
- MAE_Mean, MAE_Std (massimo movimento avverso)
- MFE_Mean, MFE_Std (massimo movimento favorevole)
- MAE_Win_Mean, MAE_Win_Std (MAE dei soli vincenti)
**Sezione 3: Derived Thresholds**
- MinZ (soglia di entrata usata)
- SLWidth (larghezza SL in ATR)
- TrailTrigger (quando si attiva il trailing)
- TrailOffset (quanto si arretra lo SL)
- BaseLot (lotto base calcolato)
- CorrMinSamples, WeightMin, WeightAlpha
- EVT_MaxAbsZ
**Sezione 4: Agent Details**
- Per ogni agente: Name, Weight, Rho (correlazione), LastZ, Bias, BiasN, RhoLearn, RhoLearnN
**Sezione 5: Neural Network**
- NN_Epochs, NN_Loss, NN_Arch, NN_LR
**Sezione 6: Input Parameters** (per poter replicare il backtest)
- Tutti gli Inp_ parametri come sono stati usati
### Periodicità del Salvataggio
- **Stato modello**: salvato ogni `saveInterval = N × 5` trade chiusi da SL/TP
- **Analisi CSV**: salvata UNA volta in `OnDeinit`
- **Agent Learning CSV**: salvato UNA volta in `OnDeinit`
- **NN auto-save**: ogni 50 campioni durante il training (se TrainMode)
- **NN Loss CSV**: salvato dopo ogni training in `OnDeinit`
### Come Usare i CSV per Analisi
1. **Dopo backtest**: apri `Common\TR_Agent_Analysis_SYMBOL_TF.csv` in Excel/Google Sheets
2. Controlla: Sharpe, Win Rate, Max Drawdown, MAE/MFE
3. Confronta soglie derivate tra backtest diversi per vedere l'evoluzione
4. Usa `NN_TrainingSamples_SYMBOL_TF.csv` per analizzare la distribuzione delle feature
5. Confronta `NN_LossHistory` per verificare che la loss scenda durante il training
6. Porta il `.dat` in live e ricarica lo stato esattamente com'era in backtest