皆さん、ミーでございます。
自作サインツールの作り方をサンプルプログラムを含めて配信しておりますが、今回は、ボリンジャーバンドにタッチしたらサインを出す、そんなサインツールを皆様と一緒に作成してみようと思います。
サインツールの作成が初めてという方は、以下の記事を読んでから見ていただけると更に分かり易いです。
目次
ボリンジャーバンドとは
ボリンジャーバンド(Bollinger bands)とは、アメリカの投資家ジョン・ボリンジャーが考案したテクニカルチャートのひとつで、移動平均線とその上下2本ずつの標準偏差からなる線で構成された、良く使われているインジケーターですね。
ボリンジャーバンドは統計学を使って作られていて、大まかにいうと、高い確率で+2σ(標準偏差)と-2σのラインの間で価格は動くだろうという予測をもとに将来の価格の動きを予測するために使います。なお、統計学上、+2σと-2σの間に収まる確率は95.45%とされています。
良く、ボリンジャーバンドにタッチしたら逆張り・・・何てことを耳にしますが、そんな簡単に逆張りが成功したら、皆、億万長者になりますよね(笑)
ボリンジャーバンドはサインツールに組み込みやすいか?と言いますと、簡単に組み込めます。MQL4には、ボリンジャーバンドの値が取得できる標準関数が搭載されていますので、ボリンジャーバンドの関数を呼び出すだけで、値が取得できて、その値が特定の条件を満たせば、High/Lowエントリーみたいなことが、簡単に出来ます。
実はこんな簡単なロジックで、有料販売しているサインツールも多々ありますので、本当に有料のサインツールには気を付けてくださいね!
ボリンジャーバンドをサインツールに組み込む方法
ボリンジャーバンドをサインツールに組み込む方法ですが、【iBands】という関数を使用します。
【iBands】の関数をMQLのソースプログラムから呼び出すことで、ボリンジャーバンドの値を取得することができます。
iBandsの使い方
// iBandsの関数定義 double iBands( string symbol, // 通貨ペア int timeframe, // 時間軸 int period, // 平均期間 double deviation, // 標準偏差 int bands_shift, // バンドシフト int applied_price, // 適用価格 int mode, // ラインインデックス int shift // シフト );
使い方は、以下のような感じです。
double iResultBands_Upper = iBands(NULL,0,20,2.5,0,PRICE_CLOSE,MODE_UPPER,i);
double iResultBands_Lower = iBands(NULL,0,20,2.5,0,PRICE_CLOSE,MODE_LOWER,i);
iResultBands_Upper には、期間「20」、偏差「2.5」の上方向にあるボリンジャーバンドの値が設定されます。
iResultBands_Lower には、期間「20」、偏差「2.5」の下方向にあるボリンジャーバンドの値が設定されます。
iBandsのパラメーターである「period」「deviation」は、赤枠の期間を指定するものです。
ボリンジャーバンドを使用したサインツール
早速、ボリンジャーバンドを使用したサインツール(サンプル)のご紹介をします。
今回作成するのは、
1.ボリンジャーバンドの上限/下限にローソク足がタッチしたらサイン表示するもの
2.ボリンジャーバンドの上限/下限にローソク足の髭がタッチしたらサイン表示するもの
の2つになります。
ボリンジャーバンドの上限/下限にローソク足がタッチしたらサイン表示するもの
まずは、実際に動作するサンプルコードを記載しますので、XXX.mq4(XXXの名前は何でも良い)を作成し、コンパイルの実行をお願いします。
手順が分からない方は、
https://rpa-affiliate.com/2021/09/24/self-made-signtool-base/
の記事を参照してください。
#property indicator_chart_window #property indicator_buffers 2 extern int BandsPeriod = 20; extern double BandsDeviation = 2.5; double DrawReverseLowBuffer[]; double DrawReverseHighBuffer[]; int init() { SetIndexStyle(0,DRAW_ARROW,STYLE_SOLID,1,clrMagenta); SetIndexStyle(1,DRAW_ARROW,STYLE_SOLID,1,clrRed); SetIndexArrow(0,234); SetIndexArrow(1,233); SetIndexBuffer(0,DrawReverseLowBuffer); SetIndexBuffer(1,DrawReverseHighBuffer); return(INIT_SUCCEEDED); } int start() { int counted_bars=IndicatorCounted(); int limit = Bars - counted_bars; double iResultBands_Upper,iResultBands_Lower; for (int i=limit-1;i>=0;i--){ if(i == 0){ DrawReverseLowBuffer[i] = EMPTY_VALUE; DrawReverseHighBuffer[i] = EMPTY_VALUE; } iResultBands_Upper = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_UPPER,i); iResultBands_Lower = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_LOWER,i); if(iResultBands_Upper < High[i] && iResultBands_Upper > Low[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower < High[i] && iResultBands_Lower > Low[i]){ DrawReverseHighBuffer[i]=Low[i]; } } return(0); }
実行結果のイメージ
ボリンジャーバンドにタッチした部分でサインが出てますよね!
ただ、バンドウォークの場合には連続してサインが出る点も注意が必要ですね。ボリンジャーバンドにタッチした初回のみサインを出すようにするなど、より高勝率なサインツールを作成するには、いかにバンドウォークを避けるかがポイントになります。
良くバンドウォークを避けてエントリーしてください・・・というようなサインツールを見かけますが、実はバンドウォークを避けるのはサインツールにとって、結構難しい課題なんですよね。
サンプルコードの解説
それでは、サンプルコードで重要な部分の解説をしていきますね。
#property indicator_chart_window #property indicator_buffers 2 extern int BandsPeriod = 20; extern double BandsDeviation = 2.5;
#property indicator_chart_window は、チャートウィンドウにサインを出すことを明示します。
#property indicator_buffers 2 は、使用するインジケーターの数で、HighのサインとLowのサインの2つであることを意味します。
”BandsPeriod ”は期間、”BandsDeviation ”は偏差になります。iBansに渡す重要なパラメータになります。
また、先頭に”extern”が記載されておりますが、これを付けると、以下の画像のように、ユーザーがMT4から値を変えられるようになります。ユーザーの利便性が向上しますので、適切に使い分けを行いたいですよね。逆に、ユーザーに変更して欲しくない値には、”extern”は使用しません。
int init() { SetIndexStyle(0,DRAW_ARROW,STYLE_SOLID,1,clrMagenta); SetIndexStyle(1,DRAW_ARROW,STYLE_SOLID,1,clrRed); SetIndexArrow(0,234); SetIndexArrow(1,233); SetIndexBuffer(0,DrawReverseLowBuffer); SetIndexBuffer(1,DrawReverseHighBuffer); return(INIT_SUCCEEDED); }
上記は、MT4起動時や呼ばれる特殊な関数(init)です。その関数の中に、サイン表示に必要なサインの太さ、アイコンの種類、そして、表示するサインの配列を設定します。これは、こういうものだと覚えておく程度で構いません。
for (int i=limit-1;i>=0;i--){ if(i == 0){ DrawReverseLowBuffer[i] = EMPTY_VALUE; DrawReverseHighBuffer[i] = EMPTY_VALUE; } iResultBands_Upper = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_UPPER,i); iResultBands_Lower = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_LOWER,i); if(iResultBands_Upper < High[i] && iResultBands_Upper > Low[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower < High[i] && iResultBands_Lower > Low[i]){ DrawReverseHighBuffer[i]=Low[i]; } }
for文の中がロジックの処理となります。
ループ変数(i)の値が、limit-1から、0の間ループすることになり、初回は全てのローソク足、2回目以降は最新のローソク足が再計算されます。
次に、サイン表示配列に”EMPTY_VALUE”(空の値)を設定していますが、最新のローソク足はボリンジャーバンドの値が変動する可能性がありますので、一旦サイン表示なしに設定しています。
ボリンジャーバンドの上限、下限のラインに対して、ローソク足のHighとLowの間がタッチしていたらサインを出す処理となります。
ボリンジャーバンドの上限/下限にローソク足の髭がタッチしたらサイン表示するもの
次に、”ボリンジャーバンドの上限/下限にローソク足の髭がタッチしたらサイン表示するもの”について、サンプルコードを記載します。
ボリンジャーバンドのタッチ方法ですが、実態で判断したい場合もあれば、良く髭がタッチ!という条件で見たい場合もありますよね。このサンプルは、髭がタッチした場合にサインを出すものです。
#property indicator_chart_window #property indicator_buffers 2 extern int BandsPeriod = 20; extern double BandsDeviation = 2.5; double DrawReverseLowBuffer[]; double DrawReverseHighBuffer[]; int init() { SetIndexStyle(0,DRAW_ARROW,STYLE_SOLID,1,clrMagenta); SetIndexStyle(1,DRAW_ARROW,STYLE_SOLID,1,clrRed); SetIndexArrow(0,234); SetIndexArrow(1,233); SetIndexBuffer(0,DrawReverseLowBuffer); SetIndexBuffer(1,DrawReverseHighBuffer); return(INIT_SUCCEEDED); } int start() { int counted_bars=IndicatorCounted(); int limit = Bars - counted_bars; double iResultBands_Upper,iResultBands_Lower; for (int i=limit-1;i>=0;i--){ if(i == 0){ DrawReverseLowBuffer[i] = EMPTY_VALUE; DrawReverseHighBuffer[i] = EMPTY_VALUE; } iResultBands_Upper = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_UPPER,i); iResultBands_Lower = iBands(NULL,0,BandsPeriod,BandsDeviation,0,PRICE_CLOSE,MODE_LOWER,i); if(isSunshineLine(i)){ // 陽線の場合 if(iResultBands_Upper < High[i] && iResultBands_Upper > Close[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower > Low[i] && iResultBands_Lower < Open[i]){ DrawReverseHighBuffer[i]=Low[i]; } } else { // 陰線の場合 if(iResultBands_Upper < High[i] && iResultBands_Upper > Open[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower > Low[i] && iResultBands_Lower < Close[i]){ DrawReverseHighBuffer[i]=Low[i]; } } } return(0); } bool isSunshineLine(int index){ if(Close[index] > Open[index]){ return(true); } return(false); }
実行結果のイメージ
ボリンジャーバンドに髭がタッチしたらサインが出てますよね。サイン数は減りましたが、より、高勝率なポイントでサインが出ていると思います。
サンプルコードの解説
それでは、サンプルコードで重要な部分の解説をしていきますね。
”ボリンジャーバンドの上限/下限にローソク足がタッチしたらサイン表示するもの”のサインツールと重複する部分が多々ありますので、異なる部分のみ解説します。
if(isSunshineLine(i)){ // 陽線の場合 if(iResultBands_Upper < High[i] && iResultBands_Upper > Close[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower > Low[i] && iResultBands_Lower < Open[i]){ DrawReverseHighBuffer[i]=Low[i]; } } else { // 陰線の場合 if(iResultBands_Upper < High[i] && iResultBands_Upper > Open[i]){ DrawReverseLowBuffer[i]=High[i]; } if(iResultBands_Lower > Low[i] && iResultBands_Lower < Close[i]){ DrawReverseHighBuffer[i]=Low[i]; } }
判定ロジックが変わっていますね。今回は、陽線と陰線の判断が加わっています。また、High/Lowではなく、Open/Closeの要素も加味して判断するロジックになっています。
これは、陽線と陰線でOpen/Closeが変わるため、陽線と陰線を予め判断する必要があるためとなります。
コメントを残す