Diferença grande no tempo de execução de um código quando na conta real

 
Boa tarde, pessoal. Estou iniciando no metatrader e depois de muito tempo elaborando meu primeiro EA resolvi testá-lo em conta real. Porém está acontecendo um problema curioso (pelo menos para mim.. rs). O tempo de execução do código está extremamente lento, quando deveria executar a cada tick. Coloquei um print depois do OnTick() para ver com que velocidade o código faz um "ciclo" e ele está levando mais de um minuto e meio entre um ciclo de execução e outro. Contudo, no backtest este ciclo é muito rápido a aparenta funciona corretamente. Em função desta demora na conta real, acaba atrasando demais a atualização de algumas variáveis e executa as entradas de forma totalmente errada. Como no backtest tipo tick a tick tudo corre bem, penso que não seja algo no código. Alguém sabe me dizer o que poderia estar ocorrendo? Acredito que deva ser um erro meu, mas ja procurei bastante sobre isso e não consegui encontrar nada a respeito.  
 
Cléo Bressan:

Cléo,

voce está confuso sobre liquidez de um ativo!  Mini índice (WIN) tem +de 10000 negociações (ticks) por minuto, Boi Gordo (BGI) 1 negócio a cada 5 minutos.

Então qual é o ativo e qual é a liquidez do ativo que está operando?

 
Rogerio Giannetti Torres #:

Cléo,

voce está confuso sobre liquidez de um ativo!  Mini índice (WIN) tem +de 10000 negociações (ticks) por minuto, Boi Gordo (BGI) 1 negócio a cada 5 minutos.

Então qual é o ativo e qual é a liquidez do ativo que está operando?

    Opa Rogério. Obrigado pelo retorno. Me desculpa, mas esqueci de falar. Estou operando no mini índice mesmo, então não é um problema relacionado à liquidez.
 
cleorb #:
    Opa Rogério. Obrigado pelo retorno. Me desculpa, mas esqueci de falar. Estou operando no mini índice mesmo, então não é um problema relacionado à liquidez.

Então lascou, você vai ter que depurar seu código em REAL, para saber onde está bugando!!!  

 
cleorb:
Boa tarde, pessoal. Estou iniciando no metatrader e depois de muito tempo elaborando meu primeiro EA resolvi testá-lo em conta real. Porém está acontecendo um problema curioso (pelo menos para mim.. rs). O tempo de execução do código está extremamente lento, quando deveria executar a cada tick. Coloquei um print depois do OnTick() para ver com que velocidade o código faz um "ciclo" e ele está levando mais de um minuto e meio entre um ciclo de execução e outro. Contudo, no backtest este ciclo é muito rápido a aparenta funciona corretamente. Em função desta demora na conta real, acaba atrasando demais a atualização de algumas variáveis e executa as entradas de forma totalmente errada. Como no backtest tipo tick a tick tudo corre bem, penso que não seja algo no código. Alguém sabe me dizer o que poderia estar ocorrendo? Acredito que deva ser um erro meu, mas ja procurei bastante sobre isso e não consegui encontrar nada a respeito.  

Seu codigo esta lento e precisa melhorar a performance, em conta real cada tick eh processado.  No testador tem uma condensacao que deixa um pouco mais rapido, se nao me engano tem uma limitacao de algo como 2000 movimentos numa vela.

Se tu esta analisando velas fechadas pode jogar tudo no ontimer() que ja vai dar uma baita aliviada, porque pode testar a cada segundo se virou a vela e tal. Mas se for algo a cada negocio dai tem que estudar melhor ne.

 
Ricardo Rodrigues Lucca #:

Seu codigo esta lento e precisa melhorar a performance, em conta real cada tick eh processado.  No testador tem uma condensacao que deixa um pouco mais rapido, se nao me engano tem uma limitacao de algo como 2000 movimentos numa vela.

Se tu esta analisando velas fechadas pode jogar tudo no ontimer() que ja vai dar uma baita aliviada, porque pode testar a cada segundo se virou a vela e tal. Mas se for algo a cada negocio dai tem que estudar melhor ne.

Boa noite, Ricardo. Valeu pelo auxílio. Na verdade é mais ou menos isso que eu desconfiava que devia estar acontecendo. Vou estudar essa tua sugestão do ontimer(). Acho que pode me ajudar bastante!

 
Pessoal. Segui as dicas do Ricardo, fiz um novo código bem mais simplificado e utilizei o ontimer() para não haver uma sobrecarga de eventos. Continua exatamente a mesma coisa, funciona muito bem no testador de estratégia no modo a cada tick, seguindo a temporização do ontimer corretamente e executando as ordens como esperado, mas na real acontece o mesmo atraso de cerca de 1 minuto e meio para cada ciclo do código. Alguém tem mais alguma ideia do que possa ser? 
 
cleorb #:
Pessoal. Segui as dicas do Ricardo, fiz um novo código bem mais simplificado e utilizei o ontimer() para não haver uma sobrecarga de eventos. Continua exatamente a mesma coisa, funciona muito bem no testador de estratégia no modo a cada tick, seguindo a temporização do ontimer corretamente e executando as ordens como esperado, mas na real acontece o mesmo atraso de cerca de 1 minuto e meio para cada ciclo do código. Alguém tem mais alguma ideia do que possa ser? 

Eu falei que ia melhorar, nao resolver o problema. Mas se tu ta analisando vela fechada deveria ocorrer so na virada da vela essa lentidao. Talvez se falar mais ou mostrar o codigo a gente possa ti ajudar melhor.

 
Ricardo Rodrigues Lucca #:

Eu falei que ia melhorar, nao resolver o problema. Mas se tu ta analisando vela fechada deveria ocorrer so na virada da vela essa lentidao. Talvez se falar mais ou mostrar o codigo a gente possa ti ajudar melhor.

Desculpe, Ricardo. Não foi uma crítica, me expressei mal. Agredeço muito as suas dicas, especialmente em relação ao ontimer() que eu ainda não conhecia. Estava citando o problema sem postar o código porque achei que poderia ser algo corriqueiro e um pouco também para não expor tanto o nível do amadorismo... rsrs. Mas segue aí o código que estou desenvolvendo.

#property copyright "Cléo Rodrigo Bressan"
#property version   "2.00"

#include <Trade/Trade.mqh>;
CTrade negocio;

input double Contratos = 1; //Número de contratos negociados.
input string Inicio = "9:05"; //Horário de início das operações.
input string Termino = "17:20";//Horário de finalização das operações.
input string ClosePosition = "17:25";// Horário de encerramento forçado.

input double TP = 100;
input double SL = 100;
double priceIn = 0;
double PriceLoss = 0;
double PriceGain = 0;

//+------------------------------------------------------------------+
//| Parâmetros de entrada da média móvel do ponto pivô               |
//+------------------------------------------------------------------+
/////////////////// Inputs Pivo
input int media_pivo_periodo = 4; //Média móvel aplicada ao preço típico.
input int media_pivo_deslocamento = 0; //Deslocamento da média móvel do preço típico.
int handleMediaPivo;
int handlePivo;

input int media_pivo_periodo_d = 4; //Média móvel aplicada ao preço típico período acima.
input int media_pivo_deslocamento_d = 0; //Deslocamento da média móvel do preço típico período acima.
int handlePivo_d;
int handleMediaPivo_d;


/////////////////// Inputs KVO
input uint periodo_media_fastKVO = 34; //Perído da média rápida do KVO.
input uint periodo_media_slowKVO = 55; //Período da media lenta do KVO.
input uint Periodo_media_signalKVO = 13; //Período da linha sinal.
int  handleKVO;

input uint periodo_media_fastKVO_d = 34; //Perído da média rápida do KVO período acima.
input uint periodo_media_slowKVO_d = 55; //Período da media lenta do KVO período acima.
input uint Periodo_media_signalKVO_d = 13; //Período da linha sinal período acima.
int  handleKVO_d;

//int handleRSI;

MqlDateTime horario_inicio, horario_termino, horario_ClosePosition, horario_atual;

//int num_bars;
//int num_bars_prev;


input int intervalo_execucao = 5000; //periodicidade da execução do código em milissegundos

   double lastoffer_compra = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double lastoffer_venda = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   
   double KVO[], LinhaSinal[], MediaPivo[], Pivo[]; // RSI[];
   double KVO_d[], LinhaSinal_d[], MediaPivo_d[], Pivo_d[];



int OnInit()

  {
   handleMediaPivo = iMA(_Symbol,_Period,media_pivo_periodo,media_pivo_deslocamento,MODE_SMA,PRICE_TYPICAL);
   handlePivo      = iMA(_Symbol,_Period,1,media_pivo_deslocamento,MODE_SMA,PRICE_TYPICAL);
   handleKVO       = iCustom(_Symbol,_Period, "Pessoais/Klinger_Oscillator.ex5",periodo_media_fastKVO, periodo_media_slowKVO, Periodo_media_signalKVO);

   handleMediaPivo_d = iMA(_Symbol, PERIOD_D1,media_pivo_periodo_d,media_pivo_deslocamento_d,MODE_SMA,PRICE_TYPICAL);
   handlePivo_d      = iMA(_Symbol, PERIOD_D1,1,media_pivo_deslocamento_d,MODE_SMA,PRICE_TYPICAL);
   handleKVO_d       = iCustom(_Symbol, PERIOD_D1, "Pessoais/Klinger_Oscillator.ex5",periodo_media_fastKVO_d, periodo_media_slowKVO_d, Periodo_media_signalKVO_d);

//handleRSI         = iRSI(_Symbol, _Period, 14, PRICE_TYPICAL);

   EventSetMillisecondTimer(intervalo_execucao);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnDeinit(const int reason)
  {
   EventKillTimer();
   return(reason);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTimer()
  {

   Print("Início Novo ciclo");
   LimparOrdens();

   TimeToStruct(StringToTime(Inicio), horario_inicio);
   TimeToStruct(StringToTime(Termino), horario_termino);
   TimeToStruct(StringToTime(ClosePosition), horario_ClosePosition);

//---
   ArraySetAsSeries(KVO, true);
   ArraySetAsSeries(LinhaSinal, true);
   ArraySetAsSeries(MediaPivo, true);
   ArraySetAsSeries(Pivo, true);
//ArraySetAsSeries(RSI, true);

   CopyBuffer(handleKVO,0, 0, 5, KVO);
   CopyBuffer(handleKVO,1, 0, 5, LinhaSinal);
   CopyBuffer(handleMediaPivo,0, 0, 5, MediaPivo);
   CopyBuffer(handlePivo, 0, 0, 5, Pivo);
//CopyBuffer(handleRSI, 0, 0, 3, RSI);

   
   ArraySetAsSeries(KVO_d, true);
   ArraySetAsSeries(LinhaSinal_d, true);
   ArraySetAsSeries(MediaPivo_d, true);
   ArraySetAsSeries(Pivo_d, true);

   CopyBuffer(handleKVO_d,0, 0, 5, KVO_d);
   CopyBuffer(handleKVO_d,1, 0, 5, LinhaSinal_d);
   CopyBuffer(handleMediaPivo_d,0, 0, 5, MediaPivo_d);
   CopyBuffer(handlePivo_d, 0, 0, 5, Pivo_d);

//Print("LinhaSinal[0]: ", LinhaSinal[0]);
//Print("LinhaSinal[1]: ", LinhaSinal[1]);

//--------------------------------------------------

   if(horarioEntrada())
     {
      if(sinalCompra())
        {
         double compra = MathRound(MediaPivo[1] / 5.0) * 5.0;
         negocio.BuyLimit(Contratos, compra,_Symbol,0,0);
         Print("Entrada Operação de compra: ", PositionGetDouble(POSITION_PRICE_OPEN));
        }
      if(sinalVenda())
        {
         double venda = MathRound(MediaPivo[1] / 5.0) * 5.0;
         negocio.SellLimit(Contratos, venda,_Symbol,0,0);
         Print("Entrada Operação de venda: ", PositionGetDouble(POSITION_PRICE_OPEN));
        }
     }

   PositionSelect(_Symbol);
   long tipo_posicao = PositionGetInteger(POSITION_TYPE);

//----------------------------------------------------
//Saida em caso de COMPRA
   
   
   if(PositionSelect(_Symbol) && tipo_posicao == POSITION_TYPE_BUY && horarioEntrada())
     {
      priceIn = PositionGetDouble(POSITION_PRICE_OPEN);
      PriceGain = priceIn + TP;
      PriceLoss = priceIn - SL;

      if(MediaPivo[1] > MediaPivo[2] && lastoffer_compra > PriceLoss && tipo_posicao == POSITION_TYPE_BUY)
        {
         LimparOrdens();
         negocio.SellLimit(Contratos, PriceGain,_Symbol,0,0);
        }

      if(MediaPivo[1] < MediaPivo[2] && lastoffer_compra > PriceLoss && tipo_posicao == POSITION_TYPE_BUY)
        {
         LimparOrdens();
         negocio.SellLimit(Contratos, (MediaPivo[1]),_Symbol,0,0);
        }

      if(iClose(_Symbol, _Period, 1) < PriceLoss && tipo_posicao == POSITION_TYPE_BUY)
        {
         LimparOrdens();
         for(int i = PositionsTotal()-1; i>=0; i--)
           {
            ulong PosTicket = PositionGetTicket(i);
            negocio.PositionClose(PosTicket);
            Print("StopLoss acionado");
           }
        }
     }

//Saida em caso de VENDA
   if(PositionSelect(_Symbol) && tipo_posicao == POSITION_TYPE_SELL && horarioEntrada())
     {
      priceIn = PositionGetDouble(POSITION_PRICE_OPEN);
      PriceGain = priceIn - TP;
      PriceLoss = priceIn + SL;

      if(MediaPivo[1] < MediaPivo[2] && lastoffer_venda < PriceLoss && tipo_posicao == POSITION_TYPE_SELL)
        {
         LimparOrdens();
         negocio.BuyLimit(Contratos, PriceGain,_Symbol,0,0);
        }

      if(MediaPivo[1] > MediaPivo[2] && lastoffer_venda < PriceLoss && tipo_posicao == POSITION_TYPE_SELL)
        {
         LimparOrdens();
         negocio.BuyLimit(Contratos, (MediaPivo[1]),_Symbol,0,0);
        }

      if(iClose(_Symbol, _Period, 1) > PriceLoss && tipo_posicao == POSITION_TYPE_SELL)
        {
         LimparOrdens();
         for(int i = PositionsTotal()-1; i>=0; i--)
           {
            ulong PosTicket = PositionGetTicket(i);
            negocio.PositionClose(PosTicket);
            Print("StopLoss acionado");
           }
        }
     }
//+------------------------------------------------------------------+
//|              Fechamento pelo horário                             |
//+------------------------------------------------------------------+
   if(horarioClose())
     {
      for(int i = PositionsTotal()-1; i>=0; i--)
        {
         ulong PosTicket = PositionGetTicket(i);
         negocio.PositionClose(PosTicket);
         Print("Fechamento");
        }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool sinalCompra()
{
if(!PositionSelect(_Symbol))
   if(Ordens()==0)
      if((LinhaSinal[1] > LinhaSinal[2]) && (MediaPivo[1] < Pivo[1]))
        {
         return true;
        }
return false;
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool sinalVenda()
{
   if(!PositionSelect(_Symbol))
      if(Ordens()==0)
         if((LinhaSinal[1] < LinhaSinal[2]) && (MediaPivo[1] > Pivo[1]))
           {
            return true;
           }
return false;
}
//+------------------------------------------------------------------+
//|                 Cancela ordens pendentes                         |
//+------------------------------------------------------------------+
void LimparOrdens()
  {
   int num_posicoes = Ordens();
   for(int i = Ordens() - 1; i >= 0; i--)
      if(OrderGetTicket(i) > 0)
         negocio.OrderDelete(OrderGetTicket(i));
  }

//+------------------------------------------------------------------+
//|              Retorna número de ordens pendentes --               |
//+------------------------------------------------------------------+
int Ordens()
  {
   return (OrdersTotal());
  }

//+------------------------------------------------------------------+
//|           Define horário de entrada das operações                |
//+------------------------------------------------------------------+
bool horarioEntrada()
  {
   TimeToStruct(TimeCurrent(), horario_atual);
   if(horario_atual.hour>=horario_inicio.hour && horario_atual.hour<=horario_termino.hour)
     {
      if(horario_atual.hour == horario_inicio.hour)
         if(horario_atual.min>=horario_inicio.min)
            return true;
         else
            return false;
      if(horario_atual.hour == horario_termino.hour)
         if(horario_atual.min<=horario_termino.min)
            return true;
         else
            return false;
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//|     Função que determinao fechamento de posição pelo horario     |
//+------------------------------------------------------------------+
bool horarioClose()
  {
   TimeToStruct(TimeCurrent(), horario_atual);
   if(horario_atual.hour>=horario_ClosePosition.hour)
     {
      if(horario_atual.hour == horario_ClosePosition.hour)
         if(horario_atual.min>=horario_ClosePosition.min)
            return true;
         else
            return false;
      return true;
     }
   return false;
  }
 
cleorb #:

Desculpe, Ricardo. Não foi uma crítica, me expressei mal. Agredeço muito as suas dicas, especialmente em relação ao ontimer() que eu ainda não conhecia. Estava citando o problema sem postar o código porque achei que poderia ser algo corriqueiro e um pouco também para não expor tanto o nível do amadorismo... rsrs. Mas segue aí o código que estou desenvolvendo.

Se foi critica, vamos melhorar. Eu não vi nada que pareça que seria pra demorar, mas moveria pro OnInit: (1) Todos ArraySetAsSeries; (2) Chamadas do TimeToStruct. O motivo do 1 eh que ate onde testei nao parece ter que ficar sendo chamado toda hora pra fazer algo, nao estamos apagando o array. O segundo tem uma lentidao no lidar com a hora como eh so configuração pode ser movido pra la e fora do horario de negociação. Voce poderia fazer ele ficar atualizando no OnTimer se quiser fora da janela de negociação. O que vai resolver seu problema parece é otimizar esses indicadores ai que provavelmente é culpa deles.

Fora isso achei organizado e eu gosto da ideia de 3 tempos tambem.

 
Ricardo Rodrigues Lucca #:

Se foi critica, vamos melhorar. Eu não vi nada que pareça que seria pra demorar, mas moveria pro OnInit: (1) Todos ArraySetAsSeries; (2) Chamadas do TimeToStruct. O motivo do 1 eh que ate onde testei nao parece ter que ficar sendo chamado toda hora pra fazer algo, nao estamos apagando o array. O segundo tem uma lentidao no lidar com a hora como eh so configuração pode ser movido pra la e fora do horario de negociação. Voce poderia fazer ele ficar atualizando no OnTimer se quiser fora da janela de negociação. O que vai resolver seu problema parece é otimizar esses indicadores ai que provavelmente é culpa deles.

Fora isso achei organizado e eu gosto da ideia de 3 tempos tambem.

Opa. Valeu a análise Ricardo. Vou fazer estas modificações que você sugeriu e assim que puder testar no "real" dou um retorno aqui para relatar se era isso mesmo. 
Razão: