Oi pessoal! Tem uma parte do meu código que pede ao usuário para estabelecer um limite de análise temporal dos candles, o que irá fornecer dados para CopyTime, CopyClose etc.
Alguma solução para o MT5 considerar apenas os dias úteis nas funções CopyTime, CopyClose etc? No caso, se estivesse no fim de semana, ele consideraria a sexta-feira.
Olá Israel,
hummm não caiu a ficha.... faz um script do código demostrando o erro e cola aqui.
Oi pessoal! Tem uma parte do meu código que pede ao usuário para estabelecer um limite de análise temporal dos candles, o que irá fornecer dados para CopyTime, CopyClose etc.
Durante a semana tudo parecia funcionar bem, mas quando chegou no fim de semana os dados datetime apontaram para a abertura do mercado na semana seguinte o que gerou uma série de erros na coleta de dados para a análise.
Por exemplo, o usuário fornece o horário de início da análise:
O usuário fornece Hora: 20
O usuário fornece Minutos: 15
Resultado do primeiro resultado em CopyTime durante a semana: AnoAtual.MêsAtual,DiaAtual 20:15:00
Resultado do primeiro resultado em CopyTime no fim de semana: AnoAtual.MêsAtual,DiadaSemanaSeguinte 23:24 (???)
O processo que eu sigo é simples: eu concateno como string os dois valores fornecidos pelo usuário e depois converto com a função StringToTime e o Metatrader 5 automaticamente entende que a hora fornecida se refere ao dia atual. NO ENTANTO, quando chega no fim de semana ele joga para frente e não tenho como trabalhar no código a não ser que forneça uma data específica.
Alguma solução para o MT5 considerar apenas os dias úteis nas funções CopyTime, CopyClose etc? No caso, se estivesse no fim de semana, ele consideraria a sexta-feira.
//+------------------------------------------------------------------+ //| DECLARAÇÃO DE ENUMERAÇÕES | //+------------------------------------------------------------------+ enum HORA { UMA = 01, //01 DUAS = 02, //02 TRES = 03, //03 QUATRO = 04, //04 CINCO = 05, //05 SEIS = 06, //06 SETE = 07, //07 OITO = 08, //08 NOVE = 09, //09 DEZ = 10, //10 ONZE = 11, //11 DOZE = 12, //12 TREZE = 13, //13 QUATORZE = 14, //14 QUINZE = 15, //15 DEZESSEIS = 16, //16 DEZESSETE = 17, //17 DEZOITO = 18, //18 DEZENOVE = 19, //19 VINTE = 20, //20 VINTE_E_UM = 21, //21 VINTE_E_DOIS = 22, //22 VINTE_E_TRES = 23, //23 VINTE_E_QUATRO = 24 //24 }; enum MINUTO { ZERO_M = 00, //00 QUINZE_M = 15, //15 TRINTA_M = 30, //30 QUARENTA_E_CINCO_M = 45 //45 }; //+------------------------------------------------------------------+ //| DECLARAÇÃO DE VARIÁVEIS INPUT | //+------------------------------------------------------------------+ input HORA horaInicio_analise = VINTE; //Horário de Início da Análise input MINUTO minutoInicio_analise = QUINZE_M; //Minuto de Início da Análise input HORA horaFim = VINTE; //Horário de FIM das Operações input MINUTO minutoFim = QUARENTA_E_CINCO_M; //Minuto de FIM das Operações //+------------------------------------------------------------------+ //| DECLARAÇÃO DE VARIÁVEIS E ARRAYS GLOBAIS | //+------------------------------------------------------------------+ //--- Concatenação do horário de início da análise string horarioInicio_conc = IntegerToString(horaInicio_analise) + ":" + IntegerToString(minutoInicio_analise); //--- Concatenação do horário de fim das operações string horarioFim_conc = IntegerToString(horaFim) + ":" + IntegerToString((minutoFim); //--- Declaração de Array tipo data e hora que armazenará o período dos candles a serem analisados datetime periodoCandles[]; //+------------------------------------------------------------------+ //| FUNÇÃO DE INICIALIZAÇÃO DO EA | //+------------------------------------------------------------------+ int OnInit() { //--- Função de criação de timer EventSetTimer(1); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| FUNÇÃO DE REMOÇÃO DO EA | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Desmontar o timer EventKillTimer(); } //+------------------------------------------------------------------+ //| FUNÇÃO DE MOVIMENTAÇÃO DO PREÇO | //+------------------------------------------------------------------+ void OnTick() { } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- Declaração de Variável para calcular a diferença de tempo entre o início da análise e o fim das operações int diferencaTempo = 60; //--- Função que retornará o tempo de fechamento dos candles de acordo com o tempo estabelecido na Função e Array anteriores CopyTime(_Symbol,_Period,StringToTime(horarioInicio_conc),diferencaTempo,periodoCandles); //--- Função que irá imprimir na tela os dados armazenados no Array periodoCandles ArrayPrint(periodoCandles,Digits(),NULL,0,WHOLE_ARRAY,ARRAYPRINT_MINUTES);
Deveria apresentar uma hora de análise no Timeframe M1.
Durante a semana os horários começam do local correto, nos fins de semana ele projeta para segunda-feira e o horário fica errado.
Coloquei aqui apenas o que acredito ser necessário para o que estou comentando, tem outras coisas que não tem relação direta com o problema (tanto que o algorítmo funciona mesmo quando estas últimas são transformadas em comentário).
O tipo MqlDate tem um campo que é o dia da semana, só validar. Domingo começa em 1 e sábado é 7.
No caso eu criaria uma função condicional? Onde eu faria essa validação? (desculpe a ignorância, estou começando em programação)
Um palpite... Seria na variável periodoCandles? (ao invés de uma variável simples datetime) Mas nesse caso, como permitir a entrada de hora apenas e ao mesmo tempo estabelecer uma validação restrita de dias de semana? (no caso, quando fosse sábado ou domingo, gostaria que o EA trabalhasse o dia de sexta-feira e não ficasse tentando prever o futuro, num possível e futuro backing test, ele simplesmente ignoraria os finais de semana)
Sim agora entendi sua dúvida, você esqueceu apenas de ler o manual:
Existe três variações para chamanda de COPYTIME() e você está usando a segunda.
CopyTimeAo solicitar dados através da data de início e do número de elementos requeridos, somente dados cuja data seja menor (anterior) ou igual a data especificada são retornados. Isso significa que a hora de abertura de qualquer barra, para cujo valor é retornado (volume, spread, valor no buffer de indicador, preços de Abertura, Máximo, Mínimo, Fechamento ou Hora de Abertura) é sempre menor ou igual ao valor especificado.
Quando não tem cotação ( Feriados e finais de semana) seu código ira buscar 60 barras anteriores a hora 20:15.
Eu simplifiquei o código para você rodar verificar rapidamente o resultado das 3 variantes.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ input string horarioInicio = "20:15"; input string horarioFim = "22:00"; input int qtdBarras = 60; datetime periodoCandles[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnStart() { ZeroMemory(periodoCandles); Print("\nVariante (01): Copiar as últimas ", qtdBarras, " barras"); if(CopyTime(_Symbol, _Period, 0, qtdBarras, periodoCandles) > 0) ArrayPrint(periodoCandles, Digits(), NULL, 0, WHOLE_ARRAY, ARRAYPRINT_HEADER | ARRAYPRINT_INDEX | ARRAYPRINT_LIMIT | ARRAYPRINT_ALIGN); ZeroMemory(periodoCandles); Print("\nVariante (02): Copiar as últimas ", qtdBarras, " barras anteriores a: ", StringToTime(horarioInicio)); if(CopyTime(_Symbol, _Period, StringToTime(horarioInicio), qtdBarras, periodoCandles) > 0) ArrayPrint(periodoCandles, Digits(), NULL, 0, WHOLE_ARRAY, ARRAYPRINT_HEADER | ARRAYPRINT_INDEX | ARRAYPRINT_LIMIT | ARRAYPRINT_ALIGN); ZeroMemory(periodoCandles); Print("\nVariante (03): Copiar as barras entre: ", StringToTime(horarioInicio), " e ", StringToTime(horarioInicio)); Print("Inicio: ", StringToTime(horarioInicio), " Fim: ", StringToTime(horarioInicio)); if(CopyTime(_Symbol, _Period, StringToTime(horarioInicio), StringToTime(horarioFim), periodoCandles) > 0) ArrayPrint(periodoCandles, Digits(), NULL, 0, WHOLE_ARRAY, ARRAYPRINT_HEADER | ARRAYPRINT_INDEX | ARRAYPRINT_LIMIT | ARRAYPRINT_ALIGN); } //+------------------------------------------------------------------+
No caso eu criaria uma função condicional? Onde eu faria essa validação? (desculpe a ignorância, estou começando em programação)
Um palpite... Seria na variável periodoCandles? (ao invés de uma variável simples datetime) Mas nesse caso, como permitir a entrada de hora apenas e ao mesmo tempo estabelecer uma validação restrita de dias de semana? (no caso, quando fosse sábado ou domingo, gostaria que o EA trabalhasse o dia de sexta-feira e não ficasse tentando prever o futuro, num possível e futuro backing test, ele simplesmente ignoraria os finais de semana)
eu havia dito algo como isso:
void OnStart() { //--- MqlDateTime teste; TimeTradeServer(teste); Print("dia da semana: ", teste.day_of_week); }
Mas a resposta do @Rogerio Giannetti Torres é muito mais elaborada e provavelmente muito mais próximo do que vc esta tentando fazer.
Sim agora entendi sua dúvida, você esqueceu apenas de ler o manual:
Existe três variações para chamanda de COPYTIME() e você está usando a segunda.
CopyTimeAo solicitar dados através da data de início e do número de elementos requeridos, somente dados cuja data seja menor (anterior) ou igual a data especificada são retornados. Isso significa que a hora de abertura de qualquer barra, para cujo valor é retornado (volume, spread, valor no buffer de indicador, preços de Abertura, Máximo, Mínimo, Fechamento ou Hora de Abertura) é sempre menor ou igual ao valor especificado.
Quando não tem cotação ( Feriados e finais de semana) seu código ira buscar 60 barras anteriores a hora 20:15.
Eu simplifiquei o código para você rodar verificar rapidamente o resultado das 3 variantes.
Na verdade eu havia lido o manual sobre essa função e conferi alguns tópicos aqui no fórum antes de colocar minha dúvida. Eu havia feito várias tentativas com as variações de entrada (inclusive já havia utilizado as três que compartilhou), mas não obtive sucesso com os horários que eram apresentados, por isso vim perguntar aqui.
A terceira variante era a que eu já imaginava ser a que atende aos meus propósitos, e, aqui no horário local 08:30 (horário do servidor 14:30) ela não atende o critério do if do script que compartilhou, portanto não apresenta resultados. No entanto, se eu mudo o horário para barras já presentes no gráfico do dia (por exemplo 14:00 e 14:30), funciona normalmente. A novidade aqui foi a função ZeroMemory que, se não estou enganado, é a responsável por não mostrar resultados caso esteja fora do horário (antes ele buscava o fim de semana anterior).
Obrigado pelos apontamentos! Agora me resta colocar uma condição para que, quando isso ocorrer, o Script/EA irá buscar no último dia útil anterior que contenha o horário estabelecido. Apenas para fins de teste de programação (tem muita coisa ainda a ser desenvolvida no meu projeto), para backing test, ausência de valores é perfeito.
eu havia dito algo como isso:
Mas a resposta do @Rogerio Giannetti Torres é muito mais elaborada e provavelmente muito mais próximo do que vc esta tentando fazer.
Muito obrigado pela respota!
É um outro caminho interessante para verificar a validade do período de análise. Vou focar na função MqlDateTime para estabelecer um ajuste diário como comentei acima.
Hoje (sábado 05:50 da manhã), fiz o seguinte teste:
datetime periodoCandles[]; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- ZeroMemory(periodoCandles); //--- Função que retornará o tempo de fechamento dos candles de acordo com o tempo estabelecido na Função e Array anteriores if(CopyTime(_Symbol,_Period,StringToTime("21:05"),5,periodoCandles) > 0) ArrayPrint(periodoCandles, Digits(), NULL, 0, WHOLE_ARRAY, ARRAYPRINT_HEADER | ARRAYPRINT_INDEX | ARRAYPRINT_LIMIT | ARRAYPRINT_ALIGN); }
Obtendo os seguintes resultados:
2020.07.10 23:50:00 2020.07.10 23:51:00 2020.07.10 23:52:00 2020.07.10 23:53:00 2020.07.10 23:54:00
Note que eles não tem nada a ver com o horário que coloquei. O que houve de errado?
Hoje (sábado 05:50 da manhã), fiz o seguinte teste:
Obtendo os seguintes resultados:
2020.07.10 23:50:00 2020.07.10 23:51:00 2020.07.10 23:52:00 2020.07.10 23:53:00 2020.07.10 23:54:00
Note que eles não tem nada a ver com o horário que coloquei. O que houve de errado?
olhando por cima me parece errada a sua chamada, olhei a documentação e notei que vc esta sobrecarregando a função com a segunda variante.
int CopyTime( string symbol_name, // nome do ativo ENUM_TIMEFRAMES timeframe, // período datetime start_time, // data e hora de início int count, // quantidade de dados para copiar datetime time_array[] // array destino para copiar horas de abertura );
- 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
Oi pessoal! Tem uma parte do meu código que pede ao usuário para estabelecer um limite de análise temporal dos candles, o que irá fornecer dados para CopyTime, CopyClose etc.
Durante a semana tudo parecia funcionar bem, mas quando chegou no fim de semana os dados datetime apontaram para a abertura do mercado na semana seguinte o que gerou uma série de erros na coleta de dados para a análise.
Por exemplo, o usuário fornece o horário de início da análise:
O usuário fornece Hora: 20
O usuário fornece Minutos: 15
Resultado do primeiro resultado em CopyTime durante a semana: AnoAtual.MêsAtual,DiaAtual 20:15:00
Resultado do primeiro resultado em CopyTime no fim de semana: AnoAtual.MêsAtual,DiadaSemanaSeguinte 23:24 (???)
O processo que eu sigo é simples: eu concateno como string os dois valores fornecidos pelo usuário e depois converto com a função StringToTime e o Metatrader 5 automaticamente entende que a hora fornecida se refere ao dia atual. NO ENTANTO, quando chega no fim de semana ele joga para frente e não tenho como trabalhar no código a não ser que forneça uma data específica.
Alguma solução para o MT5 considerar apenas os dias úteis nas funções CopyTime, CopyClose etc? No caso, se estivesse no fim de semana, ele consideraria a sexta-feira.