atr trailing stop

 

I'm trying to implement an ATR trailing stop indicator .  The compiler doesn't throw any errors.  Nothing is plotted to the chart.

See "CDC ATR Trailing Stop V1" on TradingView for reference.
// ATR railing stop

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
// plot ATR stop
#property indicator_type1 DRAW_LINE
#property indicator_color1 Blue
#property indicator_style1 STYLE_SOLID
#property indicator_label1 "ATR stop"
// input parameters for ATR stop
input int ATR_period = 14; // ATR length / period
input int ATR_stop_multiplier = 2; // ATR stop multiplier
// indicator buffers
double ATRstopBuffer[];
double ATRBuffer[];
double StopLossBuffer[];

// initializacion function
int OnInit()
{
    SetIndexBuffer(0, ATRstopBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, ATRBuffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(2, StopLossBuffer, INDICATOR_CALCULATIONS);
    
    return(0);
}

// iteration function
int OnCalculate(
                const int rates_total,
                const int prev_calculated,
                const int begin,
                const double& price[])
{
    if(rates_total < ATR_period) return(0);
    
    int start; 
    if(prev_calculated == 0)
    {
        ATRstopBuffer[0] = 0.0;
        start = 1;
    }
    else start = prev_calculated - 1;
    
    for(int i = start; i < rates_total; i++)
    {
        ATRBuffer[i] = iATR(NULL, NULL, ATR_period);
        StopLossBuffer[i] = ATRBuffer[i] * ATR_stop_multiplier;
        // if trend is up plot max(previous stop, current stop)
        if(price[i] >= ATRstopBuffer[i - 1] && price[i - 1] >= ATRstopBuffer[i - 1]) ATRstopBuffer[i] = MathMax(ATRstopBuffer[i - 1], (price[i] - StopLossBuffer[i]));
        // if trend is down plot min(previous stop, current stop)
        if(price[i] <= ATRstopBuffer[i - 1] && price[i - 1] <= ATRstopBuffer[i - 1]) ATRstopBuffer[i] = MathMin(ATRstopBuffer[i - 1], (price[i] + StopLossBuffer[i]));
        // if trend change up plot current stop
        if(price[i] >= ATRstopBuffer[i - 1] && price[i - 1] <= ATRstopBuffer[i - 1]) ATRstopBuffer[i] = price[i] - StopLossBuffer[i];
        // if trend change down plot current stop
        if(price[i] <= ATRstopBuffer[i - 1] && price[i - 1] >= ATRstopBuffer[i - 1]) ATRstopBuffer[i] = price[i] + StopLossBuffer[i];

        Print("price=",price[i]);
       
    }
    return(rates_total);
}

Documentation on MQL5: Language Basics / Functions / Event Handling Functions
Documentation on MQL5: Language Basics / Functions / Event Handling Functions
  • www.mql5.com
The MQL5 language provides processing of some predefined events. Functions for handling these events must be defined in a MQL5 program; function name, return type, composition of parameters (if there are any) and their types must strictly conform to the description of the event handler function. The event handler of the client terminal...
 
user904:

I am still wrapping my head around mql5, would anyone be so kind as to let me know what I'm doing wrong?

When I try to compile it says: "OnCalculate function declared with wrong type or/and parameters"

I need to make an EA, can I do the calculation in the EA or should I build the indicator separately?

See "CDC ATR Trailing Stop V1" on TradingView for reference.

There are only two ways to define OnCalculate() - refer to https://www.mql5.com/en/docs/event_handlers/oncalculate.

So this is wrong:

int OnCalculate(
                const int rates_total,
                const int prev_calculated,
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[])
Documentation on MQL5: Event Handling / OnCalculate
Documentation on MQL5: Event Handling / OnCalculate
  • www.mql5.com
The function is called in the indicators when the Calculate event occurs for processing price data changes. There are two function types. Only one of them can be used within a single indicator. [in]  Size of the price[] array or input series available to the indicator for calculation. In the second function type, the parameter value corresponds...
 
sorry I couldn't figure out how to do the markup so I attached the .mq5 file ... I will edit the post
William Roeder:
The error message tells you what you did wrong. <Deleted>, compare your code to the documentation. Post your code if you still can't understand.

Do you really expect an answer? We can't see your broken code. There are no mind readers here and our crystal balls are cracked.

 
thank you I edited the post..
Seng Joo Thio:

There are only two ways to define OnCalculate() - refer to https://www.mql5.com/en/docs/event_handlers/oncalculate.

So this is wrong:

 
Hi William, I've changed the code a little .. I dont get any compiler errors but nothing is plotted to the chart.. could you tell me what Im doing wrong?
William Roeder:
The error message tells you what you did wrong. <Deleted>, compare your code to the documentation. Post your code if you still can't understand.

Do you really expect an answer? We can't see your broken code. There are no mind readers here and our crystal balls are cracked.

 
user904:
Hi William, I've changed the code a little .. I dont get any compiler errors but nothing is plotted to the chart.. could you tell me what Im doing wrong?

He's already used "<Deleted>", so you better read the manuals... for a start, I suggest you read https://www.mql5.com/en/docs/indicators/iatr.

Documentation on MQL5: Technical Indicators / iATR
Documentation on MQL5: Technical Indicators / iATR
  • www.mql5.com
//|                                                    Demo_iATR.mq5 | //|                        Copyright 2011, MetaQuotes Software Corp. | //|                                              https://www.mql5.com | "The method of creation of the handle is set through the 'type' parameter (function type...
 

so I found a working ATR trailing stop from someone in the forums and I'm building an EA based on it... I'm testing it now but its  not working correctly, stop loss didnt trigger.  This code is inside OnTick.  Ill upload the whole EA and indicator (chandelier.mq5) files.

I dont want a trailing stop order, I want to close the position when period closes above/below trailing stop line.  If I'd use a trailing stop it will just trigger at the touch.


If you can just check it out and tell me what Im doing wrong so I can get on trying to fix it I'd really appreciate it man.

Seng Joo Thio:

He's already used "<Deleted>", so you better read the manuals... for a start, I suggest you read https://www.mql5.com/en/docs/indicators/iatr.

 if(CopyBuffer(hATR_stop,2,0,3,atr_long_stop)<0 || CopyBuffer(hATR_stop,3,0,3,atr_short_stop)<0)
    {
        Alert("Error copying ATR trailing stop indicator buffers - error:",GetLastError(),"!!");
        return;
    }
    //---- insert copybuffer for moving average
    //----
    //----

    bool long_open=false;
    bool short_open=false;

    if(PositionSelect(_Symbol) ==true)
    {
        if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
        {
            long_open = true;
        }
        else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
        {
            short_open = true;
        }
    }

    last_close = rate[1].close;
    previous_close = rate[2].close;


    if(last_close >= atr_short_stop[1] && previous_close <= atr_short_stop[2])
    {
        if(short_open)
        {
            trade.PositionClose(_Symbol);
        }
        // buy long
        request.action = TRADE_ACTION_DEAL;
        request.price = NormalizeDouble(latest_price.ask,_Digits);
        request.symbol = _Symbol;
        request.volume = Lot;
        request.magic = EA_magic;
        request.type = ORDER_TYPE_BUY;
        request.type_filling = ORDER_FILLING_FOK;
        request.deviation = 100;
        // send order
        if(PositionSelect(_Symbol) ==false)
        {
            int ticket = OrderSend(request,result);
            if(result.retcode==10009 || result.retcode==10008) //Request is completed or order placed
            {
            Alert("A Buy order has been successfully placed with Ticket#:",result.order,"!!");
            }
            else
            {
            Alert("The Buy order request could not be completed -error:",GetLastError());
            ResetLastError();
            return;
            }
        }
    }
    else if(last_close <= atr_long_stop[1] && previous_close >= atr_long_stop[2])
    {
        if(long_open)
        {
            trade.PositionClose(_Symbol);
        }
        // sell short
        request.action = TRADE_ACTION_DEAL;
        request.price = NormalizeDouble(latest_price.bid,_Digits);
        request.symbol = _Symbol;
        request.volume = Lot;
        request.magic = EA_magic;
        request.type = ORDER_TYPE_SELL;
        request.type_filling = ORDER_FILLING_FOK;
        request.deviation = 100;
        //send order if position is closed
        if(PositionSelect(_Symbol) ==false)
        {
            
            int ticket = OrderSend(request,result);
            if(result.retcode==10009 || result.retcode==10008) //Request is completed or order placed
            {
            Alert("A Sell order has been successfully placed with Ticket#:",result.order,"!!");
            }
            else
            {
            Alert("The Sell order request could not be completed -error:",GetLastError());
            ResetLastError();
            return;
            }
        }
    }
Files:
atrx_ea.mq5  7 kb
 
user904:

so I found a working ATR trailing stop from someone in the forums and I'm building an EA based on it... I'm testing it now but its  not working correctly, stop loss didnt trigger.  This code is inside OnTick.  Ill upload the whole EA and indicator (chandelier.mq5) files.

I dont want a trailing stop order, I want to close the position when period closes above/below trailing stop line.  If I'd use a trailing stop it will just trigger at the touch.

If you can just check it out and tell me what Im doing wrong so I can get on trying to fix it I'd really appreciate it man.

You forgot this line:

    ArraySetAsSeries(atr_long_stop, true);
    ArraySetAsSeries(atr_short_stop, true);
    ArraySetAsSeries(rate, true);
    ArraySetAsSeries(ma, true);

This resulted in wrong values assigned to your previous_close.

Another bigger problem is the main logic - where you check close prices above or below the trailing stop lines. Run chandelier.mq5 on a chart and observe - you'll notice that your checks for open and close orders rarely pin-point the right bar for opening and closing - because when price close above short_stop, most of the time short_stop already becomes EMPTY_VALUE, and long_stop begins to appear. The same is true for the other direction.

So you'll need to rework your 'if' checks for the open/close parts.

 

Thank you!

I'm still testing it but think I fixed it. I did:

if(last_close >= atr_short_stop[2] && previous_close <= atr_short_stop[2])

and ..

else if(last_close <= atr_long_stop[2] && previous_close >= atr_long_stop[2]

Seng Joo Thio:

You forgot this line:

This resulted in wrong values assigned to your previous_close.

Another bigger problem is the main logic - where you check close prices above or below the trailing stop lines. Run chandelier.mq5 on a chart and observe - you'll notice that your checks for open and close orders rarely pin-point the right bar for opening and closing - because when price close above short_stop, most of the time short_stop already becomes EMPTY_VALUE, and long_stop begins to appear. The same is true for the other direction.

So you'll need to rework your 'if' checks for the open/close parts.

 

you know what.. the Stop Loss mechanism doesn't seem to be working. It's not closing the position.  What do you think it could be?

Entry is working fine.

 
user904:

Thank you!

I'm still testing it but think I fixed it. I did:

and ..

Yes, these lines should capture more signals than your original code, but still won't capture all. Example:

The circled bars will give you a close sell and open buy signal without a stop loss... so your 'if' checks must also consider such cases... or even look for additional indicators to complement this...

Reason: