Ask me anything
Ithy Logo
Sign in to save

Sblocca il Potenziale dello Scalping su XAUUSD: Il Tuo EA per MT4 Avanzato

Un Expert Advisor progettato per lo scaling del conto, protezione del profitto e trading automatico su Oro con MetaTrader 4.

mt4-xauusd-scalping-ea-code-f9r0cyhd

Il trading automatico sull'oro (XAUUSD) richiede precisione, velocità e una gestione del rischio impeccabile, specialmente quando si parte da un capitale ridotto e si mira allo scaling. Questa guida fornisce un Expert Advisor (EA) completo per MetaTrader 4 (MT4), progettato per implementare una strategia di scalping su XAUUSD, incorporando funzionalità avanzate come la gestione automatica del lotto, protezione del profitto tramite trailing stop, selezione dinamica del timeframe e gestione degli orari di trading.

Punti Salienti Essenziali

  • Gestione Automatica Completa: L'EA gestisce l'apertura/chiusura degli ordini, il calcolo del lotto (auto lot sizing per scaling), Take Profit, Stop Loss e trailing stop dinamico.
  • Strategia di Scalping su Minuti: Opera principalmente su timeframe bassi (M1, M5, M15), selezionando automaticamente il più adatto in base alla volatilità intraday per catturare piccoli movimenti di prezzo.
  • Protezione e Flessibilità: Include filtri orari (pausa 22:00-00:20), controllo dello spread, rilevamento base del tipo di conto e parametri completamente configurabili tramite input esterni con flag di attivazione/disattivazione.

Comprendere la Logica dell'Expert Advisor

Questo EA è stato costruito per affrontare le sfide specifiche dello scalping su XAUUSD, un asset noto per la sua volatilità. L'obiettivo è automatizzare il processo di trading per far crescere un conto a partire da un capitale iniziale modesto (es. 50€), applicando una gestione del rischio rigorosa.

Caratteristiche Chiave Implementate

1. Strategia di Ingresso Basata su Indicatori

L'EA utilizza una combinazione di indicatori tecnici per identificare potenziali punti di ingresso per operazioni di acquisto (Buy) e vendita (Sell). La strategia di base fornita combina:

  • Bollinger Bands (BB): Per identificare livelli di ipercomprato/ipervenduto relativi alla volatilità corrente. Ingressi considerati quando il prezzo tocca le bande esterne.
  • Relative Strength Index (RSI): Come filtro di momentum e per confermare condizioni di ipercomprato (>70/80) o ipervenduto (<30/20).
  • Stochastic Oscillator: Per identificare inversioni a breve termine tramite l'incrocio delle sue linee (%K e %D) in zone estreme.

Questi indicatori lavorano insieme per fornire segnali di ingresso più robusti, ma possono essere attivati/disattivati tramite i parametri di input.

2. Gestione Automatica del Rischio e del Lotto (Auto Lot Sizing)

Fondamentale per lo scaling, specialmente partendo da 50€. L'EA calcola automaticamente la dimensione del lotto per ogni operazione basandosi su una percentuale di rischio definita dall'utente rispetto al saldo del conto e alla distanza dello Stop Loss. Questo permette un'esposizione proporzionale alla crescita (o decrescita) del capitale.


// Esempio di calcolo lotto (funzione interna all'EA)
double CalculateLotSize(double riskPercent, double stopLossPips)
{
    double balance = AccountBalance();
    double riskAmount = balance * riskPercent / 100.0; // Calcola importo a rischio
    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE); // Valore del tick per il simbolo
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP); // Passo minimo di lottaggio
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT); // Lotto minimo
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT); // Lotto massimo

    if (stopLossPips <= 0) stopLossPips = 15; // Default minimo per evitare divisione per zero
    if (tickValue <= 0) return minLot; // Sicurezza

    // Calcola lotto teorico
    double lot = riskAmount / (stopLossPips * Point * 10 * tickValue); // Adattato per pips e valore tick

    // Normalizza e applica limiti
    lot = MathMax(minLot, lot);
    lot = MathMin(maxLot, lot);
    lot = MathFloor(lot / lotStep) * lotStep; // Arrotonda al passo di lotto corretto
    if (lot < minLot) lot = minLot; // Verifica finale

    return lot;
}

3. Protezione del Profitto: TP, SL e Trailing Stop

Ogni operazione viene aperta con livelli predefiniti di Take Profit (TP) e Stop Loss (SL) in pips. Inoltre, è implementata una funzione di Trailing Stop dinamico: una volta che l'operazione raggiunge un certo profitto (configurabile), lo Stop Loss viene spostato automaticamente per seguire il prezzo a una distanza fissa, proteggendo i guadagni accumulati e permettendo potenzialmente di catturare movimenti più ampi.

4. Selezione Automatica del Timeframe (TF) su Minuti

L'EA può analizzare la volatilità su timeframe minuti (es. M1, M5, M15, configurabili) e selezionare quello che mostra il maggior range di prezzo recente (maggior volatilità). Questo permette di adattare la strategia alle condizioni di mercato correnti, pur mantenendo l'operatività focalizzata sui movimenti rapidi tipici dello scalping.

5. Gestione Oraria e Filtro Volatilità

Il trading viene automaticamente sospeso durante le ore di bassa liquidità o chiusura del mercato (configurato di default tra le 22:00 e le 00:20). Alla riapertura (00:20), l'EA può opzionalmente verificare un livello minimo di volatilità (tramite ATR - Average True Range) prima di riprendere le operazioni, evitando entrate in mercati piatti.

6. Adattabilità al Conto e "Invisibilità"

L'EA include una funzione base per rilevare conti con spread elevato e zero commissioni, anche se questa funzionalità è limitata dalle informazioni disponibili tramite MQL4 standard. L' "invisibilità" al broker si ottiene principalmente utilizzando funzioni di trading standard, un Magic Number univoco per identificare le operazioni dell'EA e evitando strategie facilmente riconoscibili come Martingala o Grid (che non sono implementate in questo EA base).


Valutazione delle Funzionalità Chiave

Il grafico radar sottostante offre una valutazione soggettiva delle capacità dell'EA rispetto ai requisiti comuni per un sistema di scalping automatizzato su XAUUSD. I punteggi più alti indicano una maggiore aderenza alla funzionalità desiderata, basata sull'implementazione fornita.

Questo grafico illustra come l'EA si posiziona rispetto agli obiettivi chiave: eccelle nella gestione del rischio, automazione e configurabilità, offre buone capacità di scalping e protezione del profitto, mentre l'adattabilità e il fattore "invisibilità" sono presenti ma con margini di miglioramento avanzato. Lo scaling da capitale basso è fattibile ma richiede un attento monitoraggio.


Mappa Mentale della Struttura dell'EA

La mappa mentale seguente visualizza l'architettura logica dell'Expert Advisor, mostrando come le diverse componenti interagiscono per eseguire la strategia di trading.

mindmap root["EA Scalping XAUUSD (MT4)"] id1["Logica Core"] id1_1["OnInit (Inizializzazione)"] id1_1_1["Controllo Parametri Input"] id1_1_2["Verifica Saldo Minimo"] id1_1_3["Stampa Messaggi Avvio"] id1_2["OnTick (Esecuzione Principale)"] id1_2_1["Controllo Attivazione EA"] id1_2_2["Filtro Orario/Volatilità"] id1_2_3["Selezione Timeframe (Auto/Manuale)"] id1_2_4["Controllo Spread/Conto"] id1_2_5["Verifica Condizioni Ingresso"] id1_2_6["Apertura Ordini (se 0 aperti)"] id1_2_7["Gestione Trailing Stop (se attivi)"] id1_3["OnDeinit (Deinizializzazione)"] id1_3_1["Stampa Messaggi Chiusura"] id2["Strategia di Trading"] id2_1["Indicatori Tecnici"] id2_1_1["Bollinger Bands"] id2_1_2["RSI"] id2_1_3["Stochastic"] id2_2["Condizioni di Ingresso"] id2_2_1["Segnale BUY (es. Prezzo < BB Lower, RSI < 40, Stoch Cross)"] id2_2_2["Segnale SELL (es. Prezzo > BB Upper, RSI > 60, Stoch Cross)"] id2_3["Gestione Uscita"] id2_3_1["Take Profit Fisso"] id2_3_2["Stop Loss Fisso"] id2_3_3["Trailing Stop Dinamico"] id3["Gestione Rischio e Conto"] id3_1["Auto Lot Sizing"] id3_1_1["Calcolo Rischio %"] id3_1_2["Normalizzazione Lotto"] id3_2["Stop Loss Iniziale"] id3_3["Take Profit Iniziale"] id3_4["Controllo Massimo Spread"] id3_5["Controllo Slippage"] id4["Logica Operativa Ausiliaria"] id4_1["Selezione Automatica Timeframe"] id4_1_1["Analisi Volatilità (Range Candele M1-M15)"] id4_2["Filtro Orario"] id4_2_1["Pausa Trading (22:00-00:20)"] id4_2_2["Opzione Chiusura Posizioni"] id4_3["Controllo Volatilità Riapertura"] id4_3_1["Verifica ATR (opzionale)"] id4_4["Rilevamento Tipo Conto (Base)"] id4_4_1["Controllo Spread vs Commissione"] id5["Configurazione"] id5_1["Parametri Input Esterni (input)"] id5_2["Flag Attivazione/Disattivazione Funzioni (bool)"]

Questa mappa evidenzia le macro-aree dell'EA: la logica principale che gestisce il flusso, la strategia basata su indicatori, i meccanismi di gestione del rischio, le funzioni operative accessorie e la configurabilità tramite parametri esterni.


Codice Completo MQL4 dell'Expert Advisor

Di seguito è riportato il codice sorgente completo dell'EA in linguaggio MQL4. È fondamentale testare approfonditamente questo codice su un conto demo prima di utilizzarlo su un conto reale. I parametri di default sono indicativi e potrebbero necessitare di ottimizzazione.

//+------------------------------------------------------------------+
//|                                                  ScalpingXAU.mq4 |
//|         EA scalper XAUUSD con protezione profitto, scaling e     |
//|         gestione automatica conto, timeframe automatico          |
//|         Progettato per conti piccoli (da 50 EUR)                 |
//+------------------------------------------------------------------+
#property strict
#property copyright "Generato da AI (Ithy) - Richiede Test Approfonditi"
#property link      ""
#property version   "1.10" // Versione aggiornata con check ATR
#property description "EA scalper XAUUSD per conto da 50 EUR+, gestione trailing, SL/TP automatico, autoscaling lotto, timeframe automatico, trading su minuti, filtro orario/volatilità."

//--- Parametri di Input Configurabili
input group "=== Attivazione EA ==="
input bool   EnableEA               = true;       // Attiva/Disattiva completamente l'EA

input group "=== Gestione del Rischio ==="
input double InitialLot             = 0.01;       // Lotto iniziale (usato se AutoLotSizing = false)
input bool   AutoLotSizing          = true;       // Abilita calcolo lotto automatico
input double RiskPerTradePercent    = 1.0;        // Rischio % del capitale per trade (se AutoLotSizing = true)
input int    StopLossPips           = 15;         // Stop Loss in pips (1 pip = 10 punti per XAUUSD)
input int    TakeProfitPips         = 25;         // Take Profit in pips
input int    MaxSpreadPoints        = 30;         // Max spread in PUNTI (non pips) per aprire trade (es. 30 punti = 3 pips)
input int    SlippagePoints         = 3;          // Slippage massimo in PUNTI

input group "=== Trailing Stop ==="
input bool   EnableTrailingStop     = true;       // Abilita trailing stop dinamico
input int    TrailingStartPips     = 15;          // Attiva trailing dopo X pips di profitto
input int    TrailingStopPips      = 10;          // Distanza trailing stop in pips dal prezzo corrente
input int    TrailingStepPips      = 1;           // Passo di aggiornamento trailing (in pips)

input group "=== Strategia Indicatori (Attiva/Disattiva) ==="
input bool   UseIndicatorsToTrade   = true;       // Usa la strategia basata su indicatori? (altrimenti entra casualmente - NON RACCOMANDATO)
input int    BB_Period              = 20;         // Periodo Bollinger Bands
input double BB_Deviation           = 2.0;        // Deviazione Bollinger Bands
input int    RSI_Period             = 14;         // Periodo RSI
input double RSI_Level_Buy          = 35.0;       // Livello RSI per considerare Buy (sotto questo)
input double RSI_Level_Sell         = 65.0;       // Livello RSI per considerare Sell (sopra questo)
input int    Stoch_K_Period         = 5;          // Periodo K Stochastic
input int    Stoch_D_Period         = 3;          // Periodo D Stochastic
input int    Stoch_Slowing          = 3;          // Rallentamento Stochastic
input double Stoch_Level_Buy        = 25.0;       // Livello Stochastic per Buy (sotto questo)
input double Stoch_Level_Sell       = 75.0;       // Livello Stochastic per Sell (sopra questo)

input group "=== Gestione Timeframe ==="
input bool   EnableAutoTFSelection   = true;       // Abilita scelta TF automatica basata su volatilità
input ENUM_TIMEFRAMES ManualTF      = PERIOD_M5;  // Timeframe manuale (usato se EnableAutoTFSelection = false)
input int    MinTFMinutes           = 1;          // Minuti minimi per TF automatico (1=M1)
input int    MaxTFMinutes           = 15;         // Minuti massimi per TF automatico (15=M15)

input group "=== Gestione Oraria e Conto ==="
input bool   EnableTimeFilter       = true;       // Abilita filtro orario
input int    MarketCloseHour        = 22;         // Ora chiusura trading (server time)
input int    MarketOpenHour         = 0;          // Ora riapertura trading (server time)
input int    MarketOpenMinute       = 20;         // Minuto riapertura trading (server time)
input bool   CloseAllOnMarketClose  = true;       // Chiudi tutte le posizioni alla chiusura mercato?
input bool   CheckVolatilityOnOpen  = true;       // Verifica volatilità minima alla riapertura?
input double MinATR_OnOpen          = 0.1;        // Valore ATR minimo (su TF M5) per riprendere il trading
input bool   AutoDetectHighSpreadAccount = true;  // Tenta di rilevare conto ad alto spread? (Funzione base)
input double AccountStartBalance    = 50.0;       // Balance minimo richiesto per operare

input group "=== Identificazione EA ==="
input int    MagicNumber            = 67890;      // Numero Magico univoco per questo EA
input string CommentEA              = "ScalperXAU_v1.1"; // Commento per gli ordini

//--- Variabili Globali
datetime lastTradeTime = 0;       // Orario ultimo trade per evitare over-trading
int     tradeIntervalSec = 30;    // Intervallo minimo (secondi) tra nuovi trade
int     pointsMultiplier = 1;     // Moltiplicatore per pips->punti (calcolato in OnInit)

//+------------------------------------------------------------------+
//| Funzione di Inizializzazione EA                                  |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Avvio EA: ", CommentEA, " - Versione ", __FILE__, " (", __DATE__, " ", __TIME__, ")");

    if (!EnableEA) {
        Print("EA disabilitato dalle impostazioni di input.");
        return(INIT_FAILED);
    }

    if (AccountInfoDouble(ACCOUNT_BALANCE) < AccountStartBalance) {
        Print("Saldo insufficiente (", AccountInfoDouble(ACCOUNT_BALANCE), ") per avviare l'EA. Richiesto: ", AccountStartBalance);
        return(INIT_FAILED);
    }

    // Determina il moltiplicatore pips->punti basato su Digits
    if (Digits == 3 || Digits == 5) {
        pointsMultiplier = 10;
    } else if (Digits == 2 || Digits == 4) {
        pointsMultiplier = 1;
    } else {
        pointsMultiplier = 1; // Fallback
        Print("Attenzione: Numero di decimali (Digits=", Digits, ") non standard per XAUUSD. Impostato moltiplicatore Punti a 1.");
    }
     Print("Moltiplicatore Pips -> Punti: ", pointsMultiplier);


    if (AutoDetectHighSpreadAccount) {
        bool highSpread = IsHighSpreadNoCommissionAccount();
        if (highSpread) {
            Print("Rilevato Conto potenzialmente ad Alto Spread e Zero Commissioni.");
            // Qui si potrebbero adattare parametri (es. aumentare TP/SL)
        }
    }

    Print("EA inizializzato con successo. MagicNumber: ", MagicNumber);
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Funzione di Deinizializzazione EA                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("EA ", CommentEA, " terminato. Ragione: ", reason);
    // Potrebbe essere utile chiudere posizioni aperte qui se necessario, a seconda della ragione
}

//+------------------------------------------------------------------+
//| Funzione Principale Eseguita ad Ogni Tick                        |
//+------------------------------------------------------------------+
void OnTick()
{
    if (!EnableEA) return; // Stop se disabilitato

    // --- 1. Controllo Condizioni Generali (Orario, Volatilità, Spread) ---
    if (EnableTimeFilter && !IsMarketOpenAndVolatile()) {
        if (CloseAllOnMarketClose && IsInMarketCloseHours()) {
            CloseAllPositions(MagicNumber, CommentEA);
        }
        return; // Fuori orario o bassa volatilità
    }

    if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpreadPoints) {
       // Print("Spread troppo alto (", MarketInfo(Symbol(), MODE_SPREAD), " > ", MaxSpreadPoints, "). Trading sospeso.");
       return; // Spread troppo alto
    }

    // Impedisce trading troppo frequente
    if (TimeCurrent() - lastTradeTime < tradeIntervalSec) {
        ManageExistingTrades(); // Gestisce comunque i trade aperti (trailing)
        return;
    }

    // --- 2. Controllo Posizioni Esistenti ---
    if (CountOpenTrades(MagicNumber) > 0) {
        ManageExistingTrades(); // Se ci sono trade aperti, gestiscili (trailing)
        return; // Non apre nuovi trade se ce n'è già uno aperto
    }

    // --- 3. Selezione Timeframe ---
    ENUM_TIMEFRAMES selectedTF = ManualTF;
    if (EnableAutoTFSelection) {
        selectedTF = SelectBestTimeframe(MinTFMinutes, MaxTFMinutes);
    }
    if (selectedTF == 0) selectedTF = ManualTF; // Fallback

    // --- 4. Verifica Segnale di Ingresso ---
    int signal = GetTradeSignal(selectedTF); // Ottiene segnale BUY (1), SELL (-1) o NESSUNO (0)

    // --- 5. Apertura Nuova Operazione ---
    if (signal != 0) {
        double lotSize = InitialLot;
        if (AutoLotSizing) {
            lotSize = CalculateLotSize(RiskPerTradePercent, StopLossPips);
        }

        if (lotSize >= MarketInfo(Symbol(), MODE_MINLOT)) {
            bool opened = OpenOrder(signal == 1 ? OP_BUY : OP_SELL, lotSize, selectedTF);
            if (opened) {
                lastTradeTime = TimeCurrent(); // Aggiorna l'orario dell'ultimo trade
            }
        } else {
            Print("Dimensione lotto calcolata (", lotSize, ") è inferiore al minimo consentito (", MarketInfo(Symbol(), MODE_MINLOT), "). Nessun ordine piazzato.");
        }
    }
}

//+------------------------------------------------------------------+
//| Gestisce Trailing Stop e altre logiche per trade aperti          |
//+------------------------------------------------------------------+
void ManageExistingTrades() {
     if (EnableTrailingStop) {
        TrailStops(MagicNumber);
    }
    // Qui si potrebbero aggiungere altre logiche di gestione (es. chiusura parziale, break-even)
}

//+------------------------------------------------------------------+
//| Funzioni Ausiliarie                                              |
//+------------------------------------------------------------------+

// --- Funzioni Indicatori ---
double GetBollingerMiddle(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_MAIN, 0); }
double GetBollingerUpper(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 0); }
double GetBollingerLower(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 0); }
double GetRSI(ENUM_TIMEFRAMES tf) { return iRSI(Symbol(), tf, RSI_Period, PRICE_CLOSE, 0); }
double GetStochasticK(ENUM_TIMEFRAMES tf) { return iStochastic(Symbol(), tf, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_MAIN, 0); }
double GetStochasticD(ENUM_TIMEFRAMES tf) { return iStochastic(Symbol(), tf, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_SIGNAL, 0); }
double GetATR(ENUM_TIMEFRAMES tf, int period) { return iATR(Symbol(), tf, period, 0); }

// --- Calcolo Lotto Automatico ---
double CalculateLotSize(double riskPercent, double stopLossPips)
{
    if (riskPercent <= 0) return InitialLot; // Se rischio è zero o negativo, usa lotto iniziale

    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double riskAmount = balance * riskPercent / 100.0;
    double stopLossPoints = stopLossPips * pointsMultiplier; // Converti pips in punti
    if (stopLossPoints <= 0) stopLossPoints = 15 * pointsMultiplier; // SL minimo di sicurezza

    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);

    if (tickValue <= 0 || tickSize <= 0 || stopLossPoints <=0) {
         Print("Errore nel calcolo del lotto: TickValue=", tickValue, ", TickSize=", tickSize, "SL Points=", stopLossPoints);
         return MarketInfo(Symbol(), MODE_MINLOT); // Ritorna lotto minimo in caso di dati non validi
    }

    // Calcolo del valore per punto
     double valuePerPoint = tickValue / tickSize;
     if(valuePerPoint <= 0) {
         Print("Errore nel calcolo del lotto: Valore per punto non valido.");
         return MarketInfo(Symbol(), MODE_MINLOT);
     }

    double lot = riskAmount / (stopLossPoints * valuePerPoint);

    // Normalizzazione e limiti
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT);
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);

    lot = MathFloor(lot / lotStep) * lotStep; // Arrotonda al passo corretto

    if (lot < minLot) lot = minLot;
    if (lot > maxLot) lot = maxLot;

    return lot;
}


// --- Selezione Automatica Timeframe ---
ENUM_TIMEFRAMES SelectBestTimeframe(int minTFMinutes, int maxTFMinutes)
{
    ENUM_TIMEFRAMES bestTF = ManualTF; // Default
    double maxRange = 0;

    // Mappa minuti a ENUM_TIMEFRAMES (limitato a quelli supportati)
    int timeframesToCheck[] = {1, 5, 15, 30, 60}; // M1, M5, M15, M30, H1
    ENUM_TIMEFRAMES enumTFs[] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1};

    for(int i = 0; i < ArraySize(timeframesToCheck); i++)
    {
        int tfMinutes = timeframesToCheck[i];
        if (tfMinutes >= minTFMinutes && tfMinutes <= maxTFMinutes)
        {
            ENUM_TIMEFRAMES currentEnumTF = enumTFs[i];
            // Usa ATR come misura di volatilità invece del range semplice
            double currentATR = GetATR(currentEnumTF, 14); // ATR su 14 periodi

            if (currentATR > maxRange) {
                maxRange = currentATR;
                bestTF = currentEnumTF;
            }
        }
    }
    // Print("Timeframe Automatico Selezionato: ", EnumToString(bestTF), " con ATR: ", maxRange);
    return bestTF;
}

// --- Verifica Orario Mercato e Volatilità ---
bool IsMarketOpenAndVolatile()
{
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    int minute = TimeMinute(now);

    // Verifica se siamo nell'intervallo di chiusura
    if (hour == MarketCloseHour && minute >= 0) return false; // Dalle 22:00 in poi
    if (hour > MarketCloseHour) return false; // Ore successive alle 22 (es. 23)

    if (hour < MarketOpenHour) return false; // Ore prima delle 00 (es. 23 del giorno prima) - questo gestisce il cambio giorno
    if (hour == MarketOpenHour && minute < MarketOpenMinute) { // Tra le 00:00 e le 00:20
        // Opzionale: Verifica volatilità minima
        if (CheckVolatilityOnOpen) {
            double currentATR_M5 = GetATR(PERIOD_M5, 14); // Controlla ATR su M5
            if (currentATR_M5 < MinATR_OnOpen) {
               // Print("Volatilità troppo bassa (ATR M5=", currentATR_M5, ") alla riapertura. Attesa.");
               return false;
            }
        } else {
             return false; // Se non si controlla volatilità, aspetta comunque le 00:20
        }
    }
    // Se nessuna delle condizioni sopra è vera, il mercato è considerato aperto
    return true;
}

// --- Verifica se siamo nelle ore di chiusura definite ---
bool IsInMarketCloseHours() {
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    int minute = TimeMinute(now);
    if (hour == MarketCloseHour && minute >= 0) return true;
    if (hour > MarketCloseHour) return true;
    if (hour < MarketOpenHour) return true; // Include le ore prima della riapertura
    if (hour == MarketOpenHour && minute < MarketOpenMinute) return true;
    return false;
}


// --- Rilevamento Base Conto Alto Spread ---
bool IsHighSpreadNoCommissionAccount()
{
    double spread = MarketInfo(Symbol(), MODE_SPREAD); // Spread in PUNTI
    double commission = AccountInfoDouble(ACCOUNT_COMMISSION); // Commissione per lotto (a volte 0)

    // Logica euristica: se lo spread è "alto" (es > 25 punti) E la commissione è zero,
    // potrebbe essere un conto di tipo "spread-based". Molto approssimativo.
    if (spread >= MaxSpreadPoints + 5 && commission == 0) return true; // Aggiungo margine a MaxSpreadPoints
    return false;
}

// --- Verifica Condizioni di Ingresso ---
int GetTradeSignal(ENUM_TIMEFRAMES timeframe)
{
    if (!UseIndicatorsToTrade) return 0; // Se disabilitato, nessun segnale

    double priceAsk = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_ASK), Digits);
    double priceBid = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_BID), Digits);

    double bbUpper = GetBollingerUpper(timeframe);
    double bbLower = GetBollingerLower(timeframe);
    double rsi = GetRSI(timeframe);
    double stoK = GetStochasticK(timeframe);
    double stoD = GetStochasticD(timeframe);
    double stoK_prev = iStochastic(Symbol(), timeframe, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_MAIN, 1); // K precedente
    double stoD_prev = iStochastic(Symbol(), timeframe, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_SIGNAL, 1); // D precedente


    // Condizione BUY (Esempio): Prezzo vicino/sotto BB Lower + RSI sotto soglia + Stochastic incrocia verso l'alto sotto soglia
    if (priceAsk <= bbLower + (bbUpper - bbLower) * 0.1 && // Prezzo vicino o sotto la banda inferiore
        rsi < RSI_Level_Buy &&                             // RSI in ipervenduto
        stoK > stoD && stoK_prev <= stoD_prev &&           // Incrocio K sopra D
        stoK < Stoch_Level_Buy)                            // Incrocio avviene sotto la soglia di ipervenduto
    {
        return 1; // Segnale BUY
    }

    // Condizione SELL (Esempio): Prezzo vicino/sopra BB Upper + RSI sopra soglia + Stochastic incrocia verso il basso sopra soglia
    if (priceBid >= bbUpper - (bbUpper - bbLower) * 0.1 && // Prezzo vicino o sopra la banda superiore
        rsi > RSI_Level_Sell &&                             // RSI in ipercomprato
        stoK < stoD && stoK_prev >= stoD_prev &&           // Incrocio K sotto D
        stoK > Stoch_Level_Sell)                            // Incrocio avviene sopra la soglia di ipercomprato
    {
        return -1; // Segnale SELL
    }

    return 0; // Nessun Segnale
}

// --- Funzione Trailing Stop ---
void TrailStops(int magic)
{
    if (!EnableTrailingStop) return;

    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {

                double currentPrice = 0;
                double newSL = 0;
                double openPrice = OrderOpenPrice();
                double currentSL = OrderStopLoss();
                double trailingStartPoints = TrailingStartPips * pointsMultiplier;
                double trailingStopPoints = TrailingStopPips * pointsMultiplier;

                if (OrderType() == OP_BUY) {
                    currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Usa Bid per confrontare profitto Buy
                    // Verifica se il profitto attuale supera la soglia di attivazione
                    if (currentPrice - openPrice >= trailingStartPoints) {
                        // Calcola il nuovo SL
                        newSL = NormalizeDouble(currentPrice - trailingStopPoints, Digits);
                        // Modifica SL solo se il nuovo SL è più alto del precedente (o se SL è zero)
                        if (currentSL < newSL || currentSL == 0) {
                             if (!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE)) {
                                Print("Errore modifica Trailing SL BUY: ", ErrorDescription(GetLastError()), " Ticket: ", OrderTicket());
                             } else {
                                // Print("Trailing SL BUY aggiornato a: ", newSL, " Ticket: ", OrderTicket());
                             }
                        }
                    }
                } else if (OrderType() == OP_SELL) {
                    currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // Usa Ask per confrontare profitto Sell
                    // Verifica se il profitto attuale supera la soglia di attivazione
                    if (openPrice - currentPrice >= trailingStartPoints) {
                        // Calcola il nuovo SL
                        newSL = NormalizeDouble(currentPrice + trailingStopPoints, Digits);
                        // Modifica SL solo se il nuovo SL è più basso del precedente (e SL non è zero)
                        if (currentSL > newSL || currentSL == 0) {
                            if (!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE)) {
                                Print("Errore modifica Trailing SL SELL: ", ErrorDescription(GetLastError()), " Ticket: ", OrderTicket());
                            } else {
                               // Print("Trailing SL SELL aggiornato a: ", newSL, " Ticket: ", OrderTicket());
                            }
                        }
                    }
                }
            }
        } else {
             Print("Errore selezione ordine nel trailing stop: ", ErrorDescription(GetLastError()));
        }
    }
}


// --- Apertura Ordine ---
bool OpenOrder(int type, double lotSize, ENUM_TIMEFRAMES tfSignal)
{
    double price = 0;
    double sl = 0, tp = 0;
    double stopLossPoints = StopLossPips * pointsMultiplier;
    double takeProfitPoints = TakeProfitPips * pointsMultiplier;

    RefreshRates(); // Assicura prezzi aggiornati

    if (type == OP_BUY) {
        price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
        sl = NormalizeDouble(price - stopLossPoints, Digits);
        tp = NormalizeDouble(price + takeProfitPoints, Digits);
        if (TakeProfitPips <= 0) tp = 0; // Disabilita TP se pips <= 0
        if (StopLossPips <= 0) sl = 0; // Disabilita SL se pips <= 0
    } else if (type == OP_SELL) {
        price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
        sl = NormalizeDouble(price + stopLossPoints, Digits);
        tp = NormalizeDouble(price - takeProfitPoints, Digits);
        if (TakeProfitPips <= 0) tp = 0; // Disabilita TP se pips <= 0
        if (StopLossPips <= 0) sl = 0; // Disabilita SL se pips <= 0
    } else {
        return false; // Tipo non valido
    }

    // Controllo validità StopLevel
    double stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if (stopLevel > 0) {
        if (type == OP_BUY) {
            if (sl != 0 && price - sl < stopLevel * Point) {
                 Print("Stop Loss BUY troppo vicino. SL richiesto: ", price-sl, " Minimo: ", stopLevel*Point);
                 sl = NormalizeDouble(price - stopLevel*Point - Point*2, Digits); // Sposta SL leggermente oltre lo stoplevel
                 Print("Nuovo SL BUY: ", sl);
            }
             if (tp != 0 && tp - price < stopLevel * Point) {
                 Print("Take Profit BUY troppo vicino. TP richiesto: ", tp-price, " Minimo: ", stopLevel*Point);
                 tp = NormalizeDouble(price + stopLevel*Point + Point*2, Digits); // Sposta TP leggermente oltre lo stoplevel
                 Print("Nuovo TP BUY: ", tp);
            }
        } else { // OP_SELL
             if (sl != 0 && sl - price < stopLevel * Point) {
                 Print("Stop Loss SELL troppo vicino. SL richiesto: ", sl-price, " Minimo: ", stopLevel*Point);
                 sl = NormalizeDouble(price + stopLevel*Point + Point*2, Digits);
                 Print("Nuovo SL SELL: ", sl);
             }
              if (tp != 0 && price - tp < stopLevel * Point) {
                 Print("Take Profit SELL troppo vicino. TP richiesto: ", price-tp, " Minimo: ", stopLevel*Point);
                 tp = NormalizeDouble(price - stopLevel*Point - Point*2, Digits);
                 Print("Nuovo TP SELL: ", tp);
             }
        }
    }


    int ticket = OrderSend(Symbol(), type, lotSize, price, SlippagePoints, sl, tp, CommentEA + "|TF:" + EnumToString(tfSignal), MagicNumber, 0, (type == OP_BUY ? clrDeepSkyBlue : clrOrangeRed));

    if (ticket < 0) {
        Print("Errore apertura ordine ", (type == OP_BUY ? "BUY" : "SELL"), ": ", ErrorDescription(GetLastError()),
              " Prezzo=", price, " SL=", sl, " TP=", tp, " Lotto=", lotSize);
        return false;
    } else {
        Print("Ordine aperto con successo: Ticket #", ticket, " Tipo=", (type == OP_BUY ? "BUY" : "SELL"),
              " Lotto=", DoubleToString(lotSize, 2), " Prezzo=", price, " SL=", sl, " TP=", tp);
        return true;
    }
}

// --- Chiusura di Tutte le Posizioni dell'EA ---
void CloseAllPositions(int magic, string commentPrefix)
{
    int closedCount = 0;
    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {
                if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
                    double closePrice = (OrderType() == OP_BUY) ? SymbolInfoDouble(Symbol(), SYMBOL_BID) : SymbolInfoDouble(Symbol(), SYMBOL_ASK);
                    if (!OrderClose(OrderTicket(), OrderLots(), closePrice, SlippagePoints, clrGray)) {
                        Print("Errore chiusura ordine #", OrderTicket(), ": ", ErrorDescription(GetLastError()));
                    } else {
                        closedCount++;
                       // Print("Ordine #", OrderTicket(), " chiuso a causa di Market Close Filter.");
                    }
                }
            }
        }
    }
    if(closedCount > 0) Print(closedCount, " posizioni chiuse a causa del filtro orario.");
}

// --- Conta le Posizioni Aperte dell'EA ---
int CountOpenTrades(int magic)
{
    int count = 0;
    for (int i = 0; i < OrdersTotal(); i++) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {
                if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
                    count++;
                }
            }
        }
    }
    return count;
}

// --- Funzione Helper per EnumToString ---
string EnumToString(ENUM_TIMEFRAMES period)
{
  switch(period)
  {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("D1");
    case PERIOD_W1:  return("W1");
    case PERIOD_MN1: return("MN1");
    default:         return(IntegerToString(period));
  }
}
//+------------------------------------------------------------------+


Parametri di Input e Configurazione

L'EA offre una vasta gamma di parametri configurabili direttamente dall'interfaccia di MetaTrader 4. Questo permette una personalizzazione fine della strategia e della gestione del rischio. La tabella seguente riassume i parametri principali:

Parametro Descrizione Tipo Default Note
EnableEA Attiva/Disattiva l'intero EA. bool true Impostare a 'false' per fermare completamente l'EA.
InitialLot Dimensione lotto fisso (usato se AutoLotSizing=false). double 0.01 Minimo lotto possibile.
AutoLotSizing Abilita calcolo automatico del lotto. bool true Se 'true', usa RiskPerTradePercent.
RiskPerTradePercent Rischio % del capitale per trade (con AutoLotSizing). double 1.0 Es. 1.0 = rischia l'1% del saldo per trade.
StopLossPips Stop Loss in Pips (1 pip = 10 punti su XAUUSD). int 15 Distanza SL dall'apertura. 0 disabilita SL.
TakeProfitPips Take Profit in Pips. int 25 Distanza TP dall'apertura. 0 disabilita TP.
MaxSpreadPoints Spread massimo in PUNTI consentito per aprire trade. int 30 Se lo spread corrente è maggiore, l'EA non apre nuovi ordini.
EnableTrailingStop Abilita Trailing Stop dinamico. bool true Protegge i profitti.
TrailingStartPips Pips di profitto per attivare il Trailing Stop. int 15
TrailingStopPips Distanza del Trailing Stop dal prezzo attuale (in pips). int 10
UseIndicatorsToTrade Usa la strategia basata su BB/RSI/Stoch? bool true Se 'false', entra casualmente (sconsigliato).
EnableAutoTFSelection Abilita selezione automatica del Timeframe. bool true Se 'false', usa ManualTF.
ManualTF Timeframe manuale (se AutoTF è 'false'). ENUM_TIMEFRAMES PERIOD_M5
EnableTimeFilter Abilita il filtro orario (pausa 22:00-00:20). bool true Evita ore non liquide.
CheckVolatilityOnOpen Verifica volatilità minima (ATR) alla riapertura? bool true Evita mercati piatti dopo la pausa.
MagicNumber Identificativo univoco per gli ordini di questo EA. int 67890 Non cambiare se hai altri EA sullo stesso conto/simbolo.

Video: Strategia di Scalping su Oro (XAUUSD)

Per comprendere meglio le dinamiche dello scalping sull'oro, il video seguente illustra una strategia operativa su timeframe a 5 minuti, simile concettualmente a quella che l'EA cerca di automatizzare. Fornisce spunti visivi sui movimenti di prezzo e sull'applicazione di tecniche di scalping.

Strategia Provata di Scalping Forex a 5 Minuti per XAUUSD/ORO.


Sviluppo Strategie Forex MT4/MT5

Illustrazione concettuale dello sviluppo di strategie di trading per piattaforme come MetaTrader.

Note Importanti e Avvertenze

  • Testare su Conto Demo: È assolutamente cruciale testare questo EA su un conto demo per un periodo prolungato prima di considerare l'uso su un conto reale. Le performance passate non garantiscono risultati futuri.
  • Ottimizzazione dei Parametri: I parametri di default sono solo un punto di partenza. L'ottimizzazione tramite lo Strategy Tester di MT4 è necessaria per adattare l'EA alle specifiche condizioni del broker e del mercato.
  • Rischio di Capitale: Il trading, specialmente lo scalping e l'uso di leva finanziaria, comporta un rischio significativo di perdita del capitale. Non investire denaro che non puoi permetterti di perdere.
  • Volatilità di XAUUSD: L'oro può essere estremamente volatile. Assicurati che le impostazioni di Stop Loss e gestione del rischio siano adeguate alla tua tolleranza al rischio.
  • Condizioni del Broker: Spread, slippage e velocità di esecuzione del broker influenzano pesantemente le performance dello scalping. Scegli un broker affidabile con buone condizioni per XAUUSD.
  • "Invisibilità" Limitata: Nessun EA client-side può essere veramente "invisibile". I broker possono sempre vedere gli ordini inviati. L'obiettivo qui è operare in modo standard senza usare tecniche sospette.
  • VPS Consigliato: Per un funzionamento continuo 24/5, è consigliabile eseguire l'EA su un Virtual Private Server (VPS) affidabile e vicino ai server del broker.

Domande Frequenti (FAQ)

È garantito che questo EA sia profittevole?

Assolutamente no. Nessun Expert Advisor può garantire profitti. Il trading comporta rischi intrinseci e le performance dipendono da innumerevoli fattori, inclusi le condizioni di mercato, la qualità del broker, lo slippage, lo spread e l'ottimizzazione dei parametri dell'EA. Questo codice fornisce una base tecnica, ma la redditività richiede test, ottimizzazione e gestione attiva.

Come installo questo EA su MetaTrader 4?

1. Copia l'intero codice MQL4 fornito.

2. Apri MetaEditor in MT4 (Tasto F4 o Strumenti -> Editor Linguaggio MetaQuotes).

3. In MetaEditor, clicca su File -> Nuovo -> Expert Advisor (Modello) -> Avanti.

4. Dai un nome al file (es. ScalpingXAU) e clicca Fine.

5. Cancella il codice modello e incolla il codice fornito.

6. Clicca sul pulsante "Compila" (o F7). Se non ci sono errori, l'EA sarà pronto.

7. Torna in MT4, apri la finestra "Navigatore" (Ctrl+N), trova l'EA sotto "Consiglieri Esperti", e trascinalo sul grafico XAUUSD desiderato. Abilita "Trading Automatico" nella barra degli strumenti di MT4.

Installazione EA in MT4

Immagine illustrativa del processo di installazione di un EA in MT4.

Cosa significa realmente "invisibile al broker"?

Il termine "invisibile" è spesso fuorviante. Non è possibile nascondere completamente l'attività di trading al broker quando si utilizza la sua piattaforma. In questo contesto, significa:

  • Utilizzare funzioni di trading standard di MQL4 senza ricorrere a tecniche non documentate o exploit.
  • Usare un Magic Number univoco per distinguere gli ordini dell'EA da quelli manuali o di altri EA.
  • Evitare strategie ad altissima frequenza (micro-scalping) o pattern di ordini molto specifici (come Martingala aggressiva) che alcuni broker potrebbero penalizzare o identificare più facilmente.
  • La gestione di SL/TP tramite modifiche interne (come il trailing stop) è comunque visibile al broker quando l'ordine viene modificato.

L'obiettivo è operare in modo pulito e standard, non diventare letteralmente invisibili.

Posso davvero iniziare con soli 50€?

Tecnicamente sì, se il broker permette depositi minimi bassi e lotti micro (0.01). Tuttavia, iniziare con un capitale così piccolo è estremamente rischioso:

  • Margine Limitato: Anche con lotti minimi (0.01 su XAUUSD), un piccolo movimento avverso può portare rapidamente a un margin call o stop out.
  • Scalabilità Lenta: La crescita sarà molto lenta all'inizio a causa delle dimensioni minime degli ordini.
  • Impatto dello Spread/Commissioni: Costi fissi per operazione incidono percentualmente molto di più su un capitale piccolo.

L'EA include un controllo `AccountStartBalance` (default 50.0) e l'auto lot sizing tenta di gestire il rischio, ma si raccomanda un capitale iniziale maggiore per avere più margine di manovra e ridurre il rischio di azzeramento rapido del conto.

Come ottimizzo i parametri di questo EA?

L'ottimizzazione si fa tramite lo "Strategy Tester" (Tester Strategie) integrato in MetaTrader 4 (Visualizza -> Tester Strategie o Ctrl+R).

1. Seleziona l'EA "ScalpingXAU" (o come lo hai chiamato).

2. Scegli il simbolo (XAUUSD) e il periodo su cui testare (es. M5).

3. Seleziona un intervallo di date storico significativo.

4. Attiva la modalità "Ottimizzazione".

5. Vai su "Proprietà Expert", seleziona i parametri che vuoi ottimizzare (es. StopLossPips, TakeProfitPips, periodi indicatori, livelli RSI/Stoch, TrailingStart/StopPips) e definisci i valori di Inizio, Passo e Fine per l'ottimizzazione.

6. Imposta le opzioni di ottimizzazione (es. criterio "Max Profit Factor" o "Max Balance").

7. Avvia l'ottimizzazione. Il processo può richiedere molto tempo.

8. Analizza i risultati per trovare la combinazione di parametri che ha performato meglio storicamente, ma fai attenzione all'overfitting (ottimizzazione eccessiva sui dati passati).


Riferimenti Utili

Ricerche Consigliate

Sblocca il Potenziale dello Scalping su XAUUSD: Il Tuo EA per MT4 Avanzato

Un Expert Advisor progettato per lo scaling del conto, protezione del profitto e trading automatico su Oro con MetaTrader 4.

Il trading automatico sull'oro (XAUUSD) richiede precisione, velocità e una gestione del rischio impeccabile, specialmente quando si parte da un capitale ridotto e si mira allo scaling. Questa guida fornisce un Expert Advisor (EA) completo per MetaTrader 4 (MT4), progettato per implementare una strategia di scalping su XAUUSD, incorporando funzionalità avanzate come la gestione automatica del lotto, protezione del profitto tramite trailing stop, selezione dinamica del timeframe e gestione degli orari di trading.

Punti Salienti Essenziali

  • Gestione Automatica Completa: L'EA gestisce l'apertura/chiusura degli ordini, il calcolo del lotto (auto lot sizing per scaling), Take Profit, Stop Loss e trailing stop dinamico.
  • Strategia di Scalping su Minuti: Opera principalmente su timeframe bassi (M1, M5, M15), selezionando automaticamente il più adatto in base alla volatilità intraday per catturare piccoli movimenti di prezzo.
  • Protezione e Flessibilità: Include filtri orari (pausa 22:00-00:20), controllo dello spread, rilevamento base del tipo di conto e parametri completamente configurabili tramite input esterni con flag di attivazione/disattivazione.

Comprendere la Logica dell'Expert Advisor

Questo EA è stato costruito per affrontare le sfide specifiche dello scalping su XAUUSD, un asset noto per la sua volatilità. L'obiettivo è automatizzare il processo di trading per far crescere un conto a partire da un capitale iniziale modesto (es. 50€), applicando una gestione del rischio rigorosa.

Caratteristiche Chiave Implementate

1. Strategia di Ingresso Basata su Indicatori

L'EA utilizza una combinazione di indicatori tecnici per identificare potenziali punti di ingresso per operazioni di acquisto (Buy) e vendita (Sell). La strategia di base fornita combina:

  • Bollinger Bands (BB): Per identificare livelli di ipercomprato/ipervenduto relativi alla volatilità corrente. Ingressi considerati quando il prezzo tocca le bande esterne.
  • Relative Strength Index (RSI): Come filtro di momentum e per confermare condizioni di ipercomprato (>70/80) o ipervenduto (<30/20).
  • Stochastic Oscillator: Per identificare inversioni a breve termine tramite l'incrocio delle sue linee (%K e %D) in zone estreme.

Questi indicatori lavorano insieme per fornire segnali di ingresso più robusti, ma possono essere attivati/disattivati tramite i parametri di input.

2. Gestione Automatica del Rischio e del Lotto (Auto Lot Sizing)

Fondamentale per lo scaling, specialmente partendo da 50€. L'EA calcola automaticamente la dimensione del lotto per ogni operazione basandosi su una percentuale di rischio definita dall'utente rispetto al saldo del conto e alla distanza dello Stop Loss. Questo permette un'esposizione proporzionale alla crescita (o decrescita) del capitale.


// Esempio di calcolo lotto (funzione interna all'EA)
double CalculateLotSize(double riskPercent, double stopLossPips)
{
    double balance = AccountBalance();
    double riskAmount = balance * riskPercent / 100.0; // Calcola importo a rischio
    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE); // Valore del tick per il simbolo
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP); // Passo minimo di lottaggio
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT); // Lotto minimo
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT); // Lotto massimo

    if (stopLossPips <= 0) stopLossPips = 15; // Default minimo per evitare divisione per zero
    if (tickValue <= 0) return minLot; // Sicurezza

    // Calcola lotto teorico
    double lotRisked = riskAmount / (stopLossPips * Point * 10 * tickValue); // Adattato per pips e valore tick

    // Normalizza e applica limiti
    lotRisked = MathMax(minLot, lotRisked);
    lotRisked = MathMin(maxLot, lotRisked);
    lotRisked = MathFloor(lotRisked / lotStep) * lotStep; // Arrotonda al passo di lotto corretto
    if (lotRisked < minLot) lotRisked = minLot; // Verifica finale

    return lotRisked;
}

3. Protezione del Profitto: TP, SL e Trailing Stop

Ogni operazione viene aperta con livelli predefiniti di Take Profit (TP) e Stop Loss (SL) in pips. Inoltre, è implementata una funzione di Trailing Stop dinamico: una volta che l'operazione raggiunge un certo profitto (configurabile), lo Stop Loss viene spostato automaticamente per seguire il prezzo a una distanza fissa, proteggendo i guadagni accumulati e permettendo potenzialmente di catturare movimenti più ampi.

4. Selezione Automatica del Timeframe (TF) su Minuti

L'EA può analizzare la volatilità su timeframe minuti (es. M1, M5, M15, configurabili) e selezionare quello che mostra il maggior range di prezzo recente (maggior volatilità). Questo permette di adattare la strategia alle condizioni di mercato correnti, pur mantenendo l'operatività focalizzata sui movimenti rapidi tipici dello scalping.

5. Gestione Oraria e Filtro Volatilità

Il trading viene automaticamente sospeso durante le ore di bassa liquidità o chiusura del mercato (configurato di default tra le 22:00 e le 00:20). Alla riapertura (00:20), l'EA può opzionalmente verificare un livello minimo di volatilità (tramite ATR - Average True Range) prima di riprendere le operazioni, evitando entrate in mercati piatti.

6. Adattabilità al Conto e "Invisibilità"

L'EA include una funzione base per rilevare conti con spread elevato e zero commissioni, anche se questa funzionalità è limitata dalle informazioni disponibili tramite MQL4 standard. L' "invisibilità" al broker si ottiene principalmente utilizzando funzioni di trading standard, un Magic Number univoco per identificare le operazioni dell'EA e evitando strategie facilmente riconoscibili come Martingala o Grid (che non sono implementate in questo EA base).


Valutazione delle Funzionalità Chiave

Il grafico radar sottostante offre una valutazione soggettiva delle capacità dell'EA rispetto ai requisiti comuni per un sistema di scalping automatizzato su XAUUSD. I punteggi più alti indicano una maggiore aderenza alla funzionalità desiderata, basata sull'implementazione fornita.

Questo grafico illustra come l'EA si posiziona rispetto agli obiettivi chiave: eccelle nella gestione del rischio, automazione e configurabilità, offre buone capacità di scalping e protezione del profitto, mentre l'adattabilità e il fattore "invisibilità" sono presenti ma con margini di miglioramento avanzato. Lo scaling da capitale basso è fattibile ma richiede un attento monitoraggio.


Mappa Mentale della Struttura dell'EA

La mappa mentale seguente visualizza l'architettura logica dell'Expert Advisor, mostrando come le diverse componenti interagiscono per eseguire la strategia di trading.

mindmap root["EA Scalping XAUUSD (MT4)"] id1["Logica Core"] id1_1["OnInit (Inizializzazione)"] id1_1_1["Controllo Parametri Input"] id1_1_2["Verifica Saldo Minimo"] id1_1_3["Stampa Messaggi Avvio"] id1_2["OnTick (Esecuzione Principale)"] id1_2_1["Controllo Attivazione EA"] id1_2_2["Filtro Orario/Volatilità"] id1_2_3["Selezione Timeframe (Auto/Manuale)"] id1_2_4["Controllo Spread/Conto"] id1_2_5["Verifica Condizioni Ingresso"] id1_2_6["Apertura Ordini (se 0 aperti)"] id1_2_7["Gestione Trailing Stop (se attivi)"] id1_3["OnDeinit (Deinizializzazione)"] id1_3_1["Stampa Messaggi Chiusura"] id2["Strategia di Trading"] id2_1["Indicatori Tecnici"] id2_1_1["Bollinger Bands"] id2_1_2["RSI"] id2_1_3["Stochastic"] id2_2["Condizioni di Ingresso"] id2_2_1["Segnale BUY (es. Prezzo < BB Lower, RSI < 40, Stoch Cross)"] id2_2_2["Segnale SELL (es. Prezzo > BB Upper, RSI > 60, Stoch Cross)"] id2_3["Gestione Uscita"] id2_3_1["Take Profit Fisso"] id2_3_2["Stop Loss Fisso"] id2_3_3["Trailing Stop Dinamico"] id3["Gestione Rischio e Conto"] id3_1["Auto Lot Sizing"] id3_1_1["Calcolo Rischio %"] id3_1_2["Normalizzazione Lotto"] id3_2["Stop Loss Iniziale"] id3_3["Take Profit Iniziale"] id3_4["Controllo Massimo Spread"] id3_5["Controllo Slippage"] id4["Logica Operativa Ausiliaria"] id4_1["Selezione Automatica Timeframe"] id4_1_1["Analisi Volatilità (Range Candele M1-M15)"] id4_2["Filtro Orario"] id4_2_1["Pausa Trading (22:00-00:20)"] id4_2_2["Opzione Chiusura Posizioni"] id4_3["Controllo Volatilità Riapertura"] id4_3_1["Verifica ATR (opzionale)"] id4_4["Rilevamento Tipo Conto (Base)"] id4_4_1["Controllo Spread vs Commissione"] id5["Configurazione"] id5_1["Parametri Input Esterni (input)"] id5_2["Flag Attivazione/Disattivazione Funzioni (bool)"]

Questa mappa evidenzia le macro-aree dell'EA: la logica principale che gestisce il flusso, la strategia basata su indicatori, i meccanismi di gestione del rischio, le funzioni operative accessorie e la configurabilità tramite parametri esterni.


Codice Completo MQL4 dell'Expert Advisor

Di seguito è riportato il codice sorgente completo dell'EA in linguaggio MQL4. È fondamentale testare approfonditamente questo codice su un conto demo prima di utilizzarlo su un conto reale. I parametri di default sono indicativi e potrebbero necessitare di ottimizzazione.

//+------------------------------------------------------------------+
//|                                                  ScalpingXAU.mq4 |
//|         EA scalper XAUUSD con protezione profitto, scaling e     |
//|         gestione automatica conto, timeframe automatico          |
//|         Progettato per conti piccoli (da 50 EUR)                 |
//+------------------------------------------------------------------+
#property strict
#property copyright "Generato da AI (Ithy) - Richiede Test Approfonditi"
#property link      ""
#property version   "1.10" // Versione aggiornata con check ATR
#property description "EA scalper XAUUSD per conto da 50 EUR+, gestione trailing, SL/TP automatico, autoscaling lotto, timeframe automatico, trading su minuti, filtro orario/volatilità."

//--- Parametri di Input Configurabili
input group "=== Attivazione EA ==="
input bool   EnableEA               = true;       // Attiva/Disattiva completamente l'EA

input group "=== Gestione del Rischio ==="
input double InitialLot             = 0.01;       // Lotto iniziale (usato se AutoLotSizing = false)
input bool   AutoLotSizing          = true;       // Abilita calcolo lotto automatico
input double RiskPerTradePercent    = 1.0;        // Rischio % del capitale per trade (se AutoLotSizing = true)
input int    StopLossPips           = 15;         // Stop Loss in pips (1 pip = 10 punti per XAUUSD)
input int    TakeProfitPips         = 25;         // Take Profit in pips
input int    MaxSpreadPoints        = 30;         // Max spread in PUNTI (non pips) per aprire trade (es. 30 punti = 3 pips)
input int    SlippagePoints         = 3;          // Slippage massimo in PUNTI

input group "=== Trailing Stop ==="
input bool   EnableTrailingStop     = true;       // Abilita trailing stop dinamico
input int    TrailingStartPips     = 15;          // Attiva trailing dopo X pips di profitto
input int    TrailingStopPips      = 10;          // Distanza trailing stop in pips dal prezzo corrente
input int    TrailingStepPips      = 1;           // Passo di aggiornamento trailing (in pips)

input group "=== Strategia Indicatori (Attiva/Disattiva) ==="
input bool   UseIndicatorsToTrade   = true;       // Usa la strategia basata su indicatori? (altrimenti entra casualmente - NON RACCOMANDATO)
input int    BB_Period              = 20;         // Periodo Bollinger Bands
input double BB_Deviation           = 2.0;        // Deviazione Bollinger Bands
input int    RSI_Period             = 14;         // Periodo RSI
input double RSI_Level_Buy          = 35.0;       // Livello RSI per considerare Buy (sotto questo)
input double RSI_Level_Sell         = 65.0;       // Livello RSI per considerare Sell (sopra questo)
input int    Stoch_K_Period         = 5;          // Periodo K Stochastic
input int    Stoch_D_Period         = 3;          // Periodo D Stochastic
input int    Stoch_Slowing          = 3;          // Rallentamento Stochastic
input double Stoch_Level_Buy        = 25.0;       // Livello Stochastic per Buy (sotto questo)
input double Stoch_Level_Sell       = 75.0;       // Livello Stochastic per Sell (sopra questo)

input group "=== Gestione Timeframe ==="
input bool   EnableAutoTFSelection   = true;       // Abilita scelta TF automatica basata su volatilità
input ENUM_TIMEFRAMES ManualTF      = PERIOD_M5;  // Timeframe manuale (usato se EnableAutoTFSelection = false)
input int    MinTFMinutes           = 1;          // Minuti minimi per TF automatico (1=M1)
input int    MaxTFMinutes           = 15;         // Minuti massimi per TF automatico (15=M15)

input group "=== Gestione Oraria e Conto ==="
input bool   EnableTimeFilter       = true;       // Abilita filtro orario
input int    MarketCloseHour        = 22;         // Ora chiusura trading (server time)
input int    MarketOpenHour         = 0;          // Ora riapertura trading (server time)
input int    MarketOpenMinute       = 20;         // Minuto riapertura trading (server time)
input bool   CloseAllOnMarketClose  = true;       // Chiudi tutte le posizioni alla chiusura mercato?
input bool   CheckVolatilityOnOpen  = true;       // Verifica volatilità minima alla riapertura?
input double MinATR_OnOpen          = 0.1;        // Valore ATR minimo (su TF M5) per riprendere il trading
input bool   AutoDetectHighSpreadAccount = true;  // Tenta di rilevare conto ad alto spread? (Funzione base)
input double AccountStartBalance    = 50.0;       // Balance minimo richiesto per operare

input group "=== Identificazione EA ==="
input int    MagicNumber            = 67890;      // Numero Magico univoco per questo EA
input string CommentEA              = "ScalperXAU_v1.1"; // Commento per gli ordini

//--- Variabili Globali
datetime lastTradeTime = 0;       // Orario ultimo trade per evitare over-trading
int     tradeIntervalSec = 30;    // Intervallo minimo (secondi) tra nuovi trade
int     pointsMultiplier = 1;     // Moltiplicatore per pips->punti (calcolato in OnInit)

//+------------------------------------------------------------------+
//| Funzione di Inizializzazione EA                                  |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Avvio EA: ", CommentEA, " - Versione ", __FILE__, " (", __DATE__, " ", __TIME__, ")");

    if (!EnableEA) {
        Print("EA disabilitato dalle impostazioni di input.");
        return(INIT_FAILED);
    }

    if (AccountInfoDouble(ACCOUNT_BALANCE) < AccountStartBalance) {
        Print("Saldo insufficiente (", AccountInfoDouble(ACCOUNT_BALANCE), ") per avviare l'EA. Richiesto: ", AccountStartBalance);
        return(INIT_FAILED);
    }

    // Determina il moltiplicatore pips->punti basato su Digits
    if (Digits == 3 || Digits == 5) {
        pointsMultiplier = 10;
    } else if (Digits == 2 || Digits == 4) {
        pointsMultiplier = 1;
    } else {
        pointsMultiplier = 1; // Fallback
        Print("Attenzione: Numero di decimali (Digits=", Digits, ") non standard per XAUUSD. Impostato moltiplicatore Punti a 1.");
    }
     Print("Moltiplicatore Pips -> Punti: ", pointsMultiplier);


    if (AutoDetectHighSpreadAccount) {
        bool highSpread = IsHighSpreadNoCommissionAccount();
        if (highSpread) {
            Print("Rilevato Conto potenzialmente ad Alto Spread e Zero Commissioni.");
            // Qui si potrebbero adattare parametri (es. aumentare TP/SL)
        }
    }

    Print("EA inizializzato con successo. MagicNumber: ", MagicNumber);
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Funzione di Deinizializzazione EA                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("EA ", CommentEA, " terminato. Ragione: ", reason);
    // Potrebbe essere utile chiudere posizioni aperte qui se necessario, a seconda della ragione
}

//+------------------------------------------------------------------+
//| Funzione Principale Eseguita ad Ogni Tick                        |
//+------------------------------------------------------------------+
void OnTick()
{
    if (!EnableEA) return; // Stop se disabilitato

    // --- 1. Controllo Condizioni Generali (Orario, Volatilità, Spread) ---
    if (EnableTimeFilter && !IsMarketOpenAndVolatile()) {
        if (CloseAllOnMarketClose && IsInMarketCloseHours()) {
            CloseAllPositions(MagicNumber, CommentEA);
        }
        return; // Fuori orario o bassa volatilità
    }

    if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpreadPoints) {
       // Print("Spread troppo alto (", MarketInfo(Symbol(), MODE_SPREAD), " > ", MaxSpreadPoints, "). Trading sospeso.");
       return; // Spread troppo alto
    }

    // Impedisce trading troppo frequente
    if (TimeCurrent() - lastTradeTime < tradeIntervalSec) {
        ManageExistingTrades(); // Gestisce comunque i trade aperti (trailing)
        return;
    }

    // --- 2. Controllo Posizioni Esistenti ---
    if (CountOpenTrades(MagicNumber) > 0) {
        ManageExistingTrades(); // Se ci sono trade aperti, gestiscili (trailing)
        return; // Non apre nuovi trade se ce n'è già uno aperto
    }

    // --- 3. Selezione Timeframe ---
    ENUM_TIMEFRAMES selectedTF = ManualTF;
    if (EnableAutoTFSelection) {
        selectedTF = SelectBestTimeframe(MinTFMinutes, MaxTFMinutes);
    }
    if (selectedTF == 0) selectedTF = ManualTF; // Fallback

    // --- 4. Verifica Segnale di Ingresso ---
    int signal = GetTradeSignal(selectedTF); // Ottiene segnale BUY (1), SELL (-1) o NESSUNO (0)

    // --- 5. Apertura Nuova Operazione ---
    if (signal != 0) {
        double lotSize = InitialLot;
        if (AutoLotSizing) {
            lotSize = CalculateLotSize(RiskPerTradePercent, StopLossPips);
        }

        if (lotSize >= MarketInfo(Symbol(), MODE_MINLOT)) {
            bool opened = OpenOrder(signal == 1 ? OP_BUY : OP_SELL, lotSize, selectedTF);
            if (opened) {
                lastTradeTime = TimeCurrent(); // Aggiorna l'orario dell'ultimo trade
            }
        } else {
            Print("Dimensione lotto calcolata (", lotSize, ") è inferiore al minimo consentito (", MarketInfo(Symbol(), MODE_MINLOT), "). Nessun ordine piazzato.");
        }
    }
}

//+------------------------------------------------------------------+
//| Gestisce Trailing Stop e altre logiche per trade aperti          |
//+------------------------------------------------------------------+
void ManageExistingTrades() {
     if (EnableTrailingStop) {
        TrailStops(MagicNumber);
    }
    // Qui si potrebbero aggiungere altre logiche di gestione (es. chiusura parziale, break-even)
}

//+------------------------------------------------------------------+
//| Funzioni Ausiliarie                                              |
//+------------------------------------------------------------------+

// --- Funzioni Indicatori ---
double GetBollingerMiddle(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_MAIN, 0); }
double GetBollingerUpper(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 0); }
double GetBollingerLower(ENUM_TIMEFRAMES tf) { return iBands(Symbol(), tf, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 0); }
double GetRSI(ENUM_TIMEFRAMES tf) { return iRSI(Symbol(), tf, RSI_Period, PRICE_CLOSE, 0); }
double GetStochasticK(ENUM_TIMEFRAMES tf) { return iStochastic(Symbol(), tf, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_MAIN, 0); }
double GetStochasticD(ENUM_TIMEFRAMES tf) { return iStochastic(Symbol(), tf, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_SIGNAL, 0); }
double GetATR(ENUM_TIMEFRAMES tf, int period) { return iATR(Symbol(), tf, period, 0); }

// --- Calcolo Lotto Automatico ---
double CalculateLotSize(double riskPercent, double stopLossPips)
{
    if (riskPercent <= 0) return InitialLot; // Se rischio è zero o negativo, usa lotto iniziale

    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double riskAmount = balance * riskPercent / 100.0;
    double stopLossPoints = stopLossPips * pointsMultiplier; // Converti pips in punti
    if (stopLossPoints <= 0) stopLossPoints = 15 * pointsMultiplier; // SL minimo di sicurezza

    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);

    if (tickValue <= 0 || tickSize <= 0 || stopLossPoints <=0) {
         Print("Errore nel calcolo del lotto: TickValue=", tickValue, ", TickSize=", tickSize, "SL Points=", stopLossPoints);
         return MarketInfo(Symbol(), MODE_MINLOT); // Ritorna lotto minimo in caso di dati non validi
    }

    // Calcolo del valore per punto
     double valuePerPoint = tickValue / tickSize;
     if(valuePerPoint <= 0) {
         Print("Errore nel calcolo del lotto: Valore per punto non valido.");
         return MarketInfo(Symbol(), MODE_MINLOT);
     }

    double lot = riskAmount / (stopLossPoints * valuePerPoint);

    // Normalizzazione e limiti
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT);
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);

    lot = MathFloor(lot / lotStep) * lotStep; // Arrotonda al passo corretto

    if (lot < minLot) lot = minLot;
    if (lot > maxLot) lot = maxLot;

    return lot;
}


// --- Selezione Automatica Timeframe ---
ENUM_TIMEFRAMES SelectBestTimeframe(int minTFMinutes, int maxTFMinutes)
{
    ENUM_TIMEFRAMES bestTF = ManualTF; // Default
    double maxRange = 0;

    // Mappa minuti a ENUM_TIMEFRAMES (limitato a quelli supportati)
    int timeframesToCheck[] = {1, 5, 15, 30, 60}; // M1, M5, M15, M30, H1
    ENUM_TIMEFRAMES enumTFs[] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1};

    for(int i = 0; i < ArraySize(timeframesToCheck); i++)
    {
        int tfMinutes = timeframesToCheck[i];
        if (tfMinutes >= minTFMinutes && tfMinutes <= maxTFMinutes)
        {
            ENUM_TIMEFRAMES currentEnumTF = enumTFs[i];
            // Usa ATR come misura di volatilità invece del range semplice
            double currentATR = GetATR(currentEnumTF, 14); // ATR su 14 periodi

            if (currentATR > maxRange) {
                maxRange = currentATR;
                bestTF = currentEnumTF;
            }
        }
    }
    // Print("Timeframe Automatico Selezionato: ", EnumToString(bestTF), " con ATR: ", maxRange);
    return bestTF;
}

// --- Verifica Orario Mercato e Volatilità ---
bool IsMarketOpenAndVolatile()
{
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    int minute = TimeMinute(now);

    // Verifica se siamo nell'intervallo di chiusura
    if (hour == MarketCloseHour && minute >= 0) return false; // Dalle 22:00 in poi
    if (hour > MarketCloseHour) return false; // Ore successive alle 22 (es. 23)

    if (hour < MarketOpenHour) return false; // Ore prima delle 00 (es. 23 del giorno prima) - questo gestisce il cambio giorno
    if (hour == MarketOpenHour && minute < MarketOpenMinute) { // Tra le 00:00 e le 00:20
        // Opzionale: Verifica volatilità minima
        if (CheckVolatilityOnOpen) {
            double currentATR_M5 = GetATR(PERIOD_M5, 14); // Controlla ATR su M5
            if (currentATR_M5 < MinATR_OnOpen) {
               // Print("Volatilità troppo bassa (ATR M5=", currentATR_M5, ") alla riapertura. Attesa.");
               return false;
            }
        } else {
             return false; // Se non si controlla volatilità, aspetta comunque le 00:20
        }
    }
    // Se nessuna delle condizioni sopra è vera, il mercato è considerato aperto
    return true;
}

// --- Verifica se siamo nelle ore di chiusura definite ---
bool IsInMarketCloseHours() {
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    int minute = TimeMinute(now);
    if (hour == MarketCloseHour && minute >= 0) return true;
    if (hour > MarketCloseHour) return true;
    if (hour < MarketOpenHour) return true; // Include le ore prima della riapertura
    if (hour == MarketOpenHour && minute < MarketOpenMinute) return true;
    return false;
}


// --- Rilevamento Base Conto Alto Spread ---
bool IsHighSpreadNoCommissionAccount()
{
    double spread = MarketInfo(Symbol(), MODE_SPREAD); // Spread in PUNTI
    double commission = AccountInfoDouble(ACCOUNT_COMMISSION); // Commissione per lotto (a volte 0)

    // Logica euristica: se lo spread è "alto" (es > 25 punti) E la commissione è zero,
    // potrebbe essere un conto di tipo "spread-based". Molto approssimativo.
    if (spread >= MaxSpreadPoints + 5 && commission == 0) return true; // Aggiungo margine a MaxSpreadPoints
    return false;
}

// --- Verifica Condizioni di Ingresso ---
int GetTradeSignal(ENUM_TIMEFRAMES timeframe)
{
    if (!UseIndicatorsToTrade) return 0; // Se disabilitato, nessun segnale

    double priceAsk = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_ASK), Digits);
    double priceBid = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_BID), Digits);

    double bbUpper = GetBollingerUpper(timeframe);
    double bbLower = GetBollingerLower(timeframe);
    double rsi = GetRSI(timeframe);
    double stoK = GetStochasticK(timeframe);
    double stoD = GetStochasticD(timeframe);
    double stoK_prev = iStochastic(Symbol(), timeframe, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_MAIN, 1); // K precedente
    double stoD_prev = iStochastic(Symbol(), timeframe, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, 0, MODE_SIGNAL, 1); // D precedente


    // Condizione BUY (Esempio): Prezzo vicino/sotto BB Lower + RSI sotto soglia + Stochastic incrocia verso l'alto sotto soglia
    if (priceAsk <= bbLower + (bbUpper - bbLower) * 0.1 && // Prezzo vicino o sotto la banda inferiore
        rsi < RSI_Level_Buy &&                             // RSI in ipervenduto
        stoK > stoD && stoK_prev <= stoD_prev &&           // Incrocio K sopra D
        stoK < Stoch_Level_Buy)                            // Incrocio avviene sotto la soglia di ipervenduto
    {
        return 1; // Segnale BUY
    }

    // Condizione SELL (Esempio): Prezzo vicino/sopra BB Upper + RSI sopra soglia + Stochastic incrocia verso il basso sopra soglia
    if (priceBid >= bbUpper - (bbUpper - bbLower) * 0.1 && // Prezzo vicino o sopra la banda superiore
        rsi > RSI_Level_Sell &&                             // RSI in ipercomprato
        stoK < stoD && stoK_prev >= stoD_prev &&           // Incrocio K sotto D
        stoK > Stoch_Level_Sell)                            // Incrocio avviene sopra la soglia di ipercomprato
    {
        return -1; // Segnale SELL
    }

    return 0; // Nessun Segnale
}

// --- Funzione Trailing Stop ---
void TrailStops(int magic)
{
    if (!EnableTrailingStop) return;

    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {

                double currentPrice = 0;
                double newSL = 0;
                double openPrice = OrderOpenPrice();
                double currentSL = OrderStopLoss();
                double trailingStartPoints = TrailingStartPips * pointsMultiplier;
                double trailingStopPoints = TrailingStopPips * pointsMultiplier;

                if (OrderType() == OP_BUY) {
                    currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Usa Bid per confrontare profitto Buy
                    // Verifica se il profitto attuale supera la soglia di attivazione
                    if (currentPrice - openPrice >= trailingStartPoints) {
                        // Calcola il nuovo SL
                        newSL = NormalizeDouble(currentPrice - trailingStopPoints, Digits);
                        // Modifica SL solo se il nuovo SL è più alto del precedente (o se SL è zero)
                        if (currentSL < newSL || currentSL == 0) {
                             if (!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE)) {
                                Print("Errore modifica Trailing SL BUY: ", ErrorDescription(GetLastError()), " Ticket: ", OrderTicket());
                             } else {
                                // Print("Trailing SL BUY aggiornato a: ", newSL, " Ticket: ", OrderTicket());
                             }
                        }
                    }
                } else if (OrderType() == OP_SELL) {
                    currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // Usa Ask per confrontare profitto Sell
                    // Verifica se il profitto attuale supera la soglia di attivazione
                    if (openPrice - currentPrice >= trailingStartPoints) {
                        // Calcola il nuovo SL
                        newSL = NormalizeDouble(currentPrice + trailingStopPoints, Digits);
                        // Modifica SL solo se il nuovo SL è più basso del precedente (e SL non è zero)
                        if (currentSL > newSL || currentSL == 0) {
                            if (!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE)) {
                                Print("Errore modifica Trailing SL SELL: ", ErrorDescription(GetLastError()), " Ticket: ", OrderTicket());
                            } else {
                               // Print("Trailing SL SELL aggiornato a: ", newSL, " Ticket: ", OrderTicket());
                            }
                        }
                    }
                }
            }
        } else {
             Print("Errore selezione ordine nel trailing stop: ", ErrorDescription(GetLastError()));
        }
    }
}


// --- Apertura Ordine ---
bool OpenOrder(int type, double lotSize, ENUM_TIMEFRAMES tfSignal)
{
    double price = 0;
    double sl = 0, tp = 0;
    double stopLossPoints = StopLossPips * pointsMultiplier;
    double takeProfitPoints = TakeProfitPips * pointsMultiplier;

    RefreshRates(); // Assicura prezzi aggiornati

    if (type == OP_BUY) {
        price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
        sl = NormalizeDouble(price - stopLossPoints, Digits);
        tp = NormalizeDouble(price + takeProfitPoints, Digits);
        if (TakeProfitPips <= 0) tp = 0; // Disabilita TP se pips <= 0
        if (StopLossPips <= 0) sl = 0; // Disabilita SL se pips <= 0
    } else if (type == OP_SELL) {
        price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
        sl = NormalizeDouble(price + stopLossPoints, Digits);
        tp = NormalizeDouble(price - takeProfitPoints, Digits);
        if (TakeProfitPips <= 0) tp = 0; // Disabilita TP se pips <= 0
        if (StopLossPips <= 0) sl = 0; // Disabilita SL se pips <= 0
    } else {
        return false; // Tipo non valido
    }

    // Controllo validità StopLevel
    double stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if (stopLevel > 0) {
        if (type == OP_BUY) {
            if (sl != 0 && price - sl < stopLevel * Point) {
                 Print("Stop Loss BUY troppo vicino. SL richiesto: ", price-sl, " Minimo: ", stopLevel*Point);
                 sl = NormalizeDouble(price - stopLevel*Point - Point*2, Digits); // Sposta SL leggermente oltre lo stoplevel
                 Print("Nuovo SL BUY: ", sl);
            }
             if (tp != 0 && tp - price < stopLevel * Point) {
                 Print("Take Profit BUY troppo vicino. TP richiesto: ", tp-price, " Minimo: ", stopLevel*Point);
                 tp = NormalizeDouble(price + stopLevel*Point + Point*2, Digits); // Sposta TP leggermente oltre lo stoplevel
                 Print("Nuovo TP BUY: ", tp);
            }
        } else { // OP_SELL
             if (sl != 0 && sl - price < stopLevel * Point) {
                 Print("Stop Loss SELL troppo vicino. SL richiesto: ", sl-price, " Minimo: ", stopLevel*Point);
                 sl = NormalizeDouble(price + stopLevel*Point + Point*2, Digits);
                 Print("Nuovo SL SELL: ", sl);
             }
              if (tp != 0 && price - tp < stopLevel * Point) {
                 Print("Take Profit SELL troppo vicino. TP richiesto: ", price-tp, " Minimo: ", stopLevel*Point);
                 tp = NormalizeDouble(price - stopLevel*Point - Point*2, Digits);
                 Print("Nuovo TP SELL: ", tp);
             }
        }
    }


    int ticket = OrderSend(Symbol(), type, lotSize, price, SlippagePoints, sl, tp, CommentEA + "|TF:" + EnumToString(tfSignal), MagicNumber, 0, (type == OP_BUY ? clrDeepSkyBlue : clrOrangeRed));

    if (ticket < 0) {
        Print("Errore apertura ordine ", (type == OP_BUY ? "BUY" : "SELL"), ": ", ErrorDescription(GetLastError()),
              " Prezzo=", price, " SL=", sl, " TP=", tp, " Lotto=", lotSize);
        return false;
    } else {
        Print("Ordine aperto con successo: Ticket #", ticket, " Tipo=", (type == OP_BUY ? "BUY" : "SELL"),
              " Lotto=", DoubleToString(lotSize, 2), " Prezzo=", price, " SL=", sl, " TP=", tp);
        return true;
    }
}

// --- Chiusura di Tutte le Posizioni dell'EA ---
void CloseAllPositions(int magic, string commentPrefix)
{
    int closedCount = 0;
    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {
                if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
                    double closePrice = (OrderType() == OP_BUY) ? SymbolInfoDouble(Symbol(), SYMBOL_BID) : SymbolInfoDouble(Symbol(), SYMBOL_ASK);
                    if (!OrderClose(OrderTicket(), OrderLots(), closePrice, SlippagePoints, clrGray)) {
                        Print("Errore chiusura ordine #", OrderTicket(), ": ", ErrorDescription(GetLastError()));
                    } else {
                        closedCount++;
                       // Print("Ordine #", OrderTicket(), " chiuso a causa di Market Close Filter.");
                    }
                }
            }
        }
    }
    if(closedCount > 0) Print(closedCount, " posizioni chiuse a causa del filtro orario.");
}

// --- Conta le Posizioni Aperte dell'EA ---
int CountOpenTrades(int magic)
{
    int count = 0;
    for (int i = 0; i < OrdersTotal(); i++) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic) {
                if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
                    count++;
                }
            }
        }
    }
    return count;
}

// --- Funzione Helper per EnumToString ---
string EnumToString(ENUM_TIMEFRAMES period)
{
  switch(period)
  {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("D1");
    case PERIOD_W1:  return("W1");
    case PERIOD_MN1: return("MN1");
    default:         return(IntegerToString(period));
  }
}
//+------------------------------------------------------------------+


Parametri di Input e Configurazione

L'EA offre una vasta gamma di parametri configurabili direttamente dall'interfaccia di MetaTrader 4. Questo permette una personalizzazione fine della strategia e della gestione del rischio. La tabella seguente riassume i parametri principali:

Parametro Descrizione Tipo Default Note
EnableEA Attiva/Disattiva l'intero EA. bool true Impostare a 'false' per fermare completamente l'EA.
InitialLot Dimensione lotto fisso (usato se AutoLotSizing=false). double 0.01 Minimo lotto possibile.
AutoLotSizing Abilita calcolo automatico del lotto. bool true Se 'true', usa RiskPerTradePercent.
RiskPerTradePercent Rischio % del capitale per trade (con AutoLotSizing). double 1.0 Es. 1.0 = rischia l'1% del saldo per trade.
StopLossPips Stop Loss in Pips (1 pip = 10 punti su XAUUSD). int 15 Distanza SL dall'apertura. 0 disabilita SL.
TakeProfitPips Take Profit in Pips. int 25 Distanza TP dall'apertura. 0 disabilita TP.
MaxSpreadPoints Spread massimo in PUNTI consentito per aprire trade. int 30 Se lo spread corrente è maggiore, l'EA non apre nuovi ordini.
EnableTrailingStop Abilita Trailing Stop dinamico. bool true Protegge i profitti.
TrailingStartPips Pips di profitto perattivare il Trailing Stop. int 15
TrailingStopPips Distanza del Trailing Stop dal prezzo attuale (in pips). int 10
UseIndicatorsToTrade Usa la strategia basata su BB/RSI/Stoch? bool true Se 'false', entra casualmente (sconsigliato).
EnableAutoTFSelection Abilita selezione automatica del Timeframe. bool true Se 'false', usa ManualTF.
ManualTF Timeframe manuale (se AutoTF è 'false'). ENUM_TIMEFRAMES PERIOD_M5
EnableTimeFilter Abilita il filtro orario (pausa 22:00-00:20). bool true Evita ore non liquide.
CheckVolatilityOnOpen Verifica volatilità minima (ATR) alla riapertura? bool true Evita mercati piatti dopo la pausa.
MagicNumber Identificativo univoco per gli ordini di questo EA. int 67890 Non cambiare se hai altri EA sullo stesso conto/simbolo.

Video: Strategia di Scalping su Oro (XAUUSD)

Per comprendere meglio le dinamiche dello scalping sull'oro, il video seguente illustra una strategia operativa su timeframe a 5 minuti, simile concettualmente a quella che l'EA cerca di automatizzare. Fornisce spunti visivi sui movimenti di prezzo e sull'applicazione di tecniche di scalping.

Strategia Provata di Scalping Forex a 5 Minuti per XAUUSD/ORO.


Sviluppo Strategie Forex MT4/MT5

Illustrazione concettuale dello sviluppo di strategie di trading per piattaforme come MetaTrader.

Note Importanti e Avvertenze

  • Testare su Conto Demo: È assolutamente cruciale testare questo EA su un conto demo per un periodo prolungato prima di considerare l'uso su un conto reale. Le performance passate non garantiscono risultati futuri.
  • Ottimizzazione dei Parametri: I parametri di default sono solo un punto di partenza. L'ottimizzazione tramite lo Strategy Tester di MT4 è necessaria per adattare l'EA alle specifiche condizioni del broker e del mercato.
  • Rischio di Capitale: Il trading, specialmente lo scalping e l'uso di leva finanziaria, comporta un rischio significativo di perdita del capitale. Non investire denaro che non puoi permetterti di perdere.
  • Volatilità di XAUUSD: L'oro può essere estremamente volatile. Assicurati che le impostazioni di Stop Loss e gestione del rischio siano adeguate alla tua tolleranza al rischio.
  • Condizioni del Broker: Spread, slippage e velocità di esecuzione del broker influenzano pesantemente le performance dello scalping. Scegli un broker affidabile con buone condizioni per XAUUSD.
  • "Invisibilità" Limitata: Nessun EA client-side può essere veramente "invisibile". I broker possono sempre vedere gli ordini inviati. L'obiettivo qui è operare in modo standard senza usare tecniche sospette.
  • VPS Consigliato: Per un funzionamento continuo 24/5, è consigliabile eseguire l'EA su un Virtual Private Server (VPS) affidabile e vicino ai server del broker.

Domande Frequenti (FAQ)

È garantito che questo EA sia profittevole?

Assolutamente no. Nessun Expert Advisor può garantire profitti. Il trading comporta rischi intrinseci e le performance dipendono da innumerevoli fattori, inclusi le condizioni di mercato, la qualità del broker, lo slippage, lo spread e l'ottimizzazione dei parametri dell'EA. Questo codice fornisce una base tecnica, ma la redditività richiede test, ottimizzazione e gestione attiva.

Come installo questo EA su MetaTrader 4?

1. Copia l'intero codice MQL4 fornito.

2. Apri MetaEditor in MT4 (Tasto F4 o Strumenti -> Editor Linguaggio MetaQuotes).

3. In MetaEditor, clicca su File -> Nuovo -> Expert Advisor (Modello) -> Avanti.

4. Dai un nome al file (es. ScalpingXAU) e clicca Fine.

5. Cancella il codice modello e incolla il codice fornito.

6. Clicca sul pulsante "Compila" (o F7). Se non ci sono errori, l'EA sarà pronto.

7. Torna in MT4, apri la finestra "Navigatore" (Ctrl+N), trova l'EA sotto "Consiglieri Esperti", e trascinalo sul grafico XAUUSD desiderato. Abilita "Trading Automatico" nella barra degli strumenti di MT4.

Installazione EA in MT4

Immagine illustrativa del processo di installazione di un EA in MT4.

Cosa significa realmente "invisibile al broker"?

Il termine "invisibile" è spesso fuorviante. Non è possibile nascondere completamente l'attività di trading al broker quando si utilizza la sua piattaforma. In questo contesto, significa:

  • Utilizzare funzioni di trading standard di MQL4 senza ricorrere a tecniche non documentate o exploit.
  • Usare un Magic Number univoco per distinguere gli ordini dell'EA da quelli manuali o di altri EA.
  • Evitare strategie ad altissima frequenza (micro-scalping) o pattern di ordini molto specifici (come Martingala aggressiva) che alcuni broker potrebbero penalizzare o identificare più easily.
  • La gestione di SL/TP tramite modifiche interne (come il trailing stop) è comunque visibile al broker quando l'ordine viene modificato.

L'obiettivo è operare in modo pulito e standard, non diventare letteralmente invisibili.

Posso davvero iniziare con soli 50€?

Tecnicamente sì, se il broker permette depositi minimi bassi e lotti micro (0.01). Tuttavia, iniziare con un capitale così piccolo è estremamente rischioso:

  • Margine Limitato: Anche con lotti minimi (0.01 su XAUUSD), un piccolo movimento avverso può portare rapidamente a un margin call o stop out.
  • Scalabilità Lenta: La crescita sarà molto lenta all'inizio a causa delle dimensioni minime degli ordini.
  • Impatto dello Spread/Commissioni: Costi fissi per operazione incidono percentualmente molto di più su un capitale piccolo.

L'EA include un controllo `AccountStartBalance` (default 50.0) e l'auto lot sizing tenta di gestire il rischio, ma si raccomanda un capitale iniziale maggiore per avere più margine di manovra e ridurre il rischio di azzeramento rapido del conto.

Come ottimizzo i parametri di questo EA?

L'ottimizzazione si fa tramite lo "Strategy Tester" (Tester Strategie) integrato in MetaTrader 4 (Visualizza -> Tester Strategie o Ctrl+R).

1. Seleziona l'EA "ScalpingXAU" (o come lo hai chiamato).

2. Scegli il simbolo (XAUUSD) e il periodo su cui testare (es. M5).

3. Seleziona un intervallo di date storico significativo.

4. Attiva la modalità "Ottimizzazione".

5. Vai su "Proprietà Expert", seleziona i parametri che vuoi ottimizzare (es. StopLossPips, TakeProfitPips, periodi indicatori, livelli RSI/Stoch, TrailingStart/StopPips) e definisci i valori di Inizio, Passo e Fine per l'ottimizzazione.

6. Imposta le opzioni di ottimizzazione (es. criterio "Max Profit Factor" o "Max Balance").

7. Avvia l'ottimizzazione. Il processo può richiedere molto tempo.

8. Analizza i risultati per trovare la combinazione di parametri che ha performato meglio storicamente, ma fai attenzione all'overfitting (ottimizzazione eccessiva sui dati passati).


Riferimenti Utili

Ricerche Consigliate

fullertonmarkets.ladesk.com
Using MT4 MAM (Multi Account Manager)
mt4-accountmanagement.com
Home - MT4 Account Management

Last updated April 26, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI