【MQL5】 MT5のEA作成の勉強 その23 他の時間軸の移動平均線インジケータの作り方(2 / 3)※原因

【MQL5】 MT5のEA作成の勉強 その23 他の時間軸の移動平均線インジケータの作り方(2 / 3)※原因

まえがき

 前回の投稿で、他の時間軸の移動平均線インジケータを作ろうとしたところ、テストはうまくいったのに実際にチャートに挿入すると意味不明な挙動を示しました。
 今回はその原因を考察し、プログラムを修正してゆきます。

要素数と値の違い

 前回最後に述べましたが、時間軸15minの移動平均線と時間軸1hourの移動平均線では要素数が約4倍違います。最大要素が現在時刻なので、大体以下のような関係です。

配列と要素数
バッファの要素数が異なる

どうも、要素数があっていないのが原因っぽいので、LongBufferの要素数を4倍にしてみました。即ち、以下のような感じです。

このように修正

念のために補足しておきますと、時間軸15minのチャートに時間軸1hourの移動平均線を描画した場合、00分、15分、30分、45分の値はすべて同じになるので、同じように値を割り振って引き伸ばします。実際には、00分以外ではきっかり4倍ではないので、処理においてはその面も考慮します。これにより、二つのバッファの要素数は同じになります。

ソースの修正

 上記の変更を行うために前回の投稿で作成したソースのOnCalculate()関数を以下のように修正します。

   int barCount;            //計算するバーの数
   double tmp_LongBuffer[]; //一時バッファ
   
   if(prev_calculated>rates_total || prev_calculated<=0)
      barCount  = rates_total-(MA_Period*4);
   else
      barCount = rates_total-prev_calculated;
   
   int longBarCount = (int)((barCount)/4); //長期足のバッファ要素数
   
//--- インジケータの値を取得
   if(CopyBuffer(CurrentHandle, 0, 0, barCount+1, CurrentBuffer)!=barCount+1)
      return(0); 
   if(CopyBuffer(CurrentHandle, 0, 0, barCount+1, LongBuffer)!=barCount+1)
      return(0);  
   if(CopyBuffer(LongHandle, 0, 0, longBarCount, tmp_LongBuffer)!=longBarCount)
      return(0); 

長期移動平均線の描画に使うCurrentBufferLongBufferは要素数を一致させる必要があります。そこで、一旦12行目で現在の移動平均線をLongBufferに格納して要素数を合わせています。一方、時間軸1hourの移動平均線は要素数が現在の時間軸(15min)の1/4しかないので、一時配列に格納します。

 このままでは同じ移動平均線を二本引くだけになってしまうので、さらに以下のコードを追加して、一時配列の値をLongBufferに格納してゆきます。

   //端数の分が存在する場合(00分でない場合)直近の00分の位置までスライド
   //スライドした場合は長期移動平均線の最新値を格納
   int shiftBars = (int)MathMod(rates_total-1,4);
   for(int i=0; i<shiftBars; i++)
      LongBuffer[rates_total-1-i]=tmp_LongBuffer[longBarCount-1]; 
   
   //00分、15分、30分、45分に長期移動平均線の値を格納
   for(int i=longBarCount-1; i>=1  && !_StopFlag; i--)
      for(int j=0; j<4; j++)
         if((rates_total-1)-4*(longBarCount-1-i)-j>=0)
            LongBuffer[(rates_total-1)-4*(longBarCount-1-i)-shiftBars-j] = tmp_LongBuffer[i-1];

 上半分が15分単位の端数の処理、下半分で長期移動平均線の値を格納しています。隘路で300行くらいいろいろ書き連ねたのですが、最終的にこんなにスマートになって・・・。喜ぶべきなんでしょうがちょっと複雑です。

実行結果

 相当隘路したので詳しく書きたいところですが、分かり難い上に意味のない情報なので割愛して、最終版の実行結果を示します。以下のようになりました。

修正後の実行結果(赤い超長期の移動平均線は省略)

前回と違い、ちゃんと平均期間28のオレンジの線にカクカクした動きで追従しています。どうやら成功のようです。ただし、画像では分からないのですが、この線、何故か点滅します。作っている途中も思ったのですが、何故か参考にしたインジケータが毎回rates_total分の全バッファを書き換えていたためこのようになりました(線の形状は変わりません)。もしかしたら、単に計算時間がかかるから点滅して見えるだけで、他のインジケータも同じように全バッファを毎度書き換えているのかもしれませんが、この辺の勉強はいずれ。

まとめ

 何とか、インジケータにMQL5既定のiMA関数を使って、別の時間軸の移動平均線を表示させることができました。ただし、お気づきの方も多いと思いますが、現状、これでは15min1hourを表示することしかできません。もう少し工夫すれば柔軟にできるようになるのか、それともおとなしく公式コミュニティにある方法に従うべきか、今後も検証してゆきたいと思います。