English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
preview
Sviluppare un Expert Advisor per il trading da zero (Parte 10): Accesso agli indicatori personalizzati

Sviluppare un Expert Advisor per il trading da zero (Parte 10): Accesso agli indicatori personalizzati

MetaTrader 5Sistemi di trading | 8 novembre 2022, 12:22
409 0
Daniel Jose
Daniel Jose

Introduzione

Un EA per il trading può essere veramente utile solo se è in grado di utilizzare indicatori personalizzati; altrimenti, è solo un insieme di codici e istruzioni, che possono essere ben progettati e aiutare a gestire le posizioni o ad eseguire operazioni di mercato, ma probabilmente è tutto.

Bene, l'aggiunta di indicatori ad un grafico di MetaTrader 5 non è la parte più difficile. Ma accedere ai dati calcolati da questi indicatori direttamente nell'Expert Advisor, senza un'adeguata pianificazione, diventa un compito quasi impossibile. E se non sappiamo come farlo, ci limitiamo agli indicatori standard. Tuttavia, abbiamo bisogno di più per fare trading. Un buon esempio è l'indicatore VWAP (Volume Weighted Average Price). Si tratta di una media mobile molto importante per chi fa trading sui future della Borsa brasiliana. Questo MA non è presente tra gli indicatori standard di MetaTrader, ma possiamo creare un indicatore personalizzato che calcola il VWAP e lo visualizza sullo schermo. Tuttavia, le cose si complicano notevolmente quando decidiamo di utilizzare lo stesso indicatore in un sistema che verrà analizzato nell'EA. Senza le conoscenze necessarie, non saremo in grado di utilizzare questo indicatore personalizzato all'interno di un EA. In questo articolo vedremo come aggirare questa limitazione e risolvere il problema.


Pianificazione

Per prima cosa, proviamo a creare i calcoli da utilizzare nel nostro indicatore personalizzato. Fortunatamente, la formula di calcolo del VWAP, che utilizzeremo come esempio, è piuttosto semplice.


Tradotto in un linguaggio di programmazione, si ottiene quanto segue per MQL5:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
        double          Price = 0;
        ulong           Volume = 0;
        static int      siPos = 0;

        if (macroGetDate(time[rates_total - 1]) != macroGetDate(time[siPos]))
        {
                for (int c0 = rates_total - 1; macroGetDate(time[siPos]) != macroGetDate(time[c0]); siPos++);
                ArrayInitialize(VWAP_Buff, EMPTY_VALUE);
        }
        for (int c0 = siPos; c0 < rates_total; c0++)
        {
                Price += ((high[c0] + low[c0] + close[c0]) / 3) * volume[c0];
                Volume += volume[c0];
                VWAP_Buff[c0] = Price / Volume;
        }

    return rates_total;
}

La riga con i calcoli viene evidenziata, mentre il resto della funzione viene utilizzato per una corretta inizializzazione del DAILY VWAP. Tuttavia, il nostro indicatore non può ancora essere eseguito sul grafico e dobbiamo aggiungere alcune cose al codice. Il resto del codice può essere visto di seguito:

#property copyright "Daniel Jose - Indicador VWAP ( IntraDay )"
#property version "1.01"
#property indicator_chart_window
#property indicator_buffers     1
#property indicator_plots       1
#property indicator_width1      2
#property indicator_type1 	DRAW_LINE
#property indicator_color1 	clrBlack
//+------------------------------------------------------------------+
#define macroGetDate(A) (A - (A % 86400))
//+------------------------------------------------------------------+
double VWAP_Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        SetIndexBuffer(0, VWAP_Buff, INDICATOR_DATA);   
        
        return INIT_SUCCEEDED;
}

Ciò offre la possibilità di avere il VWAP su un grafico come mostrato in precedenza:


Beh, questa parte non era troppo complicata. Ora dobbiamo trovare un modo per far sì che l'EA veda il VWAP, in modo da analizzare l'indicatore in un modo specifico. In questo modo sarà possibile trarre vantaggio dall'indicatore nel trading.

Per facilitare il lavoro con l'indicatore, salviamo il VWAP in modo da poter essere facilmente accessibile.


Dopodiché, possiamo passare ad un nuovo modo di progettare. Sebbene l'indicatore VWAP sia essenzialmente corretto, è programmato in modo errato per essere utilizzato in un EA. Perché? Il problema è che l'EA non può sapere se l'indicatore è presente o meno sul grafico. Senza saperlo, non può leggere l'indicatore.

Il problema è che il nome del file ha poca importanza per il sistema. È possibile scrivere qualsiasi nome nel file, ma il nome dell'indicatore deve rispecchiare l'oggetto del calcolo. E il nostro indicatore non ha ancora un nome che lo rifletta. Anche se si chiamasse VWAP, non avrebbe alcun significato per il sistema. Per questo motivo, l'EA non sarà in grado di sapere se l'indicatore è presente o meno sul grafico.

Per far sì che l'indicatore rifletta ciò che sta calcolando, è necessario indicarlo nel codice. In questo modo creeremo un nome unico che non sarà necessariamente collegato al nome del file. Nel nostro caso, il codice di inizializzazione dell'indicatore dovrebbe essere simile a questo:

int OnInit()
{
        SetIndexBuffer(0, VWAP_Buff, INDICATOR_DATA);   
        IndicatorSetString(INDICATOR_SHORTNAME, "VWAP");
        
        return INIT_SUCCEEDED;
}

Aggiungendo semplicemente la riga evidenziata si risolve già il problema. In alcuni casi, può essere più difficile - ritorneremo su questo dopo. Per prima cosa, utilizziamo il codice dell'indicatore CUSTOM MOVING AVERAGE della libreria MetaTrader 5 come esempio. Il suo codice è il seguente:

void OnInit()
{
	SetIndexBuffer(0,ExtLineBuffer,INDICATOR_DATA);
	IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
	PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpMAPeriod);
	PlotIndexSetInteger(0,PLOT_SHIFT,InpMAShift);

	string short_name;
	switch(InpMAMethod)
	{
      		case MODE_EMA :
			short_name="EMA";
         		break;
      		case MODE_LWMA :
	         	short_name="LWMA";
	         	break;
      		case MODE_SMA :
         		short_name="SMA";
         		break;
      		case MODE_SMMA :
         		short_name="SMMA";
         		break;
      		default :
         		short_name="unknown ma";
     	}
   	IndicatorSetString(INDICATOR_SHORTNAME, short_name + "(" + string(InpMAPeriod) + ")");
   	PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
}

La parte evidenziata indica il nome di cui abbiamo bisogno. Notare che non ha nulla a che fare con il nome del file. Ma questo deve essere fatto esattamente all'interno dell'indicatore personalizzato.

Ora che abbiamo fatto questo e ci siamo assicurati che l'EA sarà in grado di controllare se l'indicatore personalizzato sia in esecuzione o meno sul grafico, possiamo passare alla fase successiva.


Accesso all'indicatore tramite l'EA

Possiamo continuare a fare come prima. Ma idealmente, per capire davvero cosa sta succedendo, si dovrebbe creare del codice completamente nuovo. Poiché l'idea è quella di imparare a sviluppare un Expert Advisor per il trading da zero, passiamo attraverso questa fase. Pertanto, nel prosieguo del nostro viaggio, creeremo un Expert Advisor isolato. Poi possiamo includerlo o meno nel codice finale. Procediamo ora alla scrittura del codice. L'EA inizia con un codice pulito, come si può vedere qui sotto:

//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick(){}
//+------------------------------------------------------------------+
void OnTimer(){}
//+------------------------------------------------------------------+

Procediamo come segue: per prima cosa, assumeremo che l'indicatore VWAP sia presente sul grafico e caricheremo l'ultimo valore calcolato dall'indicatore nell'Expert Advisor. Ripeteremo questa operazione ogni secondo. Ma come farlo? Semplice. Guarda come appare il codice EA dopo la modifica:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
double  Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        handle = ChartIndicatorGet(ChartID(), 0, "VWAP");
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle != INVALID_HANDLE)
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Le parti evidenziate sono quelle che abbiamo aggiunto al codice pulito. Il risultato è il seguente:


Perché ha funzionato? Questo perché MQL5 fornisce i mezzi per leggere e scrivere i dati tra i sistemi. Uno dei modi per leggere è utilizzare la funzione CopyBuffer. Funziona come segue:


In questo modo è possibile leggere i dati da qualsiasi indicatore personalizzato, cioè non siamo limitati agli indicatori standard di MetaTrader 5. Ciò significa che possiamo creare qualsiasi indicatore e funzionerà.

Consideriamo ora un altro scenario. Questa volta il VWAP non è presente sul grafico. Ma l'EA ne ha bisogno e quindi dobbiamo caricarlo sul grafico. Come farlo? È piuttosto semplice anche questo. Inoltre, lo abbiamo già utilizzato per altri scopi - quando abbiamo creato una sottofinestra per l'Expert Advisor. Quello che faremo ora è utilizzare la funzione iCustom. Ma questa volta caricheremo un indicatore personalizzato. Il codice dell'EA sarà così:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
double  Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        handle = ChartIndicatorGet(ChartID(), 0, "VWAP");
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle == INVALID_HANDLE) handle = iCustom(NULL, PERIOD_CURRENT, "VWAP.EX5");else
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Il codice evidenziato è l'unica aggiunta che abbiamo fatto al sistema originale. L'esecuzione dell'EA produce ora il seguente risultato:


La figura seguente mostra ciò che abbiamo implementato:

Questo è tutto ciò che serve al livello più elementare. Ma se si osserva attentamente, si noterà che il VWAP non è visibile sul grafico. Anche se l'EA lo utilizza, l'utente non sa cosa sta succedendo. Anche questo problema può essere facilmente risolto e il codice finale si presenta come quello qui sotto. Ricordate: è sempre bene poter analizzare e osservare ciò che l'EA sta facendo, perché non è molto sicuro lasciargli piena libertà, quindi vi sconsiglio di farlo:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
long    id;
double  Buff[];
string  szCmd;
//+------------------------------------------------------------------+
int OnInit()
{
        szCmd = "VWAP";
        handle = ChartIndicatorGet(id = ChartID(), 0, szCmd);
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        ChartIndicatorDelete(id, 0, szCmd);
        IndicatorRelease(handle);
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle == INVALID_HANDLE)
        {
                if ((handle = iCustom(NULL, PERIOD_CURRENT, "VWAP.EX5")) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle);
        }else
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Il codice EA di cui sopra leggerà l'ultimo valore calcolato dal VWAP e lo visualizzerà sullo schermo. Se l'indicatore non è presente sul grafico, verrà caricato e visualizzato. Se rimuoviamo l'EA dal grafico, anche il VWAP verrà rimosso dallo schermo. In questo modo, l'EA avrà sempre a disposizione gli elementi necessari per eseguire i calcoli. I risultati di quanto ho spiegato sono mostrati di seguito:


Si potrebbe pensare che questo non sia molto fattibile, poiché ovviamente non abbiamo apportato alcuna modifica all'indicatore. Ma anche con i passaggi precedenti, possiamo implementare tutto ciò che riguarda gli indicatori personalizzati. Per una spiegazione finale, consideriamo un altro esempio. Applichiamo una media mobile e utilizziamo l'Expert Advisor allo stesso modo di come abbiamo fatto con il VWAP, solo che ora specificheremo i parametri della media.


Secondo caso: utilizzo delle medie mobili

Il calcolo della media mobile non è importante in questa sede, poiché ci concentreremo su come passare i parametri in un indicatore personalizzato. Ecco il nuovo indicatore personalizzato:

#property copyright "Daniel Jose 16.05.2021"
#property description "Basic Moving Averages (Optimizes Calculation)"
#property indicator_chart_window
//+------------------------------------------------------------------+
enum eTypeMedia
{
        MME,    //Exponential moving average
        MMA     //Arithmetic moving average
};
//+------------------------------------------------------------------+
#property indicator_buffers             1
#property indicator_plots               1
#property indicator_type1               DRAW_LINE
#property indicator_width1              2
#property indicator_applied_price       PRICE_CLOSE
//+------------------------------------------------------------------+
input color      user00 = clrRoyalBlue; //Cor
input int        user01 = 9;            //Periods
input eTypeMedia user02 = MME;          //MA type
input int user03 = 0;            //Displacement
//+------------------------------------------------------------------+
double Buff[], f_Expo;
//+------------------------------------------------------------------+
int OnInit()
{
        string sz0 = "MM" + (user02 == MME ? "E": (user02 == MMA ? "A" : "_")) + (string)user01;
        
        f_Expo = (double) (2.0 / (1.0 + user01));
        ArrayInitialize(Buff, EMPTY_VALUE);
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        PlotIndexSetInteger(0, PLOT_LINE_COLOR, user00);
        PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, user01);
        PlotIndexSetInteger(0, PLOT_SHIFT, user03);
        IndicatorSetString(INDICATOR_SHORTNAME, sz0);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
        double Value;
        int c0;

        switch (user02)
        {
                case MME:
                        if (user01 < rates_total)
                        {       
                                for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : 0); c0 < rates_total - user03; c0++)
                                        Buff[c0] = (c0 > 0? ((price[c0] - Buff[c0 - 1]) * f_Expo) + Buff[c0 - 1] : price[c0] * f_Expo);
                                for (; c0 < rates_total; c0++)
                                        Buff[c0] = EMPTY_VALUE;
                        }
                        break;
                case MMA:
                        if (user01 < rates_total)
                        {
                                if (prev_calculated == 0) 
                                {       
                                        Value = 0;
                                        for (int c1 = 0; c1 < user01; c1++) Value += price[user01 - c1];
                                        Buff[user01] = Value / user01;
                                }
                                for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : user01 + 1); c0 < rates_total - user03; c0++)
                                        Buff[c0] = ((Buff[c0 - 1] * user01) - price[c0 - user01] + price[c0]) / user01;
                                for (; c0 < rates_total; c0++)
                                        Buff[c0] = EMPTY_VALUE;
                        }
                        break;
        }
        
        return rates_total;
}
//+------------------------------------------------------------------+

Ora Il nome dell'indicatore dipenderà da diversi fattori. In seguito possiamo effettuare il controllo dell'EA e adattarlo a ogni situazione. Ad esempio, supponiamo che il nostro EA utilizzi due medie mobili e le visualizzi sul grafico. Prestate attenzione alle parti evidenziate nel codice sopra riportato - abilitare l'EA e la funzione iCustom in questo caso, per modificare e configurare i parametri dell'indicatore. È importante capire questo aspetto per poterlo implementare se necessario. Quindi, una delle medie è una MA esponenziale a 17 periodi e l'altra è una MA aritmetica a 52 periodi. La MA a 17 periodi sarà verde e quella a 52 periodi sarà rossa. L'EA vedrà l'indicatore come una funzione nella forma seguente:

Media (Colore, Periodo, Tipo, Scostamento) quindi ora l'indicatore non è un file separato ma una funzione EA. Questo è molto comune nella programmazione, perché chiamiamo un programma con i relativi parametri per eseguire un determinato compito e alla fine otteniamo il risultato in modo più semplice. La domanda è: Come possiamo fare in modo che il nostro EA crei e gestisca questo scenario nello stesso modo in cui abbiamo fatto con il VWAP?

A tal fine, è necessario modificare il codice EA. Il codice completo del nuovo EA è riportato di seguito:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
long    id;
int     handle1, handle2;
double  Buff1[], Buff2[];
string  szCmd1, szCmd2;
//+------------------------------------------------------------------+
int OnInit()
{
        szCmd1 = "MME17";
        szCmd2 = "MMA52";
        id = ChartID();
        handle1 = ChartIndicatorGet(id, 0, szCmd1);
        handle2 = ChartIndicatorGet(id, 0, szCmd2);
        SetIndexBuffer(0, Buff1, INDICATOR_DATA);
        SetIndexBuffer(0, Buff2, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        ChartIndicatorDelete(id, 0, szCmd1);
        ChartIndicatorDelete(id, 0, szCmd2);
        IndicatorRelease(handle1);
        IndicatorRelease(handle2);
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i1, i2;
        
        if (handle1 == INVALID_HANDLE)
        {
                if ((handle1 = iCustom(NULL, PERIOD_CURRENT, "Media Movel.EX5", clrGreen, 17, 0)) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle1);
        };
        if (handle2 == INVALID_HANDLE)
        {
                if ((handle2 = iCustom(NULL, PERIOD_CURRENT, "Media Movel.EX5", clrRed, 52, 1)) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle2);
        };
        if ((handle1 != INVALID_HANDLE) && (handle2 != INVALID_HANDLE))
        {
                i1 = CopyBuffer(handle1, 0, 0, 1, Buff1);
                i2 = CopyBuffer(handle2, 0, 0, 1, Buff2);
                Print(Buff1[0], "<< --- >>", Buff2[0]);
        }
}
//+------------------------------------------------------------------+

Ed ecco il risultato:


Prestate attenzione alle parti evidenziate del codice dell’EA. Questo è esattamente ciò di cui abbiamo bisogno: passiamo i parametri all'indicatore utilizzando lo stesso meccanismo che abbiamo usato nel VWAP. Tuttavia, nel caso del VWAP, non è stato necessario passare alcun parametro, a differenza delle medie mobili, che prevedono il passaggio di parametri. Tutto questo offre un grado di libertà molto ampio.


Conclusioni

Questo articolo non contiene un codice universale. In ogni caso, abbiamo approfondito due diversi Expert Advisor e due diversi indicatori personalizzati, per capire come utilizzare questo tipo di sistema in un Expert Advisor più complesso e ponderato. Credo che con queste conoscenze possiamo utilizzare i nostri indicatori personalizzati. Anche il nostro EA può fornire un'analisi molto interessante. Tutto ciò dimostra che MetaTrader 5 è la piattaforma più versatile che un trader possa desiderare. Se qualcun altro non l'ha capito, semplicemente non l'ha studiata fino in fondo.

Utilizzate le conoscenze presentate in questo articolo, perché MetaTrader 5 vi permette di andare molto più lontano di quanto molti siano stati in grado di fare finora.

Ci vediamo nel prossimo articolo.


Link

Come chiamare gli indicatori in MQL5

Indicatori Personalizzati in MQL5 per Principianti

MQL5 per Principianti: Guida all'utilizzo dei valori degli indicatori tecnici negli Expert Advisor



Tradotto dal portoghese da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/pt/articles/10329

Sviluppare un Expert Advisor per il trading da zero (Parte 11): Sistema di ordini incrociati Sviluppare un Expert Advisor per il trading da zero (Parte 11): Sistema di ordini incrociati
In questo articolo creeremo un sistema di ordini incrociati. C'è un tipo di asset che rende la vita dei trader molto difficile — i contratti future. Ma perché rendono la vita difficile?
Come creare grafica 3D utilizzando DirectX in MetaTrader 5 Come creare grafica 3D utilizzando DirectX in MetaTrader 5
La grafica 3D offre strumenti eccellenti per l'analisi di enormi quantità di dati, poiché consente la visualizzazione di schemi nascosti. Questi compiti possono essere risolti direttamente in MQL5, mentre le funzioni DireсtX consentono di creare oggetti tridimensionali. In questo modo è possibile creare programmi di qualsiasi complessità, persino giochi in 3D per MetaTrader 5. Inizia ad imparare la grafica 3D disegnando semplici forme tridimensionali.
Scopri come progettare un sistema di trading tramite OBV Scopri come progettare un sistema di trading tramite OBV
Questo è un nuovo articolo che continua la nostra serie per principianti su come progettare un sistema di trading basato su alcuni degli indicatori popolari. Scopriremo un nuovo indicatore che è On Balance Volume (OBV) e impareremo come usarlo e a progettare un sistema di trading basato su di esso.
Visualizza questo! Libreria grafica di MQL5 simile a 'plot' del linguaggio R Visualizza questo! Libreria grafica di MQL5 simile a 'plot' del linguaggio R
Quando si studia la logica del trading, la rappresentazione visiva sotto forma di grafici è di grande importanza. Alcuni linguaggi di programmazione popolari tra la comunità scientifica (come R e Python) dispongono della speciale funzione "plot" utilizzata per la visualizzazione. Permette di disegnare linee, distribuzioni di punti e istogrammi per visualizzare i modelli. In MQL5, è possibile fare lo stesso utilizzando la classe CGraphics.