
Trabalhando com o tempo (Parte 2): funções
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:
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:
- Determinamos o dia do mês - domingo, quando a hora muda.
- Com base nisso, criamos uma data.
- Encontramos o próximo domingo, quando os horários serão alterados.
- 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 switchComo 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:
- Antes da transição para p horário de verão, em março.
- Antes da transição para o horário de inverno em outubro/novembro.
- 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á:
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:
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:
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





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
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.