De fato, ótimo artigo, agradeço o tempo e o esforço que você investiu para escrever o código e compartilhá-lo com a comunidade.
Tenho uma pergunta simples sobre"Nos estudos que estamos adaptando, eles se concentram em estratégias que negociam entre a abertura e o fechamento do mercado (das 9h30 às 16h, horário do leste dos EUA).Como nossa corretora usa UTC+2/3, isso se traduz em 18:30-24:00 no horário do servidor - certifique-se de ajustar para o fuso horário de sua própria corretora ao testar"
Você pode me explicar seu processo de pensamento sobre a conversão de horário?
Usando um conversor de horário genérico, minha conversão de 09:30 do horário do leste acaba sendo 16:30 para quando o mt5 está em GMT+2 e 17:30 para quando o mt5 está em GMT+3. 18:30 parece ser 1-2 horas após a abertura do mercado.
Agradeço a ajuda e obrigado novamente.
Você pode me explicar seu processo de pensamento sobre a conversão de horário?
Usando um conversor de horário genérico, minha conversão de 09:30 (horário do leste dos EUA) acaba sendo 16:30 para quando o mt5 está em GMT+2 e 17:30 para quando o mt5 está em GMT+3. 18:30 parece ser 1-2 horas após a abertura do mercado.
Agradeço a ajuda e obrigado novamente.
Você está certo, converti erroneamente o horário do servidor no artigo para o horário de abertura do mercado de ações de Nova York. Deveria ser 17:30 em vez de 18:30. Dito isso, você pode presumir que todas as minhas regras de estratégia no artigo devem ser negociadas 1 hora após a abertura do mercado. Obrigado por apontar o problema e desculpe-me pela confusão.
Obrigado pela postagem, muito interessante!
Uma pergunta sobre o código:
Em sua função MarketOpened, você usa:
"if (currentHour >= startHour && currentMinute>=startMinute)return true;" <- Isso parece que ele negociará apenas parte da hora se o mercado estiver aberto, já que retornará falso se você estiver no início de cada hora, mesmo quando o mercado estiver aberto. Ele só funciona se o minuto estiver em 0, que não é o início da sessão do mercado.
Obrigado pela postagem, muito interessante!
Uma pergunta sobre o código:
Em sua função MarketOpened, você usa:
"if (currentHour >= startHour && currentMinute>=startMinute)return true;" <- Isso parece que negociará apenas parte da hora se o mercado estiver aberto, já que retornará falso se você estiver no início de cada hora, mesmo quando o mercado estiver aberto. Isso só funciona se o minuto estiver em 0, que não é o início da sessão do mercado.
OMG, não acredito que deixei passar isso. Deveria ser:
if ((currentHour >= startHour &¤tMinute>=startMinute)||currentHour>startHour)return true;
Peço sinceras desculpas pelo erro. Obrigado por ler com tanta atenção e apontar o erro.
Ps. Para o ORB3, codifiquei o horário de abertura do mercado para 9:30. Você pode alterá-lo para essas funções para que possa corresponder ao horário do servidor do horário de abertura do mercado de Nova York.
//+------------------------------------------------------------------+ //| Obter o valor superior da banda Concretum| //+------------------------------------------------------------------+ double getUpperBand(int target_hour = 17, int target_min = 30) { // Obter o tempo da barra atual datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0); MqlDateTime current_dt; TimeToStruct(current_time, current_dt); int current_hour = current_dt.hour; int current_min = current_dt.min; // Encontre o preço de abertura de hoje no horário de destino (por exemplo, 17:30 no horário do servidor) datetime today_start = iTime(_Symbol, PERIOD_D1, 0); int bar_at_target_today = getBarShiftForTime(today_start, target_hour, target_min); if (bar_at_target_today < 0) return 0; // Retorna 0 se não houver barra de destino double open_target_today = iOpen(_Symbol, PERIOD_M1, bar_at_target_today); if (open_target_today == 0) return 0; // Nenhum preço válido // Calcular o sigma com base nos últimos 14 dias double sum_moves = 0; int valid_days = 0; for (int i = 1; i <= 14; i++) { datetime day_start = iTime(_Symbol, PERIOD_D1, i); int bar_at_target = getBarShiftForTime(day_start, target_hour, target_min); int bar_at_HHMM = getBarShiftForTime(day_start, current_hour, current_min); if (bar_at_target < 0 || bar_at_HHMM < 0) continue; // Pular se as barras não existirem double open_target = iOpen(_Symbol, PERIOD_M1, bar_at_target); double close_HHMM = iClose(_Symbol, PERIOD_M1, bar_at_HHMM); if (open_target == 0) continue; // Pular se não houver um preço de abertura válido double move = MathAbs(close_HHMM / open_target - 1); sum_moves += move; valid_days++; } if (valid_days == 0) return 0; // Retorna 0 se não houver dados válidos double sigma = sum_moves / valid_days; // Calcular a banda superior double upper_band = open_target_today * (1 + sigma); // Trace um ponto azul no nível da banda superior string obj_name = "UpperBand_" + TimeToString(current_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS); ObjectCreate(0, obj_name, OBJ_ARROW, 0, current_time, upper_band); ObjectSetInteger(0, obj_name, OBJPROP_ARROWCODE, 159); // Símbolo de ponto ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clrBlue); ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 2); return upper_band; } //+------------------------------------------------------------------+ //| Obter o valor inferior da banda Concretum| //+------------------------------------------------------------------+ double getLowerBand(int target_hour = 17, int target_min = 30) { // Obter o tempo da barra atual datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0); MqlDateTime current_dt; TimeToStruct(current_time, current_dt); int current_hour = current_dt.hour; int current_min = current_dt.min; // Encontre o preço de abertura de hoje no horário de destino (por exemplo, 17:30 no horário do servidor) datetime today_start = iTime(_Symbol, PERIOD_D1, 0); int bar_at_target_today = getBarShiftForTime(today_start, target_hour, target_min); if (bar_at_target_today < 0) return 0; // Retorna 0 se não houver barra de destino double open_target_today = iOpen(_Symbol, PERIOD_M1, bar_at_target_today); if (open_target_today == 0) return 0; // Nenhum preço válido // Calcular o sigma com base nos últimos 14 dias double sum_moves = 0; int valid_days = 0; for (int i = 1; i <= 14; i++) { datetime day_start = iTime(_Symbol, PERIOD_D1, i); int bar_at_target = getBarShiftForTime(day_start, target_hour, target_min); int bar_at_HHMM = getBarShiftForTime(day_start, current_hour, current_min); if (bar_at_target < 0 || bar_at_HHMM < 0) continue; // Pular se as barras não existirem double open_target = iOpen(_Symbol, PERIOD_M1, bar_at_target); double close_HHMM = iClose(_Symbol, PERIOD_M1, bar_at_HHMM); if (open_target == 0) continue; // Pular se não houver um preço de abertura válido double move = MathAbs(close_HHMM / open_target - 1); sum_moves += move; valid_days++; } if (valid_days == 0) return 0; // Retorna 0 se não houver dados válidos double sigma = sum_moves / valid_days; // Calcular a banda inferior double lower_band = open_target_today * (1 - sigma); // Trace um ponto vermelho no nível inferior da banda string obj_name = "LowerBand_" + TimeToString(current_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS); ObjectCreate(0, obj_name, OBJ_ARROW, 0, current_time, lower_band); ObjectSetInteger(0, obj_name, OBJPROP_ARROWCODE, 159); // Símbolo de ponto ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clrRed); ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 2); return lower_band; }
Alterar o horário do cálculo pode ser uma maneira de otimizar ainda mais a estratégia :)
OMG, não acredito que deixei passar isso. Deveria ser:
Peço sinceras desculpas pelo erro. Obrigado por ler com tanta atenção e apontar o erro.
Não se preocupe, já mesclei os mercados aberto e fechado em uma única função.
bool MarketState() { MqlDateTime structTime; TimeCurrent(structTime); structTime.sec = 0; structTime.hour = startHour; structTime.min = startMinute; datetime timeStart = StructToTime(structTime); structTime.hour = endHour; structTime.min = endMinute; datetime timeEnd = StructToTime(structTime); if(TimeCurrent() >= timeStart && TimeCurrent() < timeEnd)return true; else return false; }
Mais uma coisa: você usa dados OHLC do corretor para backtesting, sem atrasos. Esses backtests parecem um pouco otimistas em comparação com os backtests feitos com dados de ticks reais com atraso aleatório para slippage e recotações.
Mais uma vez, obrigado por seus esforços!
Não se preocupe, eu já mesclei o mercado aberto e o fechado em uma única função.
Mais uma coisa: você usa dados OHLC do corretor para backtesting, sem atraso. Esses backtests parecem um pouco otimistas em comparação com os backtests feitos com dados de ticks reais com atraso aleatório para slippage e recotações.
Mais uma vez, obrigado por seus esforços!
Muito bem em sua modificação! Atualizei todo o código em meu Github.
Para sua preocupação, a lógica de negociação ocorre a cada nova barra e não envolve movimento de tick. Além disso, o tempo médio de espera é de algumas horas, o que acredito que não causará um problema significativo de slippage. Eu diria que pouquíssimas corretoras fornecem dados reais de ticks por mais de 5 anos, e 1 min de OHLC é suficiente.
- 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
Novo artigo Estratégias de trading de rompimento: análise dos principais métodos foi publicado:
As estratégias de rompimento da faixa de abertura (Opening Range Breakout, ORB) partem da ideia de que a faixa inicial de negociação, formada logo após a abertura do mercado, reflete níveis de preço relevantes, quando compradores e vendedores chegam a um acordo sobre o valor. Ao identificar rompimentos de uma determinada faixa para cima ou para baixo, os traders podem aproveitar o momentum que costuma surgir quando a direção do mercado fica mais clara.
Neste artigo, vamos analisar três estratégias ORB adaptadas a partir de artigos da Concretum Group. Primeiro, veremos os pressupostos deste estudo, incluindo os conceitos principais e a metodologia utilizada. Em seguida, explicaremos como cada estratégia funciona, listaremos as regras de uso dos sinais em cada uma delas e faremos uma análise estatística de seu desempenho. Por fim, vamos examiná-las do ponto de vista do uso em portfólio, com atenção especial ao tema da diversificação.
Neste artigo, não vamos nos aprofundar em programação; ao contrário, vamos nos concentrar na pesquisa, incluindo a reprodução, a análise e o teste das estratégias apresentadas nessas três publicações. Isso será útil para leitores que buscam possíveis vantagens no trading ou para aqueles que tenham interesse em entender como essas estratégias foram estudadas e reproduzidas. Apesar disso, todo o código MQL5 desses robôs será apresentado. Os leitores poderão expandir e complementar essa estrutura por conta própria.
Autor: Zhuo Kai Chen