MT4ボリンジャーバンドのバンド幅を常時チャート上に表示する自作インジケーター

※本ページはプロモーションが含まれています

色んなトレードノウハウを調べては、自作のEAを作っているのですが、ボリンジャーバンドの幅(特に−2σ〜+2σ)をチェックするトレードノウハウが多い。

常にボリンジャーのバンド幅をチャート上に表示していた方が便利なので、今現在の幅がどのくらいなのかを確認できる簡単なインジケーターを作ってみました。

目次

実行結果

チャートの左上に、常に表示します。ポイント表示だけでなく、pips表示も入れました。

インジケーターダウンロード

一応、ソースを公開して解説していますが、不要な方もいると思うので。

こちらからダウンロードしてください。

MQL4ソースコード

たいしたコードではないので公開。

//+------------------------------------------------------------------+
//|                                       bb_bands_length_output.mq4 |
//|                                         Copyright 2020, Yanoteck |
//|                                   https://investment-vmoney.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Yanoteck"
#property link      "https://investment-vmoney.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window

#include <MovingAverages.mqh>

#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 SlateGray
#property indicator_color3 SlateGray
#property indicator_color4 SlateGray

//--- indicator parameters
input int    InpBandsPeriod=20;      // 期間
input int    InpBandsShift=0;        // 表示移動
input double InpBandsDeviations=2.0; // 偏差2
input double InpBandsDeviations3=3.0; // 偏差3
input double InpBandsDeviations1=1.0; // 偏差1
extern int   On_BandsDeviations1=1; //偏差1の表示 On[1]/Off[0]

//--- buffers
double ExtMovingBuffer[];
double ExtUpperBuffer[];
double ExtLowerBuffer[];
double ExtStdDevBuffer[];

double ExtUpper1Buffer[];
double ExtLower1Buffer[];
double ExtUpper3Buffer[];
double ExtLower3Buffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

//--- 1 additional buffer used for counting.
   IndicatorBuffers(8);
   IndicatorDigits(Digits);

//--- middle line
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMovingBuffer);
   SetIndexShift(0,InpBandsShift);
   SetIndexLabel(0,"Bands SMA");
//--- upper band
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,ExtUpperBuffer);
   SetIndexShift(1,InpBandsShift);
   SetIndexLabel(1,"Band2 Upper");
//--- lower band
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,ExtLowerBuffer);
   SetIndexShift(2,InpBandsShift);
   SetIndexLabel(2,"Band2 Lower");

//--- upper3 band
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,ExtUpper3Buffer);
   SetIndexShift(3,InpBandsShift);
   SetIndexLabel(3,"Band3 Upper");
//--- lower3 band
   SetIndexStyle(4,DRAW_LINE);
   SetIndexBuffer(4,ExtLower3Buffer);
   SetIndexShift(4,InpBandsShift);
   SetIndexLabel(4,"Band3 Lower");

//--- upper1 band
   SetIndexStyle(5,DRAW_LINE);
   SetIndexBuffer(5,ExtUpper1Buffer);
   SetIndexShift(5,InpBandsShift);
   SetIndexLabel(5,"Band1 Upper");
//--- lower1 band
   SetIndexStyle(6,DRAW_LINE);
   SetIndexBuffer(6,ExtLower1Buffer);
   SetIndexShift(6,InpBandsShift);
   SetIndexLabel(6,"Band1 Lower");
   
//--- work buffer
   SetIndexBuffer(7,ExtStdDevBuffer);
//--- check for input parameter
   if(InpBandsPeriod<=0)
     {
      Print("Wrong input parameter Bands Period=",InpBandsPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpBandsPeriod+InpBandsShift);
   SetIndexDrawBegin(1,InpBandsPeriod+InpBandsShift);
   SetIndexDrawBegin(2,InpBandsPeriod+InpBandsShift);
   SetIndexDrawBegin(4,InpBandsPeriod+InpBandsShift);
   SetIndexDrawBegin(5,InpBandsPeriod+InpBandsShift);
   SetIndexDrawBegin(6,InpBandsPeriod+InpBandsShift);

//--- initialization done  
//---
   return(INIT_SUCCEEDED);
  }
  
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
     Comment("");

  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---

   //ボリンジャーバンド
   double bb_3;
   double bb_2;
   double bb_1;
   double bb_center;
   double bb_M1;
   double bb_M2;
   double bb_M3;

   //1バー前のボリンジャーバンド
   double bb_3_1;
   double bb_2_1;
   double bb_1_1;
   double bb_center_1;
   double bb_M1_1;
   double bb_M2_1;
   double bb_M3_1;

   //+2シグマ ー ー2シグマの間隔      
   double bb_2_M2;
   double bb_2_M2_digit;
   double bb_3_M2;
   double bb_3_M2_digit;
   
   //ボリンジャーバンドの値を取得
   bb_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,1,0,PRICE_CLOSE,1,0);
   bb_2 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,1,0);
   bb_3 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,3,0,PRICE_CLOSE,1,0);
   bb_center = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,0,0);
   bb_M1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,1,0,PRICE_CLOSE,2,0); 
   bb_M2 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,2,0); 
   bb_M3 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,3,0,PRICE_CLOSE,2,0);


   //1バー前のボリンジャーバンドの値を取得
   bb_1_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,1,0,PRICE_CLOSE,1,1);
   bb_2_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,1,1);
   bb_3_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,3,0,PRICE_CLOSE,1,1);
   bb_center_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,0,1);
   bb_M1_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,1,0,PRICE_CLOSE,2,1); 
   bb_M2_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,2,0,PRICE_CLOSE,2,1); 
   bb_M3_1 = iBands(NULL,PERIOD_CURRENT,InpBandsPeriod,3,0,PRICE_CLOSE,2,1);


   //ボリンジャーバンドの上下幅
   bb_2_M2 = NormalizeDouble(bb_2 - bb_M2,3);
   bb_2_M2_digit = NormalizeDouble(bb_2_M2 * 100,4);   
   bb_3_M2 = NormalizeDouble(bb_3 - bb_M3,3);
   bb_3_M2_digit = NormalizeDouble(bb_3_M2 * 100,4);
   
   //print
   Comment("\n\n[Bollinger bands info]\n\n" +
   "-2σ ~ +2σ = " + string(bb_2_M2) + " (" + string(bb_2_M2_digit) + "pips)" + "\n\n" +
   "-3σ ~ +3σ = " + string(bb_3_M2) + " (" + string(bb_3_M2_digit) + "pips)" + "\n\n");


   //Draw Bollinger Bands
   int i,pos;
//---
   if(rates_total<=InpBandsPeriod || InpBandsPeriod<=0)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtMovingBuffer,false);
   ArraySetAsSeries(ExtUpperBuffer,false);
   ArraySetAsSeries(ExtLowerBuffer,false);
   ArraySetAsSeries(ExtStdDevBuffer,false);
   ArraySetAsSeries(ExtUpper3Buffer,false);
   ArraySetAsSeries(ExtLower3Buffer,false);
   ArraySetAsSeries(ExtUpper1Buffer,false);
   ArraySetAsSeries(ExtLower1Buffer,false);
   ArraySetAsSeries(close,false);
//--- initial zero
   if(prev_calculated<1)
     {
      for(i=0; i<InpBandsPeriod; i++)
        {
         ExtMovingBuffer[i]=EMPTY_VALUE;
         ExtUpperBuffer[i]=EMPTY_VALUE;
         ExtLowerBuffer[i]=EMPTY_VALUE;
         ExtUpper3Buffer[i]=EMPTY_VALUE;
         ExtLower3Buffer[i]=EMPTY_VALUE;
         ExtUpper1Buffer[i]=EMPTY_VALUE;
         ExtLower1Buffer[i]=EMPTY_VALUE;
        }
     }
//--- starting calculation
   if(prev_calculated>1)
      pos=prev_calculated-1;
   else
      pos=0;
//--- main cycle
   for(i=pos; i<rates_total && !IsStopped(); i++)
     {
      //--- middle line
      ExtMovingBuffer[i]=SimpleMA(i,InpBandsPeriod,close);
      //--- calculate and write down StdDev
      ExtStdDevBuffer[i]=StdDev_Func(i,close,ExtMovingBuffer,InpBandsPeriod);

      //--- upper line
      ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations*ExtStdDevBuffer[i];
      //--- lower line
      ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations*ExtStdDevBuffer[i];

      //--- upper line3
      ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations3*ExtStdDevBuffer[i];
      //--- lower line3
      ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations3*ExtStdDevBuffer[i];
      
      if(On_BandsDeviations1 != 0){
         //--- upper line1
         ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations1*ExtStdDevBuffer[i];
         //--- lower line1
         ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations1*ExtStdDevBuffer[i];
                  
      }

      //---
     }
   
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Calculate Standard Deviation                                     |
//+------------------------------------------------------------------+
double StdDev_Func(int position,const double &price[],const double &MAprice[],int period)
  {
//--- variables
   double StdDev_dTmp=0.0;
//--- check for position
   if(position>=period)
     {
      //--- calcualte StdDev
      for(int i=0; i<period; i++)
         StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);
      StdDev_dTmp=MathSqrt(StdDev_dTmp/period);
     }
//--- return calculated value
   return(StdDev_dTmp);
  }
  
//+------------------------------------------------------------------+

ベースソースは、MT4インストール時に最初から入っているボリンジャーバンドのカスタムインジケーターの「Bands.mq4」です。

 

これに、偏差1と3も表示する処理を入れて、それぞれの偏差の上下バンドを計算。ついで、pipsの計算も。Comment関数で表示するだけの簡単なものです。

 

偏差1のボリンジャーバンドは表示すると、チャートがぐちゃぐちゃになって、ウザい時もあるで、パラメーターでON/OFFが出来るようにしました。

矢野テック
矢野テック

本当はチェックボックスにしたかったけど、出来るんかな??。調べても分からなかった。

ソース解説

ボリンジャーバンドの各偏差の値を取得

iBands関数で、それぞれの偏差の値を取得。

bb_1 = iBands(NULL,PERIOD_CURRENT,20,1,0,PRICE_CLOSE,1,0);

iBandsの仕様はMQL4の公式リファレンスを参照してください。

あわせて読みたい
iBands - Technical Indicators - MQL4 Reference iBands - Technical Indicators - MQL4 Reference

ボリンジャーバンドの上下幅を計算して小数点の桁数丸め

NormalizeDouble関数を使って、桁数を丸める処理をいれました。これを入れないと、小数点が14桁常に表示して見づらい。

bb_2_M2 = NormalizeDouble(bb_2 - bb_M2,3);

 

このままだとポイント表示なので、pips表示用に計算。ポイントを100倍すればpipsになります。

bb_2_M2_digit = NormalizeDouble(bb_2_M2 * 100,4);

 

問題点

NormalizeDouble関数は、指定小数点で桁を丸める処理なのですが、たまにうまく表示しない時があります。値は合ってるけど、桁数がめちゃ多くなる事があります。

矢野テック
矢野テック

MQL4に最初から入ってる関数なので、どういう処理なのか不明なんだけど、たぶん桁上りの時に上手く表示できないようです。

 

ブログランキングに参加してます。この記事が少しでもお役に立ちましたら、応援ポチっとお願いします。

にほんブログ村 為替ブログ システムトレード 自作EA派へ
にほんブログ村

お友達にMT4インジケータープレゼント中

機械学習使った日々の予測結果や、細かい試行錯誤の結果はLINEで公開しています。パスワード付き記事もこちらから。

また、今ならお友達には矢野テック自作のMT4用のインジケーターをプレゼント中です。

友だち追加

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

プログラマー。FXのMT4を使った自動売買EA作成やBOT作成などが趣味。2016年から元本10万円をどこまで増やせるか挑戦中。一旦は10万⇒700万⇒2017暴落 20万。ガチホからFXトレードに変更。 現在1000万円。その過程やノウハウは無料メール講座にまとめました。1か月で学べます。→無料メール講座

ご質問はコメント欄からお願いします

コメントする

目次