移動平均線クロスを知らせてくれるインジケーター

当サイトではこれまで各種計算ロジックや VB.Net のコードなどを紹介してきましたが、FX などの運用で広く使われているプラットフォーム MT4,MT5 で動作する MQL についても開発を行っています。今回は、ごく簡単なインジケーターとして、移動平均線のゴールデンクロスとデッドクロスで矢印とアラートを表示するインジケーターのコードを紹介します。


このインジケーターを作成しようと考えた経緯ですが、個人的に移動平均線がクロスしたタイミングを知る必要が出てきたためです。しかしながら、こういう単純なインジケーターはネット上で無料のものがいくつも見つかるので、自作するまでもないと思い最初はそれらをダウンロードして使用してみました。

ところが、実際に動かしてみると以下の問題が発生するケースが多いことがわかりました。

  • クロス後、足が確定するごとにアラートが表示される!

例えば、15分足で動かしていて12時にクロスのアラートが表示されたとします。再びクロスしない限りアラートは鳴らないはずなんですが、なぜか次の12時15分の足が確定したときにもアラートが表示されるインジケーターが多いのです。なぜ作者が気付かないのか不思議ですが、ネット上で入手できるインジケーターをいくつか試した時点で探すのを諦め、自作することにしました。


このインジケーター “MA_CrossAlert” のコードを以下に記載しています。詳細な説明は省略しますが、簡単に言うと「バッファーを4つ用意し、短期移動平均線、長期移動平均線、ゴールデンクロスの矢印、デッドクロスの矢印を格納する。足が確定したとき、ひとつ前の終値と比較し、クロスしていればロウソク足から30ポイント離れた位置に矢印を表示してアラートを鳴らす」というロジックです。

//+------------------------------------------------------------------+
//|                                                MA_CrossAlert.mq4 |
//|                                            iNak Engineering, LLC |
//|                                             https://inak-eng.jp/ |
//+------------------------------------------------------------------+
#property copyright "iNak Engineering, LLC"
#property link      "https://inak-eng.jp/"
#property version   "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Yellow
#property indicator_color2 Cyan
#property indicator_color3 Red
#property indicator_color4 Blue

#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 5
#property indicator_width4 5

double Buf_MA_1[];
double Buf_MA_2[];
double Buf_GC[];
double Buf_DC[];

extern int MA_1_Mode = 0;    //Short Term MA Mode
extern int MA_1_Period = 25; //Short Term MA Period
extern int MA_1_Price = 0;   //Short Term MA Price
extern int MA_2_Mode = 0;    //Long Term MA Mode
extern int MA_2_Period = 50; //Long Term MA Period
extern int MA_2_Price = 0;   //Long Term MA Price

int nowbar;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   SetIndexBuffer(0,Buf_MA_1);
   SetIndexBuffer(1,Buf_MA_2);
   SetIndexBuffer(2,Buf_GC);
   SetIndexBuffer(3,Buf_DC);

   SetIndexStyle(2,DRAW_ARROW,STYLE_SOLID);
   SetIndexArrow(2,233);

   SetIndexStyle(3,DRAW_ARROW,STYLE_SOLID);
   SetIndexArrow(3,234);

   nowbar = Bars;

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

//---
  }
//+------------------------------------------------------------------+
//| Expert tick 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[]
)
  {
   int counted_bar = IndicatorCounted();
   int limit = Bars-counted_bar;

   if(counted_bar == 0)
      limit -= MA_2_Period-1;
   for(int i=limit-1; i>=0; i--)
     {
      Buf_MA_1[i] = iMA(NULL,0,MA_1_Period,0,MA_1_Mode,MA_1_Price,i);
      Buf_MA_2[i] = iMA(NULL,0,MA_2_Period,0,MA_2_Mode,MA_2_Price,i);
     }

   if(counted_bar == 0)
      limit -= 2;
   for(int i=limit-1; i>=0; i--)
     {
      Buf_GC[i] = EMPTY_VALUE;
      if(Buf_MA_1[i+2] <= Buf_MA_2[i+2] && Buf_MA_1[i+1] > Buf_MA_2[i+1])
        {
         Buf_GC[i+1] = Low[i+1]-30*Point;
         if(nowbar != Bars && i == 0)
           {
            Alert(Symbol(),", Golden Cross");
            nowbar = Bars;
           }
        }
      Buf_DC[i] = EMPTY_VALUE;
      if(Buf_MA_1[i+2] >= Buf_MA_2[i+2] && Buf_MA_1[i+1] < Buf_MA_2[i+1])
        {
         Buf_DC[i+1] = High[i+1]+30*Point;
         if(nowbar != Bars && i == 0)
           {
            Alert(Symbol(),", Dead Cross");
            nowbar = Bars;
           }
        }
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

メタエディターを移動し、上記コードを貼り付けてコンパイルすればインジケーターが作成できます。チャートに適用する方法などはネット上でいくつも見つかるので、そちらを参照してください。

このインジケーターのパラメーター設定画面は以下の通りです。

“Short Term MA” が短期移動平均線、”Long Term MA” が長期移動平均線になります。”Period” が移動平均線を計算する期間で、デフォルトでは短期が25、長期が50になっています。他の2つのパラメーターの設定は以下の通りです。

<Mode>

パラメーター種類内容
0SMA単純移動平均線
1EMA指数移動平均線
2SMMA平滑移動平均線
3LWMA線形加重移動平均線

<Price>

パラメーター種類内容
0CLOSE終値
1OPEN始値
2HIGH高値
3LOW安値
4MEDIAN中央値
5TYPICAL代表値
6WEIGHTED加重終値

各パラメーターを設定後、下図のように2本の移動平均線とゴールデンクロス、デッドクロスの矢印が表示されれば問題なく動作しています。

移動平均線がクロスしたときのアラートは、足が確定したときだけ表示されます。まだ確定していない段階でクロスしても表示されませんので、この点は注意して下さい。

単純なインジケーターですが、最低限の機能は有しています。これをベースにして、改変は自由に行ってもらって構いません。自身の運用に役立てて下さい。