English Русский 中文 Español Deutsch 日本語
preview
Trabalhando com o tempo (Parte 2): funções

Trabalhando com o tempo (Parte 2): funções

MetaTrader 5Exemplos | 24 janeiro 2022, 10:40
737 1
Carl Schreiber
Carl Schreiber

Variáveis globais

Em vez de preguntar à corretora, que provavelmente dará uma resposta imprecisa (e quem quer explicar onde está o horário de negociação?), seremos nós mesmos a ver a que horas ela recebe as cotações nas semanas em que os fusos horários são trocados. Mas é claro que não vamos fazer isso manualmente, deixaremos o software fazer o trabalho por nós.

Neste artigo continuaremos com o arquivo de inclusão DealingWithTime.mqh, com que trabalhamos na primeira parte. Neste arquivo, antes das funções e depois das substituições de macros vêm as variáveis requeridas, que são declaradas como variáveis globais:

//--- global variables for time switches
int      DST_USD=0,                             // act time shift USD
         DST_EUR=0,                             // act time shift EU
         DST_AUD=0,                             // act time shift Australia
         DST_RUS=0;                             // D'2014.10.26 02:00', -10800,



Estas variáveis DST_USD, DST_EUR, etc. tomarão o valor real da diferença de tempo nos respectivos países e regiões - EUA, Europa, etc. Os valores das variáveis serão preenchidos com funções. No horário normal de inverno, os valores são zero: o tempo não muda durante este período.

Em seguida, temos variáveis com a data da próxima mudança de horário. Elas indicam quando os novos valores das variáveis terão que ser calculados, para que cálculos desnecessários não sejam realizados antes disso e para que os recursos computacionais não sejam desperdiçados:

datetime nxtSwitch_USD,                         // date of next switch
         nxtSwitch_EUR,                         // date of next switch
         nxtSwitch_AUD,                         // date of next switch
         nxtSwitch_RUB = D'2014.10.26 02:00';   // Russia is different :(



Há uma pequena diferença nas configurações para a Rússia, veremos isso um pouco mais tarde.

Esta estrutura e sua variável global são o coração de todo o programa. :)

struct _OffsetBroker
  {
   int   USwinEUwin,                            // US=Winter & EU=Winter
         USsumEUsum,                            // US=Summer & EU=Summer
         USsumEUwin,                            // US=Summer & EU=Winter
         actOffset,                             // actual time offset of the broker
         secFxWiWi,                             // duration of FX in sec
         secFxSuSu,                             // duration of FX in sec
         secFxSuWi,                             // duration of FX in sec
         actSecFX;                              // actual duration of FX in sec
   bool  set;                                   // are all set?
  };
_OffsetBroker OffsetBroker;



Definimos os valores de diferença junto à corretora para os três períodos pertinentes e a permanência no mercado durante esses períodos. Também escrevemos o verdadeiro valor de permanência e verificamos se todos os valores requeridos foram definidos. Encontraremos o nome da variável global, OffsetBroker, várias vezes.


Função básica para determinar a mudança de horário junto à corretora

Com a função

setBokerOffset();

EA, indicador ou script será capaz de determinar independentemente quando e como o horário da corretora é mudado. Ela é adicionada no início do código no script anexado, após a função Start(). Ela determina esses valores junto à corretora para os respectivos períodos (horário de verão, de inverno e intermediário), a partir dos quais todos os outros valores de tempo são determinados. Esta função, como todas as outras que examinamos no primeiro artigo, está contida num arquivo. Após declarar as variáveis, inicializamos e limpamos as variáveis globais pertinentes:

   datetime dateEUR,dateUSD,dateAUD,dateNxt,                   // switch date for EU, AU, & US
            arrTme[];                                          // array to copy time
   int b;
   OffsetBroker.USsumEUwin =
      OffsetBroker.USsumEUsum =
         OffsetBroker.USwinEUwin = INT_MIN;
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;          // reset variables



obtemos o fim de semana quando os relógios são trocados:

//--- AU, EU & US switches to winter time in 2020
   if(IS_DEBUG_MODE)
      Print("\n2nd half-year 2020 for ",AccountInfoString(ACCOUNT_COMPANY), "DebugMode: ",IS_DEBUG_MODE);

   nextDST("EUR", D'2020.06.21 14:00');                        // EUR: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_EUR,1,arrTme);    // get time last 1h bar before switch in EU
   dateEUR = arrTme[0];                                        // last hour on Friday before the weekend

   nextDST("USD", D'2020.06.21 14:00');                        // USD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_USD,1,arrTme);    // get time last 1h bar before switch in USA
   dateUSD = arrTme[0];                                        // last hour on Friday before the weekend

   nextDST("AUD", D'2020.06.21 14:00');                        // AUD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_AUD,1,arrTme);    // get time last 1h bar before switch in AU
   dateAUD = arrTme[0];                                        // last hour on Friday before the weekend

   dateNxt = fmax(nxtSwitch_EUR,nxtSwitch_USD)+WeekInSec;      // get the next weekend
   b = CopyTime("EURUSD",PERIOD_H1,dateNxt,1,arrTme);          // get time last 1h bar before the weekend
   dateNxt = arrTme[0];                                        // last hour on Friday before the weekend



Para simplificar, a maior parte é feita automaticamente no modo de depuração: if(IS_DEBUG_MODE). Assim, se executarmos o script em modo de depuração (F5), poderemos ver todos os detalhes, e se o executarmos diretamente no gráfico, serão mostrados apenas os mais relevantes.

Para todos os três fusos horários, a chamada de função, por exemplo nextDST("EUR", D'2020.06.21 14:00'), primeiro calcula as diferenças de tempo relevantes para a Europa e depois calcula a mudança da próxima vez. Junho cai no horário de verão e a próxima mudança será para a hora de inverno. A próxima linha é o horário de abertura da última barra H1 na sexta-feira anterior a este fim de semana: esta será a base para nossos cálculos. Veja o ponto 4 das hipóteses no final do primeiro artigo:

          4. Se faltar alguma hora entre as 17h de sexta-feira e as 17h de domingo, as cotações de domingo estarão ausentes até que a primeira cotação seja recebida e não até que as cotações da última sexta-feira apareçam.

Eu decidi usar o tempo H1 e EURUSD. Este símbolo tem provavelmente o maior histórico de cotações. Assim, se o mercado fechar às 17h de Nova Iorque, a última hora de trabalho (ou a última vela horária) abre às 16:00. Esta é a hora em que estamos interessados. Acontece que a primeira hora após o fim de semana é às 17h de domingo em Nova Iorque. Por uma questão de precisão, também definiremos a mudança de horas na Austrália, mas não a utilizaremos. Depois, no primeiro fim de semana após a mudança de hora, determinamos a hora da próxima mudança de horário.

Em seguida, é utilizada a função chckFriday(...) para calcular a diferença de tempo da corretora de acordo com o período selecionado. O cálculo é baseado na hora 16:00 de Nova Iorque. A função também está incluída no arquivo include.

   chckFriday(dateEUR,"EUR");                                  // function to determine broker offset for the Friday given
   chckFriday(dateUSD,"USD");                                  // function to determine broker offset for the Friday given
   chckFriday(dateNxt,"NXT");                                  // function to determine broker offset for the Friday given



O mesmo princípio é usado para calcular as mudanças de horas restantes para o segundo semestre do ano, que na verdade não precisamos e podemos comentar:

   if(IS_DEBUG_MODE)
      Print("\n1st half-year 2021 for ",AccountInfoString(ACCOUNT_COMPANY), "DebugMode: ",IS_DEBUG_MODE);
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;

   nextDST("AUD", D'2021.01.21 14:00');                        // AUD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_AUD,1,arrTme);    // get time last 1h bar before switch in EU
   dateAUD = arrTme[0];                                        // last hour on Friday before the weekend

...
   chckFriday(dateUSD,"USD");                                  // function to determine broker offset for the Friday given
   chckFriday(dateEUR,"EUR");                                  // function to determine broker offset for the Friday given
   chckFriday(dateNxt,"NXT");                                  // function to determine broker offset for the Friday given



Finalmente, após definir a mudança de horário da corretora e atribuir valores aos campos pertinentes, os valores da mudança de tempo (nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0) são zerados para uso posterior. Embora só deva haver um recálculo se tiver "acontecido" um fim de semana com uma mudança de horário no decorrer do histórico, ainda assim é melhor fazer um recálculo com antecedência para não esquecer mais tarde. Em seguida, verificamos se todas as variáveis necessárias foram definidas. O resultado é exibido no log dos EAs:

   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;          // reset variables for use by a user
   if(OffsetBroker.USsumEUwin != INT_MIN
      && OffsetBroker.USsumEUsum != INT_MIN
      && OffsetBroker.USwinEUwin != INT_MIN
     )
      OffsetBroker.set = true;
   else
      OffsetBroker.set = false;
   if(OffsetBroker.set)
      Print("\nTime Offset of ",AccountInfoString(ACCOUNT_COMPANY),": ",
            "\nUS=Winter & EU=Winter (USwinEUwin) = ",OffsetBroker.USwinEUwin,
            "\nUS=Summer & EU=Summer (USsumEUsum) = ",OffsetBroker.USsumEUsum,
            "\nUS=Summer & EU=Winter (USsumEUwin) = ",OffsetBroker.USsumEUwin,
            "\n");
   else
      Print(__FILE__,"[",__LINE__,"] Assigning the broker offset went wrong - somehow.");
   return(OffsetBroker.set);



Se tudo estiver bem, aparecerá uma entrada como esta:

Time Offset of MetaQuotes Software Corp.:
US=Winter & EU=Winter (USwinEUwin)       =   -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)    =   -7200

Qualquer usuário poderá usar esses valores para variáveis de entrada em vez de adicionar funções antes da inicialização do próprio EA no testador de estratégia ou em tempo real no gráfico. Mostrarei um exemplo no final do artigo.


Determinando e definindo a mudança de horário da corretora

Vamos dar uma olhada de perto na função chckFriday(...). Determina a mudança de tempo da corretora em diferentes períodos e atribui um valor para o campo pertinente da variável global OffsetBroker com base na estrutura _OffsetBroker. A estrutura tem três campos:

   int   USwinEUwin,                            // US=Winter & EU=Winter
         USsumEUsum,                            // US=Summer & EU=Summer
         USsumEUwin,                            // US=Summer & EU=Winter



A eles são atribuídos os valores da mudança de horário da corretora nos respectivos períodos. Estes são os períodos:

  • O mesmo tempo para ambas as regiões - inverno (padrão) ou verão.
  • Nos EUA é (ainda) hora de verão e na Europa é (já) é hora de inverno.

A situação inversa, quando é ( ainda ) inverno nos EUA e (já) é verão na Europa, não existe. Surge a pergunta: por que não há uma quarta categoria e o que se passa com a Austrália?

Aqui estão as regras de mudança:

  • Europa: último domingo de outubro e último domingo de março
  • EUA: primeiro domingo de novembro e segundo domingo de março
  • Austrália: primeiro domingo de novembro e último domingo de março


Então, quanto à primeira pergunta: A Europa muda para o horário de inverno uma ou duas semanas antes dos EUA: nos EUA ainda é horário de verão e na Europa já é horário de inverno, portanto o valor é atribuído ao campo USsumEUwin da variável OffsetBroker. Depois, na primavera, os EUA mudam para o horário de verão mais cedo. Acontece que é verão nos EUA por uma semana ou duas, enquanto ainda é inverno na Europa. O mesmo valor é atribuído ao campo USsumEUwin da variável OffsetBroker. Por isso, não ocorre o inverso, já que na Europa é horário de verão e nos EUA ainda é horário de inverno. Isto elimina efetivamente a necessidade de calcular as diferenças de tempo da corretora para ambos os períodos de mudança de horário, outono e primavera. No entanto, fazemos o cálculo, apenas para completar e controlar.

Quanto à segunda pergunta: A Austrália muda de horário em novembro, ao mesmo tempo que os EUA, e na primavera muda como a Europa. Ou seja, não há novos finais de semana para fazer a transição. Entretanto, os relógios na Austrália avançam 1 hora quando é inverno na Europa e nos EUA, porque o Natal e o Ano Novo são lá no verão.

Com os valores das mudanças de horários para um determinado período, também é possível calcular a duração do mercado forex nas semanas em questão: estes valores são armazenados nos campos secFxWiWiВи, secFxSuSu e secFxSuWi, e o valor real atual, em ActSecFX. A seção "Aplicações" no final do artigo mostra o que fazer com isso.

Para atribuir valores, eles devem primeiro ser calculados. Após a declaração das variáveis e a redefinição das variáveis globais, os valores das mudanças de horário na Europa e nos EUA são calculados para a hora da corretora selecionada tB:

//+------------------------------------------------------------------+
//| auxiliary function to determine time offset of the broker        |
//+------------------------------------------------------------------+
int chckFriday(
   datetime tB,                                                // time Broker: the last hour on Friday
   string cmt=""                                               // text to start the line
)
  {

   int hNY, hGMT, hTC, hDiff;
   nxtSwitch_AUD = nxtSwitch_USD = nxtSwitch_EUR = 0;          // reset to be save
   nextDST("EUR",tB);                                          // get the offset for EUR of the time tB given
   nextDST("USD",tB);                                          // get the offset for USD of the time tB given


Neste caso, tB é o início da última hora na sexta-feira, quando são 16h em Nova Iorque. Esta é a base para outros cálculos, para esta hora podemos calcular o GMT:

tGMT = tNY + (NYShift + DST_USD)

ou seja, a mudança de horário da corretora segundo o GMT. Eis como se define a mudança: da última hora na sexta-feira segundo o tempo tB subtraímos o número de segundos transcorridos desde o início do dia SoB(tB). Obtemos 00:00 do dia e depois adicionamos o número de segundos à hora 16:00 (16*3600). É assim que obtemos a hora de Nova Iorque, a partir da qual calculamos a hora GMT: NYShift + DST_USD. Agora é fácil determinar a diferença de horário da corretora a partir em relação ao GMT, e escrever o valor resultante no campo correspondente da variável OffsetBroker.
A função calcula em horas, e não em segundos, com a substituição de macros HoD() (Hour of Day, hora do dia) para facilitar o trabalho:

   hNY   = HoD(tB - SoD(tB) + 16*3600);                        // get the hour of New York time
   hGMT  = HoD(tB - SoD(tB) + 16*3600 + NYShift + DST_USD);    // get the hour of GMT
   hTC   = HoD(tB);                                            // get the hour of the time given
   hDiff = hGMT - HoD(tB);                                     // get the difference between GMT and the broker



Não é tão difícil.

A seguinte parte foi acrescentada para fins de verificação. Garante que não surja a situação impossível quando se trata de verão nos EUA e inverno na Europa:

   if(DST_USD==0 && DST_EUR!=0)                                // this should not occur
      Alert(__LINE__," ",TOSTR(DST_USD),TOSTR(DST_EUR),"  USwin && EUsum");



Agora podemos usar a diferença encontrada e a permanência no mercado:

//--- set the broker offset for the various time situations:
   if(DST_USD+DST_EUR==0)                                      // both in winter (normal) time
     {
      OffsetBroker.actOffset = OffsetBroker.USwinEUwin = hDiff*3600;
      OffsetBroker.actSecFX  = OffsetBroker.secFxWiWi = SoW(tB);
     }
   else
      if(DST_USD == DST_EUR)                                   // else both in summer time
        {
         OffsetBroker.actOffset = OffsetBroker.USsumEUsum = hDiff*3600;
         OffsetBroker.actSecFX  = OffsetBroker.secFxSuSu = SoW(tB);
        }
      else
         if(DST_USD!=0 && DST_EUR==0)                          // US:summer EU:winter
           {
            OffsetBroker.actOffset = OffsetBroker.USsumEUwin = hDiff*3600;
            OffsetBroker.actSecFX  = OffsetBroker.secFxSuWi = SoW(tB);
           }




Em seguida, registramos todos os valores encontrados e retornamos a última mudança de horário real:

//--- calc the ring of times NY->GMT->Broker->GMT->NY <= the last NY must always be 16!!
   Print(cmt,": ",DoWs(tB),TimeToString(tB),": ",TOSTR(hNY),TOSTR(hGMT),TOSTR(hTC),TOSTR(hDiff),
         " BrokerTime => GMT: ",TimeToString(tB+OffsetBroker.actOffset),
         " => tNY: ",TimeToString((tB + OffsetBroker.actOffset)-(NYShift + DST_USD)),
         "  End-FX after: ",OffsetBroker.actSecFX/3600,"h"
        );
   return(OffsetBroker.actOffset);



Ficam mais ou menos assim:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End FX in: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End FX in: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End FX in: 143h

Vamos dar uma olhada aqui. Primeiro, a Europa muda a hora no dia 25 de outubro. Uma semana depois, em 1 de novembro, as horas são alteradas nos Estados Unidos. Entre estas duas datas, a última hora de sexta-feira no servidor da MetaQuotes começa às 22:00, não às 23:00 e a semana termina com esta vela, ou seja, depois de 142horas ao invés das usuais 143. 143 ou 142 horas? Para o mercado forex, uma semana tem 120 horas: 5*24=120? Segundos da semana (SoW(), Seconds of Week) e funções similares funcionam com a semana do calendário, que começa no domingo às 00:00 horas. Mas de domingo 00:00 a sexta-feira 23:00 agora 6* 24-1 = 143 horas. Com base neste valor em qualquer ponto da semana, é possível calcular o tempo restante de permanência no mercado até o final da semana.

A lógica e os cálculos também são verificados com base nestas três linhas. Também é possível determinar a hora local de acordo com o Tempo Médio de Greenwich (GMT). Da esquerda para a direita: registro da hora da corretora, hora de cálculo sengundo Nova Iorque, hNY: 16, hora segundo Greenwich Média baseada na hora de Nova Iorque, hora da corretora e diferença: -2 ou -3. Na segunda parte, o cálculo do GMT a partir do horário da corretora (tB+OffsetBroker.actOffset), e depois com base no GMT - tempo em Nova Iorque novamente ((tB + OffsetBroker.actOffset)-(NYShift + DST_USD)). O valor para Nova Iorque deve sempre ser tNY=16:00. Uma segunda verificação é realizada abaixo para tempos aleatórios no histórico e para outras corretoras.


Cálculo de fim de semana quando as horas mudam

Antes de passarmos ao trabalho com tempo usando o histórico do EURUSD, vejamos a função de cálculo subjacente - nextDST(...).
A função é chamada com o parâmetro zone para o fuso horário "USD", "EUR" ou "AUD" (embora na verdade não precisemos do AUD) e com o parâmetro t - a hora atual, geralmente a hora atual da corretora TimeCurrent(). Primeiro, verificamos se é necessário um recálculo (neste exemplo, para EUR):

void nextDST(string zone, datetime t)
  {
   if((zone == "EUR") && t < nxtSwitch_EUR)
     {
      if(IS_DEBUG_MODE)
         Print("no change as time < nxtSwitch_EUR");
      return;
     }
...


Aqui fica claro por que é tão importante redefinir os valores de nxtSwitch_EUR no início do teste - caso contrário, nenhum recálculo poderá ser realizado durante todo o teste.

Depois de declarar uma variável e inicializar, chegamos à essência da função. Esta função não é minha. Algum tempo atrás, em algum lugar da Internet, encontrei um algoritmo que determinava um determinado dia dentro do mês. É usado para determinar o horário de verão ou inverno para o momento selecionado. O algoritmo em si é simples:

  1. Determinamos o dia do mês - domingo, quando a hora muda.
  2. Com base nisso, criamos uma data.
  3. Encontramos o próximo domingo, quando os horários serão alterados.
  4. Definimos a mudança de horário, 0h ou -1h, e o domingo da próxima mudança.

A magia deste algoritmo reside na linha de código que determina o dia do mês em que o horário é modificado. Na Europa, é o último domingo de março, calculado assim (como eu disse, a ideia da fórmula não é minha):

d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determine the last Sunday in March for the EU switch
Como resultado, para o ano de 2021, o último domingo de março é obtido como d=25:

31 - MOD(ROUNDDOWN(5*2021/4);7) = 25.


Em seguida, forma-se um marcador de tempo para o dia em que ocorre a mudança da hora na Europa: 25 de março de 2021, no último domingo de março:
spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format

Todas as datas são calculadas da mesma forma.
A seguir vem uma seção de código grande que define a transição atual para verão ou para inverno e a próxima data de transição europeia para data selecionada. Como resultado, precisamos encontrar três períodos no ano: antes da primeira transição, entre a primeira e a segunda transição, e depois da segunda transição. A próxima transição será no próximo ano, e isto deve ser levado em conta:

   if(zone == "EUR")
     {
      d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determine the last Sunday in March for the EU switch
      spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format
      if(t < spr)
        {
         DST_EUR = 0;                                             // no time offset
         nxtSwitch_EUR = spr;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      d = (int)(31 - MathMod((1 + MathFloor(5*y/4)), 7));         // determine the last Sunday in October for the EU switch
      aut = StringToTime(""+(string)y+".10."+(string)d+" 03:00"); // convert to datetime format
      if(t < aut)
        {
         DST_EUR =-3600;                           // = +1h => 09:00 London time = GMT+05h+DST_EU = GMT+0+1 = GMT+1;
         nxtSwitch_EUR = aut;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      y++;                                                        // re-calc the spring switch for the next year
      d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determine the last Sunday in March for the EU switch
      spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format
      if(t < spr)
        {
         DST_EUR = 0;                                             // no time offset
         nxtSwitch_EUR = spr;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      Print("ERROR for ",zone," @ ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR),"  winter: ",TimeToString(aut),"  spring: ",TimeToString(spr));
      return;
     }



Todos os três períodos são mostrados no mesmo ano:

  1. Antes da transição para p horário de verão, em março.
  2. Antes da transição para o horário de inverno em outubro/novembro.
  3. Horário de inverno até a transição para o horário de verão no próximo ano.

Os períodos são calculados para EUR, USD e AUD.

Chamada única de função nextDST(..), assim:

nextDST("EUR", D'2019.02.05 20:00');
nextDST("EUR", D'2019.06.05 20:00');
nextDST("EUR", D'2019.11.20 20:00');
        
nextDST("USD", D'2019.02.05 20:00');
nextDST("USD", D'2019.06.05 20:00');
nextDST("USD", D'2019.11.20 20:00');
        
nextDST("AUD", D'2019.02.05 20:00');
nextDST("AUD", D'2019.06.05 20:00');
nextDST("AUD", D'2019.11.20 20:00');



verifica todos os três momentos num ano para três regiões. E aqui está o resultado:

Europa: último domingo de março e último domingo de outubro:
    EUR-DST for 2019.02.05 20:00 DST:        0   nxtSwitch: Su. 2019.03.31 03:00
    EUR-DST for 2019.06.05 20:00 DST: -3600   nxtSwitch: Su. 2019.10.27 03:00
    EUR-DST for 2019.11.20 20:00 DST:        0   nxtSwitch: Su. 2020.03.29 03:00

EUA: 2º domingo de março e 1º domingo de novembro:
    USD-DST for 2019.02.05 20:00 DST:        0   nxtSwitch: Su. 2019.03.10 03:00
    USD-DST for 2019.06.05 20:00 DST: -3600   nxtSwitch: Su. 2019.11.03 03:00
    USD-DST for 2019.11.20 20:00 DST:        0   nxtSwitch: Su. 2020.03.08 03:00

Austrália: primeiro domingo de novembro e último domingo de março
    AUD-DST for 2019.02.05 20:00 DST: -3600   nxtSwitch: Su. 2019.03.31 03:00
    AUD-DST for 2019.06.05 20:00 DST:        0   nxtSwitch: Su. 2019.11.03 03:00
    AUD-DST for 2019.11.20 20:00 DST: -3600   nxtSwitch: Su. 2020.03.29 03:00

A mudança de horário na Austrália pode ser confusa, porque a Austrália está localizada no hemisfério sul, onde o início do ano é no meio do verão - o horário de verão ocorre quando é inverno na Europa.


Mudança de horário na Rússia

Tive que escrever separadamente o código para trabalhar com o tempo na Rússia. Como houve mudanças na Rússia relacionadas à mudança de horário, decidi usar uma matriz bidimensional que contém o tempo das transições. Você pode solicitá-lo usando esta função:

long RussiaTimeSwitch[][2] =
  {
   D'1970.01.00 00:00', -10800,
   D'1980.01.00 00:00', -10800,
   D'1981.04.01 00:00', -14400,
...
   D'2012.01.00 00:00', -14400,
   D'2014.10.26 02:00', -10800,
   D'3000.12.31 23:59', -10800
  };
int SzRussiaTimeSwitch = 67;                    // ArraySize of RussiaTimeSwitch

//+------------------------------------------------------------------+
//| Russian Time Switches                                            |
//+------------------------------------------------------------------+
void offsetRubGMT(const datetime t)
  {
   int i = SzRussiaTimeSwitch; //ArrayRange(RussiaTimeSwitch,0); 66
   while(i-->0 && t < RussiaTimeSwitch[i][0])
      continue;
// t >= RussiaTimeSwitch[i][0]
   nxtSwitch_RUB  = (datetime)RussiaTimeSwitch[fmin(SzRussiaTimeSwitch-1,i+1)][0];
   DST_RUS        = (int)RussiaTimeSwitch[fmin(SzRussiaTimeSwitch-1,i+1)][1];
   return;
  }
//+------------------------------------------------------------------+





Função que atualiza valores

Chegamos ao último recurso deste projeto. Essa função garante que todos os valores importantes estejam atualizados:

//+------------------------------------------------------------------+
//| function to determine broker offset for the time tB given        |
//+------------------------------------------------------------------+
void checkTimeOffset(datetime tB)
  {
   if(tB < nxtSwitch_USD && tB < nxtSwitch_EUR && tB < nxtSwitch_AUD)
      return;                                                  // nothing has changed, return



No início, a função pergunta se você precisa definir a diferença de tempo (e a data da próxima transição). Caso contrário, a função é finalizada.

Caso contrário, a função nextDST() calcula os valores correspondentes para EUR, USD, AUD e RUB (descritos acima):

   if(tB>nxtSwitch_USD)
      nextDST("USD", tB);                                      // US has switched
   if(tB>nxtSwitch_EUR)
      nextDST("EUR", tB);                                      // EU has switched
   if(tB>nxtSwitch_AUD)
      nextDST("AUD", tB);                                      // AU has switched
   if(tB>nxtSwitch_RUB)
      nextDST("RUB", tB);                                      // RU has switched



Para determinar a mudança de horário da corretora, são necessários apenas USD e EUR. E AUD e RUB apenas dão os valores reais para os respectivos países. Se você não precisar deles, você pode comentar //.

Em seguida, dependendo do período, no campo OffsetBroker.actOffset é escrito a diferença de tempo da corretora válida do período correspondente, e no OffsetBroker.actSecFX é escrito o tempo de funcionamento do mercado no momento atual:

   if(DST_USD+DST_EUR==0)                                      // both in winter (normal) time
     {
      OffsetBroker.actOffset = OffsetBroker.USwinEUwin;
      OffsetBroker.actSecFX  = OffsetBroker.secFxWiWi;
     }
   else
      if(DST_USD == DST_EUR)                                   // else both in summer time
        {
         OffsetBroker.actOffset = OffsetBroker.USsumEUsum;
         OffsetBroker.actSecFX  = OffsetBroker.secFxSuSu;
        }
      else
         if(DST_USD != DST_EUR)                                // US:summer EU:winter
           {
            OffsetBroker.actOffset = OffsetBroker.USsumEUwin;
            OffsetBroker.actSecFX  = OffsetBroker.secFxSuWi;
           }



E isso é tudo. Consideramos todas as funções necessárias: a função para determinar a diferença de tempo da corretora da cotação e a função que sempre determina a diferença de tempo atual, a partir da qual você pode facilmente determinar o Greenwich Mean Time (GMT) e, portanto, a hora local, mesmo quando se trabalha no testador de estratégia.

Existem duas maneiras de trabalhar com elas.


O script mostra a configuração e o uso

Em anexo está um arquivo do script DealingWithTimeScript.mq5:

#include <DealingWithTime.mqh>
//+------------------------------------------------------------------+
//| Finding the broker offsets                                       |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- step 1: set the broker time offsets in winter, summer and in between
   bool isTimeSet = setBokerOffset();
   if(!isTimeSet)
     {
      Alert("setBokerOffset failed");
      return;
     }



O log do EA exibirá:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Offset for MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

Os valores encontrados podem ser atribuídos a variáveis de entrada. Este é um exemplo para o próximo capítulo. Já discutimos acima como essa parte funciona. Simulamos o caminho do passado até a hora atual da corretora, calculamos e imprimimos os valores GMT de Nova Iorque e o tempo restante que o mercado forex estará aberto para os marcadores de tempo selecionados aleatoriamente.

Todo o histórico para o período de 1h do EURUSD pode ser obtido usando a função CopyTime("EURUSD",PERIOD_H1,datetime(0),TimeCurrent(),arr1h).

Para não nos afogar num monte de dados, vamos analisar os dados de barras definidas aleatoriamente. Para fazer isso, selecionamos a quantidade de dados. Se definirmos 5, haverá cerca de 10 barras, porque a distância média aleatória do passo é cerca de meio sz/5:

//--- step 2: get the quotes (here only 1h time stamps)
   datetime arr1h[], tGMT, tNY, tLeft;
   CopyTime("EURUSD",PERIOD_H1,datetime(0),TimeCurrent(),arr1h);
   int b       = 0,
       sz      = ArraySize(arr1h)-1,                  // oldest time stamp
       nChecks = sz/5,                                // ~2*5+1 randomly chosen bars
       chckBar = MathRand()%nChecks;                  // index of the first bar to check



Percorremos todas as barras, desde a mais antiga até a atual, como ao testar ou otimizar em um testador de estratégia: while(++b<=sz). Verificaremos a situação em cada nova barra: checkTimeOffset(arr1h[b]). Lembramos que esta função verifica principalmente a necessidade de recálculo, de modo que a chamada não é muito consumidora de recursos, apesar da freqüência:

//---  step 3: simulate an EA or an indicator go through the time from the past to now
   while(++b<=sz)
     {
      //--- check the time situation, normally do it at the first bar after the weekend
      checkTimeOffset(arr1h[b]);



Agora calculamos apenas para a barra definida por um valor aleatório GMT (tGMT), tNY Nova Iorque, e tLeft o tempo restante até o fechamento do mercado. Os valores são exibidos e a próxima barra é calculada:

      //--- for a randomly selected bar calc. the times of GMT, NY & tLeft and print them
      if(b>=chckBar || b==sz)
        {
         tGMT  = arr1h[b] + OffsetBroker.actOffset;         // GMT
         tNY   = tGMT - (NYShift+DST_USD);                  // time in New York
         tLeft = OffsetBroker.actSecFX - SoW(arr1h[b]);     // time till FX closes
         PrintFormat("DST_EUR:%+ 6i  DST_EUR:%+ 6i  t[%6i]  tBrk: %s%s  "+
                     "GMT: %s%s  NY: %s%s  End-FX: %2ih => left: %2ih ",
                     DST_EUR,DST_USD,b,
                     DoWs(arr1h[b]),TimeToString(arr1h[b],TIME_DATE|TIME_MINUTES),
                     DoWs(tGMT),TimeToString(tGMT,TIME_DATE|TIME_MINUTES),
                     DoWs(tNY),TimeToString(tNY,TIME_DATE|TIME_MINUTES),
                     OffsetBroker.actSecFX/3600,tLeft/3600
                    );
         chckBar += MathRand()%nChecks;               //  calc. the index of the next bar to check
        }



Isto é o que o script dá na conta de demonstração no servidor da MetaQuotes:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Diferença para a MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

DST_EUR: -3600  DST_EUR: -3600  t[ 28194]  tBrk: Mo.2002.05.20 22:00  GMT: Mo.2002.05.20 19:00  NY: Mo.2002.05.20 15:00  End-FX: 143h => left: 97h 
DST_EUR: -3600  DST_EUR: -3600  t[ 40805]  tBrk: We.2004.05.26 06:00  GMT: We.2004.05.26 03:00  NY: Tu.2004.05.25 23:00  End-FX: 143h => left: 65h 
DST_EUR: -3600  DST_EUR: -3600  t[ 42882]  tBrk: Th.2004.09.23 19:00  GMT: Th.2004.09.23 16:00  NY: Th.2004.09.23 12:00  End-FX: 143h => left: 28h 
DST_EUR:      +0  DST_EUR:     +0  t[ 44752]  tBrk: Tu.2005.01.11 17:00  GMT: Tu.2005.01.11 15:00  NY: Tu.2005.01.11 10:00  End-FX: 143h => left: 78h 
DST_EUR:      +0  DST_EUR: -3600  t[ 64593]  tBrk: We.2008.03.26 03:00  GMT: We.2008.03.26 01:00  NY: Tu.2008.03.25 21:00  End-FX: 142h => left: 67h 
DST_EUR:      +0  DST_EUR:     +0  t[ 88533]  tBrk: Tu.2012.02.07 13:00  GMT: Tu.2012.02.07 11:00  NY: Tu.2012.02.07 06:00  End-FX: 143h => left: 82h 
DST_EUR:      +0  DST_EUR:     +0  t[118058]  tBrk: We.2016.11.16 06:00  GMT: We.2016.11.16 04:00  NY: Tu.2016.11.15 23:00  End-FX: 143h => left: 65h 
DST_EUR: -3600  DST_EUR: -3600  t[121841]  tBrk: Mo.2017.06.26 05:00  GMT: Mo.2017.06.26 02:00  NY: Su.2017.06.25 22:00  End-FX: 143h => left: 114h 
DST_EUR:      +0  DST_EUR: -3600  t[144995]  tBrk: Mo.2021.03.22 06:00  GMT: Mo.2021.03.22 04:00  NY: Mo.2021.03.22 00:00  End-FX: 142h => left: 112h 
DST_EUR: -3600  DST_EUR: -3600  t[148265]  tBrk: Tu.2021.09.28 15:00  GMT: Tu.2021.09.28 12:00  NY: Tu.2021.09.28 08:00  End-FX: 143h => left: 80h 

Já discutimos os dois primeiros blocos. A terceira e última parte mostra para pontos selecionados aleatoriamente a respectiva diferença de tempo entre a UE e os EUA, o índice de pontos de tempo, a hora da corretora, a hora de Greenwich e Nova Iorque, a hora de abertura do mercado naquele momento e o tempo restante - segundos convertidos em horas para maior clareza. Tudo isso pode ser verificado rapidamente: 20/05/2002, hora da corretora (MQ) é 22:00, com transição para o horário de verão, GMT = broker-3 = 19:00 e hora de Nova Iorque = GMT - (5-1) = 15:00, o mercado fechará em 97 horas. 97 = 4*24 (Mon.22:00-Fri.22:00 = 96h) +1h (Fri.22:00-23:00).

Assim, basta acrescentar duas chamadas de função ao EA ou indicador:

   bool isTimeSet = setBokerOffset();
   if(!isTimeSet)
     {
      Alert("setBokerOffset failed");
      return;
     }
..
   checkTimeOffset(TimeCurrent());



Uso alternativo por meio de variáveis de entrada

Consideremos um exemplo de trabalho com variáveis de entrada. O script deu os seguintes valores:

Time Offset of MetaQuotes Software Corp.:
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

No EA, pode ficar assim:

#include <DealingWithTime.mqh>
// offsets of MetaQuotes demo account: DO NOT USE THEM FOR DIFFERENT BROKERS!!
input int   USwinEUwin=  -7200;    // US=Winter & EU=Winter
input int   USsumEUsum= -10800;    // US=Summer & EU=Summer
input int   USsumEUwin=  -7200;    // US=Summer & EU=Winter

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   OffsetBroker.USwinEUwin = USwinEUwin;
   OffsetBroker.USsumEUsum = USsumEUsum;
   OffsetBroker.USsumEUwin = USsumEUwin;
   OffsetBroker.actOffset  = WRONG_VALUE; 
   
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;
   //--- Just a simple test if not set or changed
   if(OffsetBroker.USwinEUwin+OffsetBroker.USsumEUsum+OffsetBroker.USsumEUwin==0)
      OffsetBroker.set     = false;
   else
      OffsetBroker.set     = true;
   //...
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   checkTimeOffset(TimeCurrent());
   tGMT  = TimeCurrent() + OffsetBroker.actOffset;    // GMT
   tNY   = tGMT - (NYShift+DST_USD);                  // time in New York
   tLon  = tGMT - (LondonShift+DST_EUR);              // time in London
   tSyd  = tGMT - (SidneyShift+DST_AUD);              // time in Sidney
   tMosc = tGMT - (MoskwaShift+DST_RUS);              // time in Moscow
   tTok  = tGMT - (TokyoShift);                       // time in Tokyo - no DST

   //...
   
  }



Eu especifiquei os valores obtidos para o servidor MetaQuotes. Certifique-se de usar os valores para a sua corretora!

OnTick() calcula primeiro as diferenças de tempo e, logo depois, o GMT e a hora local de Nova Iorque, Londres, Sydney, Moscou e Tóquio. Tudo é muito simples, mas não se esqueça dos parênteses.


Conclusão

Em vez de concluir, vou simplesmente mostrar os resultados da função setBokerOffset() em contas de demonstração junto a diferentes corretoras:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200



EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of RoboForex Ltd: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Alpari International: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 143h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 143h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Pepperstone Group Limited: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -10800


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 143h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 143h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Eightcap Pty Ltd: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -10800

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of InstaForex Companies Group: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 141h
USD: Fr.2020.10.30 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 141h
NXT: Fr.2020.11.06 21:00: hNY:16  hGMT:21  hTC:21  hDiff: 0   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 141h
USD: Fr.2021.03.12 21:00: hNY:16  hGMT:21  hTC:21  hDiff: 0   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 141h
EUR: Fr.2021.03.26 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 141h
NXT: Fr.2021.04.02 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 141h

Time Offset of JFD Group Ltd: 
US=Winter & EU=Winter (USwinEUwin) = 0
US=Summer & EU=Summer (USsumEUsum) = -3600
US=Summer & EU=Winter (USsumEUwin) = -3600



Desejo-lhe sucesso no trading!



Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/9929

Arquivos anexados |
DealingWithTime.mqh (52.89 KB)
Últimos Comentários | Ir para discussão (1)
Carl Schreiber
Carl Schreiber | 5 jul 2023 em 19:02

A versão do DealingWithTime.mqh v. 1.01 do artigo Lidando com o Tempo (Parte 2): As Funções ( https://www.mql5.com/en/articles/9929 ) pararam de funcionar porque o MQ mudou o comportamento do CopyTime( ) funcionam algum tempo após a publicação deste artigo. Agora esta função não retorna mais valores de tempo futuro se forem maiores que TimeCurrent() especificado para os parâmetros start_time e/ou stop_time. Em vez disso, o tempo de abertura da última barra atual é retornado como o maior valor possível.

Uma vez que o final da sessão FX foi determinado desta forma para determinar o deslocamento de tempo do corretor, isso agora leva a valores incorretos!

Este cálculo foi alterado na versão 2.03. Esta versão já está disponível no CodeBase aqui: https://www.mql5.com/en/code/45287 .

Mas também o cálculo da mudança de horário foi completamente alterado, de modo que agora os tempos complicados da mudança de horário de Sydney (Austrália) de volta aos anos 70 são cobertos.

Anexa-se também a tabela DST 1975 - 2030.xlsx em arquivo zip com todas as mudanças de horário desde a década de 70 para que todos possam verificar o correto funcionamento das fórmulas, aqui está um exemplo de série da tabela:

1º de janeiro de 1982 é o horário padrão nos EUA (DST==0) e a próxima mudança será em 25 de abril de 1982, o último (25º do mês) domingo de abril (4). A tabela já está ordenada por fuso horário geográfico (coluna A), depois por fuso horário do ano (coluna L, spr=primavera, aut=outono,) e por fim por data de consulta (coluna C). A tabela pode ser criada automaticamente pelo EA incluído (um script não pode ser executado no modo de depuração). Test_DST 2.mq5 se você executá-lo no modo de depuração e copiar as linhas do log do diário no depurador e colá-las em uma planilha; O separador de células seria o espaço.

Além disso, agora existe uma nova e simples função SecTillClose() , que fornece o tempo restante em segundos (a moeda de tempo do MQ) até que o mercado forex seja fechado - sem CopyTime() . Isso é interessante para quem deseja fechar suas posições antes do final de semana ou não deseja abrir uma nova posição em um período definido antes do final de semana.

O indicador incluído DealingWithTime_TestIndi.mq5, como um comentário no gráfico, mostra não apenas o horário de verão na Europa, EUA e Austrália (Sydney), mas também o horário atual e a diferença de horário de várias cidades. Aqui você encontra uma tabela com diferentes horários locais das principais cidades para comparação: https://www.timeanddate.com/worldclock/ . Portanto, você pode verificar os valores a qualquer momento. Esse indicador também mostra como esses valores são determinados e usados (o que é subtraído ou adicionado do quê), facilitando o uso por conta própria - copie e cole, a forma mais rápida de programação.

As duas últimas linhas também mostram o último segundo da sessão FX atual e o tempo restante em horas (o que é mais fácil de julgar) e em segundos. Em Nova York, quando a sessão FX fecha às 17h00, horário local, em uma sexta-feira, não há nenhum bar válido aberto às 17h00, horário de Nova York. Portanto, nesta função, 1 segundo é subtraído para obter o último tempo de abertura válido da última barra no tempo do corretor. No entanto, alguns corretores encerram sua sessão FX alguns minutos antes, deixando de fornecer preços e não aceitando mais ordens de negociação.

Construindo uma rede neural profunda do zero em linguagem MQL Construindo uma rede neural profunda do zero em linguagem MQL
Neste artigo, vou apresentar a vocês uma rede neural profunda implementada em linguagem MQL com suas diferentes funções de ativação, entre elas estão a função tangente hiperbólica para as camadas ocultas e a função Softmax para a camada de saída. Avançaremos do primeiro passo até o final para formar completamente a rede neural profunda.
Como se tornar um bom programador (Parte 6): 9 hábitos para desenvolver de maneira produtiva Como se tornar um bom programador (Parte 6): 9 hábitos para desenvolver de maneira produtiva
O resultado final do projeto não tem a ver apenas com a escrita de código. A minha experiência me ensinou a identificar certos hábitos que ajudam a melhorar a produtividade na hora de desenvolver. Mais tarde, falaremos sobre alguns deles neste artigo. Este artigo é uma leitura obrigatória destinada a todos que desejam melhorar suas habilidades na escrita de algoritmos complexos.
Deixando o gráfico mais interessante — Adicionando uma tela de fundo Deixando o gráfico mais interessante — Adicionando uma tela de fundo
Muitas estações de trabalho contém alguma imagem representativa e que mostra algo sobre o usuário, estas imagens deixam o ambiente de trabalho mais bonito e animador,. Aprenda como deixar o gráfico mais interessante colocando um papel de parede nele.
Conjunto de ferramentas para marcação manual de gráficos e negociação (Parte III). Otimização e novas ferramentas Conjunto de ferramentas para marcação manual de gráficos e negociação (Parte III). Otimização e novas ferramentas
Desenvolveremos o tema do desenho de objetos gráficos em gráficos usando atalhos de teclado. Foram acrescentadas novas ferramentas à biblioteca, em particular uma linha reta, que atravessa máximos arbitrários, e um conjunto de retângulos que permitem estimar tanto o nível quanto o tempo de reversão. Também veremos a possibilidade de otimizar o código para melhorar o desempenho. O exemplo de implementação será reescrito como um indicador, o que tornará possível definir Shortcuts junto com outros programas de negociação. O nível de proficiência do código está um pouco acima do nível de iniciante.