FX自動売買基礎と応用

マルチタイムフレーム移動平均線(MA)を方式別に比較する方法【MQLプログラミングの基礎】


1.ファイルの新規作成時にパラメーターとバッファーを追加


この記事では、マルチタイムフレーム移動平均線(MA)を方式別に比較する方法を説明します。今回は、次の四つの方式でマルチタイムフレームMAを比較します。

①単純に上位足のMAの値を利用したもの。iBarShift関数を使って上位足の値をそのまま表示する階段状のマルチタイムフレーム方式。

②上記①で作ったMAの確定点を結んだもの。いわゆる平滑化するパターン。

③MAの期間に上位時間足との比率を掛けた疑似的マルチタイムフレーム方式。例えば上位足が1時間足で、表示する足が15分足の場合、1時間足は60分なので15分足の4倍です。1時間足の期間20のMAを15分足で表示するなら、期間を4倍して80MAとします。

④確定した足までは上位時間足の終値を利用し、確定していない最新足については表示中の足の終値を利用する複合方式。(この④が最もリアルに近い表示内容です)

まずファイルの新規作成で「カスタムインディケータ」を選択したあと、ファイル名を「MTF_MA_test」としてパラメーターを追加します。今回はMAの期間を、名前「PERIOD」、タイプ「int」、初期値「20」で登録します。

カスタムインディケータの一般プロパティ

「カスタムインディケータのイベントハンドラ」の画面では、「OnTimer」と「OnChartEvent」のどちらにもチェックを入れず次へ進み、「カスタムインディケータの描画プロパティ」画面のプロット欄で、MA用の四つのバッファーを追加します。

一つ目はラベルを「MA0」、カラーを「White」、二つ目はラベルを「MA1」、カラーを「Magenta」、三つ目はラベルを「MA2」、カラーを「DodgerBlue」、四つ目はラベルを「MA3」、カラーを「YellowGreen」にして登録し、「完了」をクリックすれば、ひな形の完成です。

カスタムインディケータの描画プロパティ


2.MAの線種を変更し時間足を指定


続いて、ファイル上部のプロパティで、MA0、MA1、MA2の線種を変更します。MA0は「STYLE_DOT」、MA1は「STYLE_DASH」、MA2は「STYLE_DASHDOT」とします。

MA1に関しては、描画タイプも「DRAW_LINE」から「DRAW_SECTION」に変えておきましょう。LINEのままでは途中の点の値を消すと線が繋がらなくなってしまいますが、SECTIONにすれば飛び飛びの点を棒線で結んでくれます。


//--- plot MA0
#property indicator_style1  STYLE_DOT
//--- plot MA1
#property indicator_type2   DRAW_SECTION
#property indicator_style2  STYLE_DASH
//--- plot MA2
#property indicator_style3  STYLE_DASHDOT

また、バッファーの名前が長いので「MA0Buffer」→「MA0」という具合に該当箇所の「Buffer」を省いて短くします。


double MA0[];
double MA1[];
double MA2[];
double MA3[];

同様にOnInit関数内の「//— indicator buffers mapping」にあるバッファー名も、次のように短く変更します。


SetIndexBuffer(0,MA0);
SetIndexBuffer(1,MA1);
SetIndexBuffer(2,MA2);
SetIndexBuffer(3,MA3);

そして、時間足を指定するパラメーターを追加します。今回は列挙型の「ENUM_TIMEFRAMES」を使い、1時間足を指定します。「//— input parameters」の下に次のコードを加えましょう。


input ENUM_TIMEFRAMES TF = PERIOD_H1;


3.階段状のマルチタイムフレームMAを表示


上記では、MAの線種を変更してバッファー名を短縮し、時間足を指定するパラメーターを追加しました。続いて、OnCalculate関数内にメインの回路を作り、マルチタイムフレームMAを表示させましょう。

今回は上位に相当する時間足を1時間として、表示しているチャートが1時間足より大きい場合はそこで処理を終了します。計算する足の最大値は「limit」、最小値は「min」として定義します。limitがminより小さいときはminまで計算を続けて、上位足に相当する本数だけは最低限毎回計算するようにします。


if (_Period > TF) return 0;
int limit = Bars - prev_calculated -2;
int min = PeriodSeconds(TF) / PeriodSeconds();
if (limit < min) limit = min;

そして、定義したlimitから最新足まで計算させます。上位足にあたる足の番号を「iBarShift」で出し、それを利用してマルチタイムフレームMAを表示します。


for (int i = limit; i >= 0; i--) {
   int bar = iBarShift(NULL, TF, Time[i]);
   MA0[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar); 
}

これでコンパイルしてチャートにセットすると、マルチタイムフレームMAが階段状に表示されることが分かります。

マルチタイムフレームMAが階段状に表示される


4.MA0の確定点を結んだ平滑化パターンのマルチタイムフレームMAを表示


次に、階段状のマルチタイムフレームMAの確定点を結ぶ、平滑化パターンのMAを表示します。途中まではMA0と同じ処理で、そのあと1本前の足のときに相当する上位足の番号を出し、今の足から前の足を見て上位足が同じだった場合に、前の足の値を空にします。これで途中の値をなくして、確定した点だけが残るようになります。


MA1[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar); 
int barPre = iBarShift(NULL, TF, Time[i + 1]);
if (bar == barPre) MA1[i + 1] = EMPTY_VALUE;

これでコンパイルすると、MA0の確定点だけが結ばれたマルチタイムフレームMAが追加表示されます。

MA0の確定点を結んだ平滑化パターンのマルチタイムフレームMAを表示


5.疑似的マルチタイムフレームMAを表示


今度は、MAの期間に上位時間足との比率を掛けた、疑似的マルチタイムフレームMAを表示します。計算する時間足は現在の時間足なので「0」、期間は上位時間足との比率を掛けて「PERIOD * min」とします。今回、MAを表示している時間足は15分足、上位足が1時間足なのでmin=4、つまり期間を4倍するということです。


MA2[i] = iMA(NULL, 0, PERIOD * min, 0, MODE_SMA, PRICE_CLOSE, i);

これでコンパイルすると、水色の疑似的マルチタイムフレームMAが追加表示されます。平滑化されたMA1よりも少し遅れて動くことが分かります。

疑似的マルチタイムフレームMAを表示


6.複合方式のマルチタイムフレームMAを表示


上記では、上位足のMAの値を利用した階段状のマルチタイムフレームMA、その確定点を結んだ平滑化パターンのマルチタイムフレームMA、期間に上位時間足との比率を掛けた疑似的マルチタイムフレームMAの3種類を表示することができました。最後に、複合方式のマルチタイムフレームMAを表示します。

この複合方式のマルチタイムフレームMAは、確定した足までは上位時間足の終値を、最新の未確定足については表示中の時間足の終値を利用する計算方式です。まずは終値を合計する「sum」という変数を定義し、1からPERIODまで上位足19本の終値を合計していきます。その合計に、表示中の時間足の終値を足して、PERIODで割ります。


double sum = 0;
for (int j = 1; j < PERIOD; j++) {
   sum += iClose(NULL, TF, bar + j);
}
MA3[i] = (sum + Close[i]) / PERIOD;  

これでコンパイルすると、緑色の複合方式のマルチタイムフレームMAが追加表示されます。

複合方式のマルチタイムフレームMAを表示

実際の上位足の値を利用し、きちんと計算して求めた複合方式のマルチタイムフレームMAは、平滑化したラインよりも階段状のラインに似た軌跡を描きます。この結果から、MAを平滑化してしまうと実際の値とのずれが大きくなることが分かります。


7.ソースコード


今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                                  MTF_MA_test.mq4 |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
//--- plot MA0
#property indicator_label1  "MA0"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_DOT
#property indicator_width1  1
//--- plot MA1
#property indicator_label2  "MA1"
#property indicator_type2   DRAW_SECTION
#property indicator_color2  clrFuchsia
#property indicator_style2  STYLE_DASH
#property indicator_width2  1
//--- plot MA2
#property indicator_label3  "MA2"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDodgerBlue
#property indicator_style3  STYLE_DASHDOT
#property indicator_width3  1
//--- plot MA3
#property indicator_label4  "MA3"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrYellowGreen
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- input parameters
input ENUM_TIMEFRAMES TF = PERIOD_H1;
input int      PERIOD = 20;
//--- indicator buffers
double         MA0[];
double         MA1[];
double         MA2[];
double         MA3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, MA0);
   SetIndexBuffer(1, MA1);
   SetIndexBuffer(2, MA2);
   SetIndexBuffer(3, MA3);

//---
   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[])
{
//---
   if (_Period > TF) return 0;

   int limit = Bars - prev_calculated - 2;
   int min = PeriodSeconds(TF) / PeriodSeconds();
   if (limit < min) limit = min;

   for (int i = limit; i >= 0; i--) {
      int bar = iBarShift(NULL, TF, Time[i]);
      MA0[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);

      MA1[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);
      int barPre = iBarShift(NULL, TF, Time[i + 1]);
      if (bar == barPre) MA1[i + 1] = EMPTY_VALUE;

      MA2[i] = iMA(NULL, 0, PERIOD * min, 0, MODE_SMA, PRICE_CLOSE, i);

      double sum = 0;
      for (int j = 1; j < PERIOD; j++) {
         sum += iClose(NULL, TF, bar + j);
      }
      MA3[i] = (sum + Close[i]) / PERIOD;
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}


本記事の監修者・HT FX


2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする

ホーム » FX自動売買基礎と応用 » マルチタイムフレーム移動平均線(MA)を方式別に比較する方法【MQLプログラミングの基礎】