ロジック紹介
MT4に標準搭載されているZigZagインジケーターの頂点と底辺に矢印を表示するインジケーターになります。
以下の動画は通常のZigZagで、ご存知の方も多いと思いますがリペイント(再描画)します。
この動画をご覧いただくと高安値が更新されると最新のラインが引き直される(リペイント)のが分かると思います。
なので、今回のインジは直近に引かれたライン端には矢印は表示させないようにします。
※1つ目の頂点・底辺もリペイントする事はありますが、今回のインジでは対応しませんのでご了承下さい。
作成動画
実際にこのインジケーターを作成動画をYouTubeでもアップしていますので是非ご覧下さい。
以下の記事では動画では書いていない細かい説明も記述していますので、動画でもまだ理解が難しい場合は合わせて読んでみて下さい。
パラメーター
パラメーターは日本語にしていますが、シンプルにZigZagインジケーターと同じです。
【ZigZagの深さ:Depth】初期値:12
【転換率:Deviation】初期値:5
【反転までの判断期間:Backstep】初期値:3
ソースコード
全体コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
//+------------------------------------------------------------------+ //| Zn_ZigZag_Apex_Arrow.mq4 | //| Copyright 2021, Zyuna32246 | //| https://zyunafx.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, Zyuna32246" #property link "https://zyunafx.com/" #property version "1.00" #property strict #property indicator_chart_window #property indicator_buffers 2 //表示用インジケーターバッファ #property indicator_color1 clrSkyBlue //上矢印色 #property indicator_width1 2 //矢印線幅 #property indicator_color2 clrRed //下矢印色 #property indicator_width2 2 //矢印線幅 //インジケーター設定 input int Depth=12; //ZigZagの深さ input int Deviation=5; //転換率 input int Backstep=3; //反転までの判断期間 //バッファ double up[]; //上矢印用のバッファ double dn[]; //下矢印用のバッファ //+------------------------------------------------------------------+ int OnInit() { IndicatorBuffers(2); //インジケーター用配列個数 SetIndexBuffer(0,up); //配列up[]をインジ用に割り当て SetIndexStyle(0,DRAW_ARROW); //描画タイプをアローと定義 SetIndexArrow(0,233); //上矢印 SetIndexBuffer(1,dn); //配列dn[]をインジ用に割り当て SetIndexStyle(1,DRAW_ARROW); //描画タイプをアローと定義 SetIndexArrow(1,234); //下矢印 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 limit=rates_total-prev_calculated; //計算済バー数がない場合(初期動作) if(prev_calculated==0){ limit--; //バー総数から1を引く int count=0; //最初のZigZag検出用のカウントを0にする //現在バーから過去に向かってZigZag値を検索する for(int i=0;i<=limit;i++){ //ZigZagの頂点・底辺の場合は価格を取得し、それ以外は0が入る。 double Zg=NormalizeDouble(iCustom(_Symbol,0,"ZigZag",Depth,Deviation,Backstep,0,i),5); if(Zg!=0.0 && count==0){ //価格が入っていて、カウントが0(ラインの端)の場合 count++; //カウントに1を足す }else if(Zg==NormalizeDouble(High[i],5)){ //価格が高値と同じであるならば dn[i]=High[i]+15*Point(); //配列dnに高値+15ポイントを代入 }else if(Zg==NormalizeDouble(Low[i],5)){ //価格が安値と同じであるならば up[i]=Low[i]-15*Point(); //配列upに安値-15ポイントを代入 } } //計算済バー数が0でない場合(初期以降の処理) }else{ int t=0; //バー数用の変数 int count=0; //最初のZigZag検出用のカウントを0にする //最初の頂点・底辺を飛ばして2つ目までの本数をtにカウントしてバッファに値を代入 //tが100より小さいという条件から外れるまで中の処理を繰り返す while(t<100){ //ZigZagの頂点・底辺の場合は価格を取得し、それ以外は0が入る。 double Zg=NormalizeDouble(iCustom(_Symbol,0,"ZigZag",Depth,Deviation,Backstep,0,t),5); if(Zg!=0.0 && count==0){ //価格が入っていて、カウントが0(ラインの端)の場合 count++; //カウントに1を足す }else if(Zg==NormalizeDouble(High[t],5)){ //価格が高値と同じであるならば dn[t]=High[t]+15*Point(); //配列dnに高値+15ポイントを代入 break; //頂点を見つけたらwhile文を抜ける }else if(Zg==NormalizeDouble(Low[t],5)){ //価格が安値と同じであるならば up[t]=Low[t]-15*Point(); //配列upに安値-15ポイントを代入 break; //底辺を見つけたらwhile文を抜ける } t++; //tに1を足す } } return(rates_total); } //+------------------------------------------------------------------+ |
チャート挿入時の初期動作(prev_calculated==0)
チャートにインジケーターを適用した時に、過去に向かって処理するコードと、ティック更新される毎に処理するコードの2つ記載しています。
理由は処理の負荷を軽減する為で、ティック更新される度に現在から過去までを毎回処理するよりは、先述の説明の通り2つに分けて更新時は最低限の範囲での処理で済ませた方が良いからです。
では、まず最初だけ処理するコードが以下の抜粋部分です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//計算済バー数がない場合(初期動作) if(prev_calculated==0){ limit--; //バー総数から1を引く int count=0; //最初のZigZag検出用のカウントを0にする //現在バーから過去に向かってZigZag値を検索する for(int i=0;i<=limit;i++){ //ZigZagの頂点・底辺の場合は価格を取得し、それ以外は0が入る。 double Zg=NormalizeDouble(iCustom(_Symbol,0,"ZigZag",Depth,Deviation,Backstep,0,i),5); if(Zg!=0.0 && count==0){ //価格が入っていて、カウントが0(ラインの端)の場合 count++; //カウントに1を足す }else if(Zg==NormalizeDouble(High[i],5)){ //価格が高値と同じであるならば dn[i]=High[i]+15*Point(); //配列dnに高値+15ポイントを代入 }else if(Zg==NormalizeDouble(Low[i],5)){ //価格が安値と同じであるならば up[i]=Low[i]-15*Point(); //配列upに安値-15ポイントを代入 } } } |
チャートに適用された時に現在から過去に向かって頂点と底辺を探して行き、下矢印(dn配列)と上矢印(up配列)に値が入る事でその箇所に矢印が表示されます。
初期動作以降の動作
次にティック更新時の処理は以下の抜粋部分です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//計算済バー数が0でない場合(初期以降の処理) }else{ int t=0; //バー数用の変数 int count=0; //最初のZigZag検出用のカウントを0にする //最初の頂点・底辺を飛ばして2つ目までの本数をtにカウントしてバッファに値を代入 //tが100より小さいという条件から外れるまで中の処理を繰り返す while(t<100){ //ZigZagの頂点・底辺の場合は価格を取得し、それ以外は0が入る。 double Zg=NormalizeDouble(iCustom(_Symbol,0,"ZigZag",Depth,Deviation,Backstep,0,t),5); if(Zg!=0.0 && count==0){ //価格が入っていて、カウントが0(ラインの端)の場合 count++; //カウントに1を足す }else if(Zg==NormalizeDouble(High[t],5)){ //価格が高値と同じであるならば dn[t]=High[t]+15*Point(); //配列dnに高値+15ポイントを代入 break; //頂点を見つけたらwhile文を抜ける }else if(Zg==NormalizeDouble(Low[t],5)){ //価格が安値と同じであるならば up[t]=Low[t]-15*Point(); //配列upに安値-15ポイントを代入 break; //底辺を見つけたらwhile文を抜ける } t++; //tに1を足す } } |
こちらの処理は一言で言うと、1つ目の頂点・底辺を探して価格を矢印配列(up[],dn[])に代入する処理になります。
現在バー(0)から過去に向かって1つ目の価格が見つかって代入されれば処理終了です。
まとめ
ZigZagを表示すれば頂点と底辺はすぐに分かるので、このインジケーターは必要ないかもしれませんが、こうすれば頂点と底辺の値が取得出来る。という所で参考になればと思い作成しました。
これを応用すればZigZagでトレンドラインを引く事や、価格の切上げ切り下げなど沢山の事が可能になります。
以上、皆さんのご参考になれば( ・Д・)
コメント