English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
preview
Sviluppare un Expert Advisor per il trading da zero (Parte 7): Aggiunta dei Volumi al Prezzo (I)

Sviluppare un Expert Advisor per il trading da zero (Parte 7): Aggiunta dei Volumi al Prezzo (I)

MetaTrader 5Trading | 6 ottobre 2022, 10:00
517 0
Daniel Jose
Daniel Jose

Introduzione

Chiunque faccia trading provando ad avere un certo grado di sicurezza deve avere questo indicatore sul proprio grafico. Molto spesso l'indicatore viene utilizzato da coloro che preferiscono la lettura del nastro durante il trading. Inoltre, l'indicatore può essere utilizzato da coloro che fanno trading solo sulla base dell'analisi della Price Action. Questo è un indicatore di volumi orizzontale estremamente utile che può essere utilizzato per analizzare i volumi degli scambi che si sono verificati in un particolare momento di prezzo. Tuttavia, la lettura corretta dell'indicatore può essere difficile. Aggiungerò un link alla fine dell'articolo, per far si, tu possa imparare di più su questo.

Qui non ci soffermeremo su come interpretare le letture degli indicatori, perché questo è al di là dello scopo di questo articolo. Lo scopo di questo articolo è quello di mostrare come progettare e creare questo indicatore in modo tale che non degradi le prestazioni della piattaforma MetaTrader 5. Ecco un fatto interessante: anche se molti pensano che questo indicatore dovrebbe essere aggiornato in tempo reale, in realtà un piccolo ritardo è accettabile, purché sia davvero piccolo. Sulla base della mia esperienza, non ho visto grandi problemi con un ritardo nell'aggiornamento delle informazioni di circa 1 secondo. Tuttavia, se è importante per te usare il tempo reale, dovrai fare piccoli cambiamenti. Le modifiche dovrebbero essere apportate non nell'indicatore in sè, ma nei punti in cui l'Expert Advisor chiama questo indicatore in modo che la chiamata avvenga in tempo reale. Tuttavia, credo che l'impatto sulle prestazioni sarà minimo, quindi il ritardo può essere trascurato.


Interfaccia

L'interfaccia di controllo della classe Volume At Price è molto semplice, ma per un controllo completo è necessario garantire le corrette proprietà del grafico su cui verrà applicato l'indicatore. Le proprietà sono mostrate nella figura seguente, con il controllo principale evidenziato.

Se la griglia non è visibile, non sarà possibile ridimensionare l'indicatore come mostrato nelle animazioni seguenti. Si noti che l'interfaccia è molto semplice ed intuitiva: ha solo due controlli, uno dei quali indica la dimensione, e l'altro mostra il punto di partenza per l'analisi dei volumi.

    

In generale, questo indicatore è abbastanza efficace e molto interessante in implementazione e costruzione. In questo articolo, lavoreremo con il suo livello base, e poi lo miglioreremo nel prossimo articolo.

Non ho altro da dire sull'interfaccia, quindi passiamo all'implementazione del codice.


Implementazione

Al fine di avere il minor lavoro possibile durante la creazione dell'indicatore, divideremo il nostro codice sorgente in più parti e faremo anche alcune modifiche e aggiunte. Iniziamo suddividendo il codice in più parti, poiché gran parte di ciò di cui abbiamo bisogno è già scritto altrove. La parte principale è nella classe C_Wallpaper. Cosa dobbiamo fare? Creeremo un indicatore basato su una bitmap? Sì, qualsiasi immagine sullo schermo di un computer dovrebbe essere trattata come una BITMAP, ma dovrebbe essere costruita in un modo speciale. Quindi, la nuova classe di oggetti C_Wallpaper sarà così:

class C_WallPaper : public C_Canvas
{
        protected:
                enum eTypeImage {IMAGEM, LOGO, COR};
//+------------------------------------------------------------------+
        private :
        public  :
//+------------------------------------------------------------------+
                ~C_WallPaper()
                        {
                                Destroy();
                        }
//+------------------------------------------------------------------+
                bool Init(const string szName, const eTypeImage etype, const char cView = 100)
                        {
                                if (etype == C_WallPaper::COR) return true;
                                if (!Create(szName, 0, 0, Terminal.GetWidth(), Terminal.GetHeight())) return false;
                                if(!LoadBitmap(etype == C_WallPaper::IMAGEM ? "WallPapers\\" + szName : "WallPapers\\Logos\\" + _Symbol, cView)) return false;
                                ObjectSetInteger(Terminal.Get_ID(), szName, OBJPROP_BACK, true);

                                return true;
                        }
//+------------------------------------------------------------------+
                void Resize(void)
                        {
                                ResizeBitMap(Terminal.GetWidth(), Terminal.GetHeight());
                        }
//+------------------------------------------------------------------+
};


Guarda, il codice è diventato molto più compatto: abbiamo rimosso le parti comuni tra le classi C_Wallpaper e C_VolumeAtPrice e abbiamo messo tutto in un'altra classe, che è la classe C_C_Canvas.

Ma perché non utilizzare la classe C_Canvas di MetaTrader 5? La questione è più personale che pratica. Mi piace avere più controllo su tutto ciò che scrivo e sviluppo, ma questa è più una cattiva abitudine per un programmatore di C di qualcosa di veramente necessario. Ecco perché ho bisogno di creare una classe per disegnare oggetti sullo schermo. Naturalmente, è possibile utilizzare la classe già disponibile in MetaTrader 5. Ora concentriamoci sulla classe C_VolumeAtPrice, che è l'obiettivo principale di questo articolo. La classe ha sette funzioni che sono mostrate nella seguente tabella.

Funzione Descrizione Tipo di accesso 
Init Inizializza la classe con valori specificati dall'utente. Generale
Update Aggiorna i dati Volume At Price a intervalli specifici. Generale
Resize Cambia la dimensione dell'immagine Volume At Price sul grafico, il che rende più facile analizzare alcuni dettagli. Generale
DispatchMessage  Utilizzato per inviare messaggi ad una classe di oggetti. Generale
FromNowOn  Inizializza le variabili di sistema Privato
SetMatrix Crea e mantiene una matrice con i dati dei volumi Privato
Redraw Crea un'immagine dei volumi Privato

Passiamo ora all'implementazione del sistema, iniziando con la dichiarazione delle variabili nel codice qui sotto:

#define def_SizeMaxBuff                 4096
//+------------------------------------------------------------------+
#define def_MsgLineLimit                "Starting point from Volume At Price"
//+------------------------------------------------------------------+
class C_VolumeAtPrice : private C_Canvas
{
#ifdef macroSetInteger
        ERROR ...
#endif
#define macroSetInteger(A, B) ObjectSetInteger(Terminal.Get_ID(), m_Infos.szObjEvent, A, B)
        private :
                uint    m_WidthMax,
                        m_WidthPos;
                bool    m_bChartShift,
                        m_bUsing;
                double  m_dChartShift;
                struct st00
                {
                        ulong   nVolBuy,
                                nVolSell,
                                nVolTotal;
                        long    nVolDif;
                }m_InfoAllVaP[def_SizeMaxBuff];
                struct st01
                {
                        ulong    memTimeTick;
                        datetime StartTime,
                                 CurrentTime;
                        int      CountInfos;
                        ulong    MaxVolume;
                        color    ColorSell,
                                 ColorBuy,
                                 ColorBars;
                        int      Transparency;
                        string   szObjEvent;
                        double   FirstPrice;
                }m_Infos;


La parte evidenziata in questo codice è quello a cui si dovrebbe prestare attenzione. Questa parte assicura che la definizione non provenga da un altro file in un modo tale da andare in conflitto con la definizione che useremo in quel file. Infatti, il compilatore MQL5 mostra un avvertimento quando si tenta di sovrascrivere una definizione esistente, e in alcuni casi è difficile capire come risolverlo. Pertanto, per rendere la nostra vita un po' più facile, usiamo il test evidenziato nel codice sopra. Il resto della roba in questo codice non è particolarmente interessante. L'unica cosa a cui prestare attenzione è la definizione def_SizeMaxBuff. Indica quale sarà la dimensione del nostro array di dati dei volumi. Se necessario, è possibile modificare questo valore in un altro, ma secondo i risultati dei test, questo valore è più che adeguato per la stragrande maggioranza dei casi. Esso rappresenta le variazioni nei ticks tra il prezzo basso e il prezzo, e quindi il valore corrente può essere gestito in una vasta gamma di casi.


La funzione Init: dove tutto ha inizio

È questa la funzione che inizializza correttamente tutte le variabili. E' chiamata nell' Expert Advisor come segue:

//.... Dati iniziali....

input color     user10   = clrForestGreen;      //Colore della linea di Take Profit
input color     user11   = clrFireBrick;        //Colore della linea di Stop
input bool      user12   = true;                //Giorno di Trade?
input group "Volume At Price"
input color     user15  = clrBlack;             //Colore delle barre
input char      user16  = 20;                   //Transparenza (from 0 to 100 )
//+------------------------------------------------------------------+
C_SubWindow             SubWin;
C_WallPaper             WallPaper;
C_VolumeAtPrice         VolumeAtPrice;
//+------------------------------------------------------------------+          
int OnInit()
{
        Terminal.Init();
        WallPaper.Init(user03, user05, user04);
        if ((user01 == "") && (user02 == "")) SubWin.Close(); else if (SubWin.Init())
        {
                SubWin.ClearTemplateChart();
                SubWin.AddThese(C_TemplateChart::SYMBOL, user02);
                SubWin.AddThese(C_TemplateChart::INDICATOR, user01);
        }
        SubWin.InitilizeChartTrade(user06, user07, user08, user09, user10, user11, user12);
        VolumeAtPrice.Init(user10, user11, user15, user16);

// ... Resto del codice

Non ci sono molti parametri qui, e rappresentano principalmente le informazioni sui colori che l'indicatore utilizzerà. Successivamente, diamo un'occhiata al suo codice interno per questa funzione. Il codice sottostante mostra come tutto viene inizializzato:

void Init(color CorBuy, color CorSell, color CorBar, char cView)
{
        m_Infos.FirstPrice = Terminal.GetRatesLastDay().open;
        FromNowOn(macroSetHours(macroGetHour(Terminal.GetRatesLastDay().time), TimeLocal()));
        m_Infos.Transparency = (int)(255 * macroTransparency(cView));
        m_Infos.ColorBars = CorBar;
        m_Infos.ColorBuy = CorBuy;
        m_Infos.ColorSell = CorSell;
        if (m_bUsing) return;
        m_Infos.szObjEvent = "Event" + (string)ObjectsTotal(Terminal.Get_ID(), -1, OBJ_EVENT);
        CreateObjEvent();
        m_bChartShift = ChartGetInteger(Terminal.Get_ID(), CHART_SHIFT);
        m_dChartShift = ChartGetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE);
        ChartSetInteger(Terminal.Get_ID(), CHART_SHIFT, true);
        ChartSetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE, 0.1);
        Create("VaP" + (string)MathRand(), 0, 0, 1, 1);
        Resize();
        m_bUsing = true;
};


Come puoi vedere, è tutto molto semplice qui. E ci sono ancora alcune caratteristiche che rendono il codice interessante. Una di queste è Terminal.GetRatesLastDay().open. Anche se questo può sembrare strano, è in realtà una situazione molto comune quando seguiamo i principi della Programmazione Orientata agli Oggetti (OOP). Uno di questi principi afferma che nulla al di fuori della classe dovrebbe avere accesso alle variabili interne della classe. Ma come ottenere i valori delle variabili all'interno della classe? Il modo corretto è usare un form che appare solo in OOP, quindi vediamo come viene dichiarata la funzione GetRatesLastDay all'interno della classe C_Terminal. Questo può essere visto nel codice qui sotto:

inline MqlRates GetRatesLastDay(void) const { return m_Infos.Rates; }


Vediamo come funziona effettivamente. Iniziamo con la parola riservata inline. Indicherà al compilatore che il codice deve essere messo in tutte le posizioni dove compare. Invece di generare una chiamata alla funzione, il compilatore copia in realtà tutto il codice dalla funzione al punto in cui la funzione è riferita. Questo velocizza l'esecuzione del codice grazie al minor consumo di memoria. Ma nel caso specifico, ciò che effettivamente accade è che verrà fatto riferimento alla variabile m_Infos.Rates. Questa variabile è di tipo MqlRates, cioè possiamo accedere ai valori della struttura MqlRates. In questo caso, non si passa l'indirizzo della variabile di riferimento. Ma in alcuni casi, al fine di rendere il codice più veloce, passiamo l'indirizzo del riferimento, nel qual caso è possibile modificare il valore di una variabile all'interno della classe, che dovrebbe essere vietato. Per evitare che ciò accada, usiamo la parola riservata const, che garantisce che la variabile non verrà mai modificata senza la classe stessa. Sebbene molte parole riservate dal C++ siano presenti anche in MQL5 in forma documentata, alcune di esse non lo sono ancora, ma fanno parte di MQL5 perché è molto simile al C++. Alla fine dell'articolo, aggiungerò link per coloro che vogliono saperne di più sul C++ e utilizzare le stesse conoscenze nella programmazione MQL5.

Ora all'interno del codice della funzione Init abbiamo una parte interessante, l'ho evidenziata di seguito per spiegare cosa sta facendo:

m_bChartShift = ChartGetInteger(Terminal.Get_ID(), CHART_SHIFT);
m_dChartShift = ChartGetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE);
ChartSetInteger(Terminal.Get_ID(), CHART_SHIFT, true);
ChartSetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE, 0.1);


Quando l'EA viene lanciato, cambia il grafico, ma è buona norma ripristinare il sistema al suo stato iniziale quando l'utente lo spegne. Pertanto, salviamo le impostazioni di scorrimento del grafico e poi creiamo uno scorrimento minimo. Questo viene fatto con i punti evidenziati, quindi abbiamo bisogno di vedere sul grafico la griglia per essere in grado di regolare le dimensioni. Questo viene fatto in modo interattivo, come mostrato all'inizio dell'articolo. Vedi CHART_SHIFT per maggiori informazioni.


Protezione degli oggetti sullo schermo

Anche se le funzioni interne della classe sono molto semplici, ci sono alcuni punti che meritano particolare attenzione. Il primo è un sistema di sicurezza che non consente all'utente di rimuovere il punto che indica l'inizio dell'analisi dei volumi:


Il punto è molto piccolo, quindi devi stare attento a notarlo.

NOTA IMPORTANTE: Se si desidera modificare il punto di analisi, prestare attenzione al timeframe del grafico. Ad esempio, se è necessario spostare l'analisi dalle 9:00 alle 9:02, è necessario utilizzare un timeframe di 1 minuto o 2 minuti. E se si utilizza un grafico, ad esempio, di 5 minuti, non è possibile farlo.

Successivamente, dobbiamo fare attenzione a garantire che l'utente non elimini accidentalmente questo elemento. Questo viene fatto nel codice seguente :

void DispatchMessage(int iMsg, string sparam)
{
        switch (iMsg)
        {

// ... L'interno del codice

                case CHARTEVENT_OBJECT_DELETE:
                        if ((sparam == m_Infos.szObjEvent) && (m_bUsing))
                        {
                                m_bUsing = false;
                                CreateObjEvent();
                                Resize();
                                m_bUsing = true;
                        }
                break;
        }                       
};


Quando la classe si rende conto che l'oggetto è stato cancellato, ricrea immediatamente quell'oggetto, impedendo così all'utente di essere lasciato senza un oggetto richiesto dalla classe e quindi di essere costretto a riavviare l'EA. Usa il modello mostrato nel codice ogni volta che devi assicurarti che l'utente non elimini un oggetto sensibile. Ma dobbiamo aggiungere codice aggiuntivo per garantire che l'evento sia notato dall'EA:

ChartSetInteger(m_Infos.ID, CHART_EVENT_OBJECT_DELETE, 0, true);

Questa semplice linea assicura che MetaTrader 5 riporterà la cancellazione dell'oggetto. Vedi CHART_EVENT_OBJECT_DELETE per maggiori informazioni.


Creazione di un grafico Volume At Price

Questo è il cuore della classe, ha tre funzioni: una pubblica e due private. Iniziamo con la funzione pubblica, è mostrata di seguito:

inline virtual void Update(void)
{
        MqlTick Tick[];
        int i1, p1;

        if (m_bUsing == false) return;
        if ((i1 = CopyTicksRange(Terminal.GetSymbol(), Tick, COPY_TICKS_TRADE, m_Infos.memTimeTick)) > 0)
        {
                if (m_Infos.CountInfos == 0)
                {
                        macroSetInteger(OBJPROP_TIME, m_Infos.StartTime = macroRemoveSec(Tick[0].time));
                        m_Infos.FirstPrice = Tick[0].last;
                }                                               
                for (p1 = 0; (p1 < i1) && (Tick[p1].time_msc == m_Infos.memTimeTick); p1++);
                for (int c0 = p1; c0 < i1; c0++) SetMatrix(Tick[c0]);
                if (p1 == i1) return;
                m_Infos.memTimeTick = Tick[i1 - 1].time_msc;
                m_Infos.CurrentTime = macroRemoveSec(Tick[i1 - 1].time);
                Redraw();
        };      
};

Le linee evidenziate sono molto importanti per il sistema. Quando il sistema inizia a funzionare, non sa esattamente da dove partire. Queste linee aggiornano questi punti, informano l'utente dove è iniziata l'analisi e qual era il prezzo di partenza, in modo che il sistema possa creare una tabella interna. Il sistema aspetterà sempre l'arrivo di un nuovo tick. Una volta che succede abbiamo dati da analizzare e raccogliere per presentarli sullo schermo. Quindi, ecco la funzione:

inline void SetMatrix(MqlTick &tick)
{
        int pos;
                                
        if ((tick.last == 0) || ((tick.flags & (TICK_FLAG_BUY | TICK_FLAG_SELL)) == (TICK_FLAG_BUY | TICK_FLAG_SELL))) return;
        pos = (int) ((tick.last - m_Infos.FirstPrice) / Terminal.GetPointPerTick()) * 2;
        pos = (pos >= 0 ? pos : (pos * -1) - 1);
        if ((tick.flags & TICK_FLAG_BUY) == TICK_FLAG_BUY) m_InfoAllVaP[pos].nVolBuy += tick.volume; else
        if ((tick.flags & TICK_FLAG_SELL) == TICK_FLAG_SELL) m_InfoAllVaP[pos].nVolSell += tick.volume;
        m_InfoAllVaP[pos].nVolDif = (long)(m_InfoAllVaP[pos].nVolBuy - m_InfoAllVaP[pos].nVolSell);
        m_InfoAllVaP[pos].nVolTotal = m_InfoAllVaP[pos].nVolBuy + m_InfoAllVaP[pos].nVolSell;
        m_Infos.MaxVolume = (m_Infos.MaxVolume > m_InfoAllVaP[pos].nVolTotal ? m_Infos.MaxVolume : m_InfoAllVaP[pos].nVolTotal);
        m_Infos.CountInfos = (m_Infos.CountInfos == 0 ? 1 : (m_Infos.CountInfos > pos ? m_Infos.CountInfos : pos));
}


Forse questa funzione non è così importante, dal momento che memorizza e detiene i valori dei volumi nel prezzo, ma le linee evidenziate in esso sono il cuore del sistema. Per capire davvero cosa sta succedendo in queste due linee, pensiamo un po'. Considera quanto segue: cos'è più veloce - memorizzare ciascuno dei prezzi e notare i volumi in ognuno di essi, o memorizzare solo i volumi, chiedendosi che prezzo è? La seconda opzione è più veloce, quindi salviamo i volumi e scopriamo dove si trova il prezzo. Ma quale sarà il primo prezzo nel sistema? Perché sì, abbiamo bisogno di un valore iniziale, senza di esso tutto andrà in pezzi. Che ne dici di utilizzare il prezzo del primo tick scambiato? Sì, questo è fantastico. Perfetto. Ma abbiamo un problema: se il prezzo sale, è fantastico, tutti i dati possono essere facilmente memorizzati in un array. Ma cosa succede se scende? In questo caso, avremo valori negativi e non saremo in grado di accedere ad un array con un indice negativo. Potremmo usare due array invece di uno, ma questo porterebbe a un carico inutile. C'è una soluzione semplice. Diamo un'occhiata alla tabella qui sotto:


Se l'indice è positivo non dobbiamo preoccuparci, ma se è negativo avremo problemi perché stiamo usando un array bidirezionale, dove il valore zero è ciò che rappresenta il prezzo del primo tick, i valori negativi sono quelli che si sono mossi verso il basso, e i valori positivi sono quelli che sono cresciuti. Dopo: se abbiamo due direzioni, quindi moltiplicando l'indice per 2, otteniamo la colonna centrale. non sembra essere d'aiuto. Ma se convertiamo i valori negativi in positivo e sottraiamo 1, otteniamo la colonna giusta. Se guardi da vicino, puoi vedere che i valori sono intrecciati in questa colonna di destra, che ci dà l'indice perfetto per accedere a un array che sappiamo che crescerà, ma non sappiamo quanto crescerà. Ed è esattamente quello che fanno le due linee evidenziate: creano un indice per il nostro array, alternando valori che sono più alti con quelli che sono più bassi del prezzo di partenza. Ma sebbene questa sia un'ottima soluzione, non servirà a nulla se non possiamo mostrare i dati sullo schermo, che è esattamente ciò che fa la funzione successiva.

void Redraw(void)
{
        uint x, y, y1, p;
        double reason = (double) (m_Infos.MaxVolume > m_WidthMax ? (m_WidthMax / (m_Infos.MaxVolume * 1.0)) : 1.0);
        double desl = Terminal.GetPointPerTick() / 2.0;
        Erase();
        p = m_WidthMax - 8;
        for (int c0 = 0; c0 <= m_Infos.CountInfos; c0++)
        {
                if (m_InfoAllVaP[c0].nVolTotal == 0) continue;
                ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, m_Infos.FirstPrice + (Terminal.GetPointPerTick() * (((c0 & 1) == 1 ? -(c0 + 1) : c0) / 2)) + desl, x, y);
                y1 = y + Terminal.GetHeightBar();
                FillRectangle(p + 2, y, p + 8, y1, macroColorRGBA(m_InfoAllVaP[c0].nVolDif > 0 ? m_Infos.ColorBuy : m_Infos.ColorSell, m_Infos.Transparency));
                FillRectangle((int)(p - (m_InfoAllVaP[c0].nVolTotal * reason)), y, p, y1, macroColorRGBA(m_Infos.ColorBars, m_Infos.Transparency));
        }
        C_Canvas::Update();
};

Questa funzione traccia il grafico dei volumi e la parte evidenziata si occupa di invertire il calcolo effettuato durante l'acquisizione dei volumi. Al fine di ottenere il display nel punto giusto, il prezzo si sposta un po' in modo che le barre siano posizionate correttamente. Il resto della funzione sta solo disegnando routine. Sono necessarie alcune spiegazioni qui. Nota che ci sono due chiamate FillRectangle. Perche? La prima chiamata indica quale volume era più grande: venditori o compratori, e la seconda chiamata traccia effettivamente il volume. Ma perché non costruirle insieme dividendo la banda dei volumi tra compratori e venditori? Il motivo è che con l'aumento dei volumi in una fascia di prezzo, inizia a interferire con l'analisi in altre fasce di prezzo più piccole. Diventa difficile determinare quale volume era più grande, se in vendita o acquisto. In questo modo, questo problema scompare, rendendo la lettura dei dati più facile e comprensibile. Di conseguenza, il grafico sarà simile alla figura seguente:


Tutte le altre funzioni di classe servono come supporto per quelle precedentemente spiegate, quindi non sono così importanti da essere trattate in dettaglio.


Conclusioni

Qui ho presentato un Volume at Price molto semplice, ma è uno strumento estremamente efficace. Se stai iniziando a imparare la programmazione e vuoi concentrarti sulla Programmazione Orientata agli Oggetti (OOP), devi studiare attentamente questo codice, perché ha diversi concetti molto buoni, perché tutto il codice è basato su un approccio al 100% orientato agli oggetti .

L'applicazione contiene l'Expert Advisor fino alla fase di sviluppo corrente.


Link utili



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

File allegati |
EA_1.06.zip (3280.48 KB)
Sviluppare un Expert Advisor per il trading da zero (Parte 8): Un salto concettuale Sviluppare un Expert Advisor per il trading da zero (Parte 8): Un salto concettuale
Qual è il modo più semplice per implementare nuove funzionalità? In questo articolo, faremo un passo indietro e poi due passi avanti.
Scienza dei dati e apprendimento automatico (Parte 03): Regressioni a matrice Scienza dei dati e apprendimento automatico (Parte 03): Regressioni a matrice
Questa volta i nostri modelli sono realizzati da matrici, il che ci permette flessibilità e consente di creare modelli potenti che possono gestire non solo cinque variabili indipendenti ma anche molte variabili finché restiamo entro i limiti di calcolo di un computer, questo articolo sarà una lettura interessante, questo è sicuro.
Impara come progettare un sistema di trading con il Parabolic SAR Impara come progettare un sistema di trading con il Parabolic SAR
In questo articolo continueremo la nostra serie su come progettare un sistema di trading utilizzando gli indicatori più popolari. Impareremo a conoscere nel dettaglio l'indicatore Parabolic SAR e come progettare un sistema di trading da utilizzare in MetaTrader 5 utilizzando alcune semplici strategie.
Imparare come progettare un sistema di trading con ATR Imparare come progettare un sistema di trading con ATR
In questo articolo, impareremo un nuovo strumento tecnico che può essere utilizzato nel trading, come continuazione all'interno della serie in cui impariamo a progettare semplici sistemi di trading. Questa volta lavoreremo con un altro indicatore tecnico popolare: Average True Range (ATR).