色んなトレードノウハウを調べては、自作のEAを作っているのですが、ボリンジャーバンドの幅(特に−2σ〜+2σ)をチェックするトレードノウハウが多い。
常にボリンジャーのバンド幅をチャート上に表示していた方が便利なので、今現在の幅がどのくらいなのかを確認できる簡単なインジケーターを作ってみました。
実行結果
チャートの左上に、常に表示します。ポイント表示だけでなく、pips表示も入れました。
インジケーターダウンロード
一応、ソースを公開して解説していますが、不要な方もいると思うので。
こちらからダウンロードしてください。
BB_bands_length_output
MQL4ソースコード
たいしたコードではないので公開。
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
//+------------------------------------------------------------------+ //| 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関数で、それぞれの偏差の値を取得。
1 |
bb_1 = iBands(NULL,PERIOD_CURRENT,20,1,0,PRICE_CLOSE,1,0); |
iBandsの仕様はMQL4の公式リファレンスを参照してください。
ボリンジャーバンドの上下幅を計算して小数点の桁数丸め
NormalizeDouble関数を使って、桁数を丸める処理をいれました。これを入れないと、小数点が14桁常に表示して見づらい。
1 |
bb_2_M2 = NormalizeDouble(bb_2 - bb_M2,3); |
このままだとポイント表示なので、pips表示用に計算。ポイントを100倍すればpipsになります。
1 |
bb_2_M2_digit = NormalizeDouble(bb_2_M2 * 100,4); |
問題点
NormalizeDouble関数は、指定小数点で桁を丸める処理なのですが、たまにうまく表示しない時があります。値は合ってるけど、桁数がめちゃ多くなる事があります。
MQL4に最初から入ってる関数なので、どういう処理なのか不明なんだけど、たぶん桁上りの時に上手く表示できないようです。
ご質問はコメント欄からお願いします