目次
概要
ダブルボトム・ダブルトップを捉えるインジケータがないかなと思って、探してみたら、以下のURLで紹介されているインジケータを見つけました。
https://www.mql5.com/ja/code/22618
無料で使用できるという点で素晴らしいのですが、
使用してみて、以下の点で不満点を覚えました。
・MT4では使用できない
・高値と安値を交互で表示されない
そのため、少しソースコードを改造してみました。
ソースコード
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 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
#property version "1.00" #property description "Double top indicator" #property indicator_chart_window #property indicator_buffers 4 #property indicator_plots 4 //--- plot TopDbl #property indicator_label1 "Double Top" #property indicator_type1 DRAW_ARROW #property indicator_color1 Aqua #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- plot Top #property indicator_label2 "Top" #property indicator_type2 DRAW_ARROW #property indicator_color2 Aqua #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- plot BottomDbl #property indicator_label3 "Double Bottom" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrOrangeRed #property indicator_style3 STYLE_SOLID #property indicator_width3 1 //--- plot Bottom #property indicator_label4 "Bottom" #property indicator_type4 DRAW_ARROW #property indicator_color4 clrRed #property indicator_style4 STYLE_SOLID #property indicator_width4 1 //--- input parameters input uint InpMinHeight = 10; // Minumum Height/Depth input uint InpMaxDist = 20; // Maximum distance between the twin tops/bottoms input uint InpMinBars = 3; // Maximum number of bars after the top/bottom //3本目のバーが出るまで判断を待つ input uint LimitSearchCount = 3; // 最低探索回数。(例)3連続高値・安値を更新しなかった場合、その点を直近の高値・安値と考える //--- indicator buffers double BufferTop[]; double BufferTopDBL[]; double BufferBottom[]; double BufferBottomDBL[]; //--- global variables double min_height; int min_hgt; int min_bars; int max_dist; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- set global variables min_hgt=int(InpMinHeight<1 ? 1 : InpMinHeight); min_height=min_hgt*Point(); min_bars=int(InpMinBars<1 ? 1 : InpMinBars); max_dist=int(InpMaxDist<1 ? 1 : InpMaxDist); //--- indicator buffers mapping SetIndexBuffer(0,BufferTopDBL,INDICATOR_DATA); SetIndexBuffer(1,BufferTop,INDICATOR_DATA); SetIndexBuffer(2,BufferBottomDBL,INDICATOR_DATA); SetIndexBuffer(3,BufferBottom,INDICATOR_DATA); //--- setting a code from the Wingdings charset as the property of PLOT_ARROW PlotIndexSetInteger(0,PLOT_ARROW,82); PlotIndexSetInteger(1,PLOT_ARROW,159); PlotIndexSetInteger(2,PLOT_ARROW,82); PlotIndexSetInteger(3,PLOT_ARROW,159); //--- setting indicator parameters IndicatorSetString(INDICATOR_SHORTNAME,"Double top (Min height: "+(string)min_hgt+", max distance: "+(string)max_dist+", min bars: "+(string)min_bars+")"); IndicatorSetInteger(INDICATOR_DIGITS,Digits()); //--- setting buffer arrays as timeseries ArraySetAsSeries(BufferTop,true); ArraySetAsSeries(BufferTopDBL,true); ArraySetAsSeries(BufferBottom,true); ArraySetAsSeries(BufferBottomDBL,true); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 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[]) { //--- Установка массивов буферов как таймсерий ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(close,true); //--- Проверка и расчёт количества просчитываемых баров if(rates_total<fmax(min_bars,4)) return 0; //--- Проверка и расчёт количества просчитываемых баров int limit=rates_total-prev_calculated; if(limit>1) { limit=rates_total-min_bars-1; ArrayInitialize(BufferTop,EMPTY_VALUE); ArrayInitialize(BufferTopDBL,EMPTY_VALUE); ArrayInitialize(BufferBottom,EMPTY_VALUE); ArrayInitialize(BufferBottomDBL,EMPTY_VALUE); } //--- Расчёт индикатора for(int i=limit; i>=0 && !IsStopped(); i--) { BufferBottom[i]=BufferBottomDBL[i]=BufferTop[i]=BufferTopDBL[i]=EMPTY_VALUE; BufferTop[i+min_bars]=(IsTop(rates_total,i+min_bars,high,low) ? high[i+min_bars] : EMPTY_VALUE); BufferBottom[i+min_bars]=(IsBottom(rates_total,i+min_bars,high,low) ? low[i+min_bars] : EMPTY_VALUE); //もしも現在の足(i)が、前回の最大値を超えたにも関わらず、その間に、最小値が存在しない場合は、最小値をつける if(close[i]>FindPrevTopValue(rates_total,i)) { MarkPrevBottom(rates_total,i,low); } if(close[i]<FindPrevBottomValue(rates_total,i)) { MarkPrevTop(rates_total,i,high); } //もしも現在注目している足(i+min_bars)が、高値と判断したにも関わらず、前回の高値との間に、最小値が存在しない場合は、最小値をつける if(BufferTop[i+min_bars]!=EMPTY_VALUE) { MarkPrevBottom(rates_total,i+min_bars,low); } if(BufferBottom[i+min_bars]!=EMPTY_VALUE) { MarkPrevTop(rates_total,i+min_bars,high); } if(BufferTop[i+min_bars]==high[i+min_bars]) { if(FindPrevTop(rates_total,i+min_bars,high)) BufferTopDBL[i+min_bars]=high[i+min_bars]; else BufferTopDBL[i+min_bars]=EMPTY_VALUE; } if(BufferBottom[i+min_bars]==low[i+min_bars]) { if(FindPrevBottom(rates_total,i+min_bars,low)) BufferBottomDBL[i+min_bars]=low[i+min_bars]; else BufferBottomDBL[i+min_bars]=EMPTY_VALUE; } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsTop(const int rates_total,const int index,const double &high[],const double &low[]) { bool fl=true; for(int j=1; j<=min_bars; j++) if(high[index-j]>=high[index]) fl=false; if(fl) { int i=index+1; int SearchCount=0; while(i<rates_total) { if(high[i]>=high[index]) { return false; } else { SearchCount++; } if(SearchCount>LimitSearchCount || BufferBottom[i]!=EMPTY_VALUE) { return true; } i++; //if(high[index]-low[i]>=min_height) // return true; } } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsBottom(const int rates_total,const int index,const double &high[],const double &low[]) { bool fl=true; for(int j=1; j<=min_bars; j++) if(low[index-j]<=low[index]) fl=false; if(fl) { int i=index+1; int SearchCount=0; while(i<rates_total) { if(low[i]<=low[index]) { return false; } else { SearchCount++; } if(SearchCount>LimitSearchCount|| BufferTop[i]!=EMPTY_VALUE) { return true; } //if(high[i]-low[index]>=min_height) return true; // return true; i++; } } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool FindPrevTop(const int rates_total,const int index,const double &high[]) { int i=index+1; while(i<rates_total && i<=index+max_dist) { if(BufferTop[i]==high[i]) return true; i++; } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool FindPrevBottom(const int rates_total,const int index,const double &low[]) { int i=index+1; while(i<rates_total && i<=index+max_dist) { if(BufferBottom[i]==low[i]) return true; i++; } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double FindPrevBottomValue(const int rates_total,const int index) { int i=index+1; while(i<rates_total) { if(BufferBottom[i]!=EMPTY_VALUE) return BufferBottom[i]; i++; } return 999999; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double FindPrevTopValue(const int rates_total,const int index) { int i=index+1; while(i<rates_total) { if(BufferTop[i]!=EMPTY_VALUE) return BufferTop[i]; i++; } return 0; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool MarkPrevBottom(const int rates_total,const int index,const double &low[]) { int i=index; //最小値をとる足のインデックス int low_index=index; while(i<rates_total) { if(BufferBottom[i]!=EMPTY_VALUE) { return true; } if(low[i]<low[low_index]) { low_index=i; } i++; if(BufferTop[i]!=EMPTY_VALUE && BufferBottom[i]==EMPTY_VALUE) { BufferBottom[low_index]=low[low_index]; return false; } } return false; } bool MarkPrevTop(const int rates_total,const int index,const double &high[]) { int i=index; //最大値をとる足のインデックス int high_index=index; while(i<rates_total) { if(BufferTop[i]!=EMPTY_VALUE) { return true; } if(high[i]>high[high_index]) { high_index=i; } i++; if(BufferBottom[i]!=EMPTY_VALUE && BufferTop[i]==EMPTY_VALUE) { BufferTop[high_index]=high[high_index]; return false; } } return false; } //+------------------------------------------------------------------+ |
結果
振り返り
・高値と安値を交互で表示させたいなら、デフォルトで入っているZigZagインジケータでよくない?と感じた。
・一つの足に高値と安値が同時に同居する場合がある。高値と安値を交互に表示させたいのであれば、ZigZagインジケータのロジックが参考になりそう。
・高値と安値が頻繁に発生するので、少し厳選したい。平均足を使用する手法とか考えられたらいいかも。
・ダブルボトム・ダブルトップを見つける機能が実質機能していないので、なんとかしたい。
ほとんどの場合でBufferTopDBL (BufferBottomDBL)とBufferTop (BufferBottom)に同じ値が入る。
BufferTopDBL (BufferBottomDBL)に値を入れる条件を絞る必要がある。
例えば、1つ前の高値(安値)の±3Pips以内に入っているなど。
関連記事
~FXを始めてみませんか?~
XMは、口座を開設するだけで、3000円のボーナスが無料でもらえます。
資金はないけど、FXを試しに挑戦してみたい方でも大丈夫です。
(サイト主もXMを使用しています)
コメント