I'm trying to convert a particular QQE indicator written in pine language (TradingView) to MQ5 for MT5 and facing issues

 

Hi,

I'm new to MQL5 programming and have been going through different API functions trying to see what works. Unfortunately I'm facing a lot of trouble in trying to convert the logic from a basic QQE indicator (written in pine) to an MT5 indicator.

The indicator should just plot two lines. The trend line (FastAtrRsiTL), and the RSI line (RsiMa).

I first started writing code without compiling, and then when I felt that the logic was 90% there I kept working to the point that everything compiles without warnings or errors.

I'm unable to see the lines and I'm confused both with OnInit() and OnExecute() logic.



Here is the pine script with the required logic:

study("QQE")

RSI_Period = input(14,title='RSI')

SF = input(5,title='Slow Factor')

QQE=input(1.618)



Wilders_Period = RSI_Period * 2 - 1



Rsi = rsi(close,RSI_Period)

RsiMa = ema(Rsi, SF)

AtrRsi = abs(RsiMa[1] - RsiMa)

MaAtrRsi = ema(AtrRsi, Wilders_Period)

dar = ema(MaAtrRsi,Wilders_Period) * QQE





DeltaFastAtrRsi= dar

RSIndex=RsiMa

newshortband=  RSIndex + DeltaFastAtrRsi

newlongband= RSIndex - DeltaFastAtrRsi

longband=RSIndex[1] > longband[1] and RSIndex > longband[1]?

 max(longband[1],newlongband):newlongband

shortband=RSIndex[1] < shortband[1] and  RSIndex < shortband[1]?

 min(shortband[1], newshortband):newshortband

trend=cross(RSIndex, shortband[1])?1:cross(longband[1], RSIndex)?-1:nz(trend[1],1)

FastAtrRsiTL = trend==1? longband: shortband



plot(FastAtrRsiTL,color=red)

plot(RsiMa,color=green)




Here is my effort to convert this to a working MT5 indicator (.mq5):

#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30
#property indicator_level2 70
#property indicator_buffers 9
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  clrGreen
#property indicator_color2  clrRed
#property indicator_label1  "FastAtrRsiTL"
#property indicator_label2  "RSIndex"


input int RSI_Period = 14;
input int SF = 5;
input double QQE_factor = 1.618;

double Rsi[];
double RsiMa[];
double AtrRsi[];
double MaAtrRsi[];
double dar[];
double longband[];
double shortband[];
double RSIndex[];
double FastAtrRsiTL[];
int totalBars = Bars(Symbol(), Period());
int Wilders_Period;
int StartBar;

int OnInit()
{
    IndicatorSetString(INDICATOR_SHORTNAME, "QQE exactrade");

    Wilders_Period = (RSI_Period * 2) - 1;
    
    ArrayInitialize(Rsi, 0.0);
    ArrayInitialize(RsiMa, 0.0);
    ArrayInitialize(AtrRsi, 0.0);
    ArrayInitialize(MaAtrRsi, 0.0);
    ArrayInitialize(dar, 0.0);
    ArrayInitialize(longband, 0.0);
    ArrayInitialize(shortband, 0.0);
    ArrayInitialize(RSIndex, 0.0);
    ArrayInitialize(FastAtrRsiTL, 0.0);

    ArrayResize(Rsi, totalBars);
    ArrayResize(RsiMa, totalBars);
    ArrayResize(AtrRsi, totalBars);
    ArrayResize(MaAtrRsi, totalBars);
    ArrayResize(dar, totalBars);
    ArrayResize(longband, totalBars);
    ArrayResize(shortband, totalBars);
    ArrayResize(RSIndex, totalBars);
    ArrayResize(FastAtrRsiTL, totalBars);

    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, RSI_Period);
    PlotIndexSetInteger(0, PLOT_LINE_STYLE, STYLE_SOLID);
    PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 1);
    PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrRed);
    PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, RSI_Period);
    PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_SOLID);
    PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 1);
    PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrGreen);
    IndicatorSetInteger(INDICATOR_DIGITS, 3);

    // Set index buffers and plot lines
    SetIndexBuffer(0, FastAtrRsiTL, INDICATOR_DATA);
    SetIndexBuffer(1, RsiMa, INDICATOR_DATA);
    SetIndexBuffer(2, Rsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, AtrRsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(4, MaAtrRsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(5, dar, INDICATOR_CALCULATIONS);
    SetIndexBuffer(6, longband, INDICATOR_CALCULATIONS);
    SetIndexBuffer(7, shortband, INDICATOR_CALCULATIONS);
    SetIndexBuffer(8, RSIndex, INDICATOR_CALCULATIONS);

    return INIT_SUCCEEDED;
}


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 limit = rates_total - prev_calculated;
    int startBar = prev_calculated;

    for (int i = startBar; i < rates_total; i++)
    {
        // Calculate RSI
        Rsi[i] = iRSI(Symbol(), Period(), RSI_Period, PRICE_CLOSE);

        // Calculate RSI Moving Average
        RsiMa[i] = iMAOnArray(Rsi, totalBars, SF, 0, MODE_EMA, i);

        // Calculate ATR RSI
        AtrRsi[i] = MathAbs(RsiMa[i - 1] - RsiMa[i]);

        // Calculate MA ATR RSI
        MaAtrRsi[i] = iMAOnArray(AtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i);

        // Calculate Delta Fast ATR RSI
        dar[i] = iMAOnArray(MaAtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i) * QQE_factor;

        double DeltaFastAtrRsi = dar[i];

        // Calculate new shortband and longband values
        double newshortband = RsiMa[i] + DeltaFastAtrRsi;
        double newlongband = RsiMa[i] - DeltaFastAtrRsi;

        // Crossover condition: RsiMa crosses above longband
        if (RsiMa[i - 1] > longband[i - 1] && RsiMa[i] > longband[i - 1])
        {

            longband[i] = MathMax(longband[i - 1], newlongband);
        }
        else
        {
            longband[i] = newlongband;
        }

        // Crossover condition: RsiMa crosses below shortband
        if (RsiMa[i - 1] < shortband[i - 1] && RsiMa[i] < shortband[i - 1])
        {
            shortband[i] = MathMin(shortband[i - 1], newshortband);
        }
        else
        {
            shortband[i] = newshortband;
        }

        // Determine the value of FastAtrRsiTL based on trend
        if (RsiMa[i] > shortband[i - 1] && RsiMa[i - 1] < shortband[i - 1])
        {
            // Trend is up
            FastAtrRsiTL[i] = longband[i];
        }
        else if (RsiMa[i] < longband[i - 1] && RsiMa[i - 1] > longband[i - 1])
        {
            // Trend is down
            FastAtrRsiTL[i] = shortband[i];
        }
    }

    return rates_total;
}





/* MQL5 implementation of iMAOnArray by Budyoni Damyanov */
double iMAOnArray(double& array[], int total, int period, int ma_shift, ENUM_MA_METHOD ma_method, int shift)
{
    double buf[];
    ArrayResize(buf, total);

    switch (ma_method)
    {
        case MODE_SMA:
        {
            double sum = 0;
            int pos = total - 1;

            for (int i = 1; i < period; i++, pos--)
                sum += array[pos];

            while (pos >= 0)
            {
                sum += array[pos];
                buf[pos] = sum / period;
                sum -= array[pos + period - 1];
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_EMA:
        {
            double pr = 2.0 / (period + 1);
            int pos = total - 2;

            while (pos >= 0)
            {
                if (pos == total - 2)
                    buf[pos + 1] = array[pos + 1];
                
                buf[pos] = array[pos] * pr + buf[pos + 1] * (1 - pr);
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_SMMA:
        {
            double sum = 0;

            int pos = total - period;

            while (pos >= 0)
            {
                if (pos == total - period)
                {
                    sum = 0;
                    for (int i = 0, k = pos; i < period; i++, k++)
                    {
                        sum += array[k];
                        buf[k] = 0;
                    }
                }
                else
                {
                    sum = buf[pos + 1] * (period - 1) + array[pos];
                }

                buf[pos] = sum / period;
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_LWMA:
        {
            double sum = 0.0, lsum = 0.0;
            double price;
            int weight = 0, pos = total - 1;

            for (int i = 1; i <= period; i++, pos--)
            {
                price = array[pos];
                sum += price * i;
                lsum += price;
                weight += i;
            }

            pos++;
            int i = pos + period;

            while (pos >= 0)
            {
                buf[pos] = sum / weight;

                if (pos == 0)
                    break;

                pos--;
                i--;

                price = array[pos];
                sum = sum - lsum + price * period;
                lsum -= array[i];
                lsum += price;
            }

            return buf[shift + ma_shift];
        }
    }

    return 0;
}
 
phade:

Hi,

I'm new to MQL5 programming and have been going through different API functions trying to see what works. Unfortunately I'm facing a lot of trouble in trying to convert the logic from a basic QQE indicator (written in pine) to an MT5 indicator.

The indicator should just plot two lines. The trend line (FastAtrRsiTL), and the RSI line (RsiMa).

I first started writing code without compiling, and then when I felt that the logic was 90% there I kept working to the point that everything compiles without warnings or errors.

I'm unable to see the lines and I'm confused both with OnInit() and OnExecute() logic.



Here is the pine script with the required logic:




Here is my effort to convert this to a working MT5 indicator (.mq5):

I haven't checked beyond this, but that needs fixing:


int handle = INVALID_HANDLE;
OnInit() { handle = iRSI(); }

OnCalculate()
{
double buffer[];
CopyBuffer(handle, ..., buffer);
}
 
phade:

Hi,

I'm new to MQL5 programming and have been going through different API functions trying to see what works. Unfortunately I'm facing a lot of trouble in trying to convert the logic from a basic QQE indicator (written in pine) to an MT5 indicator.

The indicator should just plot two lines. The trend line (FastAtrRsiTL), and the RSI line (RsiMa).

I first started writing code without compiling, and then when I felt that the logic was 90% there I kept working to the point that everything compiles without warnings or errors.

I'm unable to see the lines and I'm confused both with OnInit() and OnExecute() logic.



Here is the pine script with the required logic:




Here is my effort to convert this to a working MT5 indicator (.mq5):

Your loop needs to start here, if you want ontick updates:

    int startBar = prev_calculated - (prev_calculated == rates_total);;
EDIT:

You can spare ArrayInitialize and ArrayResize, if you hand them to the Framework.

    SetIndexBuffer(3, AtrRsi, INDICATOR_CALCULATIONS);

EDIT2:

You should remove this, and use rates_total instead.

int totalBars = Bars(Symbol(), Period());

EDIT3:

Use comments to give description in the input dialog.

input int RSI_Period = 14; // RSI periods to use

EDIT4:

I don't know how you want it to be, but you could adapt to the symbol here

    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
 
phade:

Hi,

I'm new to MQL5 programming and have been going through different API functions trying to see what works. Unfortunately I'm facing a lot of trouble in trying to convert the logic from a basic QQE indicator (written in pine) to an MT5 indicator.

The indicator should just plot two lines. The trend line (FastAtrRsiTL), and the RSI line (RsiMa).

I first started writing code without compiling, and then when I felt that the logic was 90% there I kept working to the point that everything compiles without warnings or errors.

I'm unable to see the lines and I'm confused both with OnInit() and OnExecute() logic.



Here is the pine script with the required logic:




Here is my effort to convert this to a working MT5 indicator (.mq5):

Here is another issue, if you are not using this, so delete it:

    int limit = rates_total - prev_calculated;

Also, you are doing this:

RsiMa[i - 1]
Since you start your loop here:

for (int i = startBar; i < rates_total; i++)
You might end up with i == 0, and i-1 == -1 which will end up in an access violation on the array.

Therefore is suggest changing your start to something like this:

for (int i = MathMax(startBar, RSI_Period); i < rates_total; i++)

EDIT:

Also, please check the results of your CopyBuffer function call, if it failes, immediately return from OnCalculate like this, without doing any calculations:

    return prev_calculated;
 

Thank you. I took your suggestions and now the code is modified to this (see code block).


I am seeing the lines now, and it's visually what I wanted. But I face a strange problem now - when I change to other timeframes, the lines disappear. The indicator is always showing 0 digits as well, it looks like it has trouble updating or something.


#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30
#property indicator_level2 70
#property indicator_buffers 9
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  clrGreen
#property indicator_color2  clrRed
#property indicator_label1  "FastAtrRsiTL"
#property indicator_label2  "RSIndex"


input int RSI_Period = 14;
input int SF = 5;
input double QQE_factor = 1.618;

double Rsi[];
double RsiMa[];
double AtrRsi[];
double MaAtrRsi[];
double dar[];
double longband[];
double shortband[];
double RSIndex[];
double FastAtrRsiTL[];
int totalBars = Bars(Symbol(), Period());
int Wilders_Period;
int StartBar;

int rsiHandle = INVALID_HANDLE;

int OnInit()
{
    IndicatorSetString(INDICATOR_SHORTNAME, "QQE exactrade");

    Wilders_Period = RSI_Period * 2 - 1;
    
    // Get handle of RSI indicator
    rsiHandle = iRSI(Symbol(), Period(), RSI_Period, PRICE_CLOSE);

    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, RSI_Period);
    PlotIndexSetInteger(0, PLOT_LINE_STYLE, STYLE_SOLID);
    PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 1);
    PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrRed);
    PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, RSI_Period);
    PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_SOLID);
    PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 1);
    PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrGreen);
    IndicatorSetInteger(INDICATOR_DIGITS, 3);

    // Set index buffers and plot lines
    SetIndexBuffer(0, FastAtrRsiTL, INDICATOR_DATA);
    SetIndexBuffer(1, RsiMa, INDICATOR_DATA);
    SetIndexBuffer(2, Rsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, AtrRsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(4, MaAtrRsi, INDICATOR_CALCULATIONS);
    SetIndexBuffer(5, dar, INDICATOR_CALCULATIONS);
    SetIndexBuffer(6, longband, INDICATOR_CALCULATIONS);
    SetIndexBuffer(7, shortband, INDICATOR_CALCULATIONS);
    SetIndexBuffer(8, RSIndex, INDICATOR_CALCULATIONS);

    return INIT_SUCCEEDED;
}


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 startBar = prev_calculated - (prev_calculated == rates_total);
    int limit = rates_total - prev_calculated;
    //int startBar = prev_calculated;
    
    // Copy data from RSI indicator to Rsi buffer
    CopyBuffer(rsiHandle, 0, 0, rates_total, Rsi);

    for (int i = startBar; i < rates_total; i++)
    {
        // Calculate RSI Moving Average
        RsiMa[i] = iMAOnArray(Rsi, totalBars, SF, 0, MODE_EMA, i);

        // Calculate ATR RSI
        AtrRsi[i] = MathAbs(RsiMa[i - 1] - RsiMa[i]);

        // Calculate MA ATR RSI
        MaAtrRsi[i] = iMAOnArray(AtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i);

        // Calculate Delta Fast ATR RSI
        dar[i] = iMAOnArray(MaAtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i) * QQE_factor;

        double DeltaFastAtrRsi = dar[i];

        // Calculate new shortband and longband values
        double newshortband = RsiMa[i] + DeltaFastAtrRsi;
        double newlongband = RsiMa[i] - DeltaFastAtrRsi;

        // Crossover condition: RsiMa crosses above longband
        if (RsiMa[i - 1] > longband[i - 1] && RsiMa[i] > longband[i - 1])
        {

            longband[i] = MathMax(longband[i - 1], newlongband);
        }
        else
        {
            longband[i] = newlongband;
        }

        // Crossover condition: RsiMa crosses below shortband
        if (RsiMa[i - 1] < shortband[i - 1] && RsiMa[i] < shortband[i - 1])
        {
            shortband[i] = MathMin(shortband[i - 1], newshortband);
        }
        else
        {
            shortband[i] = newshortband;
        }

        // Determine the value of FastAtrRsiTL based on trend
        if (RsiMa[i] > shortband[i - 1] && RsiMa[i - 1] < shortband[i - 1])
        {
            // Trend is up
            FastAtrRsiTL[i] = longband[i];
        }
        else if (RsiMa[i] < longband[i - 1] && RsiMa[i - 1] > longband[i - 1])
        {
            // Trend is down
            FastAtrRsiTL[i] = shortband[i];
        }
    }

    return rates_total;
}





/* MQL5 implementation of iMAOnArray by Budyoni Damyanov */
double iMAOnArray(double& array[], int total, int period, int ma_shift, ENUM_MA_METHOD ma_method, int shift)
{
    double buf[];
    ArrayResize(buf, total);

    switch (ma_method)
    {
        case MODE_SMA:
        {
            double sum = 0;
            int pos = total - 1;

            for (int i = 1; i < period; i++, pos--)
                sum += array[pos];

            while (pos >= 0)
            {
                sum += array[pos];
                buf[pos] = sum / period;
                sum -= array[pos + period - 1];
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_EMA:
        {
            double pr = 2.0 / (period + 1);
            int pos = total - 2;

            while (pos >= 0)
            {
                if (pos == total - 2)
                    buf[pos + 1] = array[pos + 1];
                
                buf[pos] = array[pos] * pr + buf[pos + 1] * (1 - pr);
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_SMMA:
        {
            double sum = 0;

            int pos = total - period;

            while (pos >= 0)
            {
                if (pos == total - period)
                {
                    sum = 0;
                    for (int i = 0, k = pos; i < period; i++, k++)
                    {
                        sum += array[k];
                        buf[k] = 0;
                    }
                }
                else
                {
                    sum = buf[pos + 1] * (period - 1) + array[pos];
                }

                buf[pos] = sum / period;
                pos--;
            }

            return buf[shift + ma_shift];
        }

        case MODE_LWMA:
        {
            double sum = 0.0, lsum = 0.0;
            double price;
            int weight = 0, pos = total - 1;

            for (int i = 1; i <= period; i++, pos--)
            {
                price = array[pos];
                sum += price * i;
                lsum += price;
                weight += i;
            }

            pos++;
            int i = pos + period;

            while (pos >= 0)
            {
                buf[pos] = sum / weight;

                if (pos == 0)
                    break;

                pos--;
                i--;

                price = array[pos];
                sum = sum - lsum + price * period;
                lsum -= array[i];
                lsum += price;
            }

            return buf[shift + ma_shift];
        }
    }

    return 0;
}
 
phade #:

Thank you. I took your suggestions and now the code is modified to this (see code block).


I am seeing the lines now, and it's visually what I wanted. But I face a strange problem now - when I change to other timeframes, the lines disappear. The indicator is always showing 0 digits as well, it looks like it has trouble updating or something.


See my previous posts....
 

edit - 

I just noticed you posted more suggestions now, I'll take these into account and make a new modification. Cheers.

 
phade #:

Thank you. I took your suggestions and now the code is modified to this (see code block).


I am seeing the lines now, and it's visually what I wanted. But I face a strange problem now - when I change to other timeframes, the lines disappear. The indicator is always showing 0 digits as well, it looks like it has trouble updating or something.


If you do this, use a separate, local buffer, like I showed. Do not use a framework buffer for Copy* functions.

 // Copy data from RSI indicator to Rsi buffer
    CopyBuffer(rsiHandle, 0, 0, rates_total, Rsi);

EDIT:

You need error handling around CopyBuffer....

Look at ResetLastError() and GetLastError() to manage failed calls.
 
phade #:

edit - 

I just noticed you posted more suggestions now, I'll take these into account and make a new modification. Cheers.

welcome
 
phade #:

edit - 

I just noticed you posted more suggestions now, I'll take these into account and make a new modification. Cheers.

Try to adjust your call to CopyBuffer in such a way, that you only copy the data that's required for the actual call...

This can be a little more complex, but will speed up the indicator significantly.

Currently you copy all history at the first run to calculate all historic values, but on every new tick, you also copy all history of the rsi buffer.

That's inefficient. You should use and limit your data here. But watch out for the indexing on that array, because it is only as large as the amount of data you copy.

So in subsequent calls, you will need to adjust your access index to that array in such a way, that you offset it by the data that has been already calculated, and therefore not copied....

I hope I made it clear enough. Consult the documentation on TimeSeries, maybe use ArrayAsSeries, or an offset variable...
 
Dominik Christian Egert #:
Try to adjust your call to CopyBuffer in such a way, that you only copy the data that's required for the actual call...

This can be a little more complex, but will speed up the indicator significantly.

Currently you copy all history at the first run to calculate all historic values, but on every new tick, you also copy all history of the rsi buffer.

That's inefficient. You should use and limit your data here. But watch out for the indexing on that array, because it is only as large as the amount of data you copy.

So in subsequent calls, you will need to adjust your access index to that array in such a way, that you offset it by the data that has been already calculated, and therefore not copied....

I hope I made it clear enough. Consult the documentation on TimeSeries, maybe use ArrayAsSeries, or an offset variable...



To be honest it's not clear to me right now. I will have to look at it again another day. I overestimated how difficult it would be to translate this logic into an mq5 script.

As I am new to this, it will take time to fully understand. I feel that you've pointed me in the right direction and that's fulfilling enough for now at this time. 

I changed OnCalculate() now like so:

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 startBar = prev_calculated - (prev_calculated == rates_total);
    int totalBars = rates_total;

    // Check if all data calculated  https://www.mql5.com/en/docs/series/copybuffer
    if (BarsCalculated(rsiHandle) < rates_total)
    {
      Print("Could not copy data, no new data calculated");
      return prev_calculated;
    }

    // in case all data can't be coppied
    int to_copy;
    
    if (prev_calculated > rates_total || prev_calculated <= 0){
        to_copy = rates_total;
    }
    else{
        to_copy = rates_total - prev_calculated;
        // Last value is always copied
        to_copy++;
    }

    // Try to copy
    if (CopyBuffer(rsiHandle, 0, 0, to_copy, Rsi) <= 0) 
    {
      Print("Could not copy data, no new data calculated");
      return prev_calculated;
    }
    
    
    for (int i = MathMax(startBar, RSI_Period); i < rates_total; i++){
        // Calculate RSI Moving Average
        RsiMa[i] = iMAOnArray(Rsi, totalBars, SF, 0, MODE_EMA, i);

        // Calculate ATR RSI
        AtrRsi[i] = MathAbs(RsiMa[i - 1] - RsiMa[i]);

        // Calculate MA ATR RSI
        MaAtrRsi[i] = iMAOnArray(AtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i);

        // Calculate Delta Fast ATR RSI
        dar[i] = iMAOnArray(MaAtrRsi, totalBars, Wilders_Period, 0, MODE_EMA, i) * QQE_factor;

        double DeltaFastAtrRsi = dar[i];

        // Calculate new shortband and longband values
        double newshortband = RsiMa[i] + DeltaFastAtrRsi;
        double newlongband = RsiMa[i] - DeltaFastAtrRsi;

        // Crossover condition: RsiMa crosses above longband
        if (RsiMa[i - 1] > longband[i - 1] && RsiMa[i] > longband[i - 1]){

            longband[i] = MathMax(longband[i - 1], newlongband);
        }
        else{
            longband[i] = newlongband;
        }

        // Crossover condition: RsiMa crosses below shortband
        if (RsiMa[i - 1] < shortband[i - 1] && RsiMa[i] < shortband[i - 1]){
            shortband[i] = MathMin(shortband[i - 1], newshortband);
        }
        else
        {
            shortband[i] = newshortband;
        }

        // Determine the value of FastAtrRsiTL based on trend
        if (RsiMa[i] > shortband[i - 1] && RsiMa[i - 1] < shortband[i - 1]){
            // Trend is up
            FastAtrRsiTL[i] = longband[i];
        }
        else if (RsiMa[i] < longband[i - 1] && RsiMa[i - 1] > longband[i - 1]){
            // Trend is down
            FastAtrRsiTL[i] = shortband[i];
        }
    }

    return rates_total;
}

but now I see no lines.. nothing. I'm giving up for now.