//+------------------------------------------------------------------+
//|   Qualitative Quantitative Estimation Indicator for Metatrader 4 |
//|                                    Copyright © 2006Roman Ignatov |
//|                                   mailto:roman.ignatov@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 200 Roman Ignatov"
#property link      "mailto:roman.ignatov@gmail.com"

#property indicator_separate_window

#property indicator_level1 50.0
#property indicator_levelcolor Silver
#property indicator_levelwidth 1
#property indicator_levelstyle 2

#property indicator_buffers 3

#property indicator_color1 DodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

#property indicator_color2 PaleGoldenrod
#property indicator_style2 STYLE_DOT

#property indicator_color3 Gold
#property indicator_style3 STYLE_DOT


extern int SF = 5; // original 5
extern int RSI_Period = 14; // original 14
extern double DARFACTOR_Slow = 4.236; //original 4.236
extern double DARFACTOR_Fast = 2.618; //original 2.618


int Wilders_Period;
int StartBar;

double TrLevelSlow[];
double TrLevelFast[];
double AtrRsi[];
double MaAtrRsi[];
double Rsi[];
double RsiMa[];

int init()
{
    Wilders_Period = RSI_Period * 2 - 1;
    if (Wilders_Period < SF)
        StartBar = SF;
    else
        StartBar = Wilders_Period;

    IndicatorBuffers(6);

    SetIndexBuffer(0, RsiMa);
    SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 1);
    SetIndexLabel(0, "Value 1");
    SetIndexDrawBegin(0, StartBar);

    SetIndexStyle(1, DRAW_LINE, STYLE_DOT);
    SetIndexBuffer(1, TrLevelSlow);
    SetIndexLabel(1, "Value 2");
    SetIndexDrawBegin(1, StartBar);

    SetIndexStyle(2, DRAW_LINE, STYLE_DOT);
    SetIndexBuffer(2, TrLevelFast);
    SetIndexLabel(2, "Value 3");
    SetIndexDrawBegin(2, StartBar);

    SetIndexBuffer(3, AtrRsi);
    SetIndexBuffer(4, MaAtrRsi);
    SetIndexBuffer(5, Rsi);
    IndicatorShortName(StringConcatenate("QQE(", SF, ")"));
    return(0);
}


int start(){
    int counted, i;
    double rsi0, rsi1;
    double darSlow, tr, dv;
    double darFast, trFast, dvFast;
    
    if(Bars <= StartBar)
        return (0);

    counted = IndicatorCounted();
    if(counted < 1)
        for(i = Bars - StartBar; i < Bars; i++){
            TrLevelFast[i] = 0.0;
            TrLevelSlow[i] = 0.0;
            AtrRsi[i] = 0.0;
            MaAtrRsi[i] = 0.0;
            Rsi[i] = 0.0;
            RsiMa[i] = 0.0;
        }
    
    counted = Bars - counted - 1;
        
    for (i = counted; i >= 0; i--){
        Rsi[i] = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, i);
    }

    for (i = counted; i >= 0; i--){
        RsiMa[i] = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
        AtrRsi[i] = MathAbs(RsiMa[i + 1] - RsiMa[i]);
    }

    for (i = counted; i >= 0; i--){
        MaAtrRsi[i] = iMAOnArray(AtrRsi, 0, Wilders_Period, 0, MODE_EMA, i);
    }

    i = counted + 1;
    tr = TrLevelSlow[i];
    trFast = TrLevelFast[i];
    rsi1 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
    while (i > 0){
        i--;
        rsi0 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
        
        /* For the Slow */
        darSlow = iMAOnArray(MaAtrRsi, 0, Wilders_Period, 0, MODE_EMA, i) * DARFACTOR_Slow;

        dv = tr;
        if (rsi0 < tr){
            tr = rsi0 + darSlow;
            if (rsi1 < dv){
                if (tr > dv){
                    tr = dv;
                }
            }
        }
        else if (rsi0 > tr){
            tr = rsi0 - darSlow;
            if (rsi1 > dv){
                if (tr < dv){
                    tr = dv;
                }
            }
        }
        TrLevelSlow[i] = tr;
        /* END */
        /* For the Fast */
        darFast = iMAOnArray(MaAtrRsi, 0, Wilders_Period, 0, MODE_EMA, i) * DARFACTOR_Fast;
        
        dvFast = trFast;
        if (rsi0 < trFast){
            trFast = rsi0 + darFast;
            if (rsi1 < dvFast){
                if (trFast > dvFast){
                    trFast = dvFast;
                }
            }
        }
        else if (rsi0 > trFast){
            trFast = rsi0 - darFast;
            if (rsi1 > dvFast){
                if (trFast < dvFast){
                    trFast = dvFast;
                }
            }
        }
        TrLevelFast[i] = trFast;        
        /* END */
        
        rsi1 = rsi0;
    }
    
    return(0);
}