English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Manuale MQL5: Gestire gli eventi tipici dei grafici

Manuale MQL5: Gestire gli eventi tipici dei grafici

MetaTrader 5Esempi | 11 gennaio 2022, 17:01
94 0
Denis Kirichenko
Denis Kirichenko

Introduzione

Nel mio articolo vorrei descrivere le capacità e la pratica dell'utilizzo di OnChartEvent() con eventi tipici (standard) predefiniti dagli sviluppatori MQL5. Gli articoli MQL5 e Code Base contengono già esempi di utilizzo di questo gestore.

Tuttavia, il mio scopo è analizzare questo strumento nel contesto della programmazione orientata agli eventi (EOP). Credo che questo gestore possa essere utilizzato con successo per sistemi di trading completamente automatici e semi-automatici.


1. Evento "ChartEvent"

Quindi, prima vediamo cos'è questo tipo di evento.

Secondo la documentazione, l'evento ChartEvent può apparire quando si lavora con un grafico, in particolare quando:

  • premendo un tasto sulla tastiera quando una finestra del grafico è a fuoco.
  • creazione di un oggetto grafico.
  • eliminazione di un oggetto grafico.
  • cliccando su un oggetto grafico.
  • trascinando un oggetto grafico con il mouse.
  • finire di modificare il testo in un campo di testo di un oggetto grafico LabelEdit.

Pertanto, questo evento porta interattività e consente di interagire con un grafico. Inoltre, tale interazione può essere il risultato del trading manuale, oltre che di alcune operazioni algoritmiche (trading automatizzato).

Gli sviluppatori MQL5 classificano l'evento ChartEvent in base ai tipi specificati nell'enumerazione ENUM_CHART_EVENT.

È importante notare che questo elenco ha una gamma di eventi definiti dall'utente, che fungono da riserva nascosta, del quale il programmatore potrà fare uso. Gli sviluppatori MQL5 forniscono 65535 ID per eventi personalizzati.

Per lavorare con eventi personalizzati, è disponibile una funzione generatore speciale EventChartCustom() per le esigenze del programmatore. Tuttavia, questo articolo non considera gli eventi personalizzati.


2. Gestore e generatore di ChartEvent

Tutta l'elaborazione dell'evento ChartEvent viene eseguita da una speciale funzione di gestione OnChartEvent(). Ciò è coerente con il concetto di linguaggio MQL5, dove ad esempio l'evento Trade è gestito dalla funzione OnTrade(), l'evento Init è gestito dalla funzione OnInit(), ecc.

La funzione OnChartEvent() ha la seguente firma:

void OnChartEvent(const int id,         // event identifier  
                  const long& lparam,   // parameter of the event of type long
                  const double& dparam, // parameter of the event of type double
                  const string& sparam  // parameter of the event of type string
                  )

Tutti i parametri di input sono costanti e quando viene chiamato il gestore trasmettono alcune informazioni utili.

Pertanto, il valore del parametro id può rivelare quale particolare evento ha chiamato il gestore. Altri possono avere valori di tipo long, double e string. In questo modo è possibile ottenere ulteriori informazioni su un evento.

Successivamente, creeremo un esempio in cui i valori dei parametri specificati verranno utilizzati per analizzare cosa sta succedendo.

La parte personalizzata dell'evento ChartEvent, che deve essere implementata da un programmatore, è connessa alla funzione EventChartCustom(). Questa stessa funzione può generare l'evento. La firma della funzione è la seguente:

bool  EventChartCustom(long    chart_id,        // receiving chart identifier
                       ushort  custom_event_id, // event identifier
                       long    lparam,          // the long parameter
                       double  dparam,          // the double parameter
                       string  sparam           // the string parameter
                       )

La funzione generatore, infatti, può creare un evento e inviarlo a qualsiasi grafico compreso quello corrente con qualsiasi valore dei parametri di input. Questi ultimi sono i tipi: ushort, long, double, string.

Le funzioni OnChartEvent() e EventChartCustom() insieme formano un potente strumento che è un buon esempio dei vantaggi della programmazione orientata agli eventi.


3. Modello di elaborazione degli eventi standard

Ora prenderò in considerazione i tipi di eventi del grafico e fornirò un esempio per ciascuno di essi. Ogni evento avrà la sua versione dedicata di EventProcessor.mq5 e il suo codice conterrà la gestione di un evento grafico. Ci sono 10 eventi tipici in MQL5.

Per tre di essi (evento del mouse, evento di creazione di oggetti grafici, evento di rimozione di oggetti grafici) dobbiamo preparare un grafico. Può essere eseguito utilizzando la funzione ChartSetInteger(). Consente a un grafico di rispondere a eventi specificati.

Un tipico blocco per l'elaborazione degli eventi del grafico potrebbe assomigliare a:

void OnChartEvent(const int id, 
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   string comment="Last event: ";

//--- select event on chart
   switch(id)
     {
      //--- 1
      case CHARTEVENT_KEYDOWN:
        {
         comment+="1) keystroke";
         break;
        }
      //--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         break;
        }
      //--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         break;
        }
      //--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         break;
        }
      //--- 5
      case CHARTEVENT_OBJECT_DELETE:
        {
         comment+="5) delete graphical object";
         break;
        }
      //--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         break;
        }
      //--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         break;
        }
      //--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         break;
        }
      //--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) finish editing text";
         break;
        }
      //--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         comment+="10) modify chart";
         break;
        }
     }
//---
   Comment(comment);
  }

In ogni caso ho aggiunto la stringa che descrive un evento selezionato. Di conseguenza, nella riga dei commenti possiamo vedere l'ultimo evento accaduto sul grafico. Se esegui il modello ed esegui varie manipolazioni con il grafico, noterai che la riga di commento potrebbe avere record diversi.

Ovviamente, si fa poco uso di un tale Expert Advisor che determina solo il tipo di evento. Dobbiamo ampliare le sue capacità.


4. Esempi di elaborazione di eventi standard


4.1. Evento di battitura

Prendiamo il primo caso e lavoriamo con i pulsanti sulla tastiera, in modo che il nostro EA risponda alle sequenze di tasti. Lascia che compri quando premi la "freccia su" e vendi quando premi la "freccia giù". Quindi questo caso sarà il seguente:

//--- 1
      case CHARTEVENT_KEYDOWN:
        {
         //--- "up" arrow
         if(lparam==38)
            TryToBuy();

         //--- "down" arrow
         else if(lparam==40)
            TryToSell();

         comment+="1) keystroke";
         //---         
         break;
        }

Vedere il codice sorgente EA allegato per i dettagli sull'implementazione di TryToBuy() e TryToSell(). I parametri di trading (lot size, Stop Loss, Take Profit, ecc.) sono specificati come variabili di input (InpLot, InpStopLoss, InpTakeProfit, ecc.). Va anche detto che il parametro lparam ottiene il codice del tasto premuto.

La versione aggiornata dell'EA si chiama EventProcessor1.mq5.


4.2. Evento del mouse

Questo tipo di evento verrà gestito solo se è stata specificata la proprietà CHART_EVENT_MOUSE_MOVE per il grafico. Per questo motivo il blocco di inizializzazione dell'EA contiene tali stringhe:

//--- mouse move
bool is_mouse=false;
if(InpIsEventMouseMove)
   is_mouse=true;
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,is_mouse);

Va notato che se usi un mouse, allora, naturalmente, si verificherà spesso un evento del mouse. Per questo motivo può essere utile avere la possibilità di disabilitare l'elaborazione di questo evento. I parametri lparam e dparam del gestore riportano le coordinate X e Y a seconda dei casi.

Discuteremo ora un esempio inventato. Supponiamo che ci sia uno spostamento della barra zero dal bordo destro. Passando il cursore sulla parte dello schermo a destra dello spostamento verrà visualizzata una finestra che suggerisce di acquistare o vendere.

Per farlo dobbiamo prima determinare lo spostamento. Introdurremo una variabile di input per determinare la dimensione di uno spostamento della barra zero dal bordo destro in percentuale (InpChartShiftSize).

Fig.1 Finestra di un'operazione di trading

Fig.1 Finestra di un'operazione di trading

Utilizzeremo le funzioni che abilitano lo spostamento e ne determineremo la dimensione ChartShiftSet() e ChartShiftSizeSet(). Quindi identificheremo se la coordinata X del cursore era precedentemente a sinistra dal bordo e se si è spostata a destra. In caso affermativo, apparirà una finestra che suggerisce di acquistare/vendere (Fig.1).

Il codice che implementa l'obiettivo impostato è simile a:

//--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         //--- if a mouse event is processed
         if(InpIsEventMouseMove)
           {
            long static last_mouse_x;

            //--- enable shift
            if(ChartShiftSet(true))
               //--- set shift size 
               if(ChartShiftSizeSet(InpChartShiftSize))
                 {
                  //--- chart width
                  int chart_width=ChartWidthInPixels();

                  //--- calculate X coordinate of shift border
                  int chart_shift_x=(int)(chart_width-chart_width*InpChartShiftSize/100.);

                  //--- border crossing condition
                  if(lparam>chart_shift_x && last_mouse_x<chart_shift_x)
                    {
                     int res=MessageBox("Yes: buy / No: sell","Trade operation",MB_YESNO);
                     //--- buy
                     if(res==IDYES)
                        TryToBuy();
                     //--- sell
                     else if(res==IDNO)
                        TryToSell();
                    }

                  //--- store mouse X coordinate
                  last_mouse_x=lparam;
                 }
           }

         //---
         break;
        }

L'acquisto e la vendita vengono effettuati dalle funzioni di trading create in precedenza. La versione aggiornata dell'EA si chiamerà EventProcessor2.mq5.


4.3. Evento di creazione di oggetti grafici

Questo tipo di evento viene generato quando viene creato un oggetto su un grafico. Simile a un evento del mouse, questo tipo deve ricevere un'autorizzazione per la gestione con la proprietà CHART_EVENT_OBJECT_CREATE. Deve essere specificato solo una volta nel blocco di inizializzazione se vogliamo rispondere alla comparsa di un nuovo oggetto grafico.

//--- object create
bool is_obj_create=false;
if(InpIsEventObjectCreate)
   is_obj_create=true;
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,is_obj_create);

Solo un parametro del gestore conterrà informazioni. È un parametro di stringa sparam che contiene il nome dell'oggetto grafico creato. Possiamo trovare quell'oggetto in base al nome, gestirlo e poi decidere cosa fare dopo.

Qui c'è un semplice esempio. Disegneremo una linea orizzontale sul grafico e lasceremo che il robot la posizioni al prezzo massimo di tutte le barre riflesse sul grafico e disegneremo altre due linee. La riga inferiore sarà posta al prezzo minimo e la terza riga sarà tra le prime due equidistanti da entrambe.

Il codice per l'implementazione dell'attività:

//--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         //--- if graphical object creation event is processed
         if(InpIsEventObjectCreate)
           {
            //--- capture creation of horizontal line
            int all_hor_lines=ObjectsTotal(0,0,OBJ_HLINE);

            //--- if this is the only line
            if(all_hor_lines==1)
              {
               string hor_line_name1=sparam;

               //--- calculate levels
               int visible_bars_num=ChartVisibleBars();

               //--- arrays for high and low prices
               double highs[],lows[];
               //---
               int copied=CopyHigh(_Symbol,_Period,0,visible_bars_num-1,highs);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy highs!");
                  return;
                 }
               copied=CopyLow(_Symbol,_Period,0,visible_bars_num-1,lows);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy lows!");
                  return;
                 }
               //--- high and low prices
               double ch_high_pr,ch_low_pr,ch_mid_pr;
               //---
               ch_high_pr=NormalizeDouble(highs[ArrayMaximum(highs)],_Digits);
               ch_low_pr=NormalizeDouble(lows[ArrayMinimum(lows)],_Digits);
               ch_mid_pr=NormalizeDouble((ch_high_pr+ch_low_pr)/2.,_Digits);

               //--- place created line on high
               if(ObjectFind(0,hor_line_name1)>-1)
                  if(!ObjectMove(0,hor_line_name1,0,0,ch_high_pr))
                    {
                     Print("Failed to move!");
                     return;
                    }
               //--- create line on low
               string hor_line_name2="Hor_line_min";
               //---
               if(!ObjectCreate(0,hor_line_name2,OBJ_HLINE,0,0,ch_low_pr))
                 {
                  Print("Failed to create the 2nd horizontal line!");
                  return;
                 }
               //--- create line between high and low 
               string hor_line_name3="Hor_line_mid";
               //---
               if(!ObjectCreate(0,hor_line_name3,OBJ_HLINE,0,0,ch_mid_pr))
                 {
                  Print("Failed to create the 3rd horizontal line!");
                  return;
                 }
              }
           }
         break;
        }

Il nome della versione aggiornata dell'EA è EventProcessor3.mq5.

Fig. 2. Risultato della gestione dell'evento di creazione di un oggetto grafico

Fig. 2. Risultato della gestione dell'evento di creazione di un oggetto grafico

Dopo aver completato la procedura, ho ricevuto la seguente immagine (Fig. 2). Quindi, le funzioni integrate danno a un EA la capacità di reagire alla creazione di un oggetto grafico e quindi agire su di esso.


4.4. Evento di modifica delle proprietà di un oggetto grafico tramite una finestra di dialogo delle proprietà

Questo tipo di evento è parzialmente simile al precedente. Si attiva quando una delle proprietà di un oggetto grafico viene modificata tramite una finestra di dialogo delle proprietà. Questo strumento potrebbe essere utile, ad esempio, per la sincronizzazione delle proprietà grafiche di oggetti dello stesso tipo.

Immagina un numero di alcuni oggetti su un grafico. Un trader di solito ha molte linee diverse su un grafico. Queste righe devono essere rese invisibili per un po' di tempo senza essere eliminate. Troveremo una soluzione a questo compito. La linea modificata può essere decolorata e lo stesso può essere fatto su altri oggetti grafici. Quindi il codice potrebbe essere il seguente:

//--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         //---
         string curr_obj_name=sparam;
         //--- find the changed object
         if(ObjectFind(0,curr_obj_name)>-1)
           {
            //--- get object color
            color curr_obj_color=(color)ObjectGetInteger(0,curr_obj_name,OBJPROP_COLOR);
            //--- total number of objects on chart
            int all_other_objects=ObjectsTotal(0);
            //--- find other objects
            for(int obj_idx=0;obj_idx<all_other_objects;obj_idx++)
              {
               string other_obj_name=ObjectName(0,obj_idx);
               if(StringCompare(curr_obj_name,other_obj_name)!=0)
                  if(!ObjectSetInteger(0,other_obj_name,OBJPROP_COLOR,curr_obj_color))
                    {
                     Print("Failed to change the object color!");
                     return;
                    }
              }
            //--- redraw chart
            ChartRedraw();
           }
         //---
         break;

Supponiamo che ci sia un insieme di linee sul grafico (Fig.3).

Fig.3. Linee dinamiche multicolori

Fig.3. Linee dinamiche multicolori

Se proviamo a cambiare il colore di una qualsiasi delle linee, o per essere precisi, a decolorarla (Fig.4) nella finestra di dialogo delle proprietà, non ci saranno linee visibili sul grafico. Allo stesso tempo, gli oggetti grafici saranno ancora presenti lì.

Fig.4. Modifica del colore di una linea

Fig.4. Modificare il colore di una linea

La versione aggiornata dell'EA si chiama EventProcessor4.mq5.


4.5. Evento di cancellazione di oggetti grafici

Come suggerisce il nome di questo tipo di evento, appare all'eliminazione di un oggetto da un grafico. È l'ultimo evento di un gruppo, che richiede un'autorizzazione preventiva diretta per la gestione. Può essere fatto tramite la proprietà CHART_EVENT_OBJECT_DELETE.

//--- object delete
   bool is_obj_delete=false;
   if(InpIsEventObjectDelete)
      is_obj_delete=true;
   ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,is_obj_delete);

Ecco un altro esempio ipotetico. Sul grafico in cui è allegato il tuo EA, c'è una serie di oggetti grafici di diversi tipi. Supponiamo di dover eliminare oggetti di un solo tipo particolare. Ad esempio, linee verticali (Fig.5).

Fig.5. Cinque verticali e altre linee

Fig.5. Cinque verticali e altre linee

Dobbiamo rimuovere solo una verticale e l'Esperto rimuoverà le altre (Fig.6).

Fig.6. Linee rimanenti

Fig.6. Linee rimanenti

Le seguenti voci appariranno nel registro "Esperti":

NS      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines before removing: 4
MD      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines removed from the chart: 4
QJ      0       10:31:18.078    EventProcessor5 (EURUSD.e,W1)   Vertical lines after removing: 0

Un aspetto importante deve essere menzionato. Una volta rimosso un oggetto, non è possibile accedere alle sue proprietà. Significa che se non recuperiamo in anticipo i dati richiesti sull'oggetto, non sarà accessibile dopo che è stato rimosso. Pertanto, se abbiamo bisogno di scoprire il tipo di un oggetto rimosso, dobbiamo memorizzarlo prima che l'oggetto stesso venga rimosso. Ho un suggerimento per gli sviluppatori MQL5 di creare una cronologia di un grafico disponibile nel terminale. Questo ci permetterà di fare riferimento alle proprietà degli oggetti rimossi.

Chiameremo l'ultima versione di Expert EventProcessor5.mq5.


4.6. Evento di clic del mouse sul grafico

Questo evento verrà generato se si fa clic sul grafico con il tasto sinistro del mouse. Fare clic con il pulsante destro del mouse sul grafico per aprire un menu di scelta rapida e facendo clic con il pulsante centrale verrà visualizzato un mirino. I parametri lparam e dparam del gestore riportano le coordinate X e Y a seconda dei casi.

Il seguente semplice compito servirà come esempio. Dobbiamo fare in modo che una freccia 'acquista' venga disegnata nel punto in cui avviene il clic del mouse. L'oggetto 'freccia' ha un solo punto di ancoraggio. Di conseguenza è necessaria una sola trasformazione delle coordinate X e Y ai valori del tempo e del prezzo del punto di ancoraggio.

Il codice per l'esempio sopra:

//--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         //--- object counter 
         static uint sign_obj_cnt;
         string buy_sign_name="buy_sign_"+IntegerToString(sign_obj_cnt+1);
         //--- coordinates 
         int mouse_x=(int)lparam;
         int mouse_y=(int)dparam;
         //--- time and price
         datetime obj_time;
         double obj_price;
         int sub_window;
         //--- convert the X and Y coordinates to the time and price values
         if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
           {
            //--- create object
            if(!ObjectCreate(0,buy_sign_name,OBJ_ARROW_BUY,0,obj_time,obj_price))
              {
               Print("Failed to create buy sign!");
               return;
              }
            //--- redraw chart
            ChartRedraw();
            //--- increase object counter
            sign_obj_cnt++;
           }
         //---
         break;
        }

La versione corrente dell'esperto è denominata EventProcessor6.mq5.


4.7. Evento di clic del mouse su un oggetto grafico

Questo tipo di eventi del grafico differisce dal precedente solo per il fatto che un clic del mouse avviene su un oggetto grafico. Il parametro stringa sparam conterrà il nome dell'oggetto cliccato. Nell'esempio precedente abbiamo creato le frecce 'acquista'. Facciamo in modo che un clic sull'oggetto di questo tipo lo trasformi in una freccia di "vendita".

Il codice di questo blocco del gestore può essere simile a:

//--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         //---
         string sign_name=sparam;

         //--- delete buy arrow
         if(ObjectDelete(0,sign_name))
           {
            //--- redraw chart
            ChartRedraw();
            //---
            static uint sign_obj_cnt;
            string sell_sign_name="sell_sign_"+IntegerToString(sign_obj_cnt+1);

            //--- coordinates 
            int mouse_x=(int)lparam;
            int mouse_y=(int)dparam;
            //--- time and price
            datetime obj_time;
            double obj_price;
            int sub_window;
            //--- convert the X and Y coordinates to the time and price values
            if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
              {
               //--- create object
               if(!ObjectCreate(0,sell_sign_name,OBJ_ARROW_SELL,0,obj_time,obj_price))
                 {
                  Print("Failed to create sell sign!");
                  return;
                 }
               //--- redraw chart
               ChartRedraw();
               //--- increase object counter
               sign_obj_cnt++;
              }
           }
         //---
         break;
        }

Per il bene di questo esempio ho mantenuto intatto il caso della gestione del clic del mouse. Avviando l'EA, ho fatto clic con il pulsante sinistro del mouse tre volte e ho ottenuto tre frecce da acquistare (Fig.7). Ho evidenziato la loro posizione in giallo.

Fig.7. Frecce "Acquista"

Fig.7. "Compra" frecce

Se ora clicchiamo su ciascuna freccia 'acquista', riceveremo la seguente immagine (Fig.8).

Fig.8. Frecce "Compra" e "Vendi"

Fig.8. Frecce "Compra" e "vendi"

Le frecce "Vendi" sono apparse come previsto, ma le frecce "Compra" non erano progettate per apparire. C'è un motivo per cui sto portando un elenco di oggetti sul grafico in cui ho evidenziato in giallo i nomi delle frecce "compra".

È facile notare che l'EA ha creato la 4a, la 5a e la 6a freccia "compra". Perché è successo? È successo perché il primo clic sull'oggetto ha attivato due eventi: il primo è stato il clic effettivo sull'oggetto e il secondo - un clic sul grafico. L'ultimo evento genera la creazione di una freccia 'acquista'. Qui sorge la necessità di aggiungere un meccanismo che impedisca la gestione del secondo evento, che è un clic sul grafico. Mi sembra che il controllo del tempo possa svolgere tale funzione.

Aggiungiamo una variabile globale gLastTime. Faciliterà un controllo sul tempo di creazione di una freccia "acquista". Se un semplice click handler viene chiamato per meno di 250 ms dopo che è stata creata una freccia 'sell', allora questa chiamata deve essere passata.

Prima che il grafico venga ridisegnato, la stringa sottostante deve essere aggiunta al blocco di gestione di un clic sull'oggetto:

//--- store the moment of creation
gLastTime=GetTickCount();

La verifica del tempo va aggiunta al blocco di movimentazione con un click sul grafico.

uint lastTime=GetTickCount();
if((lastTime-gLastTime)>250)
  {
   //--- click handling
  }

Creiamo ancora tre frecce sul grafico del tipo 'buy' (Fig.9).

Fig.9. Frecce "Compra"

Fig.9. "Compra" frecce

Cercheremo di cliccarci sopra nonostante le loro piccole dimensioni. Le frecce si sono trasformate in 'vendi' al clic (Fig.10).

Fig.10. Frecce "Vendi"

Fig.10. Frecce "vendi"

Simile a quelli precedenti, chiameremo la nuova versione EventProcessor7.mq5.


4.8. Evento di spostamento di un oggetto grafico con il mouse

Questo evento si verifica quando un oggetto viene spostato all'interno di un'area del grafico. Il gestore riceve il nome dell'oggetto spostato sotto forma di un parametro stringa sparam.

Ecco un altro esempio. I trader intraday molto spesso fanno trading entro un certo intervallo di tempo. Le linee verticali saranno i limiti di un intervallo di tempo. L'immagine assomiglierà approssimativamente alla Fig.11. L'intervallo di interesse è evidenziato.

Fig.11. Limiti di un intervallo di tempo

Fig.11. Limiti di un intervallo di tempo

L'intervallo di tempo può essere modificato manualmente. Quindi il nostro semi-automa dovrà reagire a un tale cambiamento.

A livello globale creeremo delle variabili che descrivono i nomi dei due verticali - gTimeLimit1_name e gTimeLimit2_name. Dobbiamo anche creare un paio di variabili per i nomi dei rettangoli, che oscurano il tempo di non negoziazione sul grafico. Dovranno essere create anche le variabili globali per i punti di ancoraggio. Poiché abbiamo due rettangoli, avremo quattro punti.

Il codice del caso del gestore CHARTEVENT_OBJECT_DRAG:

//--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         string curr_obj_name=sparam;
         //--- if one of the vertical lines is moved
         if(!StringCompare(curr_obj_name,gTimeLimit1_name) || 
            !StringCompare(curr_obj_name,gTimeLimit2_name))
           {
            //--- the time coordinate of vertical lines
            datetime time_limit1=0;
            datetime time_limit2=0;
            //--- find the first vertical line
            if(ObjectFind(0,gTimeLimit1_name)>-1)
               time_limit1=(datetime)ObjectGetInteger(0,gTimeLimit1_name,OBJPROP_TIME);
            //--- find the second vertical line
            if(ObjectFind(0,gTimeLimit2_name)>-1)
               time_limit2=(datetime)ObjectGetInteger(0,gTimeLimit2_name,OBJPROP_TIME);

            //--- if vertical lines are found
            if(time_limit1>0 && time_limit2>0)
               if(time_limit1<time_limit2)
                 {
                  //--- update properties of rectangles
                  datetime start_time=time_limit1;
                  datetime finish_time=time_limit2;
                  //---
                  if(RefreshRecPoints(start_time,finish_time))
                    {
                     //---
                     if(!ObjectMove(0,gRectLimit1_name,0,gRec1_time1,gRec1_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit1_name,1,gRec1_time2,gRec1_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                     //---
                     if(!ObjectMove(0,gRectLimit2_name,0,gRec2_time1,gRec2_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit2_name,1,gRec2_time2,gRec2_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                    }
                 }
           }
         //---
         break;
        }

Questo codice contiene una funzione personalizzata RefreshRecPoints(). Si tratta di aggiornare i valori dei punti di ancoraggio per due rettangoli. Il blocco dell'inizializzazione EA può fornire informazioni sulla creazione di oggetti grafici. La versione aggiornata si chiamerà EventProcessor8.mq5.


4.9. Fine della modifica di un testo nell'evento del campo di testo

Questo tipo di evento ha una natura altamente specializzata e compare quando si modifica il testo nel campo di inserimento dati. Il parametro sparam contiene il nome dell'oggetto su cui si lavora.

Ecco un esempio da considerare. Nel campo di inserimento dati inseriremo l'operazione di trading che stiamo per eseguire. Lascia che ci siano solo due operazioni: compra e vendi. Se inseriamo la parola 'Acquista' nel campo di immissione, l'EA acquisterà un asset e se inseriamo 'Sell', l'asset verrà venduto. Faremo in modo che questo campo non faccia distinzione tra maiuscole e minuscole, ovvero possiamo digitare "comprare" e "vendere". Il testo e il campo di input saranno colorati di rosso in vendita e blu in acquisto (Fig.12).

Fig.12. Acquista attraverso il campo di testo

Fig.12. Acquista attraverso il campo di testo

Il codice nel caso CHARTEVENT_OBJECT_ENDEDIT:

//--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) end of editing a text in the data entry field";
         //---
         string curr_obj_name=sparam;
         //--- if specified text field is being edited
         if(!StringCompare(curr_obj_name,gEdit_name))
           {
            //--- get object description
            string obj_text=NULL;
            if(ObjectGetString(0,curr_obj_name,OBJPROP_TEXT,0,obj_text))
              {
               //--- check value
               if(!StringCompare(obj_text,"Buy",false))
                 {
                  if(TryToBuy())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrBlue);
                 }
               else if(!StringCompare(obj_text,"Sell",false))
                 {
                  if(TryToSell())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrRed);
                 }
               else
                 {
                  //--- set text color
                  ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrGray);
                 }
               //--- redraw chart
               ChartRedraw();
              }
           }
         //---
         break;
        }

La versione aggiornata dell'EA si chiama EventProcessor9.mq5. Puoi trovare il blocco della creazione del campo di testo nel file sorgente.


4.10. Evento di modifica del grafico

L'ultimo evento che considereremo in questo articolo è legato alla modifica delle impostazioni del grafico. Questo è un evento particolare perché a questo punto ci occupiamo del grafico stesso, non degli oggetti sul grafico. Gli sviluppatori affermano che questo evento viene generato quando viene modificata la dimensione di un grafico o viene introdotta una nuova impostazione.

Ecco un altro esempio. Supponiamo che ci sia il divieto di alterare alcune delle impostazioni del grafico. Quindi tutti i tentativi di modificare le impostazioni sotto restrizione verranno ignorati. In effetti, l'EA restituirà semplicemente i valori precedenti. Esistono i seguenti parametri dell'oggetto "Chart":

  • griglia di visualizzazione;
  • tipo di visualizzazione del grafico;
  • Colore dello sfondo

Codice per questo caso:

//--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         //--- current height and width of the chart         
         int curr_ch_height=ChartHeightInPixelsGet();
         int curr_ch_width=ChartWidthInPixels();
         //--- if chart height and width have not changed
         if(gChartHeight==curr_ch_height && gChartWidth==curr_ch_width)
           {
            //--- fix the properties:
            //--- display grid
            if(!ChartShowGridSet(InpToShowGrid))
              {
               Print("Failed to show grid!");
               return;
              }
            //--- type of chart display
            if(!ChartModeSet(InpMode))
              {
               Print("Failed to set mode!");
               return;
              }
            //--- background color
            if(!ChartBackColorSet(InpBackColor))
              {
               Print("Failed to set background сolor!");
               return;
              }
           }
         //--- store window dimensions
         else
           {
            gChartHeight=curr_ch_height;
            gChartWidth=curr_ch_width;
           }
         //---
         comment+="10) modify chart";
         //---
         break;
        }

L'ultima versione si chiamerà EventProcessor10.mq5.


Conclusione

In questo articolo ho cercato di illustrare la diversità degli eventi tipici dei grafici in MetaTrader 5. Spero che questi esempi di gestione degli eventi saranno utili per i programmatori che iniziano a programmare in MQL5.

Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/689

File allegati |
code_en.zip (19.59 KB)
Come installare e utilizzare OpenCL per i calcoli Come installare e utilizzare OpenCL per i calcoli
È passato più di un anno da quando MQL5 ha iniziato a fornire supporto nativo per OpenCL. Tuttavia, non molti utenti hanno capito il vero valore nell'utilizzo del calcolo parallelo nei loro Expert Advisor, indicatori o script. Questo articolo ti aiuta a installare e configurare OpenCL sul tuo computer in modo che tu possa provare a utilizzare questa tecnologia nel terminale di trading MetaTrader 5.
MQL5 Cloud Network: Stai ancora calcolando? MQL5 Cloud Network: Stai ancora calcolando?
Presto sarà passato un anno e mezzo dal lancio di MQL5 Cloud Network. Questo evento all'avanguardia ha inaugurato una nuova era del trading algoritmico: ora con un paio di clic, i trader possono avere centinaia e migliaia di core di calcolo a loro disposizione per l'ottimizzazione delle loro strategie di trading.
Un'altra classe OOP MQL5 Un'altra classe OOP MQL5
Questo articolo mostra come costruire da zero un Expert Advisor orientato agli oggetti. Dal concepimento di un'idea di trading teorica alla programmazione di un MQL5 EA che porta quell’idea nel mondo reale. Imparare facendo è IMHO un approccio solido per avere successo. Mostrerò un esempio pratico per farti vedere come potrai codificare trasformare le tue idee in codice, per creare i tuoi robot Forex. Il mio obiettivo è anche quello di invitarvi ad aderire ai principi OO.
Indicatore per grafici a point and figure Indicatore per grafici a point and figure
Esistono molti tipi di grafici che forniscono informazioni sulla situazione attuale del mercato. Molti di loro, come il grafico Point e Figure, sono l'eredità del passato remoto. L'articolo descrive un esempio di grafici a point and figure utilizzando un indicatore in tempo reale.