ショウは続く- または ZigZag 再び。

Rider | 21 4月, 2016

はじめに

ZigZag バージョンが大量にあることは、このインディケータにおける不変的で持続的な関心が存在することを証明します。ひじょうに値打ちのある関心です。これはおそらく、主要な市場変動を表す鮮明なグラフ表現によって即時アクションを促し、直接トレーダーの感情に影響する唯一のインディケータです。実際、これは、このインディケータは直接のトレードシグナルを作成するものではないものの、人は 現在の市場状況に継続的にに最大にアプローチする試みる、という大半の人の十分な理解によって、その現象を説明する唯一のものです。最終予測フラクチャの無限の再描画を観察することは、特にそれを知るときには疑わしい利点です。

少しお話をします。信じる信じないは別として、これはすべての始まりなのです。

リリック

この市場にやってきて、「留まった」人はだれも、遅かれ早かれ初めに思ったほどそれが単純ではないことを理解します。それを理解したらすぐに、読み始めます(もちろんそれができる人が)。ですが、なんとなく ひじょうに奇妙に読んだことを認識します。要するに、われわれは 正しいものではなく、もっともシンプルなものを選択するのです。それに対応して、われわれの武器庫に表面的にあるもの、理解するのに明白で、簡単に(迅速に)アルゴリズム言語に翻訳できるもののみ追加するのです。その例は数多く存在します。その一つがあります。ベストなものではないでしょうが、それをそのまま見てみます。

だれもがまだ反証されていないが厳密に証明もされていないTA の論文を知り、覚えています。

価格がわれわれのすべてである!

これを言葉どおり正面から受け取り、市場の制御ポイントではなくなにがなんでもその最大値と最小値-これは簡単で明白です、を検索し始めます。ものさしでサポート/レジスタンスレベルを描き、そこからフィボナッチレベル、バーの周期などをカウントします。ますます悪いことに、だれかのトレーディングシステムから警告や、それはどの市場に対するものか、そのシステムが作成された時期などには注意を払うことなく理解しやすいことがらのみを取り入れるのです。さらに悪いのは、ギャンをシンプルに、単純化し始めるのです。価格/時間のソリューションを見つけた(あるいはそれに非常に近い)と私が思う人です。まだだれも完全に理解していない何かを単純化するなんてどうやったらできるのでしょうか?

そしてその後、すべてがいくぶん誤った動作をすることが判ります。フィフティフィフティよりややましなだけで、われわれは達人たちは間違っている、彼らの方法は役に立たない、書物は金のためだけに書かれている、黄金分割など存在しない、などと声高に言い始めるのです。これが、極値を見るとき、それがミニマックスの同義語ではないが、これがほんとうに最大値または最小値で、まだ到達する必要があるのはその内部の本質を示すことであるのを忘れた結果です。この浅はかな見解に基づいて、まさに現時点でこの場所にあるこのポイントを何が作ったか分析しようとせず、将来を予測しようとするのです。

お金を稼ぎたいのはやまやまですが、ときどき立ち止まり少し考えたって打ちのめされることはないのです。 これは知っておいて損はありません。『人間は異なる結果を期待して同じことを繰り返す唯一の生き物である』という言葉が正しいことにはっきりと気づき始めるのです。われわれは木を切っているのではありませんよね?:)

私も熱意によって夢中になっています。たぶん、それは私のことでもあるからです。角を落とす番です。達人がすべて教祖であるとは限らない、スプーンで食べさせられるものはおいしくなければ役にも立たないことを特別に知っている人ほどすべてを語らない人達だ、ということを理解しておきます。

テーマに戻ります。

マルチフレーム フラクタル ZigZag


私は最小値と最大値を表示するだけでなく、
価格変動によって理論的に推論される(LREP-この短縮形はたぶん帰化される?)、可能であれば確認されている市場の極値点インディケータを必要としていました。それをトレードシグナル ジェネレータにする問題は最初に述べられませんでした。まず、標準的な(MT4 に組み込まれている物ではなく、一般的な意味で『標準的な』)ZigZag でプレーしようとしましたが、以下のように何か警戒させ、この考えを放棄することを余儀なくするものがありました。

私は個人的に、最後の項目はもっとも受け入れられまs年。私には興味が感じられないものです。個人的なことは何もありません。

私は、でマークのポイントと、ウィリアムの『フラクタル』を記憶しています(どちらがどちらから借用したか知りませんが、それらは酷似しています)。『ひとつ』のようでした。少なくとも前回のそして続く値動きで推論されたものです。おそらく、これらポイントを選択するのに、だれもがこの種の方法を好むとは限りません。ですが、最初の特定に対して、『貴重な極値』、『極大』などの言葉以外にそれ以上に正確で適切なものを考え出した人はまだ一人もいないのです。

独自のことがらはよりよいものではないでしょうが、確かにさらに同系であります。借用コードを探し、自分独自の簡単なフラクタルインディケータ、より正確には、類似インディケータを書かなかったのはそのためです。ポイント選択のルールは標準的なものとわずかに異なります。私は iCustom によってそれを違うタイムフレームで呼び出そうとしました。しかしその後、現行(ワーキング)タイムフレーム(TF)ですべてを計算する方が合理的であろうということが判ったのです。それより先、プログラムロジックがすべてをそれ自体で促しました:将来それ自体を提案するモジュール構築に関して、サブスタンダード TF に関して。以下は取得されたものの
結果です。

画像はパラメータ 1440、360、60 での表示となっています。H1 チャートは、黒色の線(60)が全フラクタルポイントを取らず、そのうちのいくつかを拒否しているがわかるよう例証することに配慮して選択されています。1番目の画像は先端を表示するため、2番目の画像は単純にチャートの中央から採られています。

カラースキームは最良ではありません。添付の画像はそれについての私の見解を示しています。


コード


それがどのように実装されるか見ます。だんまり芝居で演技すべきではないですか?;)
インディケータは
現行ワーキングタイムフレーム(TF)で、3つのエミュレートされた大きな TF で計算された一連のZigZag ノードを形成します。それは、コードに実装された以下の制限を伴うサブスタンダードを含むすべてと全 TF で動作します。
-大きな TF はワーキング TF で分割可能である必要があります。そうでなければ、直近の正しい値が強制的に設定されます。
-ワーキング TF は直近の大きな TF より大きくならなりません。
-パラメータ期間は分で指定され、降順で設定する必要があります。
-最大 TF の期間は 43200(1か月) を超えません。これは限度ではありません。より大きな期間も可能です。
特徴は、各 TF にはバッファが一つだけ使用されることです。それを2つ使う必要はありません。。なぜなら、TF の合理的な組み合わせでは、ワーキング TF の単一バーにおける異なる2つの方向の極値が
表示 される確率が小さすぎるためです。

以下がこのフラグメントです。

//-----------------------------------------------------------------------
// MF_Fractal_ZZ_3in1.mq4
//-----------------------------------------------------------------------
#property copyright "Copyright © 2008, BiViSi Corp."
#property link      "riderfin@bk.ru"
#property link      "ICQ 499949112"

#property indicator_chart_window    
#property indicator_buffers 3
//---- style of the indicator line
#property indicator_color1 Blue 
#property indicator_color2 Red
#property indicator_color3 Yellow        
#property indicator_style1 0
#property indicator_style2 0
#property indicator_style3 0
#property indicator_width1 5
#property indicator_width2 3
#property indicator_width3 1
//---- INOUT PARAMETERS OF THE INDICATOR
extern int VolExt=50; // VolExt+1" calculation of the last control points
extern int TFLarge=1440;
extern int TFMidle=240;
extern int TFSmall=60;
//---- Variables 
double Large[],Midle[],Small[];  // control points (indicator bufers)
datetime PrevTimePer[4];         // the time of the last calculation of every TF
datetime PrevTimeCalc=0; 
double P60,CP60;
int CurPeriod, ErrorTF=0, NumberExt, Per,  largelast=0, midlelast=0, smalllast=0;
//-----------------------------------------------------------------------
int init() 
{
   // initialization
   IndicatorBuffers(3); // for perspective" entry :)
   SetIndexBuffer(0,Large); SetIndexStyle(0,DRAW_SECTION);
   SetIndexEmptyValue(0,0.0);
   SetIndexBuffer(1,Midle); SetIndexStyle(1,DRAW_SECTION);
   SetIndexEmptyValue(1,0.0); 
   SetIndexBuffer(2,Small); SetIndexStyle(2,DRAW_SECTION);
   SetIndexEmptyValue(2,0.0);
   ArrayInitialize(PrevTimePer,0);
   CurPeriod=Period(); CP60=CurPeriod*60;
   // restrictions:
   // control of TF and inputted parameters
   if (MathCeil(TFSmall/CurPeriod) != TFSmall/CurPeriod) 
      TFSmall=MathCeil(TFSmall/CurPeriod)*CurPeriod;
   if (MathCeil(TFMidle/CurPeriod) != TFMidle/CurPeriod)
      TFMidle=MathCeil(TFMidle/CurPeriod)*CurPeriod;
   if (MathCeil(TFLarge/CurPeriod) != TFLarge/CurPeriod)
       TFLarge=MathCeil(TFLarge/CurPeriod)*CurPeriod;
   if (CurPeriod > TFSmall) 
      {Alert ("The chart period must be less than or equal to ", TFSmall," min.");
       ErrorTF=1;return;}
   if (TFSmall >= TFMidle || TFMidle >= TFLarge || TFLarge>43200)
      {Alert ("Incorrect choice of timeframes for calulation!!!"); ErrorTF=1;return;}
   return;              
}
//--------------------------------------------------------------------

次のブロックは制御ポイント検索、ZigZag ノード計算、それらをインディケータのバッファ配列に書き込むものです。
int IC=IndicatorCounted(); タイプの構造を使用することの拒否などは、それ(コードの Force #1-3 を参照)なしで十分なスピードを提供するアルゴリズム自体の計算で決まります。それはまた増やすことが可能で、
それについては少し早くなります。

//--------------------------------------------------------------------
int start()
{
   if ( ErrorTF==1 ) return; // incorrect timeframe
   FractalCalc(); 
   return;
}
//======================================================================
// Searching of the 5 bar fractals and zigzag nodes claculation
// on the emulation of the larger TF, deleting of the odd ones and representation on the current TF
//======================================================================
void FractalCalc ()
{   
   // Force  №1 - caculation only on the fully formed bar of the working TF
   if (PrevTimeCalc == Time[0]) return; else PrevTimeCalc=Time[0];
   int y, x, k, i, j, extr=0; 
   // the time of the last bar of the current TF, that closes bar №1-5 of the larger TF
   int t1, t2, t3, t4, t5;                     
   // the number of the last bar of the cur. TF, that closes bar №1-5 of the larger TF
   int limit1, limit2, limit3, limit4, limit5; 
   // the numver of bars of the cur. TF with the peaks and bases that correspond with the bars 1-5 of the larger TF
   int up1,up2,up3,up4,up5,dn1,dn2,dn3,dn4,dn5;
      
   for (y=1; y<=3; y++) // cycle of the calculated TF
      {
      if (y==1) Per=TFLarge; if (y==2) Per=TFMidle; if (y==3) Per=TFSmall;
      P60=Per*60;
      // Force №2 - calculate the fissures only with the forming of the bar of the larger TF
      if (PrevTimePer[y] !=0)
         { 
         if (Per<43200 && (Time[0] - PrevTimePer[y])<P60 )continue;
         if (Per==43200 && Month()==TimeMonth(PrevTimePer[y]))continue;
         }
      // Processing of bars absence
      // If linearly PrevTimePer[y]=Time[0], then in case of bar absence
      // the shift of whole calculation chain by the absence size will take place on the working TF
      PrevTimePer[y]=MathCeil(Time[0]/Per/60)*P60; 
      
      NumberExt=0;  extr=0;
      k=Per/CurPeriod;
      // limitation of cycle depending on currently calculated TF
      // and on the last fractal
      i=MathCeil(Bars/k)-5;
      // Force #3 - calculation starting with the last fissure
      if(y==1 && largelast !=0) i=largelast+k;
      if(y==2 && midlelast !=0) i=midlelast+k;
      if(y==3 && smalllast !=0) i=smalllast+k;
      for (x=1; x<=i; x++) 
         {
         // find peaks and bases
         // the time of the beginning of the las bar of the cur. TF, that closes bar №1 of the larger TF
         if (PrevTimePer[y] !=0) t1=PrevTimePer[y]-x*P60+(k-1)*CP60;
         else t1=MathCeil(Time[0]/Per/60)*P60-x*P60+(k-1)*CP60;
         t2=t1-P60; t3=t2-P60; t4=t3-P60; t5=t4-P60;
         limit1=iBarShift(NULL,0,t1, false); limit2=iBarShift(NULL,0,t2, false);
         limit3=iBarShift(NULL,0,t3, false); limit4=iBarShift(NULL,0,t4, false);
         limit5=iBarShift(NULL,0,t5, false);         
         up1=iHighest(NULL,0,MODE_HIGH,k,limit1); up2=iHighest(NULL,0,MODE_HIGH,k,limit2);
         up3=iHighest(NULL,0,MODE_HIGH,k,limit3); up4=iHighest(NULL,0,MODE_HIGH,k,limit4);
         up5=iHighest(NULL,0,MODE_HIGH,k,limit5);
         dn1=iLowest(NULL,0,MODE_LOW,k,limit1); dn2=iLowest(NULL,0,MODE_LOW,k,limit2);
         dn3=iLowest(NULL,0,MODE_LOW,k,limit3); dn4=iLowest(NULL,0,MODE_LOW,k,limit4);
         dn5=iLowest(NULL,0,MODE_LOW,k,limit5);

         // searching for control points
         if(High[up3]>High[up2] && High[up3]>High[up1] && High[up3]>=High[up4] && High[up3]>=High[up5])
            {
            if (y==1){Large[up3]=High[up3];largelast=up3;}
            if (y==2){Midle[up3]=High[up3];midlelast=up3;}
            if (y==3){Small[up3]=High[up3];smalllast=up3;}
            NumberExt++;  extr++;
            }
         if(Low[dn3]<Low[dn2] && Low[dn3]<Low[dn1] && Low[dn3]<=Low[dn4] && Low[dn3]<=Low[dn5])
            {
            if (y==1){Large[dn3]=Low[dn3];largelast=dn3;}
            if (y==2){Midle[dn3]=Low[dn3];midlelast=dn3;}
            if (y==3){Small[dn3]=Low[dn3];smalllast=dn3;}
            NumberExt++; extr++;
            }
         if (NumberExt>VolExt) break;   
         } 
      }

ごらんのように、コードのほとんどは計算の最適化と予想外の状況-サーバー接続が失われたり、履歴バーの喪失、に対する保護を目的としています。

次のブロックは、ある種の『草刈り』を行います。正しい ZigZag を形成するために異常な極値(2つの頂点の間に複数の底が現れる、またその逆)の削除を行うのです。最大/最小は、連続して来る2つ以上の頂点/底から選択され、等しい場合、直近の番号を持つものが選択されます。異常なものはゼロに設定されます。アルゴリズムは議論の余地を残しています。そしてもちろん、代替が可能ですが、私は現時点でそうしようと決めました。
コードには、異なる TF で頂点/底の出現を排除するコメント付エントリがありますが、もうひと手間が必要です。今の形では正常に動作しません。この考えは一時的に保留にしますが、関心があればご自分でやってみてください。
以前に計算されたシフト
のコンストラクション if (NumberExt>VolExt) break; が使用されれば、同様のフラグメントがその動作速度を上げる別の可能性を持ちますが、今はこれも保留としています。
そして、スピードについて話し始めると、もっとも明解で簡単な方法はインディケータのインプットで VolExt を減らすことです。分析に対してではなく、取引については 10~15 以上を必要とする人はほとんどいません。本物の大食家を除いては :)。

   if (extr==0) return;
   for (y=1; y<=3; y++)
      {
      if (y==1) j=ArraySize(Large);if (y==2)j=ArraySize(Midle);
      if (y==3)j=ArraySize(Small);      
      int min=0, max=0, extmin=0, extmax=0;
      NumberExt=0;      
      for (x=1;x<=j;x++)
         {
         if (y==1)
            {
            if (Large[x] == 0.0 ) continue;
            if (Large[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Large[max]>=Large[x])Large[x]=0.0;
                  else {Large[max]=0.0;max=x;}
                  extmax--;  
                  }
               else max=x;
               }
            if (Large[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Large[min]<=Large[x])Large[x]=0.0;
                  else {Large[min]=0.0;min=x;}
                  extmin--;  
                  }
               else min=x;
               }
            }         
         if (y==2)
            {
            if (Midle[x] == 0.0 ) continue;
            if (Midle[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Midle[max]>=Midle[x])Midle[x]=0.0;
                  else {Midle[max]=0.0;max=x;}
                  extmax--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Midle[max]>Midle[x])Midle[x]=0.0; 
                  if (Midle[max]==Midle[x])
                     {
                     if (Large[x] == High[x]) {Midle[max]=0.0;max=x;}
                     else Midle[x]=0.0; 
                     }
                  if (Midle[max]<Midle[x]){Midle[max]=0.0;max=x;}
                  */
                  }
               else max=x;
               }
            if (Midle[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Midle[min]<=Midle[x])Midle[x]=0.0;
                  else {Midle[min]=0.0;min=x;}
                  extmin--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Midle[min]<Midle[x])Midle[x]=0.0; 
                  if (Midle[min]==Midle[x])
                     {
                     if (Large[x] == Low[x]) {Midle[min]=0.0;min=x;}
                     else Midle[x]=0.0; 
                     }
                  if (Midle[min]>Midle[x]){Midle[min]=0.0;min=x;}
                  */
                  }
               else min=x;
               }
            }         
         if (y==3)
            {
            if (Small[x] == 0.0 ) continue;
            if (Small[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Small[max]>=Small[x])Small[x]=0.0;
                  else {Small[max]=0.0;max=x;}
                  extmax--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Small[max]>Small[x])Small[x]=0.0; 
                  if (Small[max]==Small[x])
                     {
                     if (Midle[x] == High[x]) {Small[max]=0.0;max=x;}
                     else Small[x]=0.0; 
                     }
                  if (Small[max]<Small[x]){Small[max]=0.0;max=x;}
                  */
                  }
               else max=x;
               }
            if (Small[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Small[min]<=Small[x])Small[x]=0.0;
                  else {Small[min]=0.0;min=x;}
                  extmin--;  
                  // it can be easier as the above one, but.... remove diagreements
                  /*
                  if (Small[min]<Small[x])Small[x]=0.0; 
                  if (Small[min]==Small[x])
                     {
                     if (Midle[x] == Low[x]) {Small[min]=0.0;min=x;}
                     else Small[x]=0.0; 
                     }
                  if (Small[min]>Small[x]){Small[min]=0.0;max=x;}
                  */
                  }
               else min=x;
               }
            }         
         if (NumberExt>VolExt) break;
         }
      }         

}


おわりに


結果として、たぶん明白なアルゴリズムを持つインディケータを取得しましたが、これまで誰も使用したことがないものです。これは標準的な ZigZag のデメリットから産み出され、以下のメリットを持つものです。

同時にこの修正を私自身がおこなわない理由を聞きたいことでしょう。私にとっては現時点で取得しているもので十分だからです。「現時点では」十分なのです。:)
完成した効率的なコードは無限に手を加えることができることは解っています。それは鉛筆を削るようなものです。それで何かを書きたかったことを忘れる可能性があります。私は書き始めたいと思います。すごくそう思います。:)

次にくるものは何でしょうか?それで何をすべきでしょうか?準備されているソリューションはありません。これはただの道具です。それを使って何をするのか、ピノキオを作るのか椅子を作るのか。それぞれのゼペットおじさんが自分で決めることです。
私が言えることは、乾燥した残留物にはフリーのインディケータバッファが5つ、簡単にいくつか新しいモジュールを追加する可能性、iCustom() による呼び出しに対するひじょうに適切な応答がある、ということだけです。想像してください。

残り、一番気持ちの良いことは以下に対する謝辞です:

ANG3110 -もっとも価値あることに対して-本稿を書くよう促してくれた考え方です
Korey
- ТimeCurrent の診断と最適化計算における彼のサポートと手助けに対して
委員の皆さん
は、否応なしに、意識的かどうか、私が考えたいと思う考えをときどき表現してくださいます。