Analog zu iBarShift - Seite 16

 

Im Allgemeinen lese ich diagonal und nur erste Seiten (vielleicht in der Mitte war jemand hellen Kopf? :) ), etwas, das alle versuchen, Krücken zu schrecklich unbequem Terminal-Schnittstelle, um die Geschichte zugreifen hinzuzufügen, ist es einfacher, ein Pad zwischen dem Terminal und ihre eigenen Sachen zu schreiben (in der Regel sollte es in std Bibliothek sein). Darüber hinaus als Ergebnis, müssen Sie nicht auf verschiedene Skripte für 4/5 zu schreiben. Ich habe so etwas getan:

// 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;
}

Und ein einfaches Anwendungsbeispiel:

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

refresh() über definiert seine eigene für 4/5. Das Diagramm hat nur eine Periode (M1 oder eine andere, die über define eingestellt wird, warum diese Mühe mit ihrer Fülle?).

Außerdem habe ich einige nützliche Funktionen implementiert - reverse_mode() Indexierung von beiden Seiten (wenn von links nach rechts, die Indizes bleiben gültig, wenn Entfaltung Chart). Fähigkeit zum Setzen und Verschieben von Diagrammkanten set_curtainpos(), analog zum Tester - test, move boundary, test, move. Überladene Vergleichsoperatoren in der Struktur My_point (für gültiges Verhalten in solchen Situationen: 0.0000000009 == 1.0000000000).

Wenn sich jemand quält, empfehle ich diesen Ansatz, mir persönlich tut es nicht leid.

Zy: und ich habe aufgegeben, klassische candlesticks mit open/close/high/low, und setzen Sie Punkt in den Grundlagen - eine Kerze gibt zwei Point's bearish high->low, bullish low-high. das ist wirklich sehr praktisch.

 
Aleksey Vyazmikin:

Ich werde die Korrekturen in der endgültigen Form abwarten, danke für Ihre Antwort.

Viel Glück bei den Prüfungen!

Es stellte sich heraus, dass es sehr nuanciert war.

Wenn ich gewusst hätte, wie kompliziert es sein würde, hätte ich mich nicht darauf eingelassen ))))

Diese Option sollte korrekt funktionieren.
Wenn jemand feststellt, dass es nicht richtig funktioniert, wäre ich dankbar, wenn er das Problem melden könnte.


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));}
//+------------------------------------------------------------------+
 
Wie unterscheidet sich Ihre iBars() in der Leistung von der Standard Bars()?
 
Artyom Trishkin:
Inwieweit unterscheidet sich Ihre iBars() in der Leistung von der Standard Bars()?

Das hängt davon ab, wie Sie es verwenden.
Wenn jeder Aufruf des iBar den TF oder das Symbol ändert, ist mein iBar nur noch halb so langsam.

Dies ist jedoch aus praktischer Sicht absolut unrealistisch.

Wenn Sie es zum Beispiel so verwenden:

dann wird der Vorteil meiner iBars gegenüber den normalen Bars etwa 10 Mal oder mehr betragen.

Aber das Wichtigste ist, dass es keinen Aufhängungsfehler gibt:

   Print("1");
   Print(Bars(_Symbol,PERIOD_D1,D'2018.05.02 01:58:03',D'2018.05.02 12:56:11')); // вычисляется более 10 секунд !!!!
   Print("2");
Dateien:
 
Es trat ein Fehler auf, wenn 0 =PERIOD_CURRENT als TF übergeben wurde
Dies wurde im obigen Code korrigiert. Eine Zeile hinzugefügt:
if (timeframe==0) timeframe=_Period;
 
Nikolai Semko:

Das hängt davon ab, wie Sie es verwenden.
Wenn jeder Aufruf von iBar die TF oder das Symbol ändert, dann arbeitet mein iBar etwa doppelt so langsam.

Dies ist jedoch aus praktischer Sicht eine völlig unrealistische Situation.

Wenn Sie es zum Beispiel so verwenden:

dann wäre der Vorteil meiner iBars gegenüber den Standard-Bars etwa 10 Mal oder mehr.

Aber das Wichtigste ist, dass es keinen Aufhängungsfehler gibt:

R-R-R-R-RESPEKT!

 
Nikolai Semko:

Das hängt davon ab, wie Sie es verwenden.
Wenn jeder Aufruf von iBar die TF oder das Symbol ändert, dann arbeitet mein iBar etwa doppelt so langsam.

Dies ist jedoch aus praktischer Sicht eine völlig unrealistische Situation.

Wenn Sie es zum Beispiel so verwenden:

dann wäre der Vorteil meiner iBars gegenüber den Standard-Bars etwa 10 Mal oder mehr.

Aber die Hauptsache ist, dass es keinen Einfrierfehler gibt:

Na los!

Wo sind Ihre 10 Sekunden?

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:

Na los!

Wo sind deine 10 Sekunden?

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

War es MT5?
Auf MT4 ist dieser Fehler nicht vorhanden.
 
Nikolai Semko:
War es MT5?
Dieser Fehler ist auf MT4 nicht vorhanden.
MT4
 
Renat Akhtyamov:
MT4

Probieren Sie es auf MT5 und lassen Sie sich überraschen.

Dieser Fehler wurde völlig zufällig dank des Beitrags von @Aleksey Vyazmikin entdeckt, für den ich ihm sehr danken muss.

Ich hatte diese Unterbrechungen schon früher beobachtet, konnte mir aber ihren Ursprung nicht erklären. Wer hätte das gedacht...