Analógico para iBarShift - página 16

 

Em geral, leio diagonalmente e apenas as primeiras páginas (talvez no meio estivesse a cabeça brilhante de alguém? :) ), algo que todos tentam adicionar muletas à interface terminal terrivelmente inconveniente para aceder à história, é mais fácil escrever um bloco entre o terminal e as suas próprias coisas (em geral, deveria estar na biblioteca std). Além disso, como resultado, não é necessário escrever roteiros diferentes para 4/5. Eu já fiz tal coisa:

// comp.comp() returns true if the first argument is less than the second.
// If failure, returns UINT_MAX.
template<typename A, typename T, typename Comp>
uint alg_lower_bound(const A &ar[], uint minindex, uint maxindex,
                     const T &value, Comp &comp, bool rev=false)
{
   uint count = maxindex - minindex + 1;
   uint first = minindex;
   if(rev)
      first = maxindex;
      
   while(count != 0)
   {
      uint it = first;
      uint step = count / 2;
      if(rev)
         it -= step;
      else
         it += step;
      if(comp.comp(ar[it], value))
      {
         if(rev)
            first = --it;
         else
            first = ++it;
         count -= step + 1;
      }
      else
         count = step;
   }
   
   if(first < minindex  ||  first > maxindex)
      first = UINT_MAX;
   return first;
}

class Chart
{
   struct Bar_trend
   {
      double p1;
      double p2;
      datetime time;
   };
   Bar_trend bar_trend[];
   upindex_t sz;
   upindex_t curtain;
   bool reverse_f;
   void refresh_base(datetime min = 0, datetime max = 0);
public:
   // Empty chart will be created.
   Chart(): sz(0), curtain(UPINDEXT_MAX), reverse_f(false) {}
   // Chart with points whose time is in interval min:max will be created.
   Chart(datetime min, datetime max): sz(0), curtain(UPINDEXT_MAX), reverse_f(false) { refresh_base(min, max); }
   // Reverse flag is not changed. For whole chart min and max are 0.
   void init(datetime min, datetime max);
   My_point operator[](upindex_t i)const;
   // If exact is true then time of point with returned index is equal to time.
   // If point is not found then function returns UPINDEXT_MAX.
   upindex_t bar_shift(datetime time, bool exact=true)const;
   upindex_t size()const  {return this.curtain == UPINDEXT_MAX  ?  this.sz * 2  :  this.curtain;}
   // pos can not be greater than the size(). UPINDEXT_MAX for deletion of curtain.
   // It will be reset when refresh(). Returns true in case of success.
   bool set_curtainpos(upindex_t pos);
   upindex_t get_curtainpos()const  {return this.curtain;}
   bool reverse_mode()const  {return this.reverse_f;}
   // Returns true in case of success.
   bool reverse_mode(bool mode);
   // if chart size == 0 then lowest = highest == UPINDEXT_MAX.
   void extremums(upindex_t &lowest, upindex_t &highest)const;
   // if chart is reverse then indexes will be invalidated.
   void refresh()  { refresh_base(); }
};

upindex_t Chart::bar_shift(datetime time, bool exact)const
{
   class Comp
   {
   public:
      bool comp(const Bar_trend &bt, datetime time)  {return bt.time > time;}
   }comp;
   
   uint res = alg_lower_bound(this.bar_trend, 0, this.sz-1, time, comp, true);
   if(res != UINT_MAX)
   {
      uchar shift = this.bar_trend[res].time!=time ? 1 : 0;

      if(exact  &&  this.bar_trend[res].time+shift != time)
         res = UINT_MAX;
      else
         res = this.reverse_f ? 
               ((this.sz - 1 - res) * 2 + !shift) :  
               (res * 2 + shift);
   }
   return res == UINT_MAX ? UPINDEXT_MAX : res;
}

E um simples exemplo de utilização:

Chart chart();
chart.refresh();
for(int i = 0;  i < chart.size();  ++i)
   Print(chart[i].price, chart[i].time);

refresh() via define o seu próprio para 4/5. O gráfico tem apenas um período (M1 ou outro definido através da definição, porque é que isto se incomoda com a sua abundância?).

Também implementei algumas características úteis - indexação reverse_mode() de ambos os lados (se da esquerda para a direita, os índices permanecem válidos ao desdobrar o gráfico). Habilidade de definir e mover o limite do gráfico set_curtainpos(), análogo do testador - testar, mover limite, testar, mover. Operadores de comparação sobrecarregados na estrutura My_point (para comportamento válido em tais situações: 0,0000000009 == 1,00000000000000).

Se alguém agoniza, eu recomendo esta abordagem, pessoalmente não lamento.

Zy: e desisti dos castiçais clássicos com abertura/fecho/alto/baixo, e coloquei Point na base - um castiçal dá dois Point's de alto>baixo, alto-baixo-alto. é realmente muito conveniente.

 
Aleksey Vyazmikin:

Vou esperar pelas correcções no formulário final, obrigado por responder.

Boa sorte com os exames!

Acabou por ser muito matizada.

Se eu soubesse como seria complicado, não me teria envolvido ))))

Esta opção deve funcionar correctamente.
Se alguém o encontrar a funcionar incorrectamente, ficaria grato se pudesse denunciar o problema.


int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=iBars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==iBars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }
int iBars(string symbol_name,ENUM_TIMEFRAMES  timeframe,datetime start_time,datetime stop_time) // stop_time > start_time
  {
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static datetime LastTime0=0;
   static int PerSec=0;
   static int PreBars=0,PreBarsS=0,PreBarsF=0;
   static datetime LastBAR=0;
   static datetime LastTimeCur=0;
   static bool flag=true;
   static int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
   datetime TimeCur;
   if (timeframe==0) timeframe=_Period;
   const bool changeTF=LastTimeFrame!=timeframe;
   const bool changeSymb=LastSymb!=symbol_name;
   const bool change=changeTF || changeSymb || flag;

   LastTimeFrame=timeframe; LastSymb=symbol_name;
   if(changeTF) PerSec=::PeriodSeconds(timeframe); if(PerSec==0) { flag=true; return(0);}

   if(stop_time<start_time)
     {
      TimeCur=stop_time;
      stop_time=start_time;
      start_time=TimeCur;
     }
   if(changeSymb)
     {
      if(!SymbolInfoInteger(symbol_name,SYMBOL_SELECT))
        {
         SymbolSelect(symbol_name,true);
         ChartRedraw();
        }
     }
   TimeCur=TimeCurrent();
   if(timeframe==PERIOD_W1) TimeCur-=(TimeCur+345600)%PerSec; // 01.01.1970 - Thursday. Minus 4 days.
   if(timeframe<PERIOD_W1) TimeCur-=TimeCur%PerSec;
   if(start_time>TimeCur) { flag=true; return(0);}
   if(timeframe==PERIOD_MN1)
     {
      MqlDateTime dt;
      TimeToStruct(TimeCur,dt);
      TimeCur=dt.year*12+dt.mon;
     }

   if(changeTF || changeSymb || TimeCur!=LastTimeCur)
      LastBAR=(datetime)SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE);

   LastTimeCur=TimeCur;
   if(start_time>LastBAR) { flag=true; return(0);}

   datetime tS,tF=0;
   if(timeframe==PERIOD_W1) tS=start_time-(start_time+345599)%PerSec-1;
   else if(timeframe<PERIOD_MN1) tS=start_time-(start_time-1)%PerSec-1;
   else  //  PERIOD_MN1
     {
      MqlDateTime dt;
      TimeToStruct(start_time-1,dt);
      tS=dt.year*12+dt.mon;
     }
   if(change || tS!=LastTime) { PreBarsS=Bars(symbol_name,timeframe,start_time,UINT_MAX); LastTime=tS;}
   if(stop_time<=LastBAR)
     {
      if(PreBarsS>=max_bars) PreBars=Bars(symbol_name,timeframe,start_time,stop_time);
      else
        {
         if(timeframe<PERIOD_W1) tF=stop_time-(stop_time)%PerSec;
         else if(timeframe==PERIOD_W1) tF=stop_time-(stop_time+345600)%PerSec;
         else //  PERIOD_MN1
           {
            MqlDateTime dt0;
            TimeToStruct(stop_time-1,dt0);
            tF=dt0.year*12+dt0.mon;
           }
         if(change || tF!=LastTime0)
           { PreBarsF=Bars(symbol_name,timeframe,stop_time+1,UINT_MAX); LastTime0=tF; }
         PreBars=PreBarsS-PreBarsF;
        }
     }
   else PreBars=PreBarsS;
   flag=false;
   return(PreBars);
  }
//+------------------------------------------------------------------+
int iBars(string symbol_name,ENUM_TIMEFRAMES  timeframe) {return(Bars(symbol_name,timeframe));}
//+------------------------------------------------------------------+
 
Como é que o seu iBars() difere em desempenho das Barras padrão() ?
 
Artyom Trishkin:
Quanto é que o seu iBars() difere em desempenho das Barras padrão()?

Depende de como se utiliza.
Se cada chamada para o iBar mudar o TF ou símbolo, então o meu iBar será cerca de metade mais lento.

Mas esta não é de todo uma situação realista de um ponto de vista prático.

Se o usarmos assim, por exemplo:

então a vantagem do meu iBars sobre os bares normais será de cerca de 10 ou mais vezes.

Mas o principal é que não há nenhum bug de desligamento:

   Print("1");
   Print(Bars(_Symbol,PERIOD_D1,D'2018.05.02 01:58:03',D'2018.05.02 12:56:11')); // вычисляется более 10 секунд !!!!
   Print("2");
Arquivos anexados:
 
Houve um erro que ocorreu se 0 =PERÍODO_CURSO foi passado como TF
Fixou-o no código acima. Acrescentou uma linha:
if (timeframe==0) timeframe=_Period;
 
Nikolai Semko:

Depende de como se utiliza.
Se cada chamada para o iBar irá mudar o TF ou símbolo, então o meu iBar irá trabalhar cerca do dobro da lentidão.

Mas esta não é de todo uma situação realista de um ponto de vista prático.

Se o usarmos assim, por exemplo:

então a vantagem das minhas barras iBars sobre as barras padrão seria cerca de 10 vezes ou mais.

Mas o principal é que não há nenhum bug de desligamento:

R-R-R-R-R-RESPEITO!

 
Nikolai Semko:

Depende de como se utiliza.
Se cada chamada para o iBar irá mudar o TF ou símbolo, então o meu iBar irá trabalhar cerca do dobro da lentidão.

Mas esta é uma situação completamente irrealista de um ponto de vista prático.

Se o usarmos assim, por exemplo:

então a vantagem das minhas barras iBars sobre as barras padrão seria cerca de 10 vezes ou mais.

Mas o principal é que não há nenhum bicho gelado:

Vá lá!

Onde estão os seus 10 segundos?

2018.05.05 17:45:36.860 ind EURUSD,M5: 2
2018.05.05 17:45:36.860 ind EURUSD,M5: 0
2018.05.05 17:45:36.860 ind EURUSD,M5: 1

 
Renat Akhtyamov:

Vá lá!

Onde estão os seus 10 segundos?

2018.05.05 17:45:36.860 ind EURUSD,M5: 2
2018.05.05 17:45:36.860 ind EURUSD,M5: 0
2018.05.05 17:45:36.860 ind EURUSD,M5: 1

Foi o MT5?
No MT4 este insecto não está lá.
 
Nikolai Semko:
Foi o MT5?
Este insecto não está presente no MT4.
MT4
 
Renat Akhtyamov:
MT4

Experimente-o no MT5 e surpreenda-se.

Este insecto foi completamente descoberto por acidente graças ao posto de@Aleksey Vyazmikin, pelo qual tenho de lhe agradecer muito.

Tinha observado estas interrupções antes, mas não conseguia explicar a sua origem. Quem teria pensado...