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

 

Bem pessoal, a primeira parte está feita ( ler todas as taxas de pares ).

Agora preciso usar as taxas de todos os paris copiados com a função ArrayCopyRates para colocar alguns indicadores gráficos como um RSI... como eu desenho na imagem abaixo:

Em minha pergunta inicial pretendo saber como fazer isso... e não sobre as taxas de leitura. Acho que não precisarei copiar taxas antes para desenhá-la, mas foi bom saber como fazer... agora só preciso descobrir uma maneira de dividir a área do indicador para traçar todos os pares...

 
Entenda. Então, todos os elementos devem ser desenhados como objetos.
 

Este é um Indicador que peguei em algum lugar, nunca tentei decifrá-lo. Eu mostro uma representação de 3 períodos de tempo do gráfico atual. O mais louco é que as velas são desenhadas com Histogramas. Bastante arrumado, mas não no que estou me metendo agora.

Melhores Desejos

Arquivos anexados:
 
Ok, obrigado. Eu viajo no trabalho e, quando voltar, vou testá-lo.
 
Fernando Carreiro:

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.

Assim, 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.

Apenas para expandir suas descobertas Fernando - mesmo que o símbolo seja o mesmo que o símbolo do gráfico, se o cronograma for diferente, então o array é estático.

Assim, para ter uma cópia virtual, em um indicador, ela deve ser o mesmo símbolo E o mesmo período de tempo. Qualquer outra coisa é estática.

 
honest_knave: Apenas para expandir suas descobertas Fernando - mesmo que o símbolo seja o mesmo que o símbolo do gráfico, se o cronograma for diferente, então a matriz é estática. Portanto, para ter uma cópia virtual, em um indicador, ele deve ser o mesmo símbolo E o mesmo período de tempo. Qualquer outra coisa é estática.
Obrigado pela atualização!
 
Hi,

Tenho procurado por toda parte uma solução para este problema e gostaria de agradecer a todos neste tópico por esta discussão.

Esta é minha primeira mensagem no fórum, portanto, por favor, me avisem se eu perdi algum protocolo e eu ficaria feliz em corrigir na próxima mensagem.

Estou tentando desenvolver um indicador muito simples, mas minha lógica parece ser sensível ao fato de o gráfico estar totalmente atualizado, e é por isso que estou tão interessado nesta discussão.

Meu indicador procura desenhar uma mentira na faixa do dia anterior (dia alto para dia baixo ou dia baixo para dia alto) e no dia atual desenhar linhas no alto, baixo e 50% da mentira. Se o indicador for usado em um corretor GMT (vela diária de domingo), o usuário pode definir um parâmetro de entrada para escolher se na segunda-feira ele usa apenas a faixa de sexta-feira ou domingo, ou sexta-feira + domingo. Em um corretor de fechamento de NY (GMT+2) que não faz diferença, uma vez que não há velas de domingo.

Outra característica deste indicador é permitir que o usuário mova a fibra e as linhas (alta, 50% e baixa) no dia atual se ajustarão à nova faixa definida pela fibra. Isso permitirá que o usuário ajuste a faixa caso a faixa se contraia.

O indicador será usado principalmente em múltiplos gráficos de 1h, mas o usuário deverá ser capaz de mudar os intervalos de tempo sem perder nenhuma alteração feita na fibra.

Para desenhar a fibra preciso encontrar não apenas o alto e o baixo do dia anterior, mas também o tempo para estes pontos.

A idéia é simples, mas eu tenho enfrentado alguns desafios.

Assumindo que é meio da semana para encontrar o alto e o baixo do dia anterior que eu simplesmente uso:

       Hi = iHigh(NULL, PERIOD_D1, 1);
       Lo = iLow(NULL, PERIOD_D1, 1);

Tudo bem, mas agora preciso encontrar no dia anterior qual foi a hora alta e a hora baixa. Decidi aproximar o tempo da vela de 1h no alto e no baixo usando iHighest e iLowest. E foi aí que os problemas começaram.


Para usar iHighest e iLowest preciso especificar a primeira vela de 1h e o tamanho da faixa, portanto, no meu caso, essa será a primeira vela de 1h e a última vela de 1h do dia anterior. Assim, usei a vela aberta do dia anterior para o início do dia anterior e a vela aberta do dia atual -1, para encontrar o fim do dia anterior:

       PrevDayBegin = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 1));                
       PrevDayEnd = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1);

E isso funciona muito bem se você estiver usando apenas o indicador em moedas (novamente assumindo que seja no meio da semana) porque PrevDayBegin será o índice da vela 0:00 1h e PrevDayEnd será o índice da vela 23:00 1h. O problema está nos futuros (índices, ouro, bruto, etc.). A abertura diária da vela é sempre às 0:00, mas a 1ª vela sobre futuros é à 1h nos corretores GMT+2, portanto a linha de código acima que calcula PrevDayBegin retorna a vela 1h para as 23:00 do dia anterior.

Decidi então incluir uma peça de código para acomodar esta situação e mover o PrevDayBegin até o mesmo dia da semana do PrevDayEnd:

       if(TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayBegin)) != TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayEnd)))
         PrevDayBegin--;  

E toda essa lógica funciona muito bem se você tiver todas as velas 1h atualizadas, mas dê uma olhada no tronco abaixo mostrando algumas impressões do que aconteceu hoje. Apenas para referência, fechei o MT4 no dia anterior à noite e o abri novamente hoje de manhã (por volta das 7h da manhã no Reino Unido), portanto faltaram apenas algumas horas de dados nos gráficos.

2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OUTRO DIA DA SEMANA ==
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.08 19:00)
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 20 (2017.02.08 00:00)

Olhando para o log parece que a vela mais atualizada no gráfico 1h foi 2017.02.08 20:00 (índice 0), portanto iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1) está se aproximando a (índice 1) 2017.02.08 19:00. Consequentemente, todos os cálculos para o indicador se confundem, porque iHighest e iLowest estarão usando a faixa errada.

Com base nas discussões anteriores, tentei e usei algumas das soluções sugeridas para esperar que todas as velas fossem carregadas antes de fazer os cálculos, mas aparentemente ainda não está funcionando.

Por exemplo, no OnInit() eu incluí as seguintes linhas de código para acionar a atualização dos gráficos em 1h, Diariamente e no tempo atual (caso a plataforma estivesse fechada quando o gráfico estivesse aberto em um período de tempo diferente):

   // Triggers history update
   MqlRates mqlrates_array_d1[];
   MqlRates mqlrates_array_h1[];
   MqlRates mqlrates_array[];
  
   ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1);
   ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1);
   ArrayCopyRates(mqlrates_array,NULL,0);  
Outra coisa que notei é que parece que o MT4 atualiza o Tempo da vela mais recente[0] no intervalo de tempo que está aberto no gráfico antes que ele carregue todo o histórico que falta, portanto decidi testar se o Tempo[1] também era um preço válido.

Esse código foi inserido na OnCalculate() e foi baseado nos códigos de @whroeder1(aqui) e @Fernando Carreiro& @Wemerson Guimaraes(aqui):

bool isHistoryLoading;

OnInit();
:
isHistoryLoading = true;
:

OnCalculate( ... )
:
      MqlRates mqlrates_array_d1[];
      MqlRates mqlrates_array_h1[];
      MqlRates mqlrates_array[];
      
      if(isHistoryLoading)
        {      
         ResetLastError();        
        
         if(ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1)>0)
           {
            if(GetLastError() == 0)
              {
               if((iTime(NULL,PERIOD_D1,0) > 0) && (iTime(NULL,PERIOD_D1,1) > 0))
                 {
                  ResetLastError();
  
                  if(ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1)>0)
                    {
                     if(GetLastError() == 0)
                       {
                        if((iTime(NULL,PERIOD_H1,0) > 0) && (iTime(NULL,PERIOD_H1,1) > 0))
                          {
                           ResetLastError();
      
                           if(ArrayCopyRates(mqlrates_array,NULL,0)>0)
                             {
                              if(GetLastError() == 0)
                                {
                                 if((iTime(NULL,0,0) > 0) && (iTime(NULL,0,1) > 0))                            
                                   {
                                    isHistoryLoading = false;
                                
                                    if(DebugLog)
                                      Print("Chart up-to-date!");        
                                    }
                                }
                             }
                          }
                       }
                    }                      
                 }
              }
           }
        }
        
      if(isHistoryLoading)
        {
         if(DebugLog)
           Print("Waiting for chart to update!");
         return(rates_total);
        }    

:

E este é o registro quando a plataforma foi aberta e o indicador foi carregado pela primeira vez:

2017.02.09 06:56:18.492 Indicador personalizado Prev_Day_Range_LRT_50_v0.6 SPX500,H1: carregado com sucesso
2017.02.09 06:56:18.630 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: inicializado
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Gráfico atualizado!
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: O indicador não existe! Criando-o.
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OUTRO DIA DA SEMANA ==
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 20 (2017.02.07 23:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 42 (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR Dia da Semana = 3
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Vela = 28) (Preço = 2299.33) (Hora = 2017.02.07 14:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iLowest (Vela = 20) (Preço = 2287,88) (Hora = 2017.02.07 23:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Fibra desde Time1=2017.02.07 14:00 Price1=2299.33 até Time2=2017.02.07 23:00 Price2=2287.88
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend1 131296489639296384' de Time1=2017.02.08 00:00 Price1=2299.33 até Time2=2017.02.09 00:00 Price2=2299.33
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend2 131296489639296384' a partir de Time1=2017.02.08 00:00 Price1=2293.605 até Time2=2017.02.09 00:00 Price2=2293.605
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend3 131296489639296384' de Time1=2017.02.08 00:00 Price1=2287.88 até Time2=2017.02.09 00:00 Price2=2287.88

Parece que qualquer referência a velas 0 e 1 ou à função ArrayCopyRates só estão acessando onde a informação já está carregada nos gráficos, portanto o ArrayCopyRates parece estar retornando um número válido de elementos copiados e o iTime(..., 0) e o iTime(..., 1) estão retornando um preço válido para as últimas 2 velas armazenadas quando a plataforma foi fechada no dia anterior.

Isso significa que o indicador foi plotado como se fosse ontem (PERÍODO_D1 [0] = (2017.02.08 00:00)).

O indicador é construído para que as linhas alta, 50% e baixa sejam sempre plotadas no dia atual, mesmo que o usuário mova a fibra (estas são as 3 linhas de tendência mostradas no log acima). Portanto, tenho um código na OnCalculate() que testa se a linha de tendência média é traçada no dia corrente (o usuário tem uma opção de entrada para desativar a linha superior e inferior, portanto a única linha que será sempre traçada é a linha média).

OnCalculate( ... )
:

      if(ObjectFind(Trend2Name) != -1)                // Check whether mid range line exists
        {
            
         if((TimeDay(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeDay(TimeCurrent()))
           && (TimeMonth(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeMonth(TimeCurrent()))
           && (TimeYear(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeYear(TimeCurrent()))) // Indicator has already been ploted today        
           {
            return(rates_total);
           }
         else     // Indicator exists but in a past date, so delete it and plot it on current day
           {
            if(DebugLog)
               Print("Indicator in a past date! Deleting it and creating it today!");
              
            if(ObjectFind(FibName) != -1)
              FiboLevelsDelete(0,FibName);              
            // Indicator will be created by the OnChartEvent() when it detects the fib was deleted.
           }
        }
      else        // Indicator doesn't exist, so create it
        {
         if(DebugLog)
            Print("Indicator doesn't exist! Creating it.");
         CreateIndicator();
        }
:

Após alguns tiques, os dados são parcialmente carregados e o pedaço de código acima detectará que as linhas foram traçadas em um dia anterior, apagará a fibra e desencadeará um recálculo dos intervalos e redesenho dos objetos (isto é, fibra, linhas de tendência, etc.).


2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Indicador em uma data passada! Excluindo-o e criando-o hoje!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRFibo 131296489639296384 apagado!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminação do PDRRRectangle 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminação do PDRTrend1 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminação do PDRTrend2 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminação do PDRTrend3 131296489639296384

E então voltamos ao problema que eu estava mencionando no início desta mensagem. O teste que implementei acima novamente não faz o indicador esperar que o histórico esteja totalmente carregado e, portanto, os intervalos são mal calculados com base em dados parciais.

Esta é uma versão mais completa do log mostrado no início da mensagem que mostra que não só o PrevDayEnd está sendo mal calculado como a 2ª vela (índice 1) no gráfico 1h está (2017.02.07 21:00), mas também o CurrDayBegin que deve ser a 1ª vela do dia atual no gráfico 1h está sendo aproximado pelo iBarShift para (2017.02.08 06:00).

CurrDayBegin = iTime(NULL, PERIOD_D1, 0);
      
while(TimeDayOfWeek(iTime(NULL, PERIOD_H1, iBarShift(NULL, PERIOD_H1, CurrDayBegin))) != TimeDayOfWeek(TimeCurrent()))

     // If iBarShift can't find the 0am candle and returns the 11pm candle of prev day.

  CurrDayBegin = CurrDayBegin + 3600;        // Move 1h until you find the 1st candle of today.                                        

2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OUTRO DIA DA SEMANA ==
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.07 21:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 22 (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 06:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR Dia da Semana = 3
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Vela = 8) (Preço = 2299.33) (Hora = 2017.02.07 14:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iLowest (Vela = 19) (Preço = 2288,57) (Hora = 2017.02.07 03:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Fibra desde Time1=2017.02.07 03:00 Price1=2288.57 até Time2=2017.02.07 14:00 Price2=2299.33
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend1 131296489639296384' de Time1=2017.02.08 06:00 Price1=2288.57 até Time2=2017.02.09 06:00 Price2=2288.57
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend2 131296489639296384' a partir de Time1=2017.02.08 06:00 Price1=2293.95 até Time2=2017.02.09 06:00 Price2=2293.95
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Linha de tendência 'PDRTrend3 131296489639296384' a partir de Time1=2017.02.08 06:00 Price1=2299.33 até Time2=2017.02.09 06:00 Price2=2299.33

Então, em resumo, existe um motivo para testar se todo o histoy foi carregado em um gráfico? Ou me está faltando alguma coisa no meu código?

Obrigado por ter me acompanhado nesta longa mensagem.

Por favor, me informe se você gostaria de ver o código inteiro e o log. Prefiro não anexar o código aqui, mas terei prazer em enviá-lo em particular.

Estas são screenshots do indicador:

(1) Calculadas usando histórico incompleto (por favor, note que as linhas horizontais não começam no início do dia)

Indicador calculado com histórico incompleto

(2) Recalculado utilizando o histórico completo (linhas horizontais a partir do início do dia)

Indicador recalculado usando o histórico completo

Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
  • www.mql5.com
Hi i m building a custom indicator and got problems with the 4066 Error...