//+------------------------------------------------------------------+
//|                                                   SuperTrend.mq5 |
//|                                               eATR version       |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, FxGeek"
#property link      "http://www.mql5.com"
#property version   "1.03"
#property indicator_chart_window

// プロット: 0=Filling, 1=SuperTrend, 2=TrendFlag (データウィンドウ用)
#property indicator_plots 3
// バッファ数（Filling×2 + SuperTrend×2 + TrendFlag×1 + 計算用5）
#property indicator_buffers 10

// Plot0: Filling
#property indicator_label1 "Filling"
#property indicator_type1  DRAW_FILLING
#property indicator_color1 clrGray, clrGray

// Plot1: SuperTrend (カラーライン)
#property indicator_label2 "SuperTrend"
#property indicator_type2  DRAW_COLOR_LINE
#property indicator_color2 clrGreen, clrRed, clrNONE
#property indicator_width2 2

// Plot2: TrendFlag（描画なし・データウィンドウ表示のみ）
#property indicator_label3 "TrendFlag (Up=1,Down=0)"
#property indicator_type3  DRAW_NONE
#property indicator_color3 clrWhite
#property indicator_width3 1

// 中央値の計算方法
enum ENUM_MIDDLE_TYPE
{
   MIDDLE_OPEN,   // 始値
   MIDDLE_HIGH,   // 高値
   MIDDLE_LOW,    // 安値
   MIDDLE_CLOSE,  // 終値
   MIDDLE_HL,     // 高値+安値の平均
   MIDDLE_HLC,    // 高値+安値+終値の平均
   MIDDLE_OHLC,   // 始値+高値+安値+終値の平均
   MIDDLE_HLCC    // 高値+安値+終値x2の平均
};

input int            Periode     = 10;
input double         Multiplier  = 2.0;
input bool           Show_Filling = false;                 // DRAW_FILLINGのON/OFF
input ENUM_MIDDLE_TYPE MiddleType = MIDDLE_HLCC; // 中央値の計算方法

//--- バッファ
double Filled_a[];    // Plot0 buf#0
double Filled_b[];    // Plot0 buf#1
double SuperTrend[];  // Plot1 buf#2 (data)
double ColorBuffer[]; // Plot1 buf#3 (color index)
double TrendFlag[];   // Plot2 buf#4 (Up=1/Down=0) ← データウィンドウ用

// 計算用（データウィンドウ非表示）
double Atr[];    // buf#5  ← eATR(EMA ATR)を格納
double Up[];     // buf#6
double Down[];   // buf#7
double Middle[]; // buf#8
double trend[];  // buf#9

int changeOfTrend;
int flag;
int flagh;

//+------------------------------------------------------------------+
//| OnInit                                                           |
//+------------------------------------------------------------------+
int OnInit()
{
   // まず「プロットが消費する順」に先頭から割り当てる
   SetIndexBuffer(0, Filled_a, INDICATOR_DATA);           // Plot0
   SetIndexBuffer(1, Filled_b, INDICATOR_DATA);           // Plot0

   SetIndexBuffer(2, SuperTrend, INDICATOR_DATA);         // Plot1 data
   SetIndexBuffer(3, ColorBuffer, INDICATOR_COLOR_INDEX); // Plot1 color

   SetIndexBuffer(4, TrendFlag, INDICATOR_DATA);          // Plot2 （データウィンドウ）

   // 残りは計算用
   SetIndexBuffer(5, Atr,    INDICATOR_CALCULATIONS);
   SetIndexBuffer(6, Up,     INDICATOR_CALCULATIONS);
   SetIndexBuffer(7, Down,   INDICATOR_CALCULATIONS);
   SetIndexBuffer(8, Middle, INDICATOR_CALCULATIONS);
   SetIndexBuffer(9, trend,  INDICATOR_CALCULATIONS);

   // 必要なら桁数設定なども可能
   // IndicatorSetInteger(INDICATOR_DIGITS, _Digits);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| OnCalculate                                                      |
//+------------------------------------------------------------------+
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[])
{
   if(rates_total <= Periode + 2)
      return(prev_calculated); // バッファ不足時は何もしない

   //--- (1) eATR を計算する ---------------------------------------
   // MQLの配列は series（0=最新, rates_total-1=最古）なので、
   // 最古バーから最新バーへ向かうように i = rates_total-1 → 0 へループし、
   // Atr[i] = alpha * TR[i] + (1-alpha) * Atr[i+1] とする。
   double alpha = 2.0 / (Periode + 1.0);

   // 最古バーから計算
   for(int i = rates_total - 1; i >= 0; i--)
   {
      double tr;

      if(i == rates_total - 1)
      {
         // 一番古いバーは前日終値がないので High-Low のみ
         tr = high[i] - low[i];
         Atr[i] = tr;  // 初期値
      }
      else
      {
         double range1 = high[i] - low[i];
         double range2 = MathAbs(high[i] - close[i + 1]);
         double range3 = MathAbs(low[i]  - close[i + 1]);
         tr = MathMax(range1, MathMax(range2, range3));

         // EMA で平滑化した eATR
         Atr[i] = alpha * tr + (1.0 - alpha) * Atr[i + 1];
      }
   }

   //--- (2) SuperTrend 本体の計算 ----------------------------------

   // 計算開始インデックス
   int first;
   if(prev_calculated > rates_total || prev_calculated <= 0)
   {
      first = Periode;

      // 初期区間は未定義表示にしておく
      for(int k = 0; k < first && k < rates_total; ++k)
      {
         Filled_a[k]   = EMPTY_VALUE;
         Filled_b[k]   = EMPTY_VALUE;
         SuperTrend[k] = EMPTY_VALUE;
         TrendFlag[k]  = EMPTY_VALUE;
      }
   }
   else
   {
      first = prev_calculated - 1;
   }

   // 本体ループ
   for(int i = first; i < rates_total && !IsStopped(); i++)
   {
      // --- 中央値の計算 ------------------------------------------
      switch(MiddleType)
      {
         case MIDDLE_OPEN:
            Middle[i] = open[i];
            break;
         case MIDDLE_HIGH:
            Middle[i] = high[i];
            break;
         case MIDDLE_LOW:
            Middle[i] = low[i];
            break;
         case MIDDLE_CLOSE:
            Middle[i] = close[i];
            break;
         case MIDDLE_HL:
            Middle[i] = (high[i] + low[i]) / 2.0;
            break;
         case MIDDLE_HLC:
            Middle[i] = (high[i] + low[i] + close[i]) / 3.0;
            break;
         case MIDDLE_OHLC:
            Middle[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
            break;
         case MIDDLE_HLCC:
            Middle[i] = (high[i] + low[i] + 2.0 * close[i]) / 4.0;
            break;
      }

      // --- eATR を使用して Up/Down バンド ------------------------
      Up[i]   = Middle[i] + (Multiplier * Atr[i]);
      Down[i] = Middle[i] - (Multiplier * Atr[i]);

      // --- トレンド判定 ------------------------------------------
      if(close[i] > Up[i - 1])
      {
         trend[i] = 1;
         if(trend[i - 1] == -1)
            changeOfTrend = 1;
      }
      else if(close[i] < Down[i - 1])
      {
         trend[i] = -1;
         if(trend[i - 1] == 1)
            changeOfTrend = 1;
      }
      else if(trend[i - 1] == 1)
      {
         trend[i]      = 1;
         changeOfTrend = 0;
      }
      else if(trend[i - 1] == -1)
      {
         trend[i]      = -1;
         changeOfTrend = 0;
      }

      // --- 交差フラグ --------------------------------------------
      flag  = (trend[i] < 0 && trend[i - 1] > 0) ? 1 : 0;
      flagh = (trend[i] > 0 && trend[i - 1] < 0) ? 1 : 0;

      // --- バンドの継続補正 --------------------------------------
      if(trend[i] > 0 && Down[i] < Down[i - 1])
         Down[i] = Down[i - 1];
      if(trend[i] < 0 && Up[i] > Up[i - 1])
         Up[i] = Up[i - 1];

      if(flag == 1)
         Up[i] = Middle[i] - (-Multiplier * Atr[i]);   // = Middle + Multiplier*ATR
      if(flagh == 1)
         Down[i] = Middle[i] + (-Multiplier * Atr[i]); // = Middle - Multiplier*ATR

      // --- SuperTrend と色 ----------------------------------------
      if(trend[i] == 1)
      {
         SuperTrend[i] = Down[i];
         if(changeOfTrend == 1)
         {
            SuperTrend[i - 1] = SuperTrend[i - 2];
            changeOfTrend     = 0;
            ColorBuffer[i]    = 2.0; // 無色
            ColorBuffer[i - 1]= 2.0; // 無色
         }
         else
         {
            ColorBuffer[i] = 0.0; // Green
         }
      }
      else // trend[i] == -1
      {
         SuperTrend[i] = Up[i];
         if(changeOfTrend == 1)
         {
            SuperTrend[i - 1] = SuperTrend[i - 2];
            changeOfTrend     = 0;
            ColorBuffer[i]    = 2.0; // 無色
            ColorBuffer[i - 1]= 2.0; // 無色
         }
         else
         {
            ColorBuffer[i] = 1.0; // Red
         }
      }

      // --- TrendFlag: Up=1 / Down=0 ------------------------------
      TrendFlag[i] = (trend[i] == 1) ? 1.0 : 0.0;

      // --- Filling の可否 ----------------------------------------
      if(Show_Filling)
      {
         Filled_a[i] = SuperTrend[i];
         Filled_b[i] = close[i];
      }
      else
      {
         Filled_a[i] = EMPTY_VALUE;
         Filled_b[i] = EMPTY_VALUE;
      }
   }

   return(rates_total);
}
//+------------------------------------------------------------------+
