Flexible ATR stop loss

Hi there,
Hopefully someone can give me some advice on a problem I have with setting up a variable ATR stop loss. In the example below I'm trying to change the initial stop loss from 3ATR(14) to a 5ATR(14) when the price reaches entry prices + 5*ATR(14) at entry. I'm trying to resolve it with a simple IFF function whereby referring to the entry price. Eventually, I get the stop loss to adjust but at the wrong bar . The entry price as well as the ATR at the buy don't remain fixed or referenced to the buy (see below). I also had to put in an arbitrary sell condition sell = C<MA200 as otherwise I had only one buy signal. Is there something obvious I'm overlooking or do I need to put everything in a loop https://forum.amibroker.com/t/trying-to-switch-type-of-stop-loss-while-in-trade/15568
Thank you for your help.

       
BuyPrice 	= C;                        							
SellPrice	= C;                        							
Short = Cover = 0;

Buy = C>MA(C,70);
Sell = C < MA(C,200);

Buy = ExRem(Buy,Sell);
Sell= ExRem(Sell,Buy);

entry = ValueWhen(Buy, BuyPrice); //reference to buy price

ATRentry = ValueWhen(Buy, ATR(14)); //reference to ATR at buy price

advanceSL = entry+(5*ATRentry); //level at which trailing stop changes from 3*ATR to 5*ATR
stoplevel = IIf( C<(entry+5*ATRentry) , 3*ATR(14), 5*ATR(14)); // condition to distinguish between initial and advanced trailstop

Sell = 0;

trailarray = Null;
trailstop = 0;

for( i = 1; i < BarCount; i++ )
{

   if( trailstop == 0 AND Buy[ i ] ) 
   { 
      trailstop = C[ i ] - stoplevel[i];
   }
   else Buy[ i ] = 0; 

   if( trailstop > 0 AND C[ i ] < trailstop  )
   {
      Sell[ i ] = 1;
     
      SellPrice[ i ] = Min(trailstop,O[i]);//adjust for gap downs
      trailstop = 0;
   }

   if( trailstop > 0 )
   {
      trailstop = Max( C[ i ] - stoplevel[i], trailstop );
      trailarray[ i ] = trailstop;
   }

}



Filter=1;
dynamic_color = IIf(Buy,colorGreen,colorDefault);
AddColumn(Buy,"Buy",1.2,colorBlack,dynamic_color);
AddColumn(Sell,"sell",1.2);
AddColumn(close,"close",1.2);
AddColumn(entry,"entry",1.2);
AddColumn(advanceSL,"advanceSL",1.2);
AddColumn(ATRentry,"ATRentry",1.2);

PlotShapes(Buy*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Sell*shapeDownArrow,colorRed,0,High);

Plot( Close,"Price",colorBlack,styleBar);
Plot(advanceSL,"advanceSL",colorGreen);

Plot( trailarray, "trailing stop line", colorOrange);or paste code here

Amibroker explorer

1 Like

For proper stop code you either have to use ApplyStop or looping code.

Using ValueWhen will cause similar outcome as first chart pane of below picture e.g. trying to set fix loss & profit target stops.
ApplyStop_ValueWhen


Besides the trail stop logic of post #1 is taken from knowledge base of AmiBroker.
So please add reference to original code source into the code.
Without it you wouldn't know how to do it for sure.

/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart
/// Copied/modified code below
//...
4 Likes

Thanks for a clear explanation @fxshrat .
I've read this now in many threads but I want to clear something.

like in the above code in first post,
if he has used ExRem()

Buy = ExRem(Buy,Sell);
Sell= ExRem(Sell,Buy);

entry = ValueWhen(Buy, BuyPrice); //reference to buy price

Because i had bookmarked this post of yours too.

Then with ExRem() there will not be any repetitive Buy signal so will ValueWhen() still not work ?
I have used ApplyStop() and it is far useful as it includes a lot of logic and user doesn't have to code loops for 90% of the cases.

The doubt still arises because in this thread

You are having same point over BarsSince() which in this case is just like ValueWhen() and can compute wrong output if there are redundant signals but in Post #9 @Tomasz says

BarsSince(Buy) is the right answer as long as your buy signals are not repetitive .

So can the code be used in some context where ExRem() is used or you are encouraging people to code using ApplyStop() so they don't trip over themselves if they don't understand their own code so well?
Thanks.

It is the same answer as before.

Why not using thing(s) working on every case (ApplyStop, loop) instead of using something that does not work on every case (BarsSince, ValueWhen) as soon as it starts to become more comprehensive...

Why would you want to rewrite code because of instability your "building" collapses as soon you add different parameter(s)? Why wasting time to rewrite whole thing instead of making a building that stands solid against every "hurricane"?

E.g. n-bar ApplyStop of that other thread you mentioned is just one line (too) and working on state and impulse signals. The same thing was Tomasz saying. It (BarsSince) won't work on state signals. Also what if in addition combining multiple stops giving higher preference to one stop over another (etc.).

What's the reluctance to e.g. ApplyStop? I don't get it.


As for OP of this thread... it is unclear (to me) what he is trying to achieve exactly.

Is he trying to combine regular exit and stop (trigger at either 1st or 2nd one)?
Is he trying to create just stop (And which stop type? Trail or fix stop? Or both trail and fix stop together?).

He would need to provide more information.

3 Likes

Thank you for taking the time and helping me to resolve my issue. I will try to find a work around using the applystop and/or looping approach as suggested.

Apologies for not referencing the original code source. I will do so in future posts.

In regards to my objective. In essence, I'm trying to vary the stop loss while in the trade. e.g. I start off with an initial stop off of 3ATR(14) and increase to 5ATR(14) once a certain price has reached.

Again, thank you for your time and consideration.

Also, to clarify. The applystop function references to the H of the bar. e.g. an ATR trailing stop would not be referenced to the C of the bar? Am I correct and if so is it possible to change accordingly?

To have full control over your desired stop/s use a ‘For Loop’.

Use the loop to control most of what you need. Meaning, use the loop to control excess signals, BuyPrice/SellPrice, stop adjustments etc.

1 Like

Thanks. I got it.

As i said, i'm using ApplyStop() and it works. i even used KB For-loop and got a good idea of how excess signals can be removed plus add any extra logic to manage the trade.
Combined with the Low level CBT, one can pretty much achieve any thing they want.

Here is possible solution

BuyPrice = C;                        							
SellPrice = C;                        							
Buy = C>MA(C,70);
Short = Cover = 0;

my_atr = ATR(14);
init_ATR = 3*my_atr;
adj_ATR = 5*my_atr;

/// Original trail stop looping code at
/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart
/// Modified to flexible ATR at 
/// @link https://forum.amibroker.com/t/flexible-atr-stop-loss/19645/4
/// by fxshrat@gmail.com, commercial use prohibited
Sell = 0;
trailARRAY = break_arr = Null;
color_arr = colorOrange;
trailstop = bp = break_level = break_flag = stoplevel = 0;
for( i = 1; i < BarCount; i++ )
{
    if( trailstop == 0 AND Buy[ i ] )
    {
        bp = BuyPrice[ i ];
        stoplevel = init_ATR[ i ];
        trailstop = bp - stoplevel;
        break_level = bp + adj_ATR[ i ];
    }
    else Buy[ i ] = 0; // remove excess buy signals    

    if( trailstop > 0 )
    {
        if ( C[ i ] > break_level AND break_flag == 0 ) {
			stoplevel = adj_ATR[ i ];
			trailstop = C[ i ] - stoplevel;
			break_flag = 1;			
        }
        
        if ( C[ i ] < trailstop ) {
			Sell[ i ] = 1;
			SellPrice[ i ] = C[ i ];
			bp = break_level = break_flag = trailstop = stoplevel = 0;
        }
    }

    if( trailstop > 0 )
    {
        trailstop = Max( C[ i ] - stoplevel, trailstop );
        trailARRAY[ i ] = trailstop;   
    }
    
    if ( break_level > 0 )
		break_arr[ i ] = break_level;
    
    if ( break_flag > 0 )
        color_arr[ i ] = colorRed;  
}

Plot( Close,"Price",colorBlack,styleBar);
Plot( break_arr,"Break Level",colorGold);
Plot( trailarray, "trailing stop line", color_arr, styleStaircase);
PlotShapes(Buy*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Sell*shapeDownArrow,colorRed,0,High);

intrade = Flip(Buy,Sell);

Filter = intrade OR Sell;
dynamic_color = IIf( Buy, colorGreen, color_arr );
AddColumn( IIf( intrade, 'T', 'F' ), "Buy", formatChar, colorBlack, dynamic_color );
AddColumn( IIf( Sell, 'T', Null ), "Sell", formatChar, -1, colorRed );
AddColumn( Close, "Close", 1.2 );

13

6 Likes

Thank you very much. I really appreciate your time, effort and advise. Given my novice coding skills, it would have taken me weeks to get it right, if at all.

Thank you kindly. Much appreciated

Your're welcome.

Have made a small update to simplify a bit more.
And also the upper break line now draws only till break of Close of bar above of the line.

BuyPrice = C;                        							
SellPrice = C;                        							
Buy = C>MA(C,70);
Short = Cover = 0;

my_atr = ATR(14);
init_ATR = 3*my_atr;
adj_ATR = 5*my_atr;

/// Original trail stop looping code at
/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart
/// Modified to flexible ATR at, vrs. 1.1 
/// @link https://forum.amibroker.com/t/flexible-atr-stop-loss/19645/6
/// by AmiBroker.com and fxshrat@gmail.com feat. gadocha, commercial use prohibited
Sell = 0;
trailARRAY = break_arr = Null;
color_arr = colorOrange;
bp = break_level = break_flag = 0;
trailstop = stoplevel = 0;
for( i = 1; i < BarCount; i++ )
{
    if( trailstop == 0 AND Buy[ i ] )
    {
        bp = BuyPrice[ i ];
        stoplevel = init_ATR[ i ];
        trailstop = bp - stoplevel;
        break_level = bp + adj_ATR[ i ];
    }
    else Buy[ i ] = 0; // remove excess buy signals  
    
    if ( break_flag > 0 )
        color_arr[ i ] = colorRed;

    if( trailstop > 0 )
    { 
        if ( C[ i ] > break_level AND break_flag == 0 ) {
			stoplevel = adj_ATR[ i ];
			trailstop = C[ i ] - stoplevel;
			break_flag = 1;						
        }
        
        trailstop = Max( C[ i ] - stoplevel, trailstop );
        trailARRAY[ i ] = trailstop;  
        
        if ( break_flag == 0 ) // only store till break
			break_arr[ i ] = break_level;
        
        if ( C[ i ] < trailstop ) {
			Sell[ i ] = 1;
			SellPrice[ i ] = C[ i ];
			bp = break_level = break_flag = 0;
			trailstop = stoplevel = 0;
        }        
    }     
}

Plot( Close,"Price",colorDefault,styleBar);
Plot( break_arr,"Break Level",colorGold);
Plot( trailarray, "trailing stop line", color_arr, styleStaircase);
PlotShapes(Buy*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Sell*shapeDownArrow,colorRed,0,High);

intrade = Flip(Buy,Sell);

Filter = intrade OR Sell;
dynamic_color = IIf( Buy, colorGreen, color_arr );
AddColumn( IIf( intrade, 'T', 'F' ), "Buy", formatChar, colorBlack, dynamic_color );
AddColumn( IIf( Sell, 'T', Null ), "Sell", formatChar, -1, colorRed );
AddColumn( Close, "Close", 1.2 );

13

7 Likes

I'm flattered by your help and assistance. Your enthusiasm and passion to help others and to coding is commendable.

Thank you.

3 Likes

@fxshrat
This was your other post that i had also studied and learnt very useful from it.
It is now obvious that if one knows how to use the functions correctly, then there will be no problems.
So you have used ExRem(), then ValueWhen() and finally ApplyStop().

kudos :clap:

No, no, no. I only added plotting code to the code of post #1 of that thread.
Please see what I wrote

I would do latter one (code of post #1 of that thread) bit differently but didn't bother to fix his code that time in addition. It was just about plotting Applystop signals.


Thank you too. No problem.
Unfortunately programming can be like a curse because I'm never happy with any code (always something to improve or some idea to add). :grin:

As aside there is last (small) update... I moved color_arr outside of loop.

Now it is done via array processing

//..
not_broken = Flip(Buy, IsNull(break_arr));
color_arr = IIf(not_broken, colorOrange, colorRed);
//....

Full code:

BuyPrice = C;                                             
SellPrice = C;                                             
Buy = C>MA(C,70);
Short = Cover = 0;

my_atr = ATR(14);
init_ATR = 3*my_atr;
adj_ATR = 5*my_atr;

/// Original trail stop looping code at
/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart
/// Modified to flexible ATR, vrs. 1.2 at
/// @link https://forum.amibroker.com/t/flexible-atr-stop-loss/19645/14
/// by AmiBroker.com and fxshrat@gmail.com feat. gadocha, commercial use prohibited
Sell = 0;
trailARRAY = break_arr = Null;
bp = break_level = break_flag = 0;
trailstop = stoplevel = 0;
for( i = 1; i < BarCount; i++ ) {

    if ( trailstop == 0 AND Buy[ i ] ) {
        bp = BuyPrice[ i ];
        stoplevel = init_ATR[ i ];
        trailstop = bp - stoplevel;
        break_level = bp + adj_ATR[ i ];
    }
    else Buy[ i ] = 0;   // remove excess buy signals

    if ( trailstop > 0 ) {
        if ( C[ i ] > break_level AND break_flag == 0 ) {
            stoplevel = adj_ATR[ i ];
            trailstop = C[ i ] - stoplevel;
            break_flag = 1;
        }

        trailstop = Max( C[ i ] - stoplevel, trailstop );
        trailARRAY[ i ] = trailstop;

        if ( break_flag == 0 )  // only store till break
            break_arr[ i ] = break_level;

        if ( C[ i ] < trailstop ) {
            Sell[ i ] = 1;
            SellPrice[ i ] = C[ i ];
            bp = break_level = break_flag = 0;
            trailstop = stoplevel = 0;
        }
    }
}

intrade = Flip(Buy,Sell);
not_broken = Flip(Buy, IsNull(break_arr));
color_arr = IIf(not_broken, colorOrange, colorRed);

Plot(Close,"Price",colorDefault,styleBar);
Plot(IIf(intrade, break_arr, Null),"Break Level",colorGold, styleStaircase);
Plot(IIf(intrade, trailarray, Null), "trailing stop line", color_arr, styleStaircase);
PlotShapes(Buy*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Sell*shapeDownArrow,colorRed,0,High);

Filter = intrade OR Sell;
dynamic_color = IIf(Buy, colorGreen, color_arr);
AddColumn( IIf( intrade, 'T', 'F' ), "Buy/Intrade", formatChar, colorBlack, dynamic_color );
AddColumn( IIf( Sell, 'T', Null ), "Sell", formatChar, -1, colorRed );
AddColumn( Close, "Close", 1.2 );
9 Likes