Dashboard MT5 in MQL5 — Costruire un'Interfaccia Professionale | MTInvestments

Dashboard MT5 in MQL5 —
Interfaccia
Professionale

La dashboard di Oracle v78 è costruita con centinaia di oggetti grafici MQL5 — rettangoli, testi, badge colorati, pulsanti interattivi — posizionati con coordinate pixel precise. Questa guida insegna come si costruisce da zero una UI professionale su MetaTrader 5, con il codice reale estratto da Oracle come riferimento.

Il Risultato — La Dashboard Oracle su MT5

Prima del codice, vediamo cosa costruiamo. Questa è la struttura della dashboard Oracle — simulata in HTML per illustrare la gerarchia degli elementi che si costruiscono con ObjectCreate in MQL5:

⚡ UlcerZenith Oracle v78 EUR/USD · H4 · 07/04/2026 09:15
◈ Oracle Score
Score composito 7.2 / 10
Segnale ▲ BUY · ATTIVO
Regime TREND
◈ Componenti Score
Ulcer Index H42.1 / 10 ✓
Multi-TF Align.4/5 TF ✓
Stagionalità0.85× ✓
Correlazioneρ=0.42 ✓
VolatilitàATR=0.0042
◈ Trade Setup
Entry1.08420
Stop Loss1.08020 (−40p)
Take Profit1.09620 (+120p)
Lotti (1% / €5k)0.13
◈ Timeframe
M15 H1 H4 D1 W1

Ogni elemento che vedi — il titolo, le righe label/valore, la barra score, i badge colorati, i pulsanti timeframe — è un oggetto grafico separato creato con ObjectCreate() e posizionato con coordinate pixel precise. Oracle v78 ne crea oltre 200 all'inizializzazione.

I Tipi di Oggetti Grafici — Cosa Usa Oracle

Tipo Uso principale in Oracle Note tecniche
OBJ_RECTANGLE_LABEL Sfondi e pannelli. Il rettangolo che forma il body della dashboard, le sezioni, i badge colorati. Posizionato con pixel assoluti. Non segue le barre del grafico. Ideale per UI fissa.
OBJ_LABEL Tutti i testi. Titolo, labels, valori numerici, icone Unicode. L'80% degli oggetti Oracle è OBJ_LABEL. Font configurabile. Supporta Wingdings per icone. Coordinate pixel assolute.
OBJ_BUTTON Pulsanti interattivi. I bottoni H1/H4/D1/W1 per cambiare timeframe, bottone settings. Genera CHARTEVENT_OBJECT_CLICK in OnChartEvent(). Ha stato pressed/unpressed.
OBJ_EDIT Input utente. Non usato da Oracle nella dashboard principale — utile per campi di testo editabili. Genera CHARTEVENT_OBJECT_ENDEDIT quando l'utente conferma il testo.
OBJ_BITMAP_LABEL Immagini. Logo, icone bitmap. Richiede file .bmp in MQL5/Images/. Meno usato — le icone Unicode su OBJ_LABEL sono più pratiche.
◈ Il concetto chiave dei grafici MT5
CORNER — l'ancora della tua UI
Ogni oggetto grafico ha una proprietà CORNER che definisce da quale angolo del grafico vengono misurate le coordinate X e Y. CORNER_LEFT_UPPER (0) = angolo in alto a sinistra, il default. Oracle usa CORNER_LEFT_UPPER per tutta la dashboard — coordinate X verso destra, Y verso il basso. Se ridimensioni MT5, gli oggetti rimangono fissi rispetto all'angolo configurato. Questo è il motivo per cui la dashboard deve essere aggiornata in OnChartEvent con CHARTEVENT_CHART_CHANGE.

Creare e Gestire un Oggetto — Pattern Base

MQL5 · Oggetti Grafici Pattern base — crea/aggiorna/elimina
// ============================================================
// Pattern professionale per gestione oggetti grafici
// Prefix "OZ_" su tutti i nomi — facilita eliminazione in bulk
// ============================================================

// ---- Helper: crea o aggiorna un OBJ_LABEL ----
// Se l'oggetto esiste già, aggiorna solo le proprietà cambiate
// Evita flickering da delete+recreate ad ogni tick
void SetLabel(string name, int x, int y,
              string text, color clr,
              int font_size = 9,
              string font = "Consolas",
              ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER)
  {
   // Crea solo se non esiste ancora
   if(ObjectFind(0, name) < 0)
     {
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, corner);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
     }
   
   // Aggiorna sempre le proprietà visibili
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetString(0,  name, OBJPROP_TEXT, text);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, font_size);
   ObjectSetString(0,  name, OBJPROP_FONT, font);
  }

// ---- Helper: crea o aggiorna un OBJ_RECTANGLE_LABEL ----
void SetRect(string name, int x, int y,
             int w, int h, color bg_clr,
             color border_clr = clrNONE,
             int border_width = 0)
  {
   if(ObjectFind(0, name) < 0)
     {
      ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
     }
   
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE,  x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE,  y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE,      w);
   ObjectSetInteger(0, name, OBJPROP_YSIZE,      h);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR,    bg_clr);
   ObjectSetInteger(0, name, OBJPROP_COLOR,      border_clr);
   ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
   ObjectSetInteger(0, name, OBJPROP_WIDTH,      border_width);
  }

// ---- Pulizia massiva alla rimozione dell'indicatore ----
void DeleteAllDashboard()
  {
   // Elimina tutti gli oggetti che iniziano con "OZ_"
   for(int i = ObjectsTotal(0, 0, -1) - 1; i >= 0; i--)
     {
      string name = ObjectName(0, i, 0, -1);
      if(StringFind(name, "OZ_") == 0)
         ObjectDelete(0, name);
     }
   ChartRedraw();
  }

La Dashboard Oracle — Codice Completo

Questo è il modulo che costruisce la dashboard Oracle. Il pattern è: costruisci tutto in BuildDashboard() chiamata da OnInit(), aggiorna solo i valori dinamici in UpdateDashboard() chiamata da OnCalculate() e OnTimer():

MQL5 · Dashboard Oracle Oracle_Dashboard.mqh — modulo completo
// ============================================================
// Oracle_Dashboard.mqh — costruisce l'interfaccia su MT5
// Palette Ferrari Luce: BG #0C0C0E · Gold #C8A84B · Red #CC2200
// ============================================================

// Colori palette Ferrari Luce (come costanti MQL5)
#define FL_BG     C'12,12,14'      // #0C0C0E background
#define FL_BG2    C'16,15,20'      // #100F14 pannello
#define FL_GOLD   C'200,168,75'    // #C8A84B gold
#define FL_RED    C'204,34,0'      // #CC2200 Ferrari red
#define FL_GREEN  C'0,208,132'     // #00D084 green
#define FL_WHITE  C'242,239,232'   // #F2EFE8 white
#define FL_GREY2  C'106,112,128'   // #6A7080 grey
#define FL_GREY3  C'154,159,168'   // #9A9FA8 light grey

// Dimensioni pannello (in pixel)
#define DASH_X    12        // distanza dal bordo sinistro
#define DASH_Y    28        // distanza dal bordo superiore
#define DASH_W    240       // larghezza pannello
#define ROW_H    18        // altezza riga
#define PAD      10        // padding interno
#define PREFIX   "OZ_"     // prefisso oggetti

// ============================================================
// BuildDashboard — crea tutti gli oggetti statici
// Chiamata UNA VOLTA in OnInit()
// ============================================================
void BuildDashboard()
  {
   int y = DASH_Y;

   // === PANNELLO PRINCIPALE (sfondo) ===
   // Altezza totale stimata: 12 sezioni × 20px + padding
   SetRect(PREFIX + "bg_main",
           DASH_X, DASH_Y, DASH_W, 340,
           FL_BG2,
           C'30,26,14',   // bordo gold scuro
           1);
   
   // === HEADER BAR ===
   SetRect(PREFIX + "bg_header",
           DASH_X, DASH_Y, DASH_W, 28,
           C'20,18,10', C'30,26,14', 1);
   
   // Icona + titolo header
   SetLabel(PREFIX + "lbl_title",
            DASH_X + PAD, DASH_Y + 7,
            "⚡ UlcerZenith Oracle v78",
            FL_GOLD, 8, "Consolas");
   
   y = DASH_Y + 36;

   // === SEZIONE SCORE ===
   SetLabel(PREFIX + "lbl_score_title",
            DASH_X + PAD, y,
            "◈ ORACLE SCORE", FL_GREY2, 7);
   y += 14;
   
   // Label score (valore aggiornato da UpdateDashboard)
   SetLabel(PREFIX + "val_score",
            DASH_X + PAD, y,
            "0.0 / 10", FL_GOLD, 16, "Oswald");
   y += 24;
   
   // Barra score (sfondo + fill)
   SetRect(PREFIX + "bar_score_bg",
           DASH_X + PAD, y,
           DASH_W - PAD*2, 4,
           C'30,30,35');
   SetRect(PREFIX + "bar_score_fill",
           DASH_X + PAD, y,
           0, 4,  // larghezza = 0, aggiornata da UpdateDashboard
           FL_GOLD);
   y += 12;

   // Label segnale
   SetLabel(PREFIX + "lbl_signal_k",
            DASH_X + PAD, y, "Segnale", FL_GREY3, 8);
   SetLabel(PREFIX + "val_signal",
            DASH_X + 80, y, "—", FL_GREY2, 8);
   y += ROW_H;

   // Regime
   SetLabel(PREFIX + "lbl_regime_k",
            DASH_X + PAD, y, "Regime", FL_GREY3, 8);
   SetLabel(PREFIX + "val_regime",
            DASH_X + 80, y, "—", FL_GREY2, 8);
   y += ROW_H + 6;

   // === SEPARATORE ===
   SetRect(PREFIX + "sep1",
           DASH_X + PAD, y, DASH_W - PAD*2, 1,
           C'30,26,14');
   y += 8;

   // === SEZIONE SETUP TRADE ===
   SetLabel(PREFIX + "lbl_setup_title",
            DASH_X + PAD, y,
            "◈ TRADE SETUP", FL_GREY2, 7);
   y += 14;

   // Righe entry/SL/TP/Lotti — labels statiche
   string setup_keys[] = {"Entry", "Stop Loss", "Take Profit", "Lotti (1%)"};
   string setup_ids[]  = {"entry", "sl", "tp", "lots"};
   
   for(int i = 0; i < 4; i++)
     {
      SetLabel(PREFIX + "lbl_" + setup_ids[i] + "_k",
               DASH_X + PAD, y, setup_keys[i], FL_GREY3, 8);
      SetLabel(PREFIX + "val_" + setup_ids[i],
               DASH_X + 90, y, "—", FL_WHITE, 8);
      y += ROW_H;
     }
   y += 6;

   // === PULSANTI TIMEFRAME ===
   SetRect(PREFIX + "sep2",
           DASH_X + PAD, y, DASH_W - PAD*2, 1,
           C'30,26,14');
   y += 8;
   
   SetLabel(PREFIX + "lbl_tf_title",
            DASH_X + PAD, y, "◈ TIMEFRAME", FL_GREY2, 7);
   y += 14;

   // 4 pulsanti TF — OBJ_BUTTON per gestire i click
   string tf_names[]  = {"H1",   "H4",   "D1",   "W1"};
   int    tf_periods[] = {60,    240,   1440,  10080};
   int    btn_w = 48, btn_h = 20, btn_gap = 4;
   
   for(int i = 0; i < 4; i++)
     {
      string btn_name = PREFIX + "btn_tf_" + tf_names[i];
      int    btn_x    = DASH_X + PAD + i * (btn_w + btn_gap);
      
      if(ObjectFind(0, btn_name) < 0)
        {
         ObjectCreate(0, btn_name, OBJ_BUTTON, 0, 0, 0);
         ObjectSetInteger(0, btn_name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
         ObjectSetInteger(0, btn_name, OBJPROP_SELECTABLE, false);
        }
      
      ObjectSetInteger(0, btn_name, OBJPROP_XDISTANCE, btn_x);
      ObjectSetInteger(0, btn_name, OBJPROP_YDISTANCE, y);
      ObjectSetInteger(0, btn_name, OBJPROP_XSIZE,     btn_w);
      ObjectSetInteger(0, btn_name, OBJPROP_YSIZE,     btn_h);
      ObjectSetString(0,  btn_name, OBJPROP_TEXT,      tf_names[i]);
      ObjectSetInteger(0, btn_name, OBJPROP_FONTSIZE,  8);
      ObjectSetInteger(0, btn_name, OBJPROP_COLOR,     FL_GREY3);
      ObjectSetInteger(0, btn_name, OBJPROP_BGCOLOR,   C'20,20,26');
      ObjectSetInteger(0, btn_name, OBJPROP_BORDER_COLOR, C'40,35,18');
     }
   
   // Evidenzia H4 come default attivo
   SetButtonActive("H4");
   
   ChartRedraw();
  }

// ============================================================
// UpdateDashboard — aggiorna solo i valori dinamici
// Chiamata ad ogni nuova barra e da OnTimer()
// ============================================================
void UpdateDashboard(double score, double dir, double regime,
                      double entry, double sl, double tp,
                      double lots)
  {
   // Score numerico
   ObjectSetString(0, PREFIX + "val_score",
                   OBJPROP_TEXT,
                   DoubleToString(score, 1) + " / 10");
   
   // Colore score in base al valore
   color score_clr = score >= 7.0 ? FL_GREEN :
                     score >= 4.5 ? FL_GOLD  : FL_GREY2;
   ObjectSetInteger(0, PREFIX + "val_score", OBJPROP_COLOR, score_clr);
   
   // Barra score — larghezza proporzionale
   int bar_w = (int)((DASH_W - PAD*2) * score / 10.0);
   ObjectSetInteger(0, PREFIX + "bar_score_fill", OBJPROP_XSIZE, bar_w);
   ObjectSetInteger(0, PREFIX + "bar_score_fill", OBJPROP_BGCOLOR, score_clr);
   
   // Segnale
   string sig_txt = dir > 0 ? "▲ BUY" : dir < 0 ? "▼ SELL" : "— FLAT";
   color  sig_clr = dir > 0 ? FL_GREEN : dir < 0 ? FL_RED : FL_GREY2;
   if(score < 4.5) { sig_txt = "— NO SIGNAL"; sig_clr = FL_GREY2; }
   ObjectSetString(0,  PREFIX + "val_signal", OBJPROP_TEXT,  sig_txt);
   ObjectSetInteger(0, PREFIX + "val_signal", OBJPROP_COLOR, sig_clr);
   
   // Regime
   string reg_txt = regime == 1 ? "📈 TREND" :
                    regime == 2 ? "↔ RANGE" : "💥 BREAKOUT";
   ObjectSetString(0, PREFIX + "val_regime", OBJPROP_TEXT, reg_txt);
   
   // Setup trade
   ObjectSetString(0, PREFIX+"val_entry",OBJPROP_TEXT,DoubleToString(entry,_Digits));
   ObjectSetString(0, PREFIX+"val_sl",   OBJPROP_TEXT,DoubleToString(sl,_Digits));
   ObjectSetString(0, PREFIX+"val_tp",   OBJPROP_TEXT,DoubleToString(tp,_Digits));
   ObjectSetString(0, PREFIX+"val_lots", OBJPROP_TEXT,DoubleToString(lots,2));
   
   ChartRedraw();
  }

// ============================================================
// SetButtonActive — evidenzia il pulsante TF attivo
// ============================================================
void SetButtonActive(string active_tf)
  {
   string tfs[] = {"H1", "H4", "D1", "W1"};
   for(int i = 0; i < 4; i++)
     {
      string btn_name = PREFIX + "btn_tf_" + tfs[i];
      bool active = (tfs[i] == active_tf);
      ObjectSetInteger(0, btn_name, OBJPROP_BGCOLOR,
                       active ? C'30,24,8' : C'20,20,26');
      ObjectSetInteger(0, btn_name, OBJPROP_COLOR,
                       active ? FL_GOLD : FL_GREY3);
     }
  }

OnChartEvent — Gestire i Click sui Pulsanti

MQL5 · OnChartEvent Gestione click pulsanti TF + resize grafico
// ============================================================
// OnChartEvent — gestisce click e resize
// ============================================================
string g_active_tf = "H4";   // TF corrente selezionato

void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   // ---- Click su un oggetto ----
   if(id == CHARTEVENT_OBJECT_CLICK)
     {
      // Pulsanti timeframe
      string tfs[] = {"H1", "H4", "D1", "W1"};
      for(int i = 0; i < 4; i++)
        {
         if(sparam == PREFIX + "btn_tf_" + tfs[i])
           {
            g_active_tf = tfs[i];
            SetButtonActive(tfs[i]);
            
            // Reset stato pressed (OBJ_BUTTON rimane premuto senza reset)
            ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
            
            Print("TF selezionato: ", tfs[i]);
            // Qui triggerare il ricalcolo Oracle per il nuovo TF
            ChartRedraw();
            break;
           }
        }
     }
   
   // ---- Resize del grafico — riposizionare la dashboard ----
   // Chiamato quando l'utente ridimensiona la finestra MT5
   if(id == CHARTEVENT_CHART_CHANGE)
     {
      // Ricostruisce la dashboard con le nuove dimensioni del grafico
      // Non è necessario se usi CORNER_LEFT_UPPER con coordinate fisse —
      // la dashboard rimane ancorata in alto a sinistra automaticamente
      // Serve solo se usi coordinate relative alla dimensione del grafico
      BuildDashboard();
      ChartRedraw();
     }
  }

La dashboard Oracle
dal vivo ogni mattina.

Score, regime, entry, SL, TP e lotti — tutto visibile sul grafico MT5 nelle live gratuite.
— Oracle in produzione reale.

Entra nel Canale Gratuito → Hub MQL5 Completo →

FAQ — Dashboard MT5 MQL5

Come si crea un testo sul grafico MT5 in MQL5? ▶
Usa OBJ_LABEL con ObjectCreate e poi imposta le proprietà: ObjectCreate(0, "nome", OBJ_LABEL, 0, 0, 0) crea l'etichetta. Poi: OBJPROP_XDISTANCE e OBJPROP_YDISTANCE per la posizione, OBJPROP_TEXT per il contenuto, OBJPROP_COLOR per il colore, OBJPROP_FONTSIZE per la dimensione, OBJPROP_FONT per il font. Il pattern professionale è: crea solo se non esiste (ObjectFind < 0), poi aggiorna sempre le proprietà — evita il flickering da delete+recreate ad ogni tick.
Come si gestisce il click su un pulsante in MQL5? ▶
I click sui pulsanti vengono ricevuti in OnChartEvent(). Quando l'utente clicca su un OBJ_BUTTON, viene generato l'evento CHARTEVENT_OBJECT_CLICK con il nome dell'oggetto nel parametro sparam. Codice: if(id == CHARTEVENT_OBJECT_CLICK) { if(sparam == "OZ_btn_tf_H4") { /* gestisci */ } }. Importante: dopo aver gestito il click, resetta lo stato con ObjectSetInteger(0, sparam, OBJPROP_STATE, false) — altrimenti il pulsante rimane visivamente "premuto".
Come si aggiorna la dashboard senza flickering? ▶
Il pattern corretto è separare la creazione dall'aggiornamento: BuildDashboard() in OnInit() crea tutti gli oggetti una volta sola. UpdateDashboard() in OnCalculate() e OnTimer() aggiorna solo le proprietà che cambiano (testo, colore) — mai eliminare e ricreare oggetti ad ogni tick. Per animazioni fluide, usa EventSetTimer(1) in OnInit() e aggiorna in OnTimer() ogni secondo invece che ad ogni tick — molto meno CPU e zero flickering.
Perché la dashboard scompare quando sposto MT5 su un altro monitor? ▶
La dashboard non scompare ma si sposta. Questo succede se usi CORNER_LEFT_UPPER con coordinate assolute — corretto. Il problema è se il monitor di destinazione ha una risoluzione diversa. La soluzione professionale di Oracle è intercettare CHARTEVENT_CHART_CHANGE in OnChartEvent() e richiamare BuildDashboard() — che ricrea tutti gli oggetti con le coordinate aggiornate alla nuova dimensione del grafico. Puoi anche usare ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) e CHART_HEIGHT_IN_PIXELS per calcolare posizioni relative alla dimensione del grafico corrente.
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
Disclaimer: Il codice MQL5 è a scopo educativo. Il trading comporta rischio. Nessun contenuto costituisce consulenza finanziaria. Manuel Trotta / MTInvestments P.IVA 14349331000.