マルチタイムフレームの移動平均線がクロス(シフトしたMA)したら縦線を挿入するソースコードを教えてください。 - ページ 2

 

下記のプログラムは私が以前に作成したもので、ここで取り扱った方法とは違います。

時間枠の指定は1つだけで、2つのMAに違う時間枠を割り当てることはできません。別々に指定するのは複雑過ぎて、恐らく無理です。

シフトはMA2だけに指定していますが、追加によりMA1にも割り当てることができます。

MAは完全に滑らかな曲線にはなりません。所々やや不自然な部分が出ますが元々そういう仕様です。

完全に滑らかな曲線が希望なら、MA本数を倍数指定(例えば5分足に1時間足を表示なら12倍)して疑似的なMTFを表示する方が楽です。

//+------------------------------------------------------------------+
//|                                                 MTF_Sample_4.mq4 |
//|                                                    Naguisa Unada |
//|                    https://www.mql5.com/en/users/unadajapon/news |
//+------------------------------------------------------------------+
#property copyright "Naguisa Unada"
#property link      "https://www.mql5.com/en/users/unadajapon/news"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
#define _mtfCall(_buff, _y) iCustom(NULL, TimeFrame, IndicatorFileName, PERIOD_CURRENT, MA1_Period, MA2_Period, MA_Method, MA_Price, Shift, _buff, _y)
#define _interpolate(buff) buff[i + k] = buff[i] + (buff[i + n] - buff[i]) * k / n
//--- plot MA
#property indicator_label1  "Moving Average 1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- plot MA
#property indicator_label2  "Moving Average 2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
//--- plot Arrow
#property indicator_label3  "Up Arrow"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrAqua
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Arrow
#property indicator_label4  "Down Arrow"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- input parameters
input ENUM_TIMEFRAMES      TimeFrame   = PERIOD_CURRENT; //時間枠
input int                  MA1_Period  = 24;             //計算本数1
input int                  MA2_Period  = 48;             //計算本数2
input ENUM_MA_METHOD       MA_Method   = MODE_SMA;       //計算方式
input ENUM_APPLIED_PRICE   MA_Price    = PRICE_CLOSE;    //適用価格
input int                  Shift       = 0;              //MA2 シフト
input bool                 Interpolate = true;           //ギザギザを修正
input bool                 Alert_ON    = true;           //アラートを許可
input int                  Alert_bar   = 0;              //アラートタイミング
input bool                 Show_Arrow  = true;           //矢印を表示
//--- indicator buffers
double         MA1_Buffer[];
double         MA2_Buffer[];
double         ArrUp_Buffer[];
double         ArrDn_Buffer[];
string         IndicatorFileName;
int            tFrame;
datetime       Up_time = D'2000.01.01 00:00';
datetime       Dn_time = D'2000.01.01 00:00';
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, MA1_Buffer);
   SetIndexBuffer(1, MA2_Buffer);
   SetIndexBuffer(2, ArrUp_Buffer);
   SetIndexBuffer(3, ArrDn_Buffer);

   SetIndexShift(1, Shift);
   SetIndexArrow(2, 233);
   SetIndexArrow(3, 234);
   //----
   if (TimeFrame < Period())
      tFrame = Period();
   else
      tFrame = TimeFrame;

   string TimeFrameStr = GetTimeFrameString(tFrame);
   string short_name = "Moving Average(" + IntegerToString(MA1_Period) + "," + IntegerToString(MA2_Period) + ") " + TimeFrameStr;
   IndicatorShortName(short_name);
   IndicatorFileName = WindowExpertName();
   //---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   //----
   //----
}
//+------------------------------------------------------------------+
//| 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[])
{
   //---
   int i, y, n, k, j, limit;
   datetime ctime;
   double Total, Gap;

   if (prev_calculated < 0)
      return(-1);
   if (prev_calculated == 0)
      limit = rates_total - MathMax(MA1_Period, MA2_Period);
   else
      limit = rates_total - prev_calculated + 1;

   if (tFrame == Period())
   {
      for (i = limit; i >= 0; i--)
      {
         MA1_Buffer[i] = iMA(NULL, PERIOD_CURRENT, MA1_Period, 0, MA_Method, MA_Price, i);
         MA2_Buffer[i] = iMA(NULL, PERIOD_CURRENT, MA2_Period, 0, MA_Method, MA_Price, i);
      }
   }
   else
   {
      limit = (int)MathMax(limit, MathMin(rates_total - MathMax(MA1_Period, MA2_Period), (limit + 1) * tFrame / Period()));

      for (i = limit; i >= 0; i--)
      {
         y = iBarShift(NULL, tFrame, time[i]);

         MA1_Buffer[i] = _mtfCall(0, y);
         MA2_Buffer[i] = _mtfCall(1, y);

         if (!Interpolate || (i > 0 && y == iBarShift(NULL, tFrame, time[i - 1])))
            continue;

         ctime = iTime(NULL, tFrame, y);

         for (n = 1; (i + n) < rates_total && time[i + n] >= ctime; n++)
            continue;

         for (k = 1; k < n && (i + n) < rates_total && (i + k) < rates_total; k++)
         {
            _interpolate(MA1_Buffer);
            _interpolate(MA2_Buffer);
         }
      }
   }

   if (Show_Arrow)
   {
      for (i = limit; i >= 0; i--)
      {
         Total = 0.0;
         for (j = i; j < i + 10; j++)
            Total += high[j] - low[j];
         Gap = Total / 10;

         if (MA1_Buffer[i] > MA2_Buffer[i] && MA1_Buffer[i + 1] < MA2_Buffer[i + 1])
            ArrUp_Buffer[i] = MA1_Buffer[i] - Gap;
         else
            ArrUp_Buffer[i] = EMPTY_VALUE;

         if (MA1_Buffer[i] < MA2_Buffer[i] && MA1_Buffer[i + 1] > MA2_Buffer[i + 1])
            ArrDn_Buffer[i] = MA1_Buffer[i] + Gap;
         else
            ArrDn_Buffer[i] = EMPTY_VALUE;
      }
   }

   if (Alert_ON)
      Do_Alert(Alert_bar);
   //--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
string GetTimeFrameString(int timeFrame)
{
   string TimeFrameStr;

   if (timeFrame == PERIOD_CURRENT)
      timeFrame = Period();

   switch(timeFrame)
   {
   case PERIOD_M1 :
      TimeFrameStr = "M1";
      break;
   case PERIOD_M5 :
      TimeFrameStr = "M5";
      break;
   case PERIOD_M15 :
      TimeFrameStr = "M15";
      break;
   case PERIOD_M30 :
      TimeFrameStr = "M30";
      break;
   case PERIOD_H1 :
      TimeFrameStr = "H1";
      break;
   case PERIOD_H4 :
      TimeFrameStr = "H4";
      break;
   case PERIOD_D1 :
      TimeFrameStr = "D1";
      break;
   case PERIOD_W1 :
      TimeFrameStr = "W1";
      break;
   case PERIOD_MN1 :
      TimeFrameStr = "MN1";
      break;
   }

   return(TimeFrameStr);
}
//+------------------------------------------------------------------+
void Do_Alert(int i)
{
   if (Up_time != Time[i] && MA1_Buffer[i] > MA2_Buffer[i] && MA1_Buffer[i + 1] < MA2_Buffer[i + 1])
   {
      Alert(StringSubstr(Symbol(), 0, 6) + " - " + GetTimeFrameString(tFrame) + " --- Up Trend");
      Up_time = Time[i];
   }

   if (Dn_time != Time[i] && MA1_Buffer[i] < MA2_Buffer[i] && MA1_Buffer[i + 1] > MA2_Buffer[i + 1])
   {
      Alert(StringSubstr(Symbol(), 0, 6) + " - " + GetTimeFrameString(tFrame) + " --- Down Trend");
      Dn_time = Time[i];
   }
}
//+------------------------------------------------------------------+
理由: