見出し画像

ローソク実体でZigZag 始値終値で描く方法 MT4

どうも、@ひろぽんです。今日は実体部分でZigZagを取得するコードを紹介します。無料です。


ZigZagとは?

チャートで使用するインジケータの一つで、高値と安値を交互に直線で繋いでくれます。高安、高安と上下するラインがジグザグなので、ZigZagと呼ばれています。

要するに直近の高値と安値が分かりやすくなるインジケータです。これによって高値と安値が切り上がってきているから上昇トレンドだみたいな見方が出来ます。

MT4をインストールすれば、初期状態から使えます。(ZigZag.mq4)

一見便利そうですが、ZigZagの問題点にリペイントと言うものがあるので要注意です。リペイントとは、チャートの変化に合わせてラインが描き直されることです。安値を形成して上昇、V字のラインを描くも再下落、前回安値を下回るとV字のラインが下落の直線に描き直されちゃう、なんてことがあります。

ただし、2個以上前のポイントはリペイントされないので、このポイントを元にトレンドラインを自動で引いてライントレードやプライスアクションを考える参考にしようってのが、私の作ったインジケータの内容です。(宣伝)


ZigZagを実体で取るとどうなる?

画像1

・赤線 : 高値安値でZigZag
・黄線 : 始値終値(実体)でZigZag

真ん中あたりに注目してほしいんですが、高値安値だとひょこっとヒゲだけ伸ばした変なローソク足も拾っちゃうんですよね。

そこまで大きな問題は無いんですが、トレンドの流れを把握したい時にこのような動きはノイズとなり邪魔です。

一方、実体で描いた黄色の線は傾きは緩やかですが、状況把握がしやすくなります。

どちらを使用するにしても好みなので、もし実体でZigZagを描きたい場合は以下のコードをコピペして使ってください。


注意事項

当サイトに含まれる情報の全ては、情報提供を唯一の目的としたものであり、収益の保証、或いは、直接的に投資助言業務、投資勧誘を行うものではありません。投資方針や時期選択等の最終決定は、リスク等を熟知した上、ご自身で判断されますようお願いいたします。
当サイトの利用、あるいは取引により利用者に生じたいかなる損害についても著者及び発行者はそれに対し、一切の責任を負いません。あらかじめご了承ください。
万が一、損失を被った場合でも、著者は一切の責任を負わないものとします。


実体を使ったZigZagのコード

MT4に既存のZigZagを使用し、一部変更しただけです。

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  Red
//---- indicator parameters
input int InpDepth=12;     // Depth
input int InpDeviation=5;  // Deviation
input int InpBackstep=3;   // Backstep
//---- indicator buffers
double ExtZigzagBuffer[];
double ExtHighBuffer[];
double ExtLowBuffer[];
//--- globals
int    ExtLevel=3; // recounting's depth of extremums
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
 {
  if(InpBackstep>=InpDepth)
    {
     Print("Backstep cannot be greater or equal to Depth");
     return(INIT_FAILED);
    }
//--- 2 additional buffers
  IndicatorBuffers(3);
//---- drawing settings
  SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers
  SetIndexBuffer(0,ExtZigzagBuffer);
  SetIndexBuffer(1,ExtHighBuffer);
  SetIndexBuffer(2,ExtLowBuffer);
  SetIndexEmptyValue(0,0.0);
//---- indicator short name
  IndicatorShortName("ZigZag("+string(InpDepth)+","+string(InpDeviation)+","+string(InpBackstep)+")");
//---- initialization done
  return(INIT_SUCCEEDED);
 }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
 {
  int    i,limit,counterZ,whatlookfor=0;
  int    back,pos,lasthighpos=0,lastlowpos=0;
  //double extremum;
  double extremum,exOPEN,exCLOSE,exLOW,exHIGH;
  double curlow=0.0,curhigh=0.0,lasthigh=0.0,lastlow=0.0;
//--- check for history and inputs
  if(rates_total<InpDepth || InpBackstep>=InpDepth)
     return(0);
//--- first calculations
  if(prev_calculated==0)
     limit=InitializeAll();
  else 
    {
     //--- find first extremum in the depth ExtLevel or 100 last bars
     i=counterZ=0;
     while(counterZ<ExtLevel && i<100)
       {
        if(ExtZigzagBuffer[i]!=0.0)
           counterZ++;
        i++;
       }
     //--- no extremum found - recounting all from begin
     if(counterZ==0)
        limit=InitializeAll();
     else
       {
        //--- set start position to found extremum position
        limit=i-1;
        //--- what kind of extremum?
        if(ExtLowBuffer[i]!=0.0) 
          {
           //--- low extremum
           curlow=ExtLowBuffer[i];
           //--- will look for the next high extremum
           whatlookfor=1;
          }
        else
          {
           //--- high extremum
           curhigh=ExtHighBuffer[i];
           //--- will look for the next low extremum
           whatlookfor=-1;
          }
        //--- clear the rest data
        for(i=limit-1; i>=0; i--)  
          {
           ExtZigzagBuffer[i]=0.0;  
           ExtLowBuffer[i]=0.0;
           ExtHighBuffer[i]=0.0;
          }
       }
    }
//--- main loop      
  for(i=limit; i>=0; i--)
    {
     //--- find lowest low in depth of bars
     //extremum=low[iLowest(NULL,0,MODE_LOW,InpDepth,i)];
     exOPEN = open[iLowest(NULL,0,MODE_OPEN,InpDepth,i)];
     exCLOSE = close[iLowest(NULL,0,MODE_CLOSE,InpDepth,i)];
     extremum = exOPEN<exCLOSE ? exOPEN : exCLOSE;
     exLOW = open[i]<close[i] ? open[i] : close[i];
     //--- this lowest has been found previously
     if(extremum==lastlow)
        extremum=0.0;
     else 
       { 
        //--- new last low
        lastlow=extremum; 
        //--- discard extremum if current low is too high
        //if(low[i]-extremum>InpDeviation*Point)
        if(exLOW-extremum>InpDeviation*Point)
           extremum=0.0;
        else
          {
           //--- clear previous extremums in backstep bars
           for(back=1; back<=InpBackstep; back++)
             {
              pos=i+back;
              if(ExtLowBuffer[pos]!=0 && ExtLowBuffer[pos]>extremum)
                 ExtLowBuffer[pos]=0.0; 
             }
          }
       } 
     //--- found extremum is current low
     //if(low[i]==extremum)
     if(exLOW==extremum)
        ExtLowBuffer[i]=extremum;
     else
        ExtLowBuffer[i]=0.0;
     //--- find highest high in depth of bars
     //extremum=high[iHighest(NULL,0,MODE_HIGH,InpDepth,i)];
     exOPEN = open[iHighest(NULL,0,MODE_OPEN,InpDepth,i)];
     exCLOSE = close[iHighest(NULL,0,MODE_CLOSE,InpDepth,i)];
     extremum = exOPEN>exCLOSE ? exOPEN : exCLOSE;
     exHIGH = open[i]>close[i] ? open[i] : close[i];
     //--- this highest has been found previously
     if(extremum==lasthigh)
        extremum=0.0;
     else 
       {
        //--- new last high
        lasthigh=extremum;
        //--- discard extremum if current high is too low
        //if(extremum-high[i]>InpDeviation*Point)
        if(extremum-exHIGH>InpDeviation*Point)
           extremum=0.0;
        else
          {
           //--- clear previous extremums in backstep bars
           for(back=1; back<=InpBackstep; back++)
             {
              pos=i+back;
              if(ExtHighBuffer[pos]!=0 && ExtHighBuffer[pos]<extremum)
                 ExtHighBuffer[pos]=0.0; 
             } 
          }
       }
     //--- found extremum is current high
     //if(high[i]==extremum)
     if(exHIGH==extremum)
        ExtHighBuffer[i]=extremum;
     else
        ExtHighBuffer[i]=0.0;
    }
//--- final cutting 
  if(whatlookfor==0)
    {
     lastlow=0.0;
     lasthigh=0.0;  
    }
  else
    {
     lastlow=curlow;
     lasthigh=curhigh;
    }
  for(i=limit; i>=0; i--)
    {
     switch(whatlookfor)
       {
        case 0: // look for peak or lawn 
           if(lastlow==0.0 && lasthigh==0.0)
             {
              if(ExtHighBuffer[i]!=0.0)
                {
                 //lasthigh=High[i];
                 lasthigh=Open[i]>Close[i] ? Open[i] : Close[i];
                 lasthighpos=i;
                 whatlookfor=-1;
                 ExtZigzagBuffer[i]=lasthigh;
                }
              if(ExtLowBuffer[i]!=0.0)
                {
                 //lastlow=Low[i];
                 lasthigh=Open[i]<Close[i] ? Open[i] : Close[i];
                 lastlowpos=i;
                 whatlookfor=1;
                 ExtZigzagBuffer[i]=lastlow;
                }
             }
            break;  
        case 1: // look for peak
           if(ExtLowBuffer[i]!=0.0 && ExtLowBuffer[i]<lastlow && ExtHighBuffer[i]==0.0)
             {
              ExtZigzagBuffer[lastlowpos]=0.0;
              lastlowpos=i;
              lastlow=ExtLowBuffer[i];
              ExtZigzagBuffer[i]=lastlow;
             }
           if(ExtHighBuffer[i]!=0.0 && ExtLowBuffer[i]==0.0)
             {
              lasthigh=ExtHighBuffer[i];
              lasthighpos=i;
              ExtZigzagBuffer[i]=lasthigh;
              whatlookfor=-1;
             }   
           break;               
        case -1: // look for lawn
           if(ExtHighBuffer[i]!=0.0 && ExtHighBuffer[i]>lasthigh && ExtLowBuffer[i]==0.0)
             {
              ExtZigzagBuffer[lasthighpos]=0.0;
              lasthighpos=i;
              lasthigh=ExtHighBuffer[i];
              ExtZigzagBuffer[i]=lasthigh;
             }
           if(ExtLowBuffer[i]!=0.0 && ExtHighBuffer[i]==0.0)
             {
              lastlow=ExtLowBuffer[i];
              lastlowpos=i;
              ExtZigzagBuffer[i]=lastlow;
              whatlookfor=1;
             }   
           break;               
       }
    }
//--- done
  return(rates_total);
 }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int InitializeAll()
 {
  ArrayInitialize(ExtZigzagBuffer,0.0);
  ArrayInitialize(ExtHighBuffer,0.0);
  ArrayInitialize(ExtLowBuffer,0.0);
//--- first counting position
  return(Bars-InpDepth);
 }
//+------------------------------------------------------------------+


詳しい説明は省きますが、ローソク足が確定した時、上のヒゲはHighで下のヒゲはLowです。しかし、実体部分の下縁と上縁は、陽線か陰線かによってOpenかCloseか異なります。

これを一か所一か所、三項定理で書き変えただけです。

     exOPEN = open[iHighest(NULL,0,MODE_OPEN,InpDepth,i)];
     exCLOSE = close[iHighest(NULL,0,MODE_CLOSE,InpDepth,i)];
     extremum = exOPEN>exCLOSE ? exOPEN : exCLOSE;

こんな感じで。


ZigZagで取得した高値安値をつないでトレンドラインを描くインジケータも作成しました。高値安値でも実体部分でもトレンドラインを引けるような仕様にしてます。詳しくはこちら>>

ここまで読んでいただき、ありがとうございます。

不具合等があれば、コメントもしくは@ひろぽんにDMしてください。
よろしくお願いします。

この記事が気に入ったらサポートをしてみませんか?