Discussão do artigo "Migrando do MQL4 para o MQL5"

 

Novo artigo Migrando do MQL4 para o MQL5 foi publicado:

Muitos desenvolvedores acumularam muitos indicadores e estratégias de negócios escritas no MQL4. Para usá-las no Metatrader 5, elas devem ser convertidas para o MQL5. Não é fácil reescrever todos os programas no MQL5. Seria muito mais fácil convertê-los se houvesse uma tradução referência e melhor com exemplos.

Este artigo é um guia rápido para as funções da linguagem MQL4, ele o ajudará a migrar seus programas do MQL4 para MQL5. Para cada função do MQL4 (exceto funções de negociação), são apresentadas a implementação do MQL5 e descrição, isso permite a redução do tempo de conversão significativamente. Para conveniência, as funções do MQL4 são divididas em grupos, similar à referência MQL4.

Autor: Sergey Pavlov

 

tem certeza de que funciona? ????

Uma simples compilação já levanta a questão

e, em segundo lugar, o que essa função retornará!

     CopyClose(symbol,timeframe,start,count,Close);
      return(ArrayMaximum(Close,start,count));

copia os preços de fechamento para a matriz Klose, copia da posição "start" e o número de "Counts" corretamente.

e retorna o índice do elemento máximo da matriz Klose, começando pela posição "start" e observando apenas os elementos "count"......

Qual é a sua heresia? Desculpe a franqueza.....

 
 
Nas células das tabelas onde está escrito "No analogue", você deve fornecer uma breve descrição de como essas coisas são resolvidas no mql5 com referências a uma seção específica da documentação (algo como, por exemplo, isto: "não faz sentido, porque no mql5 isso e aquilo").
 
CoreWinTT:

Tem certeza de que funciona? ????

Sim, funciona.

//+------------------------------------------------------------------+
//|teste.mq5 |
//|Direitos autorais DC2008 |
//| http://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "DC2008"
//--- Matrizes de séries temporais
double            Close[];
double            Open[];
double            High[];
double            Low[];
long              Volume[];
datetime          Time[];
//+------------------------------------------------------------------+
//| Função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ArraySetAsSeries(Close,true);
   ArraySetAsSeries(Open,true);
   ArraySetAsSeries(High,true);
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(Volume,true);
   ArraySetAsSeries(Time,true);
   ArraySetAsSeries(Low,true);

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Função de desinicialização de especialista|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Função de tique de especialista|
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   Comment(
           "\niHighest",iHighest("EURUSD",PERIOD_M2,0,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,0,10,0),"   Open",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,1,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,1,10,0),"   Low",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,2,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,2,10,0),"   High",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,3,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,3,10,0),"   Close",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,4,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,4,10,0),"   Volume",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,5,10,0),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,5,10,0),"   Time",
           "\n",""
           );

  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int iLowest(string symbol,
            int tf,
            int type,
            int count=WHOLE_ARRAY,
            int start=0)
  {
   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   if(type<=0)
     {
      CopyOpen(symbol,timeframe,start,count,Open);
      return(ArrayMinimum(Open,start,count));
     }
   if(type==1)
     {
      CopyLow(symbol,timeframe,start,count,Low);
      return(ArrayMinimum(Low,start,count));
     }
   if(type==2)
     {
      CopyHigh(symbol,timeframe,start,count,High);
      return(ArrayMinimum(High,start,count));
     }
   if(type==3)
     {
      CopyClose(symbol,timeframe,start,count,Close);
      return(ArrayMinimum(Close,start,count));
     }
   if(type==4)
     {
      CopyTickVolume(symbol,timeframe,start,count,Volume);
      return(ArrayMinimum(Volume,start,count));
     }
   if(type>=5)
     {
      CopyTime(symbol,timeframe,start,count,Time);
      return(ArrayMinimum(Time,start,count));
     }
//---
   return(0);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int iHighest(string symbol,
             int tf,
             int type,
             int count=WHOLE_ARRAY,
             int start=0)
  {
   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   if(type<=0)
     {
      CopyOpen(symbol,timeframe,start,count,Open);
      return(ArrayMaximum(Open,start,count));
     }
   if(type==1)
     {
      CopyLow(symbol,timeframe,start,count,Low);
      return(ArrayMaximum(Low,start,count));
     }
   if(type==2)
     {
      CopyHigh(symbol,timeframe,start,count,High);
      return(ArrayMaximum(High,start,count));
     }
   if(type==3)
     {
      CopyClose(symbol,timeframe,start,count,Close);
      return(ArrayMaximum(Close,start,count));
     }
   if(type==4)
     {
      CopyTickVolume(symbol,timeframe,start,count,Volume);
      return(ArrayMaximum(Volume,start,count));
     }
   if(type>=5)
     {
      CopyTime(symbol,timeframe,start,count,Time);
      return(ArrayMaximum(Time,start,count));
     }
//---
   return(0);
  }
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES TFMigrate(int tf)
{
   switch(tf)
   {
      case 0: return(PERIOD_CURRENT);
      case 1: return(PERIOD_M1);
      case 5: return(PERIOD_M5);
      case 15: return(PERIOD_M15);
      case 30: return(PERIOD_M30);
      case 60: return(PERIOD_H1);
      case 240: return(PERIOD_H4);
      case 1440: return(PERIOD_D1);
      case 10080: return(PERIOD_W1);
      case 43200: return(PERIOD_MN1);      
      default: return(PERIOD_CURRENT);
   }
}
 
marketeer:
Nas células das tabelas onde está escrito "No analogue", você deve fornecer uma breve descrição de como essas coisas são resolvidas no mql5 com referências a uma seção específica da documentação (algo como, por exemplo, isto: "não faz sentido, porque no mql5 isso e aquilo").

Isso deve ser entendido da seguinte forma: a implementação é muito complicada e não se justifica. Afinal de contas, o objetivo é abandonar completamente as funções MQL4.

Mas tentarei levar isso em consideração se eu puder fornecer links para as funções MQL5 que podem ser usadas para fazer algo semelhante.

 

Estamos tirando isso do TF m2. Certo, eu entendo.

O TF migrate está nos dando um valor de 0 bar.

  default: return(PERIOD_CURRENT);

a partir de 0 bar. Isso é estranho.

Mas se tentarmos a partir de 20, por exemplo.

Você está tentando nos confundir novamente.

e essas bobagens em todas as funções.

E por que fazer o TF migrate???

se o mql5 tem todos os TFs que o mql4 tem ainda mais......

heresia completa =))))

Como seus moderadores não perceberam tal coisa?

Caro Eugene, espero que não tenha sido você quem verificou esse artigo.

 
CoreWinTT:

heresia completa =))))

Como seus moderadores não perceberam isso?

Caro Eugene, espero que você não tenha verificado este artigo.

Prezado Vasily!

Obrigado por seus comentários, as funções da seção 18 foram atualizadas. Verifique a versão atual.

O autor trabalhou muito, pode haver erros, mas vamos corrigi-los juntos.

A função TFMigrate(int tf) é necessária para substituir os valores corretos dos períodos de tempo MQL5. Por exemplo, em MQL4 o valor numérico da constante PERIOD_H1 é 60, e em MQL5 o valor numérico de PERIOD_H1=16385, ou seja, TFMigrate(60)=16385.

 

Acho que há muito mais erros.

porque eles ocorrem mesmo em momentos tão simples, eu diria até que são os mais simples.


Em algumas seções, as funções são comparadas umas com as outras.

em outras, um análogo é escrito.


Não há um único exemplo bem-sucedido de como implementar o artigo,

Pelo que entendi, este artigo é uma tentativa de transferir algo do µl4.....


Sua atitude em relação à verificação é sempre admirável.

Acho que é o desejo desenfreado do autor de jogar poeira em seus olhos.

O que ele certamente conseguiu fazer.

pois conheço sua sensibilidade em relação ao material que está sendo verificado.

 
CoreWinTT:


E se você tentar com 20, por exemplo.

Você está tentando me confundir novamente.

e essas bobagens em todas as funções.

E por que fazer o TF migrar????

se o mql5 tem todos os TFs que o mql4 tem ainda mais......

heresia completa =)))))


Obrigado por encontrar o erro. Eu havia esquecido que a pesquisa pode ser iniciada de outro local que não a barra zero. Aqui estão as funções corrigidas:

//+------------------------------------------------------------------+
//|teste.mq5 |
//|Direitos autorais DC2008 |
//| http://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "DC2008"
//--- Matrizes de séries temporais
double            Close[];
double            Open[];
double            High[];
double            Low[];
long              Volume[];
datetime          Time[];
//+------------------------------------------------------------------+
//| Função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ArraySetAsSeries(Close,true);
   ArraySetAsSeries(Open,true);
   ArraySetAsSeries(High,true);
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(Volume,true);
   ArraySetAsSeries(Time,true);
   ArraySetAsSeries(Low,true);

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Função de desinicialização de especialista|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Função de tique de especialista|
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   Comment(Open[0],Close[0],Open[1],Close[1],
           "\niHighest",iHighest("EURUSD",PERIOD_M2,0,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,0,10,20),"   Open",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,1,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,1,10,20),"   Low",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,2,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,2,10,20),"   High",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,3,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,3,10,20),"   Close",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,4,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,4,10,20),"   Volume",
           "\niHighest",iHighest("EURUSD",PERIOD_M2,5,10,20),
           " iLowest ",iLowest("EURUSD",PERIOD_M2,5,10,20),"   Time",
           "\n",""
           );

  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int iLowest(string symbol,
            int tf,
            int type,
            int count=WHOLE_ARRAY,
            int start=0)
  {
   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   if(type<=0)
     {
      CopyOpen(symbol,timeframe,start,count,Open);
      return(ArrayMinimum(Open,0,count));
     }
   if(type==1)
     {
      CopyLow(symbol,timeframe,start,count,Low);
      return(ArrayMinimum(Low,0,count));
     }
   if(type==2)
     {
      CopyHigh(symbol,timeframe,start,count,High);
      return(ArrayMinimum(High,0,count));
     }
   if(type==3)
     {
      CopyClose(symbol,timeframe,start,count,Close);
      return(ArrayMinimum(Close,0,count));
     }
   if(type==4)
     {
      CopyTickVolume(symbol,timeframe,start,count,Volume);
      return(ArrayMinimum(Volume,0,count));
     }
   if(type>=5)
     {
      CopyTime(symbol,timeframe,start,count,Time);
      return(ArrayMinimum(Time,0,count));
     }
//---
   return(0);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int iHighest(string symbol,
             int tf,
             int type,
             int count=WHOLE_ARRAY,
             int start=0)
  {
   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   if(type<=0)
     {
      CopyOpen(symbol,timeframe,start,count,Open);
      return(ArrayMaximum(Open,0,count));
     }
   if(type==1)
     {
      CopyLow(symbol,timeframe,start,count,Low);
      return(ArrayMaximum(Low,0,count));
     }
   if(type==2)
     {
      CopyHigh(symbol,timeframe,start,count,High);
      return(ArrayMaximum(High,0,count));
     }
   if(type==3)
     {
      CopyClose(symbol,timeframe,start,count,Close);
      return(ArrayMaximum(Close,0,count));
     }
   if(type==4)
     {
      CopyTickVolume(symbol,timeframe,start,count,Volume);
      return(ArrayMaximum(Volume,0,count));
     }
   if(type>=5)
     {
      CopyTime(symbol,timeframe,start,count,Time);
      return(ArrayMaximum(Time,0,count));
     }
//---
   return(0);
  }
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES TFMigrate(int tf)
{
   switch(tf)
   {
      case 0: return(PERIOD_CURRENT);
      case 1: return(PERIOD_M1);
      case 5: return(PERIOD_M5);
      case 15: return(PERIOD_M15);
      case 30: return(PERIOD_M30);
      case 60: return(PERIOD_H1);
      case 240: return(PERIOD_H4);
      case 1440: return(PERIOD_D1);
      case 10080: return(PERIOD_W1);
      case 43200: return(PERIOD_MN1);      
      default: return(PERIOD_CURRENT);
   }
}
 
CoreWinTT:

Acho que há muito mais erros.

porque eles ocorrem mesmo em momentos tão simples, eu diria até que são os mais simples.


Em algumas seções, as funções são comparadas umas com as outras.

em outras, um análogo é escrito.


Não há um único exemplo bem-sucedido de como implementar o artigo,

Pelo que entendi, este artigo é uma tentativa de transferir algo do µl4.....


Sua atitude em relação à verificação é sempre admirável.

Acho que é o desejo desenfreado do autor de jogar poeira em seus olhos.

O que ele certamente conseguiu fazer.

pois conheço sua sensibilidade em relação ao material que está sendo verificado.


Pode haver erros, o material é bastante extenso.

O tópico da portabilidade (mais precisamente, o tópico de escrever uma classe de emulador com métodos MQL4) foi realizado em outro artigo (esperamos que seja concluído). No processo de leitura do material, pedimos ao autor que escrevesse um artigo na forma de um livro de referência para cobrir todas as funções do MQL4 (exceto para negociação - você verá uma das soluções para eles em breve), para fornecer um análogo para cada um deles em MQL5, em geral, para colocar tudo junto para que aqueles que reescrevem programas MQL4 possam encontrar rapidamente um análogo. Sobre o desejo desenfreado, se estivermos falando sobre o número de seções consideradas - insistimos em cobrir todas as funções (elas acabaram sendo mais de 250).

Quanto à comparação de funções em algumas seções, não se tratava exatamente de uma comparação. Era necessário fornecer um análogo, mesmo que fosse o mesmo. Para todas as funções. Portanto, parece que há uma comparação, mas você pode dizer pela comparação que, por exemplo, as funções de matemática são as mesmas. A propósito, como recomendação, provavelmente seria útil mencionar isso no início de cada seção, que é algo a ser observado.

Por esse motivo (arquitetura das funções do emulador), o autor tinha algumas coisas não óbvias na implementação (por exemplo, para iLowest/iHighest global Open[]...High[]..., que foram previamente declaradas globalmente e transformadas em AsSeries em OnInit), que estavam implícitas como no emulador, naturalmente, para a universalidade das funções, é melhor usar matrizes locais.

Quanto ao trabalho com indicadores técnicos, pode haver muitas perguntas, trabalhar com eles não deve ser como na MQL4 - é melhor criá-los manualmente no OnInit e consultar os descritores, em vez de criá-los cada vez em funções locais. Mas a abordagem sugerida pelo autor também funciona, porque o terminal não destrói imediatamente os indicadores. Portanto, há muitas sutilezas.

O importante é que agora há algo a ser discutido e, se você encontrar erros (inclusive os causados pela estrutura de funções proposta), ofereça suas variantes.