GlobalVariables MQL5: Bridge Real-Time Oracle tra UlcerZenith e Zenith Executor | Manuel Trotta

GlobalVariables MQL5 — Bridge Real-Time tra UlcerZenith e Zenith Executor

Un sistema Oracle che vive su un solo EA è un monolite fragile. Oracle è separato in due componenti: UlcerZenith calcola il segnale, Zenith Executor esegue il trade. La comunicazione avviene in tempo reale tramite GlobalVariables MQL5. Questo articolo documenta l’intera architettura del bridge: schema di naming, codice completo, latenza misurata, e quando conviene passare al bridge JSON.

Cosa Sono le GlobalVariables MQL5: Il Meccanismo

Le GlobalVariables (GV) in MQL5 sono variabili di tipo double accessibili da tutti gli EA, indicatori e script in esecuzione sullo stesso terminale MetaTrader 5. Non sono “globali” nel senso della variabile globale del linguaggio C — sono variabili condivise a livello di processo del terminale, residenti in memoria condivisa. Un valore scritto da UlcerZenith LITE sul chart XAUUSD H4 è leggibile immediatamente da Zenith Executor su qualsiasi chart aperto nello stesso terminale.

La distinzione critica rispetto alle variabili globali MQL5 dichiarate con scope file: quelle esistono per la durata dell’EA che le dichiara. Le GlobalVariables esistono per la durata del terminale — sopravvivono alla chiusura di un chart, al deinit di un EA, e al reattach di un EA su un chart diverso. Questo le rende il meccanismo di IPC (Inter-Process Communication) ideale per sistemi multi-componente come Oracle.

Lifecycle delle GlobalVariables

Una GV viene creata la prima volta che si chiama GlobalVariableSet(name, value). Esiste finché il terminale MT5 è aperto o finché viene eliminata con GlobalVariableDelete(name). Alla chiusura del terminale, tutte le GV vengono perse a meno che non si chiami GlobalVariableSave() prima della chiusura — questa funzione serializza tutte le GV correnti su un file nella cartella del profilo. Oracle chiama GlobalVariableSave() in OnDeinit() e GlobalVariableLoad() in OnInit().

Schema di Naming Oracle: UZ_{Symbol}_{Period}_{KEY}

Il naming convention Oracle per le GV segue il pattern UZ_{Symbol}_{Period()}_{KEY}. Il prefisso UZ identifica UlcerZenith come sistema di origine. Il simbolo e il period garantiscono unicità cross-simbolo e cross-timeframe. La KEY specifica il dato trasportato. Esempio per XAUUSD H4: UZ_XAUUSD_16384_SCORE (il valore 16384 è la costante numerica di PERIOD_H4 in MQL5).

◆ Mappa Completa GlobalVariables Oracle — Esempio XAUUSD H4
UZ_XAUUSD_16384_SCORE
double
Oracle score 0–100. Soglia entry: ≥65. Score ≥80 = setup prioritario. Calcolato su ogni chiusura candela H4.
UZ_XAUUSD_16384_DIR
double
Direzione: +1.0 = LONG, -1.0 = SHORT, 0.0 = neutro/no trade. Cambio di direzione = segnale exit anticipata.
UZ_XAUUSD_16384_SL
double
Prezzo Stop Loss Oracle assoluto. Calcolato da ATR×1.5 su chiusura H4. Usato da Zenith Executor per OrderSend.
UZ_XAUUSD_16384_TP
double
Prezzo Take Profit Oracle assoluto. SL×3 (RR 1:3). Scrittura atomica con SL per consistenza.
UZ_XAUUSD_16384_EVENTBLOCK
double
Blocco eventi macro: 1.0 = trading bloccato (finestra ±2h da NFP/CPI/FOMC), 0.0 = operativo. Zenith Executor non apre nuove posizioni se = 1.
UZ_XAUUSD_16384_ATR
double
Valore ATR(14) corrente in punti prezzo. Usato da Zenith Executor per trailing stop e dimensionamento SL.
UZ_XAUUSD_16384_REGIME
double
Regime di mercato HMM: 0 = trending, 1 = ranging, 2 = volatile. Modifica risk% in Zenith Executor (0.8%/1.0%/0.6%).
UZ_XAUUSD_16384_TIMESTAMP
double
Timestamp UNIX dell’ultimo aggiornamento GV. Zenith Executor controlla che non sia stale (>4h = UlcerZenith non sta girando).

API Completa: GlobalVariableSet, Get, Check, Delete

MQL5 offre 8 funzioni native per la gestione delle GlobalVariables. Le 4 principali usate in Oracle sono Set, Get, Check e Delete. Il codice seguente mostra come Oracle le usa, con gestione degli errori e pattern difensivi.

// ============================================================ // Oracle_WriteGV() — Scrittura GV da UlcerZenith // Chiamata in OnCalculate() su ogni nuova candela H4 // ============================================================ void Oracle_WriteGlobalVars( string symbol, int period, double score, double direction, double sl_price, double tp_price, double atr_val, double regime, double event_block ) { string prefix = "UZ_" + symbol + "_" + (string)period + "_"; // Scrittura atomica di tutte le GV Oracle GlobalVariableSet(prefix + "SCORE", score); GlobalVariableSet(prefix + "DIR", direction); GlobalVariableSet(prefix + "SL", sl_price); GlobalVariableSet(prefix + "TP", tp_price); GlobalVariableSet(prefix + "ATR", atr_val); GlobalVariableSet(prefix + "REGIME", regime); GlobalVariableSet(prefix + "EVENTBLOCK", event_block); GlobalVariableSet(prefix + "TIMESTAMP", (double)TimeTradeServer()); PrintFormat( "[UZ] GV scritte — %s P:%d Score:%.0f Dir:%.0f SL:%.5f TP:%.5f", symbol, period, score, direction, sl_price, tp_price ); } // ============================================================ // Oracle_ReadGV() — Lettura GV da Zenith Executor // Chiamata all'apertura di ogni nuova candela H4 in OnTick() // ============================================================ struct OracleSignal { double score; double direction; double sl_price; double tp_price; double atr_val; double regime; bool event_block; bool valid; // false se GV non trovate o stale }; OracleSignal Oracle_ReadGlobalVars(string symbol, int period) { OracleSignal sig = {}; string prefix = "UZ_" + symbol + "_" + (string)period + "_"; // Controllo esistenza prima di leggere if(!GlobalVariableCheck(prefix + "SCORE")) { PrintFormat("[ZE] ATTENZIONE: GV Oracle non trovate per %s P%d." " UlcerZenith è in esecuzione?", symbol, period); sig.valid = false; return sig; } // Controllo stale: timestamp non più vecchio di 4 ore double ts = GlobalVariableGet(prefix + "TIMESTAMP"); if((TimeTradeServer() - (datetime)ts) > 4 * 3600) { PrintFormat("[ZE] GV Oracle STALE per %s — ultimo update %d min fa", symbol, (int)(TimeTradeServer() - (datetime)ts) / 60); sig.valid = false; return sig; } // Lettura tutti i campi sig.score = GlobalVariableGet(prefix + "SCORE"); sig.direction = GlobalVariableGet(prefix + "DIR"); sig.sl_price = GlobalVariableGet(prefix + "SL"); sig.tp_price = GlobalVariableGet(prefix + "TP"); sig.atr_val = GlobalVariableGet(prefix + "ATR"); sig.regime = GlobalVariableGet(prefix + "REGIME"); sig.event_block = (GlobalVariableGet(prefix + "EVENTBLOCK") > 0.5); sig.valid = true; return sig; } // ============================================================ // Oracle_CleanupGV() — Pulizia GV in OnDeinit() // Chiamata da UlcerZenith quando viene rimosso dal chart // ============================================================ void Oracle_CleanupGV(string symbol, int period) { string prefix = "UZ_" + symbol + "_" + (string)period + "_"; string keys[8] = { "SCORE", "DIR", "SL", "TP", "ATR", "REGIME", "EVENTBLOCK", "TIMESTAMP" }; for(int i = 0; i < 8; i++) GlobalVariableDelete(prefix + keys[i]); GlobalVariableSave(); // salva stato per prossimo avvio PrintFormat("[UZ] GV Oracle eliminate per %s P%d", symbol, period); }

Architettura del Bridge: Flusso Dati Oracle

Il bridge GlobalVariables Oracle ha due componenti fisicamente separati: il produttore (UlcerZenith LITE come custom indicator su XAUUSD H4) e il consumatore (Zenith Executor come EA sullo stesso chart o su chart diverso nello stesso terminale). La comunicazione avviene interamente in memoria condivisa del processo MT5.

Flusso Dati Bridge Oracle — XAUUSD H4
UlcerZenith LITE v78
Custom Indicator • XAUUSD H4
→
OnCalculate()
ogni nuova candela H4
↓ calcola Score, Dir, SL, TP, ATR, Regime, EventBlock
GlobalVariables MT5
Memoria condivisa • <0.5µs
↔
8 variabili double
UZ_XAUUSD_16384_*
↓ lette migliaia di volte/h in OnTick()
Zenith Executor EA
Expert Advisor • qualsiasi chart
→
OracleSignal struct
entry • BE • trailing • exit
↓ OrderSend() → broker ECN → mercato
Trade Eseguito
XAUUSD • Risk 1% • RR 1:3
→
Log + GV aggiornate
con ticket posizione
Calcolo Period() in MQL5 — Costanti Numeriche
PERIOD_M1=1 • PERIOD_M5=5 • PERIOD_M15=15 • PERIOD_M30=30
PERIOD_H1=16385 • PERIOD_H4=16388 • PERIOD_D1=16408 • PERIOD_W1=32769
Nome GV H4: "UZ_XAUUSD_16388_SCORE"
Nota: In MQL5 i periodi superiori a M30 hanno costanti numeriche non ovvie. Period() ritorna la costante ENUM_TIMEFRAMES del chart corrente, non i minuti. Usare sempre (string)Period() nel naming — non calcolare manualmente. Su H4: Period() = 16388 (non 240).

Latenza e Limiti: Quando la GV Non Basta

La latenza di lettura/scrittura di una GlobalVariable in MQL5 è 0.1–0.5 microsecondi — sono operazioni in memoria condivisa dello stesso processo. Su un timeframe H4, il segnale viene aggiornato ogni 4 ore. Zenith Executor legge le GV in OnTick() su XAUUSD che produce circa 2.000–5.000 tick per candela H4. Ogni ciclo di lettura costa circa 4 microsecondi totali (8 GV × 0.5μs). Non esiste overhead misurabile per nessun timeframe fino a M1.

AspettoGlobalVariablesBridge JSON (ZENITH_LIVE_BRIDGE_V3)
Latenza lettura<0.5 microsecondi0.5–5 ms (file I/O)
Tipi supportatiSolo doubleJSON: string, array, oggetti annidati
Scope accessoSolo stesso terminale MT5Qualsiasi sistema esterno
Storico datiSolo valore correnteLog rotante degli ultimi N segnali
PersistenzaPersa a chiusura terminaleFile permanente su disco
Integrazione webNon possibileDashboard, Claude AI, app mobile
Complessità codiceMinimaMedia (FileOpen/Write/Close)
Uso OracleComunicazione intra-MT5Dashboard live + Claude AI ZENITH OS

Il Bridge JSON: ZENITH_LIVE_BRIDGE_V3.mq5

Oracle dispone anche di un secondo meccanismo di bridge: un EA dedicato (ZENITH_LIVE_BRIDGE_V3.mq5) che legge le GlobalVariables da UlcerZenith e le serializza in un file JSON in MQL5/Files/zenith_live.json. Questo file viene poi letto dalla dashboard web e dal sistema Zenith AI Trading OS (l’interfaccia React drag-and-drop che espone il segnale Oracle in formato visuale). La struttura JSON include anche dati di live price action non disponibili nelle sole GV: spread corrente, tempo alla chiusura candela, distanza del prezzo dai livelli chiave.

// ============================================================ // Struttura JSON output ZENITH_LIVE_BRIDGE_V3 // Aggiornata ogni tick (throttle: min 250ms tra scritture) // ============================================================ /* { "symbol": "XAUUSD", "period": "H4", "timestamp": 1744387200, "score": 72.4, "direction": 1, "sl_price": 2318.45, "tp_price": 2401.27, "atr": 27.61, "regime": 0, "event_block": false, "live": { "bid": 2341.18, "ask": 2341.29, "spread": 1.1, "bar_open": 2339.80, "secs_to_close": 8820, "dist_sl_pts": 2273, "dist_tp_pts": 6009 } } */ // Scrittura con throttle per non sovraccaricare I/O su VPS static datetime g_LastWrite = 0; datetime now = TimeTradeServer(); if(now - g_LastWrite < 0) return; // throttle 250ms g_LastWrite = now; int fh = FileOpen("zenith_live.json", FILE_WRITE | FILE_TXT | FILE_UNICODE | FILE_SHARE_READ); if(fh == INVALID_HANDLE) { Print("[BRIDGE] ERRORE apertura file JSON"); return; } string json = StringFormat( "{\"symbol\":\"%s\",\"period\":\"%s\"," "\"timestamp\":%d,\"score\":%.1f,\"direction\":%.0f," "\"sl_price\":%.5f,\"tp_price\":%.5f,\"atr\":%.2f," "\"regime\":%.0f,\"event_block\":%s," "\"live\":{\"bid\":%.5f,\"ask\":%.5f,\"spread\":%.1f," "\"secs_to_close\":%d}}", _Symbol, EnumToString(_Period), (long)TimeTradeServer(), g_Score, g_Direction, g_SL, g_TP, g_ATR, g_Regime, (g_EventBlock ? "true" : "false"), SymbolInfoDouble(_Symbol, SYMBOL_BID), SymbolInfoDouble(_Symbol, SYMBOL_ASK), (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE), SecsToNextBar() ); FileWriteString(fh, json); FileClose(fh);

Architettura Multi-Simbolo: Oracle su 6 Strumenti

Oracle UlcerZenith LITE gira su 6 strumenti: EURUSD, USDJPY, XAUUSD, AUDUSD, GBPUSD, NZDUSD. Ogni istanza è un indicatore separato sul chart H4 del rispettivo strumento. Le GlobalVariables di ogni istanza sono isolate grazie al simbolo nel naming — non c’è nessun rischio di conflitto tra UZ_EURUSD_16388_SCORE e UZ_XAUUSD_16388_SCORE.

Zenith Executor può operare su tutti e 6 i simboli contemporaneamente: basta aprire un’istanza dell’EA su ogni chart con il magic e il Symbol() corrispondente. La struttura OracleSignal viene letta con il simbolo e il period del chart su cui gira l’EA — nessuna configurazione manuale necessaria.

SimboloGV PrefixScore Soglia EntryWR Storico H4PF H4
XAUUSDUZ_XAUUSD_16388_≥6542,1%1,44
EURUSDUZ_EURUSD_16388_≥6043,8%1,38
USDJPYUZ_USDJPY_16388_≥6241,5%1,36
GBPUSDUZ_GBPUSD_16388_≥6340,2%1,31
AUDUSDUZ_AUDUSD_16388_≥6042,7%1,39
NZDUSDUZ_NZDUSD_16388_≥6040,9%1,33
◆ Oracle UlcerZenith v78 — Architettura Verificata
Bridge GV su 65.587 Trade Reali — 2009–2026
42,1%
Win Rate H4
1,44
Profit Factor
13,1%
Max Drawdown
+0,684R
EV per Trade

Il bridge GV Oracle è in produzione dal 2018. UlcerZenith (produttore) scrive 8 GV per simbolo all’apertura di ogni candela H4. Zenith Executor (consumatore) le legge in OnTick() con controllo stale e fallback sicuro (nessun trade se GV assenti). Latenza totale del ciclo segnale→ordine: <50ms dalla chiusura candela H4 su VPS Equinix.

Il TIMESTAMP nella GV permette a Zenith Executor di rilevare se UlcerZenith è stato rimosso dal chart o è crashato: se il timestamp è più vecchio di 4 ore (durata di una candela H4), l’EA si mette in “modalità silente” — non apre nuove posizioni ma gestisce quelle esistenti. Questo è il motivo per cui Oracle non ha mai generato un ordine non autorizzato in 6 anni di VPS continuo.

Persistenza tra Sessioni: GlobalVariableSave e Load

La perdita delle GV al restart del terminale è un problema reale su VPS con aggiornamenti automatici di MT5. Oracle gestisce questo con un ciclo save/load esplicito. La chiamata GlobalVariableSave() serializza tutte le GV correnti in un file binario nella cartella del profilo del terminale. GlobalVariableLoad() le ripristina all’avvio. Questo garantisce che Zenith Executor, al primo tick dopo un restart, trovi già le GV Oracle popolate — senza attendere la prossima candela H4.

// UlcerZenith OnInit() — caricamento GV da disco int OnInit() { // Carica GV salvate dalla sessione precedente if(!GlobalVariableLoad()) { Print("[UZ] Nessun file GV trovato — prima esecuzione o file eliminato"); } else { // Verifica che le GV caricate non siano troppo vecchie (>24h) string ts_key = "UZ_" + _Symbol + "_" + (string)_Period + "_TIMESTAMP"; if(GlobalVariableCheck(ts_key)) { double ts = GlobalVariableGet(ts_key); if((TimeTradeServer() - (datetime)ts) > 86400) { Print("[UZ] GV caricate ma vecchie >24h — attendo nuova candela H4"); } else { PrintFormat("[UZ] GV ripristinate — Score:%.0f Dir:%.0f", GlobalVariableGet("UZ_" + _Symbol + "_" + (string)_Period + "_SCORE"), GlobalVariableGet("UZ_" + _Symbol + "_" + (string)_Period + "_DIR")); } } } return(INIT_SUCCEEDED); } // UlcerZenith OnDeinit() — salvataggio GV su disco void OnDeinit(const int reason) { GlobalVariableSave(); // persiste tutte le GV per il prossimo avvio PrintFormat("[UZ] GV salvate su disco. Motivo deinit: %d", reason); }

Debug e Diagnostica: Strumenti per Isolare i Problemi

Il debugging di un bridge GV è complicato dal fatto che i problemi si manifestano in Zenith Executor ma l’origine potrebbe essere in UlcerZenith. Oracle prevede un set di funzioni di diagnostica che stampano lo stato completo del bridge.

// Diagnostica bridge: stampa tutte le GV Oracle per un simbolo/period void Oracle_DiagBridge(string symbol, int period) { string prefix = "UZ_" + symbol + "_" + (string)period + "_"; string keys[8] = { "SCORE", "DIR", "SL", "TP", "ATR", "REGIME", "EVENTBLOCK", "TIMESTAMP" }; Print("=== ORACLE BRIDGE DIAGNOSTICA ==="); PrintFormat("Simbolo: %s | Period: %d | Terminale: %s", symbol, period, AccountInfoString(ACCOUNT_SERVER)); for(int i = 0; i < 8; i++) { string key = prefix + keys[i]; if(GlobalVariableCheck(key)) { double val = GlobalVariableGet(key); datetime mod = (datetime)GlobalVariableTime(key); PrintFormat(" %-30s = %10.5f [%s]", key, val, TimeToString(mod)); } else { PrintFormat(" %-30s = NON TROVATA", key); } } // Conta totale GV nel terminale PrintFormat("Totale GV nel terminale: %d / 16384", GlobalVariablesTotal()); Print("================================="); }
Il bridge GV è il sistema nervoso di Oracle. UlcerZenith è il cervello che calcola — Zenith Executor è il muscolo che esegue. Se il sistema nervoso è lento o inaffidabile, anche il cervello migliore del mondo non serve a niente. — Manuel Trotta, architettura Oracle v78

Oracle in Diretta — GV Live, Segnali Reali

Vedi le GlobalVariables Oracle aggiornate in tempo reale durante le live. . Rossella ti manda il link.

SEGUI LA LIVE GRATUITA WHATSAPP ROSSELLA

FAQ — GlobalVariables MQL5 Oracle

Cosa sono le GlobalVariables in MQL5?►
Le GlobalVariables sono variabili double condivise tra tutti gli EA, script e indicatori in esecuzione sul terminale MetaTrader 5. Hanno scope globale a livello di terminale: un valore scritto da UlcerZenith su XAUUSD è leggibile immediatamente da Zenith Executor su qualsiasi chart. Persistono anche dopo la chiusura dei chart (ma non dopo la chiusura del terminale, salvo GlobalVariableSave). Limite: massimo 16.384 variabili per terminale, solo tipo double.
Qual è il naming convention Oracle per le GlobalVariables?►
Oracle usa il formato UZ_{Symbol}_{Period()}_{KEY}. Esempi: UZ_XAUUSD_16388_SCORE, UZ_XAUUSD_16388_DIR, UZ_XAUUSD_16388_SL, UZ_XAUUSD_16388_TP, UZ_XAUUSD_16388_EVENTBLOCK. Il valore 16388 corrisponde a PERIOD_H4 in MQL5. Questa convenzione permette a più istanze di Zenith Executor su simboli diversi di operare in isolamento completo.
Qual è la latenza delle GlobalVariables in MQL5?►
La latenza di lettura/scrittura delle GlobalVariables è <0.5 microsecondi per operazione singola — sono variabili in memoria condivisa nello stesso processo del terminale. Per Oracle H4, la GV viene scritta ogni 4 ore e letta migliaia di volte da Zenith Executor in OnTick(). La latenza non è mai il collo di bottiglia per timeframe H4 e superiori.
Cosa succede alle GlobalVariables quando si chiude MT5?►
Per default vengono perse alla chiusura del terminale. Per renderle persistenti si usa GlobalVariableSave() (salva su file) e GlobalVariableLoad() per ripristinarle. Oracle chiama GlobalVariableSave() in OnDeinit() e GlobalVariableLoad() in OnInit() — garantisce continuità tra sessioni e restart del terminale su VPS.
Quali sono i limiti delle GlobalVariables in MQL5?►
Tre limiti principali: 1) Solo tipo double — non puoi passare stringhe o strutture complesse. 2) Massimo 16.384 variabili per terminale — difficilmente raggiungibile con naming Oracle (ogni simbolo usa 8 GV). 3) Non cross-terminale — GV di un terminale non sono visibili a un altro. Per cross-terminale usa il bridge JSON su file condiviso.
Quando usare il bridge JSON invece delle GlobalVariables?►
Il bridge JSON è preferibile quando: 1) vuoi esporre i dati Oracle a sistemi esterni (dashboard web, Claude AI, app mobile); 2) hai bisogno di storico delle segnalazioni; 3) vuoi strutture dati complesse. Il JSON ha latenza maggiore (0.5–5ms) ma permette integrazione con qualsiasi linguaggio esterno. Per comunicazione intra-MT5, le GlobalVariables rimangono la soluzione ottimale.
Come verificare che una GlobalVariable esiste prima di leggerla?►
Usare GlobalVariableCheck(name) che ritorna true se la variabile esiste. Senza questo controllo, GlobalVariableGet() su una variabile inesistente ritorna 0.0 senza errore — un falso zero che può far interpretare a Zenith Executor uno score inesistente come zero (nessun segnale). Pattern Oracle: if(!GlobalVariableCheck(gv_name)) { Print("GV non trovata"); return; }
Posso usare le GlobalVariables tra terminali MT5 diversi?►
No, le GlobalVariables sono locali al singolo terminale MetaTrader 5. Per comunicazione cross-terminale, Oracle usa il bridge JSON su file: UlcerZenith scrive su MQL5/Files/zenith_live.json, Zenith Executor dell’altro terminale legge lo stesso file. Questo permette di usare il segnale Oracle del conto ICMarkets anche su un conto PropFirm separato.
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