iBarShiftのアナログ - ページ 16

 

一般的に、私は斜めに読んで、唯一の最初のページ(多分真ん中に誰かの明るい頭だった? :) 、何かすべての履歴にアクセスするためにひどく不便な端末インタフェースに松葉杖を追加しようと、それは端末と独自のもの(一般的に、それは標準ライブラリであるべき)の間にパッドを書く方が簡単です。 また、結果として、あなたは4/5に別のスクリプトを書く必要はありません。そんなことをしたことがあります。

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

そして、簡単な使用例。

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

refresh()経由は4/5で独自に定義しています。チャートは1つの期間(M1またはdefineで定義された他の期間、なぜ彼らの豊富なこの手間をかける?)

また、いくつかの便利な機能を実装しました。reverse_mode() は、左右どちらからでもインデックスを作成できます(左から右への場合は、チャートを展開してもインデックスが有効なままです)。チャートエッジの設定・移動機能 set_curtainpos(), テスターのアナログ - テスト, 境界の移動, テスト, 移動。My_point構造体で比較演算子をオーバーロードしました(このような状況で有効な動作のため: 0.0000000009 == 1.0000000000 )。

もし悶々とする人がいたら、個人的にはこの方法をお勧めします、残念でなりません。

Zy: それから、ローソク足も、オープン、クローズ、ハイ、ローと、クラシックなものはやめて、ポイントを ベースにしたんだ。

 
Aleksey Vyazmikin:

最終形での修正を待ちたいと思います、回答ありがとうございました。

試験、頑張ってください。

非常に微妙なニュアンスであることがわかりました。

こんなにややこしいと知っていたら、手を出さなかったのに ))))

このオプションは正しく動作するはずです。
もし、動作がおかしいと思われる方がいらっしゃいましたら、ご報告いただけると幸いです。


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));}
//+------------------------------------------------------------------+
 
iBars() と標準のBars()との性能の違いは何ですか?
 
Artyom Trishkin:
iBars()は標準のBars()とどの程度パフォーマンスが違うのでしょうか?

使い方次第です。
iBarを呼び出すたびにTFやシンボルが変わるなら、私のiBarは約半分の速度になるでしょう。

しかし、これは現実的には絶対にありえない状況です。

例えばこんな使い方をすると。

となると、私のiBarsは 通常のBarsの約10倍以上のアドバンテージがあることになります。

でも、肝心のハングアップのバグがないんですよ。

   Print("1");
   Print(Bars(_Symbol,PERIOD_D1,D'2018.05.02 01:58:03',D'2018.05.02 12:56:11')); // вычисляется более 10 секунд !!!!
   Print("2");
ファイル:
 
TFとして0 =PERIOD_CURRENTを 渡した場合、エラーが発生することがありました。
上記のコードで修正しました。行を追加しました。
if (timeframe==0) timeframe=_Period;
 
Nikolai Semko:

使い方次第です。
iBarを呼び出すたびにTFやシンボルが変更されるなら、私のiBarは約2倍遅く動作することになります。

しかし、これは現実的には全くあり得ない状況です。

例えばこんな使い方をすると。

となると、私のiBarsの優位性は、標準のBarsの約10倍以上となります。

でも、肝心のハングアップのバグがないんですよ。

りょ、りょ、りょーかい!?

 
Nikolai Semko:

使い方次第です。
もし、iBarを呼び出すたびにTFやシンボルが変更されるなら、私のiBarは約2倍遅く動作することになります。

しかし、これは現実的には全くあり得ない状況です。

例えばこんな使い方をすると。

となると、私のiBarsの優位性は、標準のBarsの約10倍以上となります。

しかし、一番のポイントはフリーズのバグがないことです。

さあ!

10秒はどこだ?

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:

おいおい!

10秒はどこだ?

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

MT5でしたっけ?
MT4では、このバグはありません。
 
Nikolai Semko:
MT5でしたっけ?
この不具合はMT4では発生しません。
エムティーフォー
 
Renat Akhtyamov:
エムティーフォー

MT5で試してみて、驚いてください。

このバグは@Aleksey Vyazmikin さんの 投稿の おかげで完全に偶然発見されたもので、彼には大変感謝しています。

以前からこの中断を観察していたが、その起源を説明することができなかった。誰が考えたんだろう...