//+------------------------------------------------------------------+
//|                                                   SuperTrend.mq5 |
//|                                           Copyright 2011, FxGeek |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, FxGeek"
#property link "http://www.mql5.com"
#property version "1.02"
#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
double Up[];     // buf#61
double Down[];   // buf#7
double Middle[]; // buf#8
double trend[];  // buf#9

int atrHandle;
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);

    atrHandle = iATR(_Symbol, _Period, Periode);
    if (atrHandle == INVALID_HANDLE)
    {
        Print(__FUNCTION__, ": iATR handle error. err=", GetLastError());
        return (INIT_FAILED);
    }

    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); // バッファ不足時は何もしない

    // ATR コピー本数の算定
    int to_copy;
    if (prev_calculated > rates_total || prev_calculated < 0)
        to_copy = rates_total;
    else
    {
        to_copy = rates_total - prev_calculated;
        if (prev_calculated > 0)
            to_copy++;
    }

    if (IsStopped())
        return (prev_calculated);

    if (CopyBuffer(atrHandle, 0, 0, to_copy, Atr) <= 0)
    {
        Print("Getting ATR failed. err=", GetLastError());
        return (prev_calculated);
    }

    // 計算開始インデックス
    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;
        }

        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);
}
//+------------------------------------------------------------------+
