MT5インジケータSMA+Envelop01.mq5

 プログラムのファイルは以下のサイトよりダウンロードできます。


ダウンロードしたファイルは、前回と同様メタエディタのナビゲータで、Indicatorsフォルダーを開いて、ファイルをコピー&ペーストします。ファイルはソースコードなので、コンパイルして下さい。
Indicatorsフォルダーの開き方は Indicatorsを選択し、マウスの右ボタンをクリックします。そして「フォルダーを開く」を選択します。

下の写真はMT5のチャートにSMA+Envelop01.mq5をアタッチしたものです。

SMA+Envelope01



SMA+Envelop01.mq5のコードは以下のようになりますが、MT4のインジケータとは若干異なるものがあります。途中の赤字は説明の部分です。

#property copyright "Copyright 2015, T.S."
#property link      "http://"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 3
#property indicator_type1 DRAW_LINE
#property indicator_type2 DRAW_LINE
#property indicator_type3 DRAW_LINE
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 Blue
input int InpPeriodSMA=20;
input int InpMAShift=0;
input double InpMABand=0.5;
double ExtMIBuffer[];
double ExtMIBufferH[];
double ExtMIBufferL[];
//+--------------------------------------
//| Custom indicator initialization function 
//+--------------------------------------
void OnInit()
  {
//bool x=ArrayGetAsSeries(ExtMIBuffer);
//Print("before  = ",x);
   SetIndexBuffer(0,ExtMIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtMIBufferH,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMIBufferL,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+4);
//各プロット番号描画インジケータラインの開始位置の指定
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpPeriodSMA);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpPeriodSMA);
   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpPeriodSMA);
//各プロット番号描画インジケータラインのシフト位置の指定
   PlotIndexSetInteger(0,PLOT_SHIFT,InpMAShift);
   PlotIndexSetInteger(1,PLOT_SHIFT,InpMAShift);
   PlotIndexSetInteger(2,PLOT_SHIFT,InpMAShift);
//各プロット番号描画インジケータラインの名前の指定
   PlotIndexSetString(0,PLOT_LABEL,"SMA");
   PlotIndexSetString(1,PLOT_LABEL,"Upper");
   PlotIndexSetString(2,PLOT_LABEL,"Lower");
   string short_name="MySMA";
//このインジケータの名前
   IndicatorSetString(INDICATOR_SHORTNAME,
                      short_name+"("+string(InpPeriodSMA)+")");
//各プロットでの値が空のときの値の指定
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);
   
//bool y=ArrayGetAsSeries(ExtMIBuffer);
//Print("after   = ",y);
  }
//------------------------------------------------- 
void OnDeinit(const int reason)
  {
//Comment("","");
  }
//
//----------------------------------------------
//+---------------------------------------------
//| Custom indicator iteration function 
//+---------------------------------------------
//int OnCalculate(const int rates_total,
// const int prev_calculated,
// const int begin,
// const double &price[]) {  } 
// の説明
//
//ここでは記載しませんが、OnCalculateには2つの型があります。
//新規にインディケータを作るときは、2つのうち1つを選択します。
//
//price[]はチャート足の寄付き値、終わり値、最高値、最安値がセットになっています。
//各値の指定はチャートにアタッチしてからプロパティのパラメータで適用価格として指定します。
//
//beginパラメータはプライス配列の最初の番号。 
//関数PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, empty_first_values)を使用し配列の始の番号をセット。 
//下のPrint("begin1 = ",begin);場合では0。
//
//次の {  } の中では 
//rates_total が InpPeriodSMA-1+beginより大きくなるまで
//return(0);でもとにもどる事をくり返します。
//
//次にArrayInitialize(ExtMIBuffer ,0);では配列を初期化します。
//次の関数はCalculateSimpleMA(rates_total,prev_calculated,begin,price);では
//3本の単純移動平均線を計算し、インディケータ配列に入力します。
//
//return(rates_total);int OnCalculate()の始に戻ります。
//
//------------------------------
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
//Print("begin = ",begin);
   if(rates_total<InpPeriodSMA-1+begin)
      return(0);
//---
   if(prev_calculated==0)
     {
      ArrayInitialize(ExtMIBuffer,0);
      ArrayInitialize(ExtMIBufferH,0);
      ArrayInitialize(ExtMIBufferL,0);
     }
//---
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpPeriodSMA-1+begin);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpPeriodSMA-1+begin);
   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpPeriodSMA-1+begin);
   CalculateSimpleMA(rates_total,prev_calculated,begin,price);
   return(rates_total);
  }
  
//
void CalculateSimpleMA(int rates_total,int prev_calculated,
                       int begin,const double &price[])
  {
   int i,limit;
//--- 指標の計算が始めてのときの計算。
//
//プロットの02番に0.0を入力
   if(prev_calculated==0)
     {
      limit=InpPeriodSMA+begin;
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++)
        {
         ExtMIBuffer [i]=0.0;
         ExtMIBufferH[i]=0.0;
         ExtMIBufferL[i]=0.0;
        }
      //プロットの02番の
      //単純移動平均と、
      //inputしたInpMABand=0.2(%)の上下エンベロープを計算。
      double firstValue=0;
      for(i=begin;i<limit;i++) firstValue+=price[i];
      firstValue/=InpPeriodSMA;
      ExtMIBuffer[limit-1]=firstValue;
      ExtMIBufferH[limit-1]=firstValue*(1+0.01*InpMABand);
      ExtMIBufferL[limit-1]=firstValue*(1-0.01*InpMABand);
     }
//--- 指標の計算が1回目以降のときの計算はここから。
   else limit=prev_calculated-1;
//---ここで大切なのはsum1 +=price[i-j]の計算です。
//ここを押えておく必要があります。
//irates_totalへ増えていき、
//i-jiの位置から減っていきます。
   for(i=limit;i<rates_total && !IsStopped();i++) //
     {
      double sum1=0;
      double sum2=0;
      double sum3=0;
      for(int j=0;j<InpPeriodSMA;j++) sum1+=price[i-j];
      sum1=sum1/InpPeriodSMA;
      ExtMIBuffer[i]=sum1;
      sum2 =sum1+(0.01)*InpMABand*sum1;
      sum3 =sum1-(0.01)*InpMABand*sum1;
      ExtMIBufferH[i]=sum2;
      ExtMIBufferL[i]=sum3;
     }
//---
  }
//---END---------------------------------------------------