iCustom in MQL5: Chiamare Indicatori Esterni dagli EA — Guida Completa | Manuel Trotta

iCustom in MQL5:
Chiamare Indicatori Esterni
da EA e Indicatori — Guida Completa

iCustom è la funzione MQL5 che permette a un Expert Advisor o a un indicatore di leggere i valori di qualsiasi altro indicatore custom. È il meccanismo che permette a Oracle v78 di leggere UlcerZenith, il suo indicatore proprietario, dall’interno dell’EA Executor. Questa guida copre la sintassi completa, la gestione degli handle, CopyBuffer con tutti i suoi parametri, i 10 errori più comuni e i pattern architetturali usati in produzione su 65.587 trade reali.

1. Architettura Handle-Based: il Modello Corretto in MQL5

In MQL4 esisteva la funzione iCustom() che restituiva direttamente il valore del buffer dell’indicatore. In MQL5 il modello è diverso e più efficiente: prima ottieni un handle (un intero che rappresenta l’istanza dell’indicatore), poi usi CopyBuffer() per leggere i dati da quel handle.

Il vantaggio di questo modello è che l’indicatore viene calcolato una sola volta anche se viene referenziato da più EA o indicatori contemporaneamente — MetaTrader gestisce la cache dei risultati internamente. Il handle è un intero ≥ 0; il valore INVALID_HANDLE (-1) indica che la creazione dell’handle è fallita.

Modello handle-based — schema generale
// SCHEMA GENERALE (da implementare sempre così)

// 1. Dichiarazione globale dell'handle
int handleMioIndicatore = INVALID_HANDLE;

// 2. Creazione dell'handle in OnInit()
int OnInit()
{
    handleMioIndicatore = iCustom(_Symbol, PERIOD_H4, "MioIndicatore");
    
    if(handleMioIndicatore == INVALID_HANDLE)
    {
        Print("ERRORE: iCustom fallito. Codice: ", GetLastError());
        return(INIT_FAILED);
    }
    
    return(INIT_SUCCEEDED);
}

// 3. Lettura del buffer con CopyBuffer in OnTick() o OnCalculate()
void OnTick()
{
    double valori[];
    ArraySetAsSeries(valori, true);
    
    if(CopyBuffer(handleMioIndicatore, 0, 0, 3, valori) <= 0)
    {
        Print("ERRORE CopyBuffer: ", GetLastError());
        return;
    }
    
    double valoreBarra0 = valori[0];  // barra corrente
    double valoreBarra1 = valori[1];  // barra precedente
    double valoreBarra2 = valori[2];  // due barre fa
}

// 4. Rilascio dell'handle in OnDeinit()
void OnDeinit(const int reason)
{
    if(handleMioIndicatore != INVALID_HANDLE)
        IndicatorRelease(handleMioIndicatore);
}

2. Sintassi Completa di iCustom

La firma di iCustom in MQL5 è più flessibile di quella di MQL4 grazie ai parametri variabili:

Firma completa di iCustom
int iCustom(
    string       symbol,     // simbolo: usa _Symbol per il corrente
    ENUM_TIMEFRAMES timeframe, // timeframe: PERIOD_H4, PERIOD_D1, etc.
    string       name,       // nome del file .ex5 SENZA l'estensione
    ...                       // parametri dell'indicatore (opzionali, variabili)
);

// ESEMPI DI CHIAMATA:

// Indicatore senza parametri aggiuntivi
int h1 = iCustom(_Symbol, PERIOD_H4, "MioIndicatore");

// Indicatore con 1 parametro intero (es. periodo)
int h2 = iCustom(_Symbol, PERIOD_H4, "UlcerIndex", 14);

// Indicatore con più parametri di tipi diversi
int h3 = iCustom(_Symbol, PERIOD_H4, "ZenithScore",
                   14,        // int: periodo UI
                   2.0,       // double: moltiplicatore ATR
                   true,      // bool: abilita filtro sessione
                   "XAUUSD"   // string: simbolo correlazione
           );

// Indicatore su simbolo diverso da quello corrente
int h4 = iCustom("EURUSD", PERIOD_H4, "MioIndicatore", 14);

// Indicatore su timeframe diverso (lettura multi-TF)
int h5 = iCustom(_Symbol, PERIOD_D1, "MioIndicatore", 14);
         // Legge l'indicatore sul Daily anche se il chart è H4
Percorso del file: il parametro name è il percorso relativo al file .ex5 nella cartella MQL5/Indicators/. Se l’indicatore è in una sottocartella: "Subfolder/MioIndicatore". Il percorso usa slash (/) o backslash (\\). Non includere l’estensione .ex5.

3. Gestione Corretta degli Handle

La gestione degli handle è il punto dove i programmatori MQL5 fanno più errori. Le regole sono semplici ma critiche:

Gestione handle — pattern produzione completo
// Pattern completo per gestione robusta degli handle
// usato in Oracle v78 per i suoi 6 handle di indicatori

// Dichiarazione globale — inizializza SEMPRE a INVALID_HANDLE
int hUlcer   = INVALID_HANDLE;
int hATR     = INVALID_HANDLE;
int hSession = INVALID_HANDLE;

int OnInit()
{
    // Crea tutti gli handle in sequenza
    hUlcer   = iCustom(_Symbol, PERIOD_H4, "UlcerZenith_v77", 14, true);
    hATR     = iATR(_Symbol, PERIOD_H4, 14);
    hSession = iCustom(_Symbol, PERIOD_H4, "SessionFilter");
    
    // Verifica TUTTI prima di procedere
    if(hUlcer == INVALID_HANDLE || hATR == INVALID_HANDLE || hSession == INVALID_HANDLE)
    {
        PrintFormat("OnInit FAILED: hUlcer=%d hATR=%d hSession=%d err=%d",
                     hUlcer, hATR, hSession, GetLastError());
        RilasciaHandles();  // rilascia quelli eventualmente validi
        return(INIT_FAILED);
    }
    
    // Attesa warm-up: aspetta che gli indicatori abbiano dati calcolati
    // Specialmente importante su simboli appena aperti o dati scarsi
    EventSetTimer(1);  // controlla ogni secondo in OnTimer()
    
    return(INIT_SUCCEEDED);
}

void RilasciaHandles()
{
    // Helper function — rilascia solo gli handle validi
    if(hUlcer   != INVALID_HANDLE) { IndicatorRelease(hUlcer);   hUlcer   = INVALID_HANDLE; }
    if(hATR     != INVALID_HANDLE) { IndicatorRelease(hATR);     hATR     = INVALID_HANDLE; }
    if(hSession != INVALID_HANDLE) { IndicatorRelease(hSession); hSession = INVALID_HANDLE; }
}

void OnDeinit(const int reason)
{
    EventKillTimer();
    RilasciaHandles();
}

// Verifica che i dati siano disponibili prima di usarli
bool DatiPronti()
{
    return(
        BarsCalculated(hUlcer)   >= 50 &&
        BarsCalculated(hATR)     >= 14 &&
        BarsCalculated(hSession) >= 1
    );
}
Errore critico: non chiamare mai IndicatorRelease su un handle INVALID_HANDLE. Causa undefined behavior. Verifica sempre con if(handle != INVALID_HANDLE) prima di rilasciare.

4. CopyBuffer: Parametri e Tutti i Casi d’Uso

CopyBuffer è la funzione che legge effettivamente i dati da un handle. Ha due forme principali: copia per conteggio (i più recenti N elementi) e copia per range temporale (tra due datetime). Entrambe restituiscono il numero di elementi copiati o -1 in caso di errore.

CopyBuffer — tutte le varianti
// VARIANTE 1: copia N elementi partendo dalla barra start_pos
// (la più usata)
int CopyBuffer(
    int    indicator_handle,  // handle dell'indicatore
    int    buffer_num,        // indice del buffer (0 = primo buffer)
    int    start_pos,         // barra da cui iniziare (0 = più recente)
    int    count,             // numero di elementi da copiare
    double& buffer[]          // array di destinazione
);

// VARIANTE 2: copia N elementi a partire da un datetime specifico
int CopyBuffer(
    int      indicator_handle,
    int      buffer_num,
    datetime start_time,    // datetime di inizio
    int      count,
    double&  buffer[]
);

// VARIANTE 3: copia tra due datetime
int CopyBuffer(
    int      indicator_handle,
    int      buffer_num,
    datetime start_time,
    datetime stop_time,
    double&  buffer[]
);

// ═══════════════════════════════════════════════════════════
// ESEMPI PRATICI
// ═══════════════════════════════════════════════════════════

double buf[];
ArraySetAsSeries(buf, true);  // indice 0 = barra più recente

// Leggi solo la barra corrente (più efficiente quando serve solo 1 valore)
double valoreSingolo[1];
CopyBuffer(hUlcer, 0, 0, 1, valoreSingolo);
// valoreSingolo[0] = valore Ulcer Index sulla barra più recente

// Leggi le ultime 3 barre (per confrontare valori recenti)
CopyBuffer(hUlcer, 0, 0, 3, buf);
// buf[0] = barra corrente, buf[1] = precedente, buf[2] = due fa

// Leggi dal secondo buffer dell'indicatore (indice 1)
double segnaleBuf[];
CopyBuffer(hUlcer, 1, 0, 3, segnaleBuf);

// Leggi le ultime 200 barre per calcolo statistico
ArrayResize(buf, 200);
int copied = CopyBuffer(hUlcer, 0, 0, 200, buf);
if(copied != 200)
    Print("Solo ", copied, " barre disponibili (richieste 200)");

// Leggi i dati dell'ultima settimana con range datetime
datetime unaSettimanaFa = TimeCurrent() - 7 * 86400;
CopyBuffer(hUlcer, 0, unaSettimanaFa, TimeCurrent(), buf);

Gestione Corretta degli Errori di CopyBuffer

Pattern completo di gestione errori CopyBuffer
// Funzione helper che gestisce tutti gli errori di CopyBuffer
bool LeggiBuffer(int handle, int bufferIdx, int count, double &out[])
{
    if(handle == INVALID_HANDLE) return(false);
    
    ArraySetAsSeries(out, true);
    int copied = CopyBuffer(handle, bufferIdx, 0, count, out);
    
    if(copied <= 0)
    {
        int err = GetLastError();
        switch(err)
        {
            case ERR_INDICATOR_DATA_NOT_FOUND:
                // I dati non sono ancora calcolati — normale all'avvio
                return(false);
            case ERR_HISTORY_NOT_FOUND:
                // Non ci sono abbastanza dati storici
                Print("Dati storici insufficienti per buffer ", bufferIdx);
                return(false);
            default:
                PrintFormat("CopyBuffer errore %d su handle %d buffer %d",
                             err, handle, bufferIdx);
                return(false);
        }
    }
    
    if(copied < count)
    {
        // Meno dati del richiesto — non necessariamente un errore
        // (es. il grafico ha meno barre di quante richieste)
        Print("CopyBuffer: ricevute ", copied, " barre su ", count, " richieste");
    }
    
    return(true);
}

5. Passaggio di Parametri all’Indicatore

I parametri passati a iCustom dopo il nome del file devono corrispondere esattamente ai parametri input dell’indicatore, nello stesso ordine e dello stesso tipo. Un errore di tipo o ordine produce un INVALID_HANDLE o, peggio, un handle valido che legge dati sbagliati in silenzio.

Passaggio parametri — corrispondenza tipi obbligatoria
// INDICATORE TARGET (UlcerZenith_v77.mq5) — parametri input:
// input int    PeriodoUI        = 14;     // periodi per il calcolo UI
// input double MoltiplicatoreATR = 2.0;  // ATR multiplier per lo stop
// input bool   FiltroSessione   = true;  // abilita filtro sessione
// input ENUM_TIMEFRAMES TFConfermta = PERIOD_D1; // TF di conferma

// CHIAMATA CORRETTA — tipi e ordine devono corrispondere esattamente
int hZenith = iCustom(_Symbol, PERIOD_H4, "UlcerZenith_v77",
    (int)    14,           // ✓ int → int
    (double) 2.0,          // ✓ double → double
    (bool)   true,         // ✓ bool → bool
    (int)    PERIOD_D1     // ✓ int (enum) → ENUM_TIMEFRAMES
);

// ERRORI COMUNI:

// ✗ Passare 14 (int) dove si aspetta double
int hErrato1 = iCustom(_Symbol, PERIOD_H4, "UlcerZenith_v77",
    14,     // OK (int literal)
    2,      // ✗ int literal dove serve double → dati SBAGLIATI in silenzio!
    true,
    PERIOD_D1
);
// Fix: usa 2.0 (double literal) o (double)2

// ✗ Saltare un parametro
int hErrato2 = iCustom(_Symbol, PERIOD_H4, "UlcerZenith_v77",
    14, 2.0  // ✗ mancano filtroSessione e TFConferma
             // usa i default dell'indicatore — ma potrebbe produrre
             // INVALID_HANDLE se i tipi successivi non corrispondono
);
// Fix: passa TUTTI i parametri o usa i default espliciti

// ✓ Uso di variabili parametrizzate (pattern EA con input)
input int    InpPeriodoUI        = 14;
input double InpMoltiplicatoreATR = 2.0;
input bool   InpFiltroSessione   = true;

int hCorretto = iCustom(_Symbol, PERIOD_H4, "UlcerZenith_v77",
    InpPeriodoUI, InpMoltiplicatoreATR, InpFiltroSessione, PERIOD_D1
);

6. Leggere Indicatori Multi-Buffer

Un indicatore può esporre più buffer. Ad esempio, UlcerZenith espone 8 buffer: lo score 0-10, il segnale direzionale, il livello di ingresso proposto, le tre bande T-Student e due buffer ausiliari. Ogni buffer ha un indice numerico (0, 1, 2 ...) che corrisponde all’ordine in cui è stato registrato con SetIndexBuffer nell’indicatore.

Lettura multi-buffer — struttura per Oracle v78
// Struttura per raccogliere tutti i valori di UlcerZenith in una barra
struct ZenithData
{
    double score;       // buffer 0: score 0-10
    double direzione;   // buffer 1: +1 long, -1 short, 0 neutro
    double entryLevel;  // buffer 2: livello prezzo suggerito per entry
    double band68;      // buffer 3: banda T-Student al 68%
    double band95;      // buffer 4: banda T-Student al 95%
    double band99;      // buffer 5: banda T-Student al 99%
    double ulcerRaw;    // buffer 6: valore grezzo Ulcer Index
    double atrAdattivo; // buffer 7: ATR adattivo corrente
};

bool LeggiZenith(ZenithData &dati, int barra = 0)
{
    double tmp[1];
    
    // Leggi ogni buffer separatamente (approccio più sicuro)
    if(CopyBuffer(hZenith, 0, barra, 1, tmp) <= 0) return(false);
    dati.score = tmp[0];
    
    if(CopyBuffer(hZenith, 1, barra, 1, tmp) <= 0) return(false);
    dati.direzione = tmp[0];
    
    if(CopyBuffer(hZenith, 2, barra, 1, tmp) <= 0) return(false);
    dati.entryLevel = tmp[0];
    
    if(CopyBuffer(hZenith, 3, barra, 1, tmp) <= 0) return(false);
    dati.band68 = tmp[0];
    
    if(CopyBuffer(hZenith, 4, barra, 1, tmp) <= 0) return(false);
    dati.band95 = tmp[0];
    
    if(CopyBuffer(hZenith, 5, barra, 1, tmp) <= 0) return(false);
    dati.band99 = tmp[0];
    
    if(CopyBuffer(hZenith, 6, barra, 1, tmp) <= 0) return(false);
    dati.ulcerRaw = tmp[0];
    
    if(CopyBuffer(hZenith, 7, barra, 1, tmp) <= 0) return(false);
    dati.atrAdattivo = tmp[0];
    
    return(true);
}

// Uso in OnTick
ZenithData zenith;
if(!LeggiZenith(zenith))
{
    Print("Dati Zenith non disponibili");
    return;
}

PrintFormat("Score: %.2f | Dir: %+.0f | Entry: %.5f | Band95: %.5f",
             zenith.score, zenith.direzione, zenith.entryLevel, zenith.band95);

7. I 10 Errori Più Comuni con iCustom

#ErroreCausaFix
1INVALID_HANDLE al primo avvioIl file .ex5 non esiste o è in una sottocartella sbagliataControlla il percorso esatto in MQL5/Indicators/
2CopyBuffer restituisce 0L’indicatore non ha ancora calcolato abbastanza barre (warm-up)Aggiungi BarsCalculated(handle) >= N come guard clause
3Parametri integer passati come doubleLiteral 2 invece di 2.0 per parametro doubleUsa sempre literals tipizzati o cast espliciti
4Buffer 0 legge dati del buffer 1Ordine buffer diverso dal previstoConta i buffer con SetIndexBuffer nell’indicatore sorgente
5Memory leakIndicatorRelease non chiamato in OnDeinitImplementa sempre RilasciaHandles() in OnDeinit
6Race condition su nuova barraLeggi buffer prima che la nuova barra sia calcolataUsa buf[1] (barra chiusa) invece di buf[0] (barra aperta)
7Simbolo errato su chart diversoUsi _Symbol ma l’EA gira su chart EURUSD e vuoi XAUUSDPassa il simbolo esplicito come stringa invece di _Symbol
8Timeframe erratoiCustom con PERIOD_H4 su chart M15: legge H4, non M15Usa _Period per il timeframe corrente del chart
9EMPTY_VALUE nei calcoliBuffer restituisce EMPTY_VALUE (2147483647.0) per barre senza datiAggiungi if(buf[0] == EMPTY_VALUE) return;
10Handle duplicatiOnInit chiamato più volte senza rilasciare il vecchio handleChiama RilasciaHandles() all’inizio di OnInit prima di ricreare

8. Performance e Ottimizzazione

In un EA che gira su ogni tick, la lettura dei buffer degli indicatori deve essere efficiente. Alcune regole pratiche:

  • Leggi solo su nuova barra, non su ogni tick: l’indicatore H4 cambia solo ogni 4 ore — non serve leggerlo su ogni tick. Usa il pattern static datetime ultimaBarra = 0 e aggiorna solo quando iTime(_Symbol, _Period, 0) != ultimaBarra.
  • Copia il minimo di barre necessario: se ti serve solo il valore corrente, copia 1 barra. Se ti serve il confronto tra corrente e precedente, copia 2. Evita di copiare 200 barre se ne usi 3.
  • Riusa gli array preallocati: dichiara gli array di destinazione come variabili globali o statiche — evita la riallocazione ad ogni tick.
Ottimizzazione — lettura su nuova barra con buffer statico
// Pattern ottimizzato: leggi solo su nuova barra
static datetime ultimaBarra = 0;
static double   zenithScore  = 0.0;   // cache del valore

void OnTick()
{
    datetime barraCorrT = iTime(_Symbol, PERIOD_H4, 0);
    if(barraCorrT == ultimaBarra) return;  // stessa barra, esci subito
    ultimaBarra = barraCorrT;
    
    // Nuova barra H4: leggi i buffer
    double buf[2];
    ArraySetAsSeries(buf, true);
    if(CopyBuffer(hZenith, 0, 1, 2, buf) < 2) return; // legge barre chiuse
    
    // Nota: start_pos=1 per leggere barra 1 e barra 2 (entrambe chiuse)
    // Evita la barra 0 che è ancora aperta e potrebbe avere dati parziali
    zenithScore = buf[0];   // barra 1 (chiusa più recente)
    
    // Processa il segnale...
    if(zenithScore >= 7.0) ConsideraSegnaleLong();
    else if(zenithScore <= 3.0) ConsideraSegnaleShort();
}

9. Caso Reale: Come Oracle v78 Usa iCustom

Oracle v78 è composto da due file MQL5 distinti: l’indicatore UlcerZenith_v77.ex5 (che calcola lo score e i buffer statistici) e l’EA ZenithExecutor.ex5 (che legge i buffer dell’indicatore e gestisce le operazioni). Questa architettura permette di aggiornare i due componenti indipendentemente e di usare l’indicatore anche senza l’EA per il solo monitoraggio visivo.

Oracle v78 — architettura iCustom in ZenithExecutor
// ZenithExecutor.mq5 — sezione rilevante per iCustom
// (semplificata per illustrare il pattern)

input string InpNomeIndicatore = "MTInvestments\\UlcerZenith_v77";
input int    InpPeriodoUI       = 14;
input double InpScoreMinLong    = 7.0;
input double InpScoreMaxShort   = 3.0;

int hZenith = INVALID_HANDLE;

int OnInit()
{
    // Crea handle con parametri identici a quelli dell'indicatore sul chart
    hZenith = iCustom(_Symbol, PERIOD_H4, InpNomeIndicatore,
                      InpPeriodoUI,   // parametro 1: periodo
                      2.0,            // parametro 2: moltiplicatore ATR
                      true,           // parametro 3: filtro sessione
                      PERIOD_D1       // parametro 4: TF conferma
    );
    
    if(hZenith == INVALID_HANDLE)
    {
        Alert("Errore creazione handle UlcerZenith. File presente in Indicators?");
        return(INIT_FAILED);
    }
    
    // Attendi che l'indicatore abbia almeno 50 barre calcolate
    int tentativi = 0;
    while(BarsCalculated(hZenith) < 50 && tentativi < 100)
    {
        Sleep(100);  // aspetta 100ms
        tentativi++;
    }
    
    if(BarsCalculated(hZenith) < 50)
    {
        Print("UlcerZenith non ha dati sufficienti dopo warm-up");
        return(INIT_FAILED);
    }
    
    Print("ZenithExecutor inizializzato. Handle: ", hZenith,
          " Barre calcolate: ", BarsCalculated(hZenith));
    return(INIT_SUCCEEDED);
}

10. Debug e Troubleshooting

Quando iCustom non funziona come atteso, il debug sistematico risolve il 95% dei problemi:

Script di diagnostica iCustom
// Script MQL5 per diagnosticare problemi con iCustom
// Incolla in uno script e premi F5 per eseguire

void OnStart()
{
    string nomeIndicatore = "MTInvestments\\UlcerZenith_v77";
    
    // Test 1: il file esiste?
    Print("=== Test iCustom Diagnostica ===");
    
    int h = iCustom(_Symbol, PERIOD_H4, nomeIndicatore, 14, 2.0, true, PERIOD_D1);
    PrintFormat("Handle: %d (INVALID=%d)", h, INVALID_HANDLE);
    
    if(h == INVALID_HANDLE)
    {
        PrintFormat("FALLITO. Errore: %d. Verifica:", GetLastError());
        Print("1. File esiste in MQL5/Indicators/", nomeIndicatore, ".ex5?");
        Print("2. Il file è compilato (verde in Navigator)?");
        Print("3. I parametri corrispondono in tipo e ordine?");
        return;
    }
    
    // Test 2: quante barre calcolate?
    Sleep(2000);  // aspetta 2 secondi per il calcolo
    int barre = BarsCalculated(h);
    PrintFormat("Barre calcolate: %d", barre);
    
    // Test 3: leggi i primi 3 valori di ogni buffer
    for(int buf = 0; buf < 8; buf++)
    {
        double vals[3];
        int copied = CopyBuffer(h, buf, 0, 3, vals);
        if(copied <= 0)
            PrintFormat("Buffer %d: ERRORE (copied=%d err=%d)", buf, copied, GetLastError());
        else
            PrintFormat("Buffer %d: [%.4f, %.4f, %.4f]", buf, vals[0], vals[1], vals[2]);
    }
    
    IndicatorRelease(h);
    Print("=== Fine diagnostica ===");
}

⚡ Oracle v78 — Architettura iCustom in Produzione

2
File MQL5 separati
8
Buffer letti via iCustom
65.587
Trade reali MT5
42,1%
Win Rate H4
Oracle v78 usa l’architettura iCustom in produzione 24/7 su VPS. L’indicatore UlcerZenith calcola score, bande T-Student e livelli di ingresso. L’EA Executor legge i buffer via iCustom e gestisce le operazioni autonomamente. I 65.587 trade verificabili sono tutti generati da questa architettura. P.IVA 14349331000.
⚡ MQL5 in produzione — 65.587 trade verificabili

Vuoi Vedere iCustom in Azione
su Oracle v78 dal Vivo?

Oracle v78 usa iCustom per leggere 8 buffer di UlcerZenith in ogni nuova barra H4. Per la prossima live gratuita scrivi a Rossella. Vedi il codice in produzione, ordini reali. Nessun costo.

ENTRA NELLA LIVE GRATUITA →

WhatsApp Rossella

FAQ — iCustom MQL5

Qual è la differenza tra iCustom in MQL4 e MQL5? ▼
In MQL4, iCustom restituisce direttamente il valore scalare del buffer. In MQL5, iCustom restituisce un handle intero e i valori si leggono con CopyBuffer. Il modello MQL5 è più efficiente perché l’indicatore viene calcolato una sola volta e i risultati sono in cache — più EA e indicatori possono leggere lo stesso handle senza ricalcolo.
Perché iCustom restituisce INVALID_HANDLE? ▼
Le cause più comuni: (1) il file .ex5 non esiste nel percorso specificato — controlla in MQL5/Indicators/ con l’esatto percorso includendo sottocartelle; (2) il file non è compilato — verificalo nel Navigator di MetaEditor; (3) i parametri passati non corrispondono ai parametri input dell’indicatore per tipo o ordine; (4) il simbolo o timeframe specificato non è disponibile. Usa GetLastError() subito dopo la chiamata per il codice di errore preciso.
Come capisco l’indice del buffer che mi interessa? ▼
Il codice sorgente dell’indicatore (.mq5) elenca tutte le chiamate a SetIndexBuffer(N, buffer, tipo). L’indice N è l’indice del buffer che passerai a CopyBuffer. Se non hai il sorgente, puoi dedurre il numero di buffer dal numero di plot visibili nel grafico + i buffer nascosti. Un approccio pratico: leggi da buffer 0 a 7 con lo script di diagnostica incluso in questo articolo e analizza i valori restituiti.
Manuel Trotta — Trader quantitativo, fondatore MTInvestments, autore Hoepli
◆ Scritto da

Manuel Trotta

Trader quantitativo italiano dal novembre 2007 — 19 anni online. Fondatore MTInvestments, creatore UlcerZenith Oracle v78 con 65.587 trade reali verificati H4 XAUUSD. Autore di 18 libri sul trading e finanza personale: "Fare Trading con Excel" (Hoepli 2019), "Diventa Investitore Profittevole in 15 Minuti al Giorno", "Il Latte con la Mucca" (memoir 2026), più 2 volumi tecnici. Speaker IT Forum Rimini. Online dal 2007 — stesso nome, stessa P.IVA.

P.IVA 14349331000 Dal Novembre 2007 18 Libri su Amazon ↗ 150K+ Follower