Alguém sabe como desenvolver um indicador de múltiplas moedas ? - página 3

 
4x_Gypsy:

A grande pista era "Mas eu não sei como fazer isto".

Da falta de qualquer tipo de resposta da OP é uma indicação de que há algo errado. Meu "palpite" é que a OP ficou frustrada com a falta de compreensão e abandonou o fio da meada. Houve um tempo atrás em que eu fiz a mesma coisa. Aprendi mais com diferentes sites/fóruns do que este porque ninguém estava tomando tempo para perceber como eu era novo e continuamente afixava exemplos e tinha discussões completamente acima do meu entendimento na época.

Por outro lado, eu vi muitas perguntas que simplesmente foram respondidas se o simples fato de arriscar uma rápida olhada na documentação e você realmente se sente um idiota respondendo a essas perguntas repetidamente.

Além disso, há ainda o google e uma opção de busca aqui. Se eu não sei como fazer algo, este é meu próximo passo para tentar resolver o problema por conta própria.

No caso do tópico deste tópico eu não sei como codificar um sistema de múltiplas moedas, eu teria respondido ao google ou pesquisado aqui por código já existente.

 
gooly:

Por outro lado, tenho visto muitas perguntas que simplesmente foram respondidas se o justo arriscar uma rápida olhada na documentação e você realmente se sentir um tolo respondendo a essas perguntas repetidas vezes.

Além disso, há ainda o google e uma opção de busca aqui. Se eu não sei como fazer algo, este é meu próximo passo para tentar resolver o problema por conta própria.

No caso do tópico deste tópico eu não sei como codificar um sistema de múltiplas moedas, eu teria respondido google ou procurado aqui por código já existente.

Obrigado pelo feedback, e feliz por ter sido positivo. lol

Lamento a quem quer que esteja preocupado com a forma como me deparei nesta situação. Sou uma pessoa verdadeiramente livre de dramas de paz que normalmente ignora a maioria das coisas com as quais eu não concordo.

 

Oi, pessoal,

Desculpe pelo longo período sem atividade aqui. Eu estava viajando para trabalhar e também ocupado com alguns projetos e tive que deixar o projeto de lado por um tempo ...

Depois de ler as atualizações do post, tenho alguns pontos a esclarecer:

  1. Não quero que alguém codifique todas as coisas para mim, só preciso me mostrar a direção certa e eu faço o resto. Bem... vou testar a solução WHRoeder agora e fazer minhas coisas e mais tarde postarei o resultado aqui. Sugestão da WHRoeder:https://www.mql5.com/en/forum/158938
  2. Antes de criar este tópico eu fiz uma busca por posts similares, mas não encontrei... então crie-a
  3. Desculpe por demorar muito tempo para responder, mas realmente foi um excesso de trabalho, mas agora eu continuo a trabalhar com o indicador
  4. Desculpe pelo meu pobre inglês! meu idioma é o português e quando eu postar o inglês, preciso usar o tradutor do google e não é perfeito.


 
Aqui meu teste.

Basta permitir que os usuários informem os ativos dayr, e depois, mostrar todos os pares Alto/Baixo valores.

Se, qualquer um dos pares seletec for o mesmo que a Janela ativa, suas taxas são atualizadas multa. Mas outros pares só mostram as taxas quando o indicador foi adicionado... e não mais as atualiza...

Como você pode ver na imagem abaixo, o indicador foi adicionado na Janela GBPUSD... e as taxas GBPUSD foram atualizadas fino tique por tique. Mas o EURUSD não é atualizado e continua com o mesmo valor.

Tarifas copiadas


Abaixo, o código do indicador:

//+------------------------------------------------------------------+
//|                                                MultiCurrency.mq4 |
//|                         Copyright 2016, Wemerson Couto Guimarães |
//|                  https://www.mql5.com/pt/users/wemersonrv/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Wemerson Couto Guimarães"
#property link      "https://www.mql5.com/pt/users/wemersonrv/seller"
#property version   "1.00"
#property strict
#property indicator_separate_window

input string UsePairs="EURUSD,GBPUSD"; // Pares separados por vírgula.

struct pair_struct{
   string symbol;
   MqlRates rates[];
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i]){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }else{
      for(i=0; i<ArraySize(pairs); i++){
         ArrayCopyRates( pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
      }
   }   
   
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {

   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }
   
   string log="";
   
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPair: " + pairs[i].symbol + 
             " - High: "+ DoubleToStr(pairs[i].rates[0].high, Digits()) + 
             " - Low: "+ DoubleToStr(pairs[i].rates[0].low, Digits());
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

 
Tento usar RefreshRates() mas ainda com o mesmo resultado... apenas o par na mesma janela funciona, outros pares não são atualizados.
 
wemersonrv:
Eu tento usar RefreshRates() mas ainda com o mesmo resultado... apenas o par na mesma janela funciona, outros pares não são atualizados.

RefreshRates() não tem nada a ver com os dados do MqlRates. O código de exemplo do WHRoeder só é válido a partir das construções Pre-600. Para a última construção, você precisa verificar os vários pontos mencionados em meu post, como testar os códigos de retorno do ArrayCopyRates(), bem como os códigos de erro, tamanho do Rates Array e, como precaução adicional apontada pela WHRoeder, a validade do atributo tempo.

PS! Se você estiver tendo dificuldades com o inglês, envie-me um PM. Eu sou português (Portugal)

 

Oi, pessoal.

Testando, incluí uma "cópia" das tarifas na função OnCalculate... adicionando um loop que primeiro LIVRE a matriz de pares em todas as iterações, depois copie as tarifas novamente. Parece que está funcionando e não retorna erro.

Não sei se esta é a melhor maneira de fazer o que eu preciso, mas aparentemente está funcionando e sem erros.


   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }

   // My change to recopy rates every tick by adding a loop at starting of OnCalculate() to do this
   // AS FMIC says, ArrayCopyRates needs the array without content, 
   // then before recopy, free the array.
   for(i=0; i<ArraySize(pairs); i++){
      ArrayFree(pairs[i].rates);
      ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT);
   }
 
wemersonrv: Teste, incluí uma "cópia" das tarifas na função OnCalculate... adicionando um loop que primeiro LIVRE a matriz de pares em todas as iterações, depois copie as tarifas novamente. Parece estar funcionando e não retorna o erro.
  1. Como indicado na documentação.
    Se forem solicitados dados (nome do símbolo e/ou cronograma diferente dos atuais) de outro gráfico, a situação é possível que o gráfico correspondente não tenha sido aberto no terminal do cliente e os dados necessários devem ser solicitados ao servidor. Neste caso, o erro ERR_HISTORY_WILL_UPDATED (4066 - os dados do histórico solicitado estão em atualização) será colocado na última variável_erro, e será necessário solicitar novamente
    E verificado aqui
    O ArrayCopyRates retornará um erro se não houver nenhum histórico (ERR_NO_HISTORY_DATA = 4073.) As chamadas repetidas também falham até que o download esteja completo. Quando há histórico mas não atualizado, o ArrayCopyRates retorna válido E também define `_LastError` para ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. Teste seu código de retorno, durma e tente novamente, se necessário. Quais são os valores de retorno das funções ? Como eu os utilizo ? - Fórum MQL4 e Erros Comuns nos Programas MQL4 e Como Evitá-los - Artigos MQL4
 

Uma atualização para aqueles que seguem esta linha!

Tenho ajudado o OP via PM a corrigir seu código, pois ele tem dificuldade com o inglês e nós dois falamos português. Em nossos testes, nos deparamos com outro "engraçado" que está acontecendo com a função"ArrayCopyRates()". Ao usar um array MqlRates com"ArrayCopyRates()" em um EA, o array de dados é um array virtual que sempre relata o status atual das coisas, portanto os dados estão sempre frescos.

Entretanto, em um Indicador, este não parece ser o caso. O array não é uma cópia virtual, mas uma cópia estática definida no tempo no momento em que o"ArrayCopyRates()" foi chamado. Os dados não são atualizados quando o Símbolo é diferente do símbolo do gráfico. Quando é o mesmo símbolo que o gráfico, então os dados do array são "ao vivo" e são atualizados como esperado, mas quando é de outro símbolo, é uma cópia estática.

Portanto, para que funcione em um Indicador, deve-se chamar a função "ArrayCopyRates()" em cada chamada ao evento OnCalculate() se forem necessários novos dados.

 

Olá a todos.

  • FMIC, obrigado por seu apoio!
  • WHRoeder, obrigado também... Você está sempre presente para todos nós !
  • Obrigado a todos os membros do fórum por suas considerações e até mesmo obrigado por todo o debate que foi gerado neste tópico. Foi muito interessante!

Isto é (quase) a mesma coisa que eu faço mais tarde, mas a diferença é que eu dirijo um ArrayFree antes do ArrayCopyRates... e eu não faço as validações que vocês me ajudaram.

Aqui o código final que a FMIC me ajudou. Agora está funcionando normalmente num código indicador..:

input string UsePairs="NZDCAD,EURUSD,GBPUSD,USDJPY"; // pairs separated by commas
struct pair_struct{
   string symbol;
   MqlRates rates[];
   bool valid;
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i] ){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
         pairs[c].valid = false;
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {

   InitializeRates();
   
   int i=0;
   string log="";
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPar: " + pairs[i].symbol;
      if( pairs[i].valid ){
         log += " - Time: "+ TimeToString( pairs[i].rates[0].time ) + 
                " - Open: "+ DoubleToString( pairs[i].rates[0].open, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Close: "+ DoubleToString( pairs[i].rates[0].close, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - High: "+ DoubleToString( pairs[i].rates[0].high, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Low: "+ DoubleToString( pairs[i].rates[0].low, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) );
      }else{
         log += " - Currently not valid!";
      }
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

void InitializeRates(){
 
   for( int i=0; i<ArraySize( pairs ); i++ ){
      pairs[i].valid = false;
      ResetLastError();
      if( ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT) > 0 ){
         if( _LastError == 0 ){
            if( ArraySize(pairs[i].rates) > 0 ){
               if( pairs[i].rates[0].time > 0 )
                  pairs[i].valid = true;
            }
         }
      }
   }

}