https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9e16c257-b672-42cb-beee-0e57c7a34882/USDJPY_iDaily.png

共通ライブラリを使ったEAでは、仕掛けシグナルEntrySignal()という関数で定義しています。

この関数に少し手を加えるだけで、仕掛けシグナルをチャートに表示させるカスタム指標を作成することができます。

上のチャートは2本の移動平均線の交差を利用した仕掛けシグナルの例です。シグナルの出た位置に矢印の記号を表示させています。ただし、移動平均線自体は別途、テクニカル指標として表示させています。

カスタム指標全体の設定

//MQL4互換ライブラリ(MQL5のみ)
#include "LibMQL4.mqh"

//プログラムのプロパティ
#property indicator_chart_window       //チャートウィンドウに表示
#property indicator_buffers 2          //使用する指標バッファの数
#property indicator_plots   2          //プロットする指標バッファの数
#property indicator_type1   DRAW_ARROW //指標0の種類:矢印
#property indicator_type2   DRAW_ARROW //指標1の種類:矢印
#property indicator_color1  clrBlue    //指標0の色:Blue
#property indicator_color2  clrRed     //指標1の色:Red

//指標バッファ用の配列
double BufBuy[];  //買いシグナル
double BufSell[]; //売りシグナル

MQL5の場合のみ、共通ライブラリの一部であるLibMQL4.mqhをインクルードします。

指標バッファ用の配列としては、買いシグナルBufBuy[]、売りシグナルBufSell[]の二つを用意します。

#properyで指標を二つ使用することを指定しますが、指標の種類としてはDRAW_ARROWという矢印記号を使用することを指定します。

初期化関数

//初期化関数
int OnInit()
{
   //配列を指標バッファに関連付ける
   SetIndexBuffer(0, BufBuy, INDICATOR_DATA);
   SetIndexBuffer(1, BufSell, INDICATOR_DATA);
   //時系列配列に設定
   ArraySetAsSeries(BufBuy, true);
   ArraySetAsSeries(BufSell, true);
   //プロット開始位置の設定
   SetIndexDrawBegin(0, SlowMAPeriod);
   SetIndexDrawBegin(1, SlowMAPeriod);
   //矢印の設定
   SetIndexArrow(0, 233); //上矢印
   SetIndexArrow(1, 234); //下矢印
   
   EntrySignal(0);
   return(INIT_SUCCEEDED);
}

OnInit()で、配列への指標バッファの関連付け、時系列配列の設定等は、他のカスタム指標と同様です。

指標の矢印記号の種類を設定するために、[SetIndexArrow()](<https://docs.mql4.com/customind/setindexarrow>)を使います。記号の種類はWingdingsの一覧から探します。ここでは、買いシグナルとして上矢印(233)、売りシグナルとして下矢印(234)を指定します。

仕掛けシグナル関数

input int FastMAPeriod = 20; //短期移動平均の期間
input int SlowMAPeriod = 50; //長期移動平均の期間

//仕掛けシグナル関数
int EntrySignal(int shift)
{
   //1本前と2本前の移動平均
   double FastMA1 = iMA(_Symbol, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, shift+1);
   double FastMA2 = iMA(_Symbol, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, shift+2);
   double SlowMA1 = iMA(_Symbol, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, shift+1);
   double SlowMA2 = iMA(_Symbol, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, shift+2);

   int ret = 0; //シグナルの初期化

   //買いシグナル
   if(FastMA2 <= SlowMA2 && FastMA1 > SlowMA1) ret = 1;
   //売りシグナル
   if(FastMA2 >= SlowMA2 && FastMA1 < SlowMA1) ret = -1;

   return ret; //シグナルの出力
}

仕掛けシグナル関数は、基本的に仕掛けシグナルに掲載した関数と同じです。手を加える点は、引数にshiftを追加するところと、その関数中で呼び出すテクニカル指標関数の最後の引数にshiftを足し合わせるところです。

この例では、iMA()関数の最後のパラメータの1shift+1に、2shift+2に書き換えます。

指標計算関数

//指標計算関数
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(open, true);

   //指標を表示する範囲
   int limit = rates_total - prev_calculated;
   limit = MathMin(limit, rates_total-SlowMAPeriod-1);

   for(int i=0; i<limit; i++) //指標の表示の繰り返し
   {
      //買いシグナル
      if(EntrySignal(i) == 1) BufBuy[i] = open[i];
      else BufBuy[i] = EMPTY_VALUE;
      //売りシグナル
      if(EntrySignal(i) == -1) BufSell[i] = open[i];
      else BufSell[i] = EMPTY_VALUE;
   }
   return(rates_total-1);
}

OnCalculate()では、for文でチャートの位置を変化させながら、EntrySignal(i)1のときに買いシグナルとしてBufBuy[i]に始値open[i]を代入します。またEntrySignal(i)-1のときに売りシグナルとしてBufSell[i]に始値open[i]を代入します。シグナルが出ていないところでは指標を表示しないように、それぞれの配列にEMPTY_VALUEを代入します。