English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
preview
Indicatori multipli su un grafico (Parte 04): Passiamo a un Expert Advisor

Indicatori multipli su un grafico (Parte 04): Passiamo a un Expert Advisor

MetaTrader 5Trading | 2 agosto 2022, 16:31
195 0
Daniel Jose
Daniel Jose

Introduzione

Nei miei articoli precedenti, ho spiegato come creare un indicatore con più finestre secondarie, cosa che diventa molto utile quando si utilizzano indicatori personalizzati. Sarete d’accordo sul fatto che sia stato piuttosto facile farlo. Quando però proviamo ad applicare la stessa funzionalità ad un Expert Advisor, le cose diventano un po' più complicate poiché non disponiamo degli strumenti che abbiamo utilizzato nel caso dell’indicatore personalizzato. A questo punto la programmazione diventa essenziale. Saper scrivere il codice corretto per creare una sottofinestra è fondamentale. Anche se questo compito non è così facile, sapere come inserire una sottofinestra in un EA non richiede una grande quantità di codice, ma solo una certa conoscenza del funzionamento di MQL5.


Pianificazione

Abbiamo già il nostro indicatore personalizzato funzionante, ovvero la nostra classe di oggetti è già funzionante e, dal momento che si tratta di una classe di oggetti, possiamo trasferirla agevolmente ad altri modelli. Nel caso di un EA, la semplice dichiarazione e il tentativo di utilizzare la classe nel nostro EA non farà funzionare le cose come nel nostro indicatore personalizzato e il motivo è che, stavolta, non abbiamo funzionalità di sottofinestra. Vediamo come risolvere. "Cosa succederebbe se utilizzassimo un indicatore personalizzato già compilato e funzionante e lo richiamassimo attraverso l'EA, utilizzando il comando iCustom? Così potrebbe funzionare, dato che la sottofinestra non è necessaria. Il comando sarebbe del seguente tipo:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
input string user01 = "";                //Used indicators
input string user02 = "";                //Assets to follow
//+------------------------------------------------------------------+
int OnInit()
{
        int m_handleSub;

//... Expert Advisor code ...

        if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED;
        if (!ChartIndicatorAdd(ChartID(), 0, m_handleSub)) return INIT_FAILED;
//... Expert Advisor code ...

        ChartRedraw();
        
        return(INIT_SUCCEEDED);
}
//...The rest of the Expert Advisor code ...

Questo semplice frammento di codice è in grado di caricare il nostro indicatore personalizzato tuttavia non funzionerà correttamente perché non abbiamo una sottofinestra. In questo caso, una volta che il codice sarà stato eseguito nell'EA, quest’ultimo applicherà il nostro indicatore direttamente alla finestra principale. Questo comporta che il nostro grafico sarà nascosto dai template caricati dall'indicatore, il che non è certamente il risultato che desideriamo.

Il problema da risolvere è quindi come creare una sottofinestra per utilizzare il nostro indicatore già funzionante. Potremmo chiederci il perché di creare una sottofinestra per il successivo lancio del nostro indicatore. In effetti non ha senso; è meglio aggiungere la funzionalità direttamente al nostro EA e superare così le eventuali limitazioni.

Partendo da questo presupposto, dobbiamo eseguire diverse operazioni:

Compito. Scopo
1 => Creare un indicatore generico. Creare e utilizzare il comando iCustom senza sporcare il grafico.
2 => Includere in qualche modo questo indicatore nell'EA.  Rendere possibile il trasferimento dell'Expert Advisor con tutte le sue funzionalità senza problemi.
3 => Generare una classe oggetto generale per la sottofinestra  Aggiungere sottofinestre tramite l'EA
4 => Ottenere la classe C_TemplateChart legata alla classe window. Gestire il contenuto delle sottofinestre senza modificare nulla nel codice già in esecuzione.

Anche se potrebbe sembrare difficile, vedrete che le difficoltà sono risolvibili in modo molto semplice. Affrontiamo quindi i singoli punti.


Implementazione: Creazione di un indicatore generico

Per risolvere questa parte del nostro compito creando un codice indicatore personalizzato, completamente pulito ma funzionale. Il codice in questo caso sarà simile al seguente:

#property copyright "Daniel Jose"
#property version   "1.00"
#property description "This file only enables support of indicators in SubWin."
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
int OnInit()
{
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
        return rates_total;
}
//+------------------------------------------------------------------+

Dobbiamo solo salvare questo file come SubSupport.mq5. Quest’ultimo però non lo troveremo insieme agli altri indicatori, bensì lo sposteremo nella directory RISORSA del nostro Expert Advisor. Di conseguenza, la struttura dei file apparirà come nell'immagine seguente:


C'è una buona ragione per questo, ma mettiamola da parte per ora. Passiamo ora al compito successivo.


Implementazione: Includere l'indicatore generale nell'EA

A tal fine, è necessario aggiungere il seguente codice all'inizio del nostro EA.

//+------------------------------------------------------------------+
#define def_Resource "Resources\\SubSupport.ex5"
//+------------------------------------------------------------------+
#resource def_Resource
//+------------------------------------------------------------------+

In questo modo, il codice compilato dell'indicatore generale verrà incluso nel nostro EA. Una volta effettuata questa operazione, sarà cancellato dall'indicatore generale il file .ex5, perché non più necessario. A questo punto è necessario prestare attenzione al fatto che se il file SubSupport.ex5 non viene trovato al momento della compilazione del codice dell'EA, il compilatore utilizzerà automaticamente il codice dell'indicatore generale SubSupport. mq5e aggiungerà il nuovo file eseguibile al nostro Expert Advisor. Quindi, se si modifica il file SubSupport.mq5 e si volesse aggiungere le modifiche all'Expert Advisor, è necessario cancellare il file SubSupport.ex5altrimenti le modifiche non verranno aggiunte.

Questo dettaglio è importante: a volte è necessario sapere come aggiungere le modifiche appena implementate alla risorsa.

L'indicatore generale, a questo punto, fa parte dell'Expert Advisor, quindi passiamo al compito successivo.


Implementazione Creazione di una classe di oggetti sottofinestra

Anche questa parte è semplice. Prima di procedere alla codifica, dobbiamo definire alcuni punti: di quali caratteristiche abbiamo realmente bisogno in questa classe? Inizialmente ho deciso di utilizzare quanto segue:

Funzione Descrizione
Init Aggiungere sottofinestre tramite l'EA
Close Aggiungere sottofinestre tramite l'EA

Queste funzioni non saranno testate, quindi suppongo che saranno richiamate solo una volta durante la vita dell'EA. Il nostro EA, però, sarà sviluppato ulteriormente pertanto è bene riflettere su come renderlo ancora più pratico in futuro. In quest’ottica, creiamo una nuova classe di oggetti chiamata C_Terminale - questa classe supporterà alcune elementi relativi al terminale grafico. Ne sapremo di più in seguito. Esaminiamo l'ultimo compito, poiché non c'è modo di implementare la soluzione in modo parziale.


Implementazione: Eredità della classe C_TemplateChart

Quando in passato ho deciso di creare qualcosa di nuovo utilizzando l'OOP (Programmazione orientata agli oggetti), l’ho fatto perché consapevole del fatto che l'utilizzo di questo approccio presentava seri vantaggi, tra cui la sicurezza e l'ereditarietà. Esiste anche il polimorfismo, ma lo useremo più avanti quando creeremo un sistema di ordini incrociati. In questo caso particolare utilizzeremo uno dei vantaggi dell'OOP: l'ereditarietà. C_TemplateChart è già una classe completamente funzionale. In questo caso, non vorremmo avere il problema di dover riprogrammare tutto da capo o rischiare di aggiungere codice alla classe, impedendo che questa possa essere utilizzata in altri luoghi. La soluzione è utilizzare l'ereditarietà, che consente di aggiungere nuovo codice o funzione senza modificare affatto il codice originale.

L'uso dell'ereditarietà presenta una serie di vantaggi, inclusi i seguenti: il codice già testato rimane tale; la complessità cresce senza un corrispondente aumento della dimensione del codice; solo le nuove funzionalità devono davvero essere testate; ciò che non cambia viene semplicemente ereditato, fornendo stabilità. In altre parole, le cose migliorano con il minimo sforzo e con la massima sicurezza. Per comprendere meglio, diamo un'occhiata alla documentazione:

La classe nonno è la classe più elementare in cui abbiamo il livello più basso di manipolazione dei dati. Quando però la classe genitore eredita qualcosa dal nonno, tutte gli elementi dichiarati come pubblici nella classe nonno possono essere visti e utilizzati dalla classe genitore. Possiamo anche aggiungere nuovi elementi alla classe genitore, senza che questo influisca su ciò che è stato ereditato ed è supportato dall'ereditarietà. Se la classe madre è già finita e funzionante e vogliamo estenderla senza modificare nulla nelle classi sottostanti, creiamo una classe figlia, che avrà tutte le caratteristiche delle classi precedenti. E’ anche possibile intervenire sul funzionamento delle cose, e questa è l’aspetto interessante dell'ereditarietà: le modifiche infatti non influiranno sulle altre classi. C'è una limitazione da segnalare: in C++, che consente l'ereditarietà multipla, un figlio può ereditare funzioni sia dal padre che dalla madre ma questo non è possibile in MQL5. Si può però beneficiare comunque dell'eredità. Di seguito è riportato un esempio di eredità multipla:

Ok, ma come farlo in MQL5? Come dichiarare un'eredità per poterne trarre vantaggio? Il modo più preciso per comprenderlo è leggere i contenuti della programmazione orientata agli oggetti (OOP). Qui andremo dritti al punto. L'ereditarietà sarà realizzata con le seguenti linee:

#include "C_TemplateChart.mqh"
//+------------------------------------------------------------------+
class C_SubWindow : public C_TemplateChart
{
// ... Class code
};

Si noti che la classe C_SubWindow erediterà pubblicamente la classe C_TemplateChart il che significa che ora possiamo usare la classe C_Sottofinestra per accedere alle funzionalità della classe C_TemplateChart.

Nel frammento di codice sopra riportato, ho evidenziato una cosa. Si noti che è tra virgolette ( " ) e non tra parentesi angolari ( < > ) come di consueto. Perché l'ho fatto? Come il linguaggio C++, anche l'MQL5 ha alcune caratteristiche molto interessanti, ma alcune confondono chi sta iniziando a imparare l'arte della programmazione. Quando inseriamo un file di intestazione tra parentesi angolari ( < > ), intendiamo un percorso assoluto: in questo caso il compilatore seguirà esattamente il percorso specificato. Quando invece usiamo le virgolette (come abbiamo fatto in questo caso), il compilatore userà un percorso relativo o, per essere più precisi, partirà dalla directory corrente in cui si trova il file di lavoro. Può sembrare strano ma a volte capita di avere lo stesso nome per file che hanno contenuti diversi e si trovano in directory diverse, ma si vuole comunque fare riferimento alla directory corrente. E’ per questo motivo che si usano le virgolette.

Le due funzioni che intendiamo utilizzare in precedenza, INIT e CLOSE, sono mostrate di seguito:

//+------------------------------------------------------------------+
bool Init(void)
{
        if (m_handleSub != INVALID_HANDLE) return true;
        if ((m_handleSub = iCustom(NULL, 0, "::" + def_Resource)) == INVALID_HANDLE) return false;
        m_IdSub = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WINDOWS_TOTAL);
        if (!ChartIndicatorAdd(Terminal.Get_ID(), m_IdSub, m_handleSub)) return false;
                
        return true;
}
//+------------------------------------------------------------------+
void Close(void)
{
        ClearTemplateChart();
        if (m_handleSub == INVALID_HANDLE) return;
        IndicatorRelease(m_IdSub);
        ChartIndicatorDelete(Terminal.Get_ID(), m_IdSub, ChartIndicatorName(Terminal.Get_ID(), m_IdSub, 0));
        ChartRedraw();
        m_handleSub = INVALID_HANDLE;
}
//+------------------------------------------------------------------+

Il codice è molto semplice e breve. Come vedete, c'è un particolare che richiede attenzione. Notate la parte evidenziata. Dovete stare attenti a non commettere errori nell'aggiungere questa parte, perché se non la lasciate così com'è, il file eseguibile SubSupport.ex5 che abbiamo chiesto di aggiungere all'EA non sarà visibile all'interno dell'EA, bensì all'esterno. Per maggiori dettagli, potete leggere Risorse. In pratica, se si utilizza ( :: ), si indica che l'EA deve utilizzare la risorsa interna disponibile al suo interno. Se invece indichiamo solo il nome della risorsa, l'EA la cercherà all'interno della directory MQL5 e se il file non dovesse esistere nella posizione specificata, la funzione fallirebbe anche se il file fosse stato aggiunto come risorsa EA.

A questo punto, una volta caricata la risorsa, controlliamo il numero di sottofinestre presenti e aggiungiamo un indicatore a quella sottofinestra.

Di seguito è possibile vedere cosa fa il codice:

input string user01 = "";               //Used indicators
input string user02 = "";               //Assets to follows
//+------------------------------------------------------------------+
int OnInit()
{
        int m_handleSub;

//...   

        if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED;
        if (!ChartIndicatorAdd(ChartID(), (int) ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL), m_handleSub)) return INIT_FAILED;

//...

        ChartRedraw();
        
   return(INIT_SUCCEEDED);
}
//...The rest of the Expert Advisor code ...

Entrambi i codici funzioneranno allo stesso modo, ma la versione della classe oggetto ci consentirà di aggiungere altre cose nel tempo, dato che la versione mostrata sopra è quella consolidata e non cambierà. Entrambe le versioni fanno la stessa cosa: creano una sottofinestra dell'EA e vi inseriscono tutti gli indicatori personalizzati creati in precedenza. Prestate attenzione alle modifiche apportate al codice rispetto alla forma che aveva all'inizio dell'articolo: le modifiche sono evidenziate in colore.


Conclusione

È molto interessante la scelta del percorso da utilizzare per raggiungere i nostri obiettivi. A volte, di fronte alle difficoltà pensiamo di non poterli raggiungere ma, con un po' di pazienza e dedizione, alla fine possiamo superare ostacoli che all'inizio sembravano insormontabili. In questo articolo vi ho mostrato come sia possibile estendere le funzionalità di una classe senza doverla modificare, grazie all'ereditarietà. Allo stesso tempo, vi ho fatto vedere come aggiungere gli indicatori ai grafici in modo che funzionino come già testati. Aggiungiamo il programma ex5 all'interno del nostro EA e lo utilizziamo senza dover eseguire il porting dell'ex5 originale, semplicemente caricando l'EA.

Il file allegato contiene tutti i miglioramenti sviluppati finora, ma presto ci saranno cose ancora più interessanti in questo codice. 😁👍


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

File allegati |
Scopriamo come creare un sistema di trading con l'indicatore RSI Scopriamo come creare un sistema di trading con l'indicatore RSI
In questo articolo, vi parlerò di uno degli indicatori più popolari e utilizzati nel mondo del trading, ovvero l’RSI. Vedremo insieme come mettere in piedi un sistema di trading con questo indicatore.
Un'analisi del motivo per cui gli Expert Advisor falliscono Un'analisi del motivo per cui gli Expert Advisor falliscono
Questo articolo presenta un'analisi di dati del mercato forex per comprendere meglio perché gli Expert Advisor registrano buone prestazioni in alcuni periodi e deludenti in altri.
Indicatori multipli su un grafico (Parte 05): Trasformiamo MetaTrader 5 in un sistema RAD (I) Indicatori multipli su un grafico (Parte 05): Trasformiamo MetaTrader 5 in un sistema RAD (I)
Tante persone non sanno programmare ma sono molto creative e hanno grandi idee. Purtroppo però, la mancanza di conoscenze di programmazione impedisce loro di realizzare queste idee. Vediamo insieme come creare un Chart Trade utilizzando la piattaforma MetaTrader 5 stessa, come se fosse un IDE.
Scopri come creare un sistema di trading con l’indicatore Momentum Scopri come creare un sistema di trading con l’indicatore Momentum
Nel mio precedente articolo ho parlato dell'importanza di identificare la tendenza di mercato, ovvero la direzione dei prezzi. In questo articolo esaminerò uno dei indicatori tecnici più importanti: l'indicatore Momentum. Vedremo insieme come progettare un sistema di trading basato sul Momentum.