Announcement

Collapse
No announcement yet.

MQL4 NEW differenze vs Mql4 Old

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    MQL4 NEW differenze vs Mql4 Old

    ciao,

    come tutti sapranno, da febbraio 2014 sono state introdotti dei cambiamenti significativi nel linguaggio metaquote langage 4 per Metatrader4.

    metatrader_4_market_en[1].png


    L'ultima build con la versione precedente del linguaggio è la 509, le successive build di Metatrader 4 dalla 600 in su presentano l'editor aggiornato al nuovo linguaggio, evoluto e potenziato.

    In questo thread raccogliamo alcune novità, quelle più interessanti ed utili, nonché dubbi, idee, soluzioni...


    Iniziamo da un cambiamento minore ma evidente, i nomi delle funzioni di base di un Expert Advisor, senza che sia cambiato nulla in termini di funzionalità.

    Se nel vecchio compilatore si usava

    OLD MQL4 - Expert Advisor

    Code:
    int init()
      {
       ...
       return(0);
      }
    Code:
    int deinit()
      {
       ...
       return(0);
      }
    Code:
    int start()
      {
       ...
       return(0);
      }

    ... ora si usano questi nuovi nomi

    NEW MQL4 - Expert Advisor

    Code:
    int OnInit()
      {
       ...
       return(INIT_SUCCEEDED);
      }
    Code:
    void OnDeinit(const int reason)
      {
       ...
      }
    Code:
    void OnTick()
      {
       ...
      }


    °°°°°°°°°°°°°°°°°°°°°°


    Anche gli INDICATORI non sono cambiati quasi per niente in MQL4 NEW

    Si può continuare a programmarti alla stessa vecchia maniera, anche utilizzando le vecchie funzioni, come anche IndicatorCounted() : il codice viene correttamente compilato ed eseguito sul grafico.

    Volendo codificare indicatori con le nuove piccole modifiche introdotte in MQL4 NEW, le lievi differenze sono le seguenti.

    Code:
    int init()
      {
       ...  
       return(0);
      }
    viene sostituito da
    Code:
    void OnInit(void)
      {
       ...
       return(INIT_SUCCEEDED);
      }

    mentre
    Code:
    int start()
      {
       ...
       return(0);
      }
    viene sostituito da
    Code:
    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[])
      {
       ...  
       return(rates_total);
      }

    Inoltre, in Mql4 OLD si usava la funzione int IndicatorCounted() per calcolare il numero di barre che non sono cambiate da quando l'indicatore è stato lanciato: questa funzione serve per evitare di dover ricalcolare ad ogni tick i valori dell'indicatore su tutte quelle barre storiche per le quali è già stato calcolato e per le quali, essendo oramai barre fissate, il valore dell'indicatore è sempre lo stesso ad ogni tick.
    Ad ogni tick, dopo il primo, dovrà essere elaborato il valore dell'indicatore soltanto per la barra corrente.

    In MQL4 NEW è stata introdotta la funzione int OnCalculate(...) che ha come primi due parametri

    PHP Code:
    const int rates_total 
    e

    PHP Code:
    const int prev_calculated 

    Facendo stampare da qualsiasi indicatore i valori di rates_total, Bars, prev_calculated e IndicatorCounter()

    PHP Code:
    Print ("rates_total="+rates_total+"   Bars="+Bars+"   prev_calculated="+prev_calculated+"   IndicatorCounted()="+IndicatorCounted()); 

    e leggendo qui: http://docs.mql4.com/basis/function/events
    il dettaglio delle variabili della funzione int OnCalculate(...) , risulta che:

    - la variabile int rates_total coincide con la variabile di sistema Bars = numero di barre del grafico
    quindi si può usare indifferentemente rates_total oppure Bars per riferirsi alla stessa variabile

    - la variabile int prev_calculated è una variabile che contiene di default il valore restituito dalla funzione IndicatorCounted()+1
    cioè vale const int prev_calculated = IndicatorCounted()+1


    Da qui, il codice che si usava per gli indicatori scritti con Mql4 OLD
    PHP Code:
    int limit;
    int counted_bars=IndicatorCounted();
    //---- last counted bar will be recounted
    if(counted_bars>0counted_bars--;
    limit=Bars-counted_bars

    coincide con quanto si fa ora con gli indicatori con MQL4 NEW
    PHP Code:
    int limit;
    //---- last counted bar will be recounted
    limit=rates_total-prev_calculated;
    if(
    prev_calculated>0)   limit++; 


    Infine, come riporta la MQL4 Reference
    per aggiornare il valore di prev_calculated , che aumenta allo scorrere delle nuove barre che incrementano il numero di barre totali del grafico...
    it is usually enough to return the value of the rates_total parameter, which contains the number of bars in the current function call
    cioè è sufficiente che la funzione int OnCalculate(...) restituisca il valore di rates_total
    ed ecco il perché del return(rates_total) che chiude la funzione OnCalculate(...)

    PHP Code:
       //--- return value of prev_calculated for next call
       
    return(rates_total);
      } 
    La vita non è un giro di prova, cogli l’attimo..
    Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

    #2
    lo scope è il campo d’azione o visibilità di una variabile.

    In Mql4 Old una variabile locale, definita in un qualsiasi punto all'interno della ormai obsoleta funzione Start() aveva visibilità in qualunque porzione di codice venisse richiamata.

    In MQL4 NEW invece, la visibilità di una variabile, il suo scope, è molto più stringente e "vive" soltanto all'interno del blocco di codice nel quale è definita, blocco individuato dalle parentesi graffe { ... } nella quale si trova:
    Variable scope is from declaration to the end of the block, in which the variable is declared. A variable declared inside a block (part of code enclosed in curly brackets) belongs to the local scope. Such a variable is not visible (and therefore not available) outside the block, in which it is declared.

    Perciò se il codice seguente funzionava per Mql4 Old, con la dichiarazione della variabile int i dentro al ciclo FOR e la variabile i che continuava a vivere anche al termine del ciclo FOR

    k5KYkx.png

    ora questo codice non funziona più per MQL4 NEW e si avrebbe l'errore undeclared indentifier


    La dichiarazione della variabile int i va spostata fuori il ciclo FOR :

    k5KYkx.png
    La vita non è un giro di prova, cogli l’attimo..
    Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

    Comment


      #3
      Bene, vediamo se posso dare anch'io un suggerimento.

      Fino alla versione 580, MQL lavorava con stringhe in formato ANSI, mentre nelle versioni successive le stringhe sono in formato Unicode. Lungi dal volere fare una trattazione su vantaggi e svantaggi di una codifica rispetto all'altra, la differenza sostanziale fra le due codifiche consiste nel numero di bytes usati per rappresentare ogni singolo carattere. A differenza della codifica ANSI che è una codifica a byte singolo e si avvale poi di tabelle di conversione (le famose CodePage) per riuscire a rappresentare i vari caratteri disponibili nelle diverse lingue, la codifica Unicode è una codifica multibyte che risulta pertanto più flessibile ed è in grado di rappresentare in maniera univoca ogni singolo carattere disponbile in ogni singola lingua.

      Tralascio gli eventuali problemi di conversione da un formato all'altro, per i quali sono state introdotte in MQL funzioni specifiche, e mi soffermo invece su un caso particolare usato in uno degli expert più diffusi: quello per generare le candele Renko, l'ormai storico e famigerato RenkoLiveChart_v32.mq4.

      In questo EA è presente la funzione UpdateChartWindow() il cui scopo è quello di tenere aggiornato il chart (che ricordo viene generato come chart offline) e simulare la ricezione di un tick, in modo che il chart generato si comporti come un normale chart.

      Code:
      void UpdateChartWindow() {
      
          static int hwnd = 0;
          if(hwnd == 0) {
              hwnd = WindowHandle(SymbolName, RenkoTimeFrame);
              if(hwnd != 0) Print("Chart window detected");
          }
      
          if(EmulateOnLineChart && MT4InternalMsg == 0)
              MT4InternalMsg = RegisterWindowMessageA("MetaTrader4_Internal_Message");
      
          if(hwnd != 0) if(PostMessageA(hwnd, WM_COMMAND, 0x822c, 0) == 0) hwnd = 0;
          if(hwnd != 0 && MT4InternalMsg != 0) PostMessageA(hwnd, MT4InternalMsg, 2, 1);
      
          return;
      }
      La funzione UpdateChartWindow() si avvale di due funzioni RegisterWindowMessageA() e PostMessageA() importate entrambe dalla libreria di sistema user32.dll. All'inizio del codice troviamo infatti

      Code:
      #import "user32.dll"
          int RegisterWindowMessageA(string lpString);
      #import
      Questa direttiva #import è necessaria perché le funzioni importate dalla user32.dll e incluse in WinUser32.mqh tramite la direttiva

      Code:
      #include <WinUser32.mqh>
      non comprende la funzione RegisterWindowMessageA();

      La funzione RegisterWindowMessageA() serve per registrare una stringa da usare come messaggio codificato, usato internamente da MT4 per le "comunicazioni" fra le varie finestre dell'applicazione e, nello specifico, l'istruzione

      Code:
      PostMessageA(hwnd, MT4InternalMsg, 2, 1)
      serve per forzare l'invio di un tick fittizio al chart offline e simulare quindi il comportamento di un chart reale.

      Il problema è che la stringa "MetaTrader4_Internal_Message" nelle nuove versioni di MT4 non è più una stringa ANSI ma viene trattata del compilatore come una stringa Unicode, pertanto non si potrà più usare la funzione RegisterWindowMessageA() (specifica per le stringhe in formato ANSI, il suffisso A sta appunto per ANSI) ma si dovrà usare la corrispettiva funzione RegisterWindowMessageW() per le stringhe in formato Unicode.

      Analogamente, al posto della funzione PostMessageA() usata per trasmettere il messaggio, trattandosi di una stringa unicode, si dovrà usale la corrispettiva funzione PostMessageW().

      I parametri formali usati nella definizione delle due funzioni sono esattamente gli stessi; pertanto le modifiche da fare sono veramente poche per adattare la routine UpdateChartWindow() alla nuova sintassi. La sezione #import diventerà pertanto

      Code:
      #import "user32.dll"
          int RegisterWindowMessageW(string lpString);
      #import
      e la routine UpdateChartWindow() diventerà

      Code:
      void UpdateChartWindow() {
      
          static int hwnd = 0;
          if(hwnd == 0) {
              hwnd = WindowHandle(SymbolName, RenkoTimeFrame);
              if(hwnd != 0) Print("Chart window detected");
          }
      
          if(EmulateOnLineChart && MT4InternalMsg == 0)
              MT4InternalMsg = RegisterWindowMessageW("MetaTrader4_Internal_Message");
      
          if(hwnd != 0) if(PostMessageA(hwnd, WM_COMMAND, 0x822c, 0) == 0) hwnd = 0;
          if(hwnd != 0 && MT4InternalMsg != 0) PostMessageW(hwnd, MT4InternalMsg, 2, 1);
      
          return;
      }
      Come si vede, la prima chiamata a PostMessageA() è rimasta inalterata trattandosi di un comando per l'aggiornamento video, mentre la seconda, trattandosi di una stringa ANSI è stata trasformata opportunamente.

      Entrambe le funzioni PostMessageA() e PostMessageW() sono già presenti nel file WinUser32.mqh incluso all'inizio del codice.

      Buon aggiornamento!

      Mimmo

      Comment


        #4
        Visto che ci sono, colgo al volo l'occasione per segnalare un altro cambiamento che in passato mi ha dato un po' di filo da torcere.:sorrriso:
        Non perché fosse qualcosa di chissà che, ma perché se le cose cambiano e uno è abituato a farle in un modo...

        Praticamente nel nuovo MQL4, alcuni programmi che prima lavoravano con i grafici senza connessione, adesso non funzionano più.
        Succede che il nostro programma (EA o indicatore che sia) una volta caricato sul grafico dal quale vogliamo generare un grafico senza connessione, non crea il grafico offline.
        A questo punto uno leva il programma dal grafico e improvvisamente il grafico senza connessione appare.

        Ciò accade per un preciso motivo... La funzione FileOpenHistory() nel vecchio MQL4 poteva scrivere un file dello storico e questo poteva essere letto in contemporanea.
        Adesso invece, bisogna specificare che il file dello storico sarà condiviso con qualcuno che lo leggerà.
        Se non lo si specifica, il file non si potrà aprire finché il programma che lo sta usando non lo chiude (da qui la misteriosa apparizione del grafico solo quando stacchiamo il nostro "generatore").

        Passiamo alla parte pratica...
        Prima bastava scrivere in questo modo la funzione per far funzionare tutto perfettamente:
        Code:
         
         FileOpenHistory(Simbolo+Timeframe+".hst",FILE_BIN|FILE_WRITE);
        Ma adesso, va assolutamente specificato che il file è condiviso, altrimenti non si apre.
        Quindi la precedente riga va trasformata in:
        Code:
         
         FileOpenHistory(Simbolo+Timeframe+".hst",FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ);
        Come si può vedere, ora va aggiunto FILE_SHARE_WRITE e FILE_SHARE_READ.
        In assenza di queste due flag, si verifica l'anomalia descritta sopra.

        Mi auguro possa essere utile a qualcuno, poiché io prima di accorgermi che il problema era quello, ci ho messo un bel po'.:_l:
        Skype: cadddami

        Comment


          #5
          Ottimo Damiano...:_applauso: :012.WAsmile:
          fra le tante novità, hai ragione, c'è anche questa..... oltre a una valanga di piccole modifiche da fare se uno vuole rispettare la direttiva "strict" e ripulire il codice dalla caterva di warning
          Mimmo

          Comment


            #6
            La variabile datetime per definizione contiene secondi, quindi un numero intero
            The datetime type is intended for storing the date and time as the number of seconds elapsed since January 01, 1970. This type occupies 8 bytes of memory.

            Nell'Mql4 Old veniva gestito come variabile int ( the size of the int type is 4 bytes )

            mentre nell'MQL4 NEW va gestito come la variabile long
            essendo: the size of the long type is 8 bytes

            Nell'esempio in figura se si usa int si ha il warning possible loss of data due to type conversion
            che scompare se si usa il corretto type long.

            k5KYkx.png
            La vita non è un giro di prova, cogli l’attimo..
            Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

            Comment


              #7
              Trattandosi di numeri positivi senza segno, meglio sarebbe usare ulong.... (ce ne stanno di più :_risata

              E se proprio uno vuol fare il pignolo e far sparire anche il warning Implicit conversion from "number" to "string" (tanto la conversione implicita l'ha già fatta il compilatore e ce ne potremmo anche sbattere) usare l'operatore di typecasting esplicito adeguato. Nello specifico

              Code:
              ....<omissis>
              Print("minuti differenza = " + (string) secondi/60);
              Mimmo

              Comment


                #8
                Originally posted by skipper View Post
                far sparire anche il warning Implicit conversion from "number" to "string" (tanto la conversione implicita l'ha già fatta il compilatore e ce ne potremmo anche sbattere) usare l'operatore di typecasting esplicito adeguato.
                approfitto di questo assist per accennare al casting, che è l'operazione con cui si converte una variabile da un tipo di dato a un altro.

                Esistono due tipi di conversione di tipo:
                - implicita, svolta in maniera automatica dal compilatore
                - esplicita, realizzata con un operatore di cast, obbligatoria quando le informazioni potrebbero andare perdute durante la conversione o quando la conversione potrebbe non riuscire per altri motivi.


                Esempio di Typecasting esplicito (conversione esplicita del tipo variabile) con MQL4 NEW

                consideriamo la funzione MathFloor(), che tra l'altro ha una sua copia identica in floor()

                per definizione è : double MathFloor(double
                val);
                Questa funzione restituisce il più grande intero che sia minore o uguale a
                val che è una variabile double

                Se si usa uno script come in figura per trovare e stampare la parte intera di una divisione, si ha il warning possible loss of data due to type conversion

                2japO9.gif


                che si risolve con un typecasting esplicito, rendendo di tipo
                int il risultato della funzione floor, che quindi passa da double a int
                secondo la sintassi var_1 = (type)var_2;
                come si può studiare qui

                La conversione implicita da double a int non può avvenire, perché nell'ordine delle conversioni implicite può avvenire un passaggio automatico da int a double, ma non l'inverso, che quindi deve essere imposto esplicitamente.

                casting.png
                La vita non è un giro di prova, cogli l’attimo..
                Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                Comment


                  #9
                  La logica di funzionamento del noto file PeriodConverter.mq4 è pressoché identica tra la vecchia versione del file per Mql4 Old e la nuova versione per MQL4 NEW
                  sebbene il codice sia stato riscritto per utilizzare una delle varie novità: la struttura MqlRates

                  PHP Code:
                  struct MqlRates
                    
                  {
                     
                  datetime time;         // Period start time
                     
                  double   open;         // Open price
                     
                  double   high;         // The highest price of the period
                     
                  double   low;          // The lowest price of the period
                     
                  double   close;        // Close price
                     
                  long     tick_volume;  // Tick volume
                     
                  int      spread;       // Spread
                     
                  long     real_volume;  // Trade volume
                    
                  }; 


                  ai cui elementi si accede con l'operatore "." come avviene con gli elementi di una classe.

                  ad es.
                  MqlRates rate;
                  rate.open=Open[start_pos];
                  rate.low=Low[start_pos];

                  In termini pratici con i dati storici non cambia nulla, il file .HST di Metatrader4_new
                  ha la stessa logica del file .HST di Metatrader4_old





                  La vita non è un giro di prova, cogli l’attimo..
                  Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                  Comment


                    #10
                    MQL4 NEW introduce due diversi identificatori di variabili esterne, oltre ad extern anche input e sinput (=static input)

                    Io userò quasi sempre il classico extern



                    extern
                    - permette di scegliere il valore della variabile di input,
                    - permette di modificare il valore della variabile all'interno del codice dell'EA
                    - permette di scegliere i valori che può assumere durante una ottimizzazione


                    input
                    - permette di scegliere il valore della variabile di input,
                    - NON permette di modificare il valore della variabile all'interno del codice dell'EA
                    - permette di scegliere i valori che può assumere durante una ottimizzazione


                    sinput
                    - permette di scegliere il valore della variabile di input,
                    - NON permette di modificare il valore della variabile all'interno del codice dell'EA
                    - NON permette di scegliere i valori che può assumere durante una ottimizzazione
                    La vita non è un giro di prova, cogli l’attimo..
                    Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                    Comment


                      #11
                      Qui un ottimo articolo scritto dalla Metaquotes che riassume i principali errori del codice scritto con Mql4 Old

                      quando viene compilato con MQL4 NEW

                      "Common Errors in MQL4 Programs and How to Avoid Them"


                      https://www.mql5.com/en/forum/149271

                      La vita non è un giro di prova, cogli l’attimo..
                      Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                      Comment


                        #12
                        Il nuovo metaquote language 4, MQL4 NEW, ha nuove funzioni utili che non c'erano nella vecchia versione Mql4 Old, come

                        int SymbolsTotal(bool selected) e string SymbolName(int pos, bool selected)

                        queste due funzioni permettono di stampare tutte le coppie di valute e CFD del server del broker.

                        Allego un semplice script brokerSymbols.mq4 che eseguito su qualsiasi grafico stampa tutte le coppie di valute e CFD nella scheda Experts/Consiglieri


                        brokerSymbols_info.png


                        Attached Files
                        La vita non è un giro di prova, cogli l’attimo..
                        Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                        Comment


                          #13
                          Sono davvero pochissime le funzioni dal vecchio Mql4 Old diventate ormai "obsolete" ed alcune logiche di programmazione da abbandonare.

                          Le novità introdotte in MQL4 NEW sono diverse ed interessanti e ne potenziano la programmazione.

                          Di seguito alcune nuove funzionalità in ordine sparso.

                          - Il tipo enumeration, è un tipo di variabile che può assumere una limitata lista di valori, utile per individuare facilmente in maniera autoesplicativa il valore di una variabile di input

                          - Le struct, classi di livello base, molto semplici. Ci sono tre struct di sistema MqlRates (memorizza informazioni sui prezzi, volume e spread di ogni barra), MqlDateTime (memorizza la data di una barra con otto campi: ora, minuti, secondi, giorno, ecc. ), MqlTick (memorizza bid, ask e volume dell'ultimo tick). Delle struct se ne può fare anche a meno nel proprio codice, basta e avanza quello che già si sa e si usa di Mql4 Old... ma va saputo cosa sono e come funzionano, se capita di leggere il codice scritto da altri.

                          - functions overloading: è il processo di creazione di più funzioni con lo stesso nome, ma con parametri diversi, al fine di raccogliere sotto un unico nome più funzioni che lavorano su un insieme di dati diversi ma che concettualmente li elaborano con la stessa logica. Ad esempio, due funzioni con identico nome che stampano gli elementi di un array, una per array di numeri interi ( void stampaArray(int& array[]) ), l'altra per elementi 'double' ( void stampaArray(double& array[]) )

                          - La funzione OnTester() per gli Expert Advisor : gestisce l'evento Tester che viene automaticamente generato alla termine di un backtest/ottimizzazione dopo che l'intervallo dei dati storici è terminato. Il suo scopo è di calcolare un valore che verrà usato come parametro di fitness customizzato nell'ottimizzazione genetica

                          Sul sito ufficiale della Metaquotes la logica dell'ottimizzazione genetica con criterio Custom è ben spiegata per mql5 ...e vale pari pari anche per MQL4 NEW: Creating Custom Criteria of Optimization of Expert Advisors

                          - poi ci sono le classi con tutta la pappardella sui costruttori e distruttori, metodi e accesso Public, Protected e Private ai membri della classe, i concetti di ereditarietà, polimorfismo, incapsulamento, ecc. ...
                          Ma io ritengo che la programmazione ad oggetti C++ like applicata ai trading system sia overdimensionata, lo "studio delle classi non vale la candela dello sforzo" e per ora le classi le ho saltate a pie' pari.
                          La vita non è un giro di prova, cogli l’attimo..
                          Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                          Comment


                            #14
                            Giusto per allargare i miei orizzonti e ampliare questa discussione, aggiungo quanto recuperato su un altro forum e copia-incollato pedestremente su file word.
                            Nota per admin : nel file ho lasciato il rif. al forum da cui ho prelevato, se inutile prego rimuovere.

                            Errori_old_ Mql4.docx

                            Comment


                              #15
                              Ottimo grazie Giancarlo, va benissimo! :014.WAsmile:
                              La vita non è un giro di prova, cogli l’attimo..
                              Realizzazione per Metatrader4 di trading system, indicatori, pattern grafici, Ottimizzazioni IS-OOS su Forex e CFD, Analisi di Portafoglio .

                              Comment

                              Working...
                              X