指数平滑移動平均線(EMA)を追加して2本のラインを表示させてみよう!
ここでは、前回完成した単純移動平均線を表示させるインジケーターに指数平滑移動平均線(EMA)を追加して2本のラインを表示させるようにカスタマイズする方法を解説します。
記事一覧で前回までの記事をチェックしよう!
「MT4インジケーター作成入門」の記事一覧
前回記事のおさらい
前回記事では、単純移動平均線を表示させるインジケーターを作成しました。
前回記事 インジケーター作成3【単純移動平均線】で完成したファイルのコードがこちら
#property strict #property indicator_chart_window #property indicator_buffers 1 // インジケーターバッファ 1つ #property indicator_color1 clrRed // 1つ目の色 赤色 #property indicator_width1 2 // 1つ目の太さ 2 extern int SMA_Period = 10; // SMAの期間 double buf[]; // ライン用の配列を宣言 //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, buf); // 配列 buf[]をインジケーター用に割り当てる SetIndexStyle(0, DRAW_LINE); // 描画タイプをラインと定義 return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ 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[]) { int i, j; int limit; if (prev_calculated == 0) // 最初 limit = rates_total - 1; // 左端のローソク足から全部 else // それ以外 limit = rates_total - prev_calculated; // ローソク足増加時「1」、通常「0」 for (i=limit; i>=0; i--) // limit本前から現在のローソク足を処理 { if (i + SMA_Period - 1 <= Bars - 1) { // buf[i]を0に初期化して buf[i] = 0; // Close[i+0] ~ Close[i+SMA_Period]の一つ手前までを足していき for (j=0; j<SMA_Period; j++) buf[i] += Close[i+j]; // SMA_Periodで割る buf[i] /= SMA_Period; } } //--- return value of prev_calculated for next call return(rates_total); }
前回完成ファイル【Sample_Indicator_03.mq4】をダウンロード
EMAを追加する
インジケーター用配列を追加
「#property」で始まる部分で、表示用インジケーターバッファを2つに変更します。
#property indicator_buffers 2
2本目のライン(EMAライン)の色と太さの初期設定を指定するため、次のコード追加します。
#property indicator_color2 clrYellow // 2つ目の色 黄色 #property indicator_width2 2 // 2つ目の太さ 2
そして、前回記事でのSMA用のパラメーターと配列の宣言と同じように、EMA用の期間を指定するパラメーター「EMA_Period」とインジケーター用配列にする配列 ema[]を次のように追加します。
extern int EMA_Period = 20;
double ema[];
OnInit()関数内に次のコードを追加して、インジケーターバッファ1番に配列 ema[]を割り当て、描画タイプの設定をします。
SetIndexBuffer(1, ema); // 配列 ema[]をインジケーター用に割り当てる SetIndexStyle(1, DRAW_LINE); // 描画タイプをラインと定義
EMAの計算式
指数平滑移動平均線(EMA)は、はじまりを単純移動平均で計算して、その後からは次の式で算出します。
EMA = (前回EMA × (期間-1) + 今回終値 × 2) ÷ (期間+1)
「前回EMA少なめ、終値増しで。」って感じですね。
EMAの計算式をコード化する
OnCalculate()関数内のfor()文内で算出開始のシフト数にも気を付けて、EMAの計算式を次のようにコード化します。
if (i + EMA_Period - 1 <= Bars - 1) { if (i + EMA_Period - 1 == Bars - 1) // 最初はSMAで算出 { ema[i] = 0; for (j=0; j<EMA_Period; j++) ema[i] += Close[i+j]; ema[i] /= EMA_Period; } else // その後は前回EMAと終値で算出 { ema[i] = ema[i+1] * (EMA_Period - 1) + Close[i] * 2; ema[i] /= EMA_Period + 1; } }
MT4のEMAと同じにする
MetaTrader4のインジケーター「Moving Average」でEMAを表示させると、ラインの始まり方が先ほど計算したEMAのライン表示と異なります。
MT4流のEMAは、はじまりが単純移動平均ではなく終値のようです。そうするには先ほどのコードの代わりに次のようなコードにします。
if (i == Bars - 1) ema[i] = Close[i]; else { ema[i] = ema[i+1] * (EMA_Period - 1) + Close[i] * 2; ema[i] /= EMA_Period + 1; }
意外とシンプルになりましたね。
今回完成したファイルのコードがこちら
#property strict #property indicator_chart_window #property indicator_buffers 2 // インジケーターバッファ 2つ #property indicator_color1 clrRed // 1つ目の色 赤色 #property indicator_width1 2 // 1つ目の太さ 2 #property indicator_color2 clrYellow // 2つ目の色 黄色 #property indicator_width2 2 // 2つ目の太さ 2 extern int SMA_Period = 10; // SMAの期間 extern int EMA_Period = 20; // EMAの期間 double buf[]; // ライン用の配列を宣言 double ema[]; // EMA用の配列を宣言 //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, buf); // 配列 buf[]をインジケーター用に割り当てる SetIndexStyle(0, DRAW_LINE); // 描画タイプをラインと定義 SetIndexBuffer(1, ema); // 配列 ema[]をインジケーター用に割り当てる SetIndexStyle(1, DRAW_LINE); // 描画タイプをラインと定義 return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ 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[]) { int i, j; int limit; if (prev_calculated == 0) // 最初 limit = rates_total - 1; // 左端のローソク足から全部 else // それ以外 limit = rates_total - prev_calculated; // ローソク足増加時「1」、通常「0」 for (i=limit; i>=0; i--) // limit本前から現在のローソク足を処理 { // SMA if (i + SMA_Period - 1 <= Bars - 1) { // buf[i]を0に初期化して buf[i] = 0; // Close[i+0] ~ Close[i+SMA_Period]の一つ手前までを足していき for (j=0; j<SMA_Period; j++) buf[i] += Close[i+j]; // SMA_Periodで割る buf[i] /= SMA_Period; } /* // 一般的なEMA if (i + EMA_Period - 1 <= Bars - 1) { if(i + EMA_Period - 1 == Bars - 1) // 最初はSMAで算出 { ema[i] = 0; for (j=0; j<EMA_Period; j++) ema[i] += Close[i+j]; ema[i] /= EMA_Period; } else // その後は前回EMAと終値で算出 { ema[i] = ema[i+1] * (EMA_Period - 1) + Close[i] * 2; ema[i] /= EMA_Period + 1; } } */ // MT4のEMA if (i == Bars - 1) ema[i] = Close[i]; else { ema[i] = ema[i+1] * (EMA_Period - 1) + Close[i] * 2; ema[i] /= EMA_Period + 1; } } //--- return value of prev_calculated for next call return(rates_total); }
今回の完成ファイル【Sample_Indicator_04.mq4】をダウンロード
あとがき
追加した指数平滑移動平均線EMAは正常に表示されましたか?
今回と同様の手順で3本目のラインやさらに多くのラインを追加していけるのでぜひ挑戦してみてください。
ではまた、次回をお楽しみに!
参考にさせていただいています。
質問なのですが
2本目もsmaで表示したい場合や
1本目、2本目のmaの種類もパラメータで変更したい場合はどのように変更したらよろしいでしょうか。
まだ先の内容をチェックしていないため
解説済みでしたら申し訳ありません。
kazさん
コメントありがとうございます。
maの種類をパラメーターで変更したい場合は、それぞれの種類をユーザー関数で作成して振り分けます。
MAの場合は、あらかじめincludeファイルが用意されていますので、MovingAverages.mqhをインクルードして使用するのもよいです。
また、iMA()関数でラインの値を取得するようにすれば、とても簡単に実現できると思います。
ご回答ありがとうございます♪
ブログ記事の先を読み進めると共に
関数にも挑戦してみます^_^
ありがとうございます。