Função para verificar se o mercado está aberto

 

Boa dia pessoal,

Alguém sabe como verificar, via código, se neste momento o mercado está aberto?

A pergunta é extremamente simples, mas ainda não encontrei uma solução confiável que se aplique à Bovespa. Tudo o que encontrei, aparentemente, funciona para bolsas fora do Brasil, mas não aqui.

Estou trabalhando com o evento OnTimer e não OnTick, assim, antes de tentar enviar uma ordem ou tomar alguma outra decisão preciso verificar se o mercado está aberto.

Já tentei comparar TimeCurrent() com TimeLocal() e TimeTradeServer(). Seria simples, TimeCurrent fica parado se não houverem ticks, mas TimeLocal (horário do computador) não é confiável e TimeTradeServer aparentemente retorna o mesmo que TimeLocal, logo, também não é confiável. E além disso, o ativo pode ficar algum tempo sem receber ticks mesmo com o mercado aberto e não retornaria uma resposta precisa.

Já tentei também algumas funções de Market Information e OrderCheck, como SymbolInfoSessionQuote() e SymbolInfoSessionTrade() mas a tabela de sessão não ajuda em nada, pois o horário não está correto:

Market Sessions


Neste momento, este é o código que elaborei pra teste:

bool isMarketOpen(string symbol){
   //tentando por Market Informations
   ENUM_SYMBOL_TRADE_MODE mode;
   mode = SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE);        //sempre retorna SYMBOL_TRADE_MODE_FULL
   printf("Symbol %s in mode %s", symbol, EnumToString(mode));
   
   //tentando por OrderCheck()
   MqlTradeRequest      m_request={0}; 
   MqlTradeCheckResult  m_check_result={0};
   
   m_request.action        = TRADE_ACTION_DEAL;
   m_request.symbol        = symbol;
   m_request.magic         = 1234;
   m_request.volume        = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   m_request.price         = 0;
   m_request.type          = ORDER_TYPE_BUY;
   m_request.sl            = 0;
   m_request.tp            = 0;
   m_request.deviation     = 0;
   m_request.type_filling  = ORDER_FILLING_IOC;
   m_request.comment       = "Teste, mercado aberto?";
   
   if(!OrderCheck(m_request, m_check_result)){         //era esperado algum erro quando o mercado está fechado
      printf("Mercado fechado! Error code: %i", m_check_result.retcode);
      return(false);
   }
   else{
      printf("Mercado aberto! Error code: %i", m_check_result.retcode);
   }
   return(true);
}

Alguma outra ideia?

 

olá eu estava com o mesmo problema pra encontra algo confiavel e então fiz esta gambiarrinha ,

apenas na primeira criada do objeto da class o progama dar uma erroscadinha porque ele precisa da variavel global no terminal para funcionar bem, depois nas novas inicializações ele fica lizo 

para garantir uma prescisão vou ajustando a hora de tempo em tempo, no meu caso foi de segundo em segundo, porem esse tempo tem que ser maior em progamas mais complexos, porque talvez o processador não processe tudo do OnTime() em menos de 1 segundo

espero que ajude quem ainda esta com esse tipo de problema e espero que o autor desse post tenha encontrado uma solução melhor para nos compartilhar, abrçs 


enum ENUM_MARKET_STATES{
     FECHADO = -1,
     SEM_CONEXAO = 0,
     ABERTO = 1
};
class MarketStates{
public: 
      // construtor // desconstrutor
   MarketStates(){ criarVariavelGlobal(); }
  ~MarketStates(){}
private: 
   void criarVariavelGlobal(){ 
      // se minha variavel global já foi configurada só vou confirmar ela no proximo tick
      if(GlobalVariableCheck("Difereça entre minha hora e da Corretora"))
          return;
      // looping até criar uma variavel global que garda a diferença entre minha hora e corretora
      while(IsStopped()){
         // verificando se esta sincronizado com o servirdo
         if( SeriesInfoInteger(_Symbol,_Period,SERIES_SYNCHRONIZED) ){
            ResetLastError();
            // criando a minha variavel global no terminal para mim saber as difereças de horas TimeLocal() e TimeCorrent()
            if(0 != GlobalVariableSet("Difereça entre minha hora e da Corretora", TimeCurrent() - TimeLocal() ))
               Print("a Variavel Global \"Difereça entre minha hora e da Corretora\" foi criada");
            else
               Print("ERRO : " + IntegerToString(GetLastError()));
            // pulando fora do loop
            break;   
          }
          // esperar mais 1 segundo para tentar de novo
          Sleep(1000);
         } 
         Print("HORA SEVIDOR (ultimo tick) : " + TimeToString((TimeCurrent())) );
         Print("HORA LOCAL : " + TimeToString(TimeLocal()) );
         Print("DIFERENÇA " + TimeToString((datetime)MathAbs(GlobalVariableGet("Difereça entre minha hora e da Corretora")), TIME_SECONDS) );
         Sleep(2000);    // esperar 2s para que 
                         // a primeira chamada da fução segundosrestantes() 
                         // não retornar um numero positivo 
                         // caso o mercado esteja fechado
                         // uma vez a variavel global criada no terminal
                         // essa demora não existira mais nas proximas iniciações do progama mql
   }
public:
   // aqui vou usar a barra M1 por ser a unica que não falta pedaço quando o mercado fecha e abre só no outro dia
   datetime timeBarra(ENUM_TIMEFRAMES tempoGrafico = PERIOD_M1, int index = 0){
      datetime time[1];
      CopyTime(_Symbol,tempoGrafico,index,1,time);
      return time[0];
   }
   int segundosRestantesDaBarra(ENUM_TIMEFRAMES tempoGrafico){
    //  ajustarDiferecaEntreMinhaHoraEServidor();
      return int( timeBarra(tempoGrafico) + PeriodSeconds(tempoGrafico) - meuTime() );
   }   
// aqui esta configurado para ser chamada de segundo em segundo no OnTime() porem nada impede de usar otura configuração
   void ajustarDiferencaEntreHoraLocalECorretora(){
      static int timeCurrentMaisUm = int(TimeCurrent()) + 1;
      static int segundosConsecultivos = 0;
      static int novaDiferenca;
      static int ajustarAgora = 2;
      static bool suporteTime = false;
      int variou = segundosRestantesDaBarra(PERIOD_M1) - 59;
      if( variou > 0)
         GlobalVariableSet("Difereça entre minha hora e da Corretora", GlobalVariableGet("Difereça entre minha hora e da Corretora") + variou);
      if(timeCurrentMaisUm == TimeCurrent()){
         segundosConsecultivos++;
         if( segundosConsecultivos == 2) novaDiferenca = timeCurrentMaisUm - int(TimeLocal());
         if( segundosConsecultivos == ajustarAgora){            
            GlobalVariableSet("Difereça entre minha hora e da Corretora", timeCurrentMaisUm - TimeLocal());
            segundosConsecultivos = 0;
            ajustarAgora++;
         }
         timeCurrentMaisUm++;
      } else if( TimeCurrent() > timeCurrentMaisUm ){
                  timeCurrentMaisUm = int(TimeCurrent()) + 1;
                  segundosConsecultivos = 0;
             }
  } 
  static datetime meuTime(){
      if( !GlobalVariableCheck("Difereça entre minha hora e da Corretora") ){
         Print("Criando outra variavel global \"Difereça entre minha hora e da Corretora\" porque a anterior foi apagada ");
         GlobalVariableSet("Difereça entre minha hora e da Corretora", TimeCurrent() - TimeLocal() );
     }
      return TimeLocal() + (datetime) GlobalVariableGet("Difereça entre minha hora e da Corretora");
   }
// função para saber se o mercado esta aberto, fechado ou sem conexão
   ENUM_MARKET_STATES mercadoStatus(){
      // verifica conecção
      if(SymbolIsSynchronized(_Symbol))
      // se segundos restantes for  menor que zero é ou porque não esta sicronizado ou o mercado ta fechado
         if(segundosRestantesDaBarra(PERIOD_M1) < 0)
            return FECHADO;
         else
            return ABERTO;
      return SEM_CONEXAO;         
   }
};

 
Francisco Gomes Da Silva:

Olá Francisco,

Ainda não encontrei uma solução confiável, vou analisar seu código pra ver se ele encaixa na no meu EA.

O mais decepcionante é que na boleta do MT é verificado se o mercado está aberto, mas esse código não está disponível para desenvolvedores.

 

Eu uso essa função no bovespa, 

porém eu comentei algumas partes porque no bovespa a corretora permite serie histórica a operação de EAs
mas não permite trade manual nessas series continuas.. aqui é tudo invertido... rs


//+------------------------------------------------------------------+
//| Gets the information about permission to trade                   |
//+------------------------------------------------------------------+
bool IsTradeAllowed()
  {
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      ShowComment("Verifique se a negociação automática é permitida nas configurações do terminal!");
      return(false);
     }
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      ShowComment("Verifique se a negociação automática é permitida nas configurações do terminal!");
      return(false);
     }
   //else
   //  {
   //   if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
   //     {
   //      ShowComment("A negociação automatizada está proibida nas configurações do programa para "+__FILE__);
   //      return(false);
   //     }
   //  }
   if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
     {
      ShowComment("A negociação automatizada é proibida para a conta "+AccountInfoInteger(ACCOUNT_LOGIN)+
            " no lado do servidor de comércio");
      return(false);
     }
   //if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
   //  {
   //   ShowComment("A negociação está proibida para a conta "+AccountInfoInteger(ACCOUNT_LOGIN)+
   //           ".\n Talvez uma senha de investidor tenha sido usada para se conectar à conta de negociação."+
   //           "\n Verifique o diário do terminal para a seguinte entrada:"+
   //           "\n\'"+AccountInfoInteger(ACCOUNT_LOGIN)+"\': A negociação foi desativada - modo investidor.");
   //   return(false);
   //  }
//---

   return(true);
  }
 
Francisco Gomes Da Silva:

Francisco do céu, ainda bem que você escreveu que é uma gambiarrinha. rs


Que código imenso cheio de loops! Ha partes opnde uma coisa cancela a outra logo em seguinda (Ex: você soma o timelocal(), e na função que faz a chamada você subtrai o mesmo valor de timelocal() que foi somado, logo, uma coisa anula a outra e é apenas gasto de processamento fazer tanto vai e vem.. 

Seria uma critica, mas não é, pois você avisou que o código é uma gambiarra.

Pela sua sinceridade, analisei seu código, peguei o seu código acima, removi todas as partes as quais uma cancela a outra, removi loops desnecessários, e seu código ficou assim:

É exatamente o que tudo aquilo lá está fazendo:

enum ENUM_MARKET_STATES {
   FECHADO = -1,
   SEM_CONEXAO = 0,
   ABERTO = 1
};
   
ENUM_MARKET_STATES mercadoStatus() {

   if(TerminalInfoInteger(TERMINAL_CONNECTED)) {   
   
      ENUM_TIMEFRAMES tempoGrafico = PERIOD_M1;
      datetime time[];
      CopyTime(_Symbol,tempoGrafico,0,1,time);
      int segundosRestantesDaBarra = ( (int)time[0]  - (int)TimeCurrent() + PeriodSeconds(tempoGrafico) );  
   
      if(segundosRestantesDaBarra < 0) {
         return FECHADO;
      } else {
         return ABERTO;
      }
   } 
   
   return SEM_CONEXAO;
}


Tomei a liberdade de mudar apenas a função SymbolIsSynchronized(_Symbol) que você utiliza para detectar se está conectado, pela função correta pra essa finalidade if(TerminalInfoInteger(TERMINAL_CONNECTED)) .

Essa lógica toda é funcional em grande parte do tempo, eu a estou utilizando (obrigado!), mas ela pode falhar em ativos ou moedas onde o volume de ticks é baixo. 

 
rrocchi:

Francisco do céu, ainda bem que você escreveu que é uma gambiarrinha. rs


Que código imenso cheio de loops! Ha partes opnde uma coisa cancela a outra logo em seguinda (Ex: você soma o timelocal(), e na função que faz a chamada você subtrai o mesmo valor de timelocal() que foi somado, logo, uma coisa anula a outra e é apenas gasto de processamento fazer tanto vai e vem.. 

Seria uma critica, mas não é, pois você avisou que o código é uma gambiarra.

Pela sua sinceridade, analisei seu código, peguei o seu código acima, removi todas as partes as quais uma cancela a outra, removi loops desnecessários, e seu código ficou assim:

É exatamente o que tudo aquilo lá está fazendo:


Tomei a liberdade de mudar apenas a função SymbolIsSynchronized(_Symbol) que você utiliza para detectar se está conectado, pela função correta pra essa finalidade if(TerminalInfoInteger(TERMINAL_CONNECTED)) .

Essa lógica toda é funcional em grande parte do tempo, eu a estou utilizando (obrigado!), mas ela pode falhar em ativos ou moedas onde o volume de ticks é baixo. 

Belissimo refactoring!!! 


Para evitar o problema com ativos pouco liquidos, e já que o objetivo é só entender se esta fechado ou não, não seria melhor usar como Simbolo o IBOV ao invés da constante _Symbol?

 
vinicius marini:

Belissimo refactoring!!! 


Para evitar o problema com ativos pouco liquidos, e já que o objetivo é só entender se esta fechado ou não, não seria melhor usar como Simbolo o IBOV ao invés da constante _Symbol?

olá, depende de que mercado, a vista ou futuro.

 
Uma dúvida : caso a função retorne que esta sem conexão,existe como procurar os servidores disponíveis  fornecidos pela corretora e  aciona-los?  Ou então uma forma, via código, de utilizar o recurso de " Escanear rede" e encontrar sozinho um novo servidor que esteja disponível? Digo isso pq  as vezes percebo que o MT5 fica travado e somente depois de um tempo ele retorna a atualizar os ticks. Se existisse alguma biblioteca que listasse todos os servidores disponíveis e no momento em que  o programa " percebesse " que estamos sem conexão ele mesmo procurasse um novo servidor e fizesse a troca, por por um novo, seria ótimo...
Razão: