Indicador pro miniindice funcionando porem travando muito, podem ajudar?

 

Caros, fiz o codigo do indicador abaixo, cujo objetivo é mostrar um valor teorico para o minidince (WINFUT) em funcão da variacao do minidolar (WDOFUT). O racional é: se o WDOFUT está caido 0.5% eu inverto o sinal dessa queda e considero que o WINFUT deveria estar subindo 0.5%. Ele funciona corretamente, mas deixa o grafico lento. Alguem poderia dar uma olhada e ver se encontra o problema que está deixando pesado (lentidao no grafico) ?

input int janela=10;
input int modo = 1;
input double multiplicador = -1;
datetime Ontem16h00=D'2024.06.18 09:01:00';
double PrecoPartidaDoMini=0;
double PrecoPartidaWDO=0;

input int tetoDePlot=400;
int contaOnCalculate=0;
enum modoEnum 
  {
      
   precoVSjanela=0,        
   precoVSpartida=1,  
   
  };
//--- input parameters
input modoEnum modoDrop=precoVSjanela;
//+------------------------------------------------------------------+
//|                                                 Ind_Cesta_v3.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Label1"
//#property indicator_type1   DRAW_ARROW
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrOrange
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double         Label1Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
   
   ArraySetAsSeries(Label1Buffer,true);
   
   tf=_Period;
   papelNaTela=_Symbol;
   
   //ArrayResize(Label1Buffer,tetoDePlot);

PrecoPartidaDoMini=precoEmFuncaoDoTempo("WIN$", Ontem16h00, 0);
PrecoPartidaWDO=precoEmFuncaoDoTempo("WDO$", Ontem16h00, 0);      

//PrecoPartidaDoMini=iOpen("WIN$",PERIOD_D1,0);  
//PrecoPartidaWDO=iOpen("WDO$",PERIOD_D1,0);     
   
//Print("iTime(WIN$,PERIOD_D1,0)",iTime("WIN$",PERIOD_D1,0));
//Print("iTime(WIN$,PERIOD_D1,1)",iTime("WIN$",PERIOD_D1,1));
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
double aux=0;

ENUM_TIMEFRAMES tf=_Period;
string papelNaTela=_Symbol;


int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   contaOnCalculate++;
   //bool cPapel = papelNaTela == "WIN$" || papelNaTela == "WINQ24";
   //if(tf != PERIOD_M1 || !cPapel )
   //   return -1;
bool condicao=segundo(TimeCurrent()==10) || segundo(TimeCurrent()==20) || segundo(TimeCurrent()==30) || segundo(TimeCurrent()==40) || segundo(TimeCurrent()==50) || segundo(TimeCurrent()==59);
//   
//   if(!condicao) 
//     {
//      return tetoDePlot-1;
//     }
      
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(open,true);
   
   //if(condicao)
   //for(int i=MathMin(tetoDePlot,tetoDePlot-prev_calculated);i>=0;i--)
   for(int i=0;i<MathMin(tetoDePlot,tetoDePlot-prev_calculated);i++)
   //for(int i=0;i<1000;i++)
   {
   
      aux=0;
      //bool c1=hora(iTime("WINQ24",PERIOD_M1,i))>9;
      //bool c2=(hora(iTime("WINQ24",PERIOD_M1,i))==10 && minuto(iTime("WINQ24",PERIOD_M1,i))>janela)||hora(iTime("WINQ24",PERIOD_M1,i))!=10;
      //bool cFinal1=hora(iTime("WINQ24",PERIOD_M1,i))<17;//(hora(iTime("WINQ24",PERIOD_M1,i))==16) && minuto(iTime("WINQ24",PERIOD_M1,i))>49)||
      //bool cFinal2=hora(iTime("WINQ24",PERIOD_M1,i))==16 && minuto(iTime("WINQ24",PERIOD_M1,i))>49;
      //bool cDia=dia(iTime("WINQ24",PERIOD_M1,i))==dia(iTime("WINQ24",PERIOD_M1,0));
      ////bool c4=c1 && c2 && cFinal1 && !cFinal2;
      //bool c4=true;
      //Label1Buffer[i]=iLow(_Symbol,_Period,iLowest(_Symbol,_Period,MODE_LOW,20,i+5));     
      //Label1Buffer[i]=close[i];     
      //Label1Buffer[i]=close[i];     
      
      //aux=-100*(precoEmFuncaoDoTempo("WDO$", iTime("WINQ24",PERIOD_M1,i),0)/precoEmFuncaoDoTempo("WDO$", iTime("WINQ24",PERIOD_M1,i),janela)-1);
      
      PrecoPartidaWDO=PrecoOpenDia("WDO$",iTime("WIN$",_Period,i));   
      PrecoPartidaDoMini=PrecoOpenDia("WIN$",iTime("WIN$",_Period,i));   
      
      
      if(modoDrop==0)
         aux=100*(precoEmFuncaoDoTempo("WDO$", iTime("WINQ24",_Period,i),0)/precoEmFuncaoDoTempo("WDO$", iTime("WINQ24",_Period,i),janela)-1);
      
      
      if(modoDrop==1)
         aux=100*(precoEmFuncaoDoTempo("WDO$", iTime("WINQ24",_Period,i),0)/PrecoPartidaWDO-1);             
      
      
      //if(c4)
      //   Label1Buffer[i]=aux*close[i+janela]/100+close[i+janela];
      
      if(modoDrop==0)
         Label1Buffer[i]=multiplicador*(aux/1)*close[i+janela]/100+close[i+janela];
      
      if(modoDrop==1)
         Label1Buffer[i]=multiplicador*(aux/1)*PrecoPartidaDoMini/100+PrecoPartidaDoMini;
      
      //if(!c4)
      //   Label1Buffer[i]=0;      
      
      
      
   }//for i
   
   if(isNewBarMinuto())
   {
      Print("contaOncalculateLinhaWDO: ",contaOnCalculate);
      contaOnCalculate=0;
   }    
   
//Print("somaTotalPesos",somaTotalPesos);
   
//   if(isNewBarMinuto())
//   {
//      Print("rates_total: ",rates_total);
//      Print("prev_calculated: ",prev_calculated);
//      Print("Label1Buffer[0]: ",Label1Buffer[0]);
//      Print("precoEmFuncaoDoTempo[ITUB4,200]: ",precoEmFuncaoDoTempo("ITUB4", iTime("WINQ24",PERIOD_M1,200),15));
//      
//   }
//--- return value of prev_calculated for next call
   return(tetoDePlot-1);
  }
//+------------------------------------------------------------------+
bool isNewBarMinuto()
  {
//--- memorize the time of opening of the last bar in the static variable
   static datetime last_time=0;
//--- current time
   datetime lastbar_time=SeriesInfoInteger(Symbol(),PERIOD_M1,SERIES_LASTBAR_DATE);

//--- if it is the first call of the function
   if(last_time==0)
     {
      //--- set the time and exit
      last_time=lastbar_time;
      return(false);
     }

//--- if the time differs
   if(last_time!=lastbar_time)
     {
      //--- memorize the time and return true
      last_time=lastbar_time;
      return(true);
     }
//--- if we passed to this line, then the bar is not new; return false
   return(false);
  }
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double variacao(string papel, int posicao)
{
double resp=0;

if(iClose(papel,PERIOD_M1,posicao+janela)>0)
  {
   resp=(iClose(papel,PERIOD_M1,posicao)/iClose(papel,PERIOD_M1,posicao+janela)-1)*100;
  }

return resp;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double precoEmFuncaoDoTempo(string papel, datetime tempo, int delta)
{
//double resp=0;
//
//if(iClose(papel,PERIOD_M1,posicao+janela)>0)
//  {
//   resp=(iClose(papel,PERIOD_M1,posicao)/iClose(papel,PERIOD_M1,posicao+janela)-1)*100;
//  }

//iTime("WINM24",PERIOD_M1,i)
//datetime when;//=D'2024.05.14 15:00';
//when = StringToTime(tempo15h);
int  iWhenM1 = iBarShift(papel, PERIOD_M1, tempo);

//Print("iWhenM1 :",iWhenM1);
double close = iClose(papel, PERIOD_M1, iWhenM1+delta);

return close;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int segundo(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.sec;
}  
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int dia(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.day;
}  
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int hora(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.hour;
}  
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int minuto(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.min;
}  
//---------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int mes(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.mon;
}  
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int ano(datetime time1){
MqlDateTime time1string;
TimeToStruct(time1,time1string);
return time1string.year;
}  
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double deltaPrecoPctBvsA(double A, double B)
{
double resp=0;

if(B>0)
   resp=B/A-1;

resp=resp*100;

return resp;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double deltaPrecoPctJanela(string papel, int i)
{
double novo = precoEmFuncaoDoTempo(papel, iTime("WINQ24",PERIOD_M1,i),0);
double antigo = precoEmFuncaoDoTempo(papel, iTime("WINQ24",PERIOD_M1,i),janela);

double resp = deltaPrecoPctBvsA(antigo,novo);

return resp;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double PrecoOpenDia(string symbol, datetime tempo)
{

string mesString=IntegerToString(mes(tempo)); 
string diaString=IntegerToString(dia(tempo)); 
if(mes(iTime(_Symbol,PERIOD_D1,0))<10)
   mesString="0"+IntegerToString(mes(tempo)); 

if(dia(iTime(_Symbol,PERIOD_D1,0))<10)
   diaString="0"+IntegerToString(dia(tempo));
   
string tempoOpenDia;//=ano(TimeCurrent())+"."+mes(TimeCurrent())+"."+dia(TimeCurrent())+"."+_Symbol+"1"+".Compra."+".TXT";  
tempoOpenDia=ano(TimeCurrent())+"."+mesString+"."+diaString;
//------++----------------------++-----------
//string tempo15h=ano(TimeCurrent())+ mes(TimeCurrent()) +dia(TimeCurrent())+" 15";
datetime when;//=D'2024.05.14 15:00'; 
when = StringToTime(tempoOpenDia);
int  iWhenM1 = iBarShift(symbol, PERIOD_D1, when);
//Print("iWhenM1 :",iWhenM1);
double Open = iOpen(symbol, PERIOD_D1, iWhenM1);

return Open;
}
 
douglas14:

Caros, fiz o codigo do indicador abaixo, cujo objetivo é mostrar um valor teorico para o minidince (WINFUT) em funcão da variacao do minidolar (WDOFUT). O racional é: se o WDOFUT está caido 0.5% eu inverto o sinal dessa queda e considero que o WINFUT deveria estar subindo 0.5%. Ele funciona corretamente, mas deixa o grafico lento. Alguem poderia dar uma olhada e ver se encontra o problema que está deixando pesado (lentidao no grafico) ?

Roda ele no profile dentro do editor do mql5 para saber o que pode estar pesando. Ele diz o tempo e quantidade de vezes que algo foi chamado.

Olhando por cima como fica fazendo essas passadas e sempre descobrindo a abertura do dia atual via manipulação de string + iBarShift + iOpen. Esse seria um ponto que começaria vendo de melhorar para fazer isso somente uma vez no dia e depois pegar de algum lugar ja salvo.

Outro ponto, se vai ficar pegando 400 fechamentos, voce pode solicitar isso em uma unica vez ao inves de picadinho. Existe tanto funcoes como CopyTime e CopyClose como CopyRates para se quiser pegar todos os dados basicos em uma tacada.

 
Ricardo Rodrigues Lucca #:

Roda ele no profile dentro do editor do mql5 para saber o que pode estar pesando. Ele diz o tempo e quantidade de vezes que algo foi chamado.

Olhando por cima como fica fazendo essas passadas e sempre descobrindo a abertura do dia atual via manipulação de string + iBarShift + iOpen. Esse seria um ponto que começaria vendo de melhorar para fazer isso somente uma vez no dia e depois pegar de algum lugar ja salvo.

Outro ponto, se vai ficar pegando 400 fechamentos, voce pode solicitar isso em uma unica vez ao inves de picadinho. Existe tanto funcoes como CopyTime e CopyClose como CopyRates para se quiser pegar todos os dados basicos em uma tacada.

Opa, obrigado pelas sugestoes. Nao conheco esse profile que vc sugeriu? Como vejo documentação disso? 

Outra ideia que tive é tentar diminuir a frequencia de chamadas do codigo. O onCalculate é chamado mais de 4 mil vezes por minuto na parte da manhã, eu nao preciso dessa frequencia toda. Voce sabe como reduzir a frequencia de chamadas?

 
Ricardo Rodrigues Lucca #:

Roda ele no profile dentro do editor do mql5 para saber o que pode estar pesando. Ele diz o tempo e quantidade de vezes que algo foi chamado.

Olhando por cima como fica fazendo essas passadas e sempre descobrindo a abertura do dia atual via manipulação de string + iBarShift + iOpen. Esse seria um ponto que começaria vendo de melhorar para fazer isso somente uma vez no dia e depois pegar de algum lugar ja salvo.

Outro ponto, se vai ficar pegando 400 fechamentos, voce pode solicitar isso em uma unica vez ao inves de picadinho. Existe tanto funcoes como CopyTime e CopyClose como CopyRates para se quiser pegar todos os dados basicos em uma tacada.

sempre usei mais EAs, recentemente comecei usar indicadores.. Vc saberia dizer se da pra rodar o indicador com base na funcao onTimer() ao inves da oncalculate?... Estou francamente pensando em plotar o grafico que quero usando objetos dentro de um EA

 
douglas14 #:

Opa, obrigado pelas sugestoes. Nao conheco esse profile que vc sugeriu? Como vejo documentação disso? 

Outra ideia que tive é tentar diminuir a frequencia de chamadas do codigo. O onCalculate é chamado mais de 4 mil vezes por minuto na parte da manhã, eu nao preciso dessa frequencia toda. Voce sabe como reduzir a frequencia de chamadas?

https://www.metatrader5.com/pt/metaeditor/help/development/profiling

Criação de perfil de código - Desenvolvimento de programas - Ajuda para o MetaEditor
  • www.metatrader5.com
A criação de perfil é a coleção das características do programa durante sua execução. Ao...
 
douglas14 #:

sempre usei mais EAs, recentemente comecei usar indicadores.. Vc saberia dizer se da pra rodar o indicador com base na funcao onTimer() ao inves da oncalculate?... Estou francamente pensando em plotar o grafico que quero usando objetos dentro de um EA

Da sim, mas isso causa problemas quando tenta utilizar o indicador "carregado" em outro ou em um EA. Isso se deve ao programa só poder ter um onTimer(), se voce usar um onTimer() no EA e tiver no seu indicador uma dependencia do onTimer(), o codigo do indicador não vai rodar pelo que lembro. Claro que isso não impede de em um EA, tu solicitar acesso ao indicador na tela X, subjanela Y e pegar os dados corretamente. Mas dai ficaria "solto" o que as vezes eh um problema maior...