Changing Trailing Stop Levels

I have successfully recreated the trailing stop code outlined in this article using Donchian channels and am happy with how it works. The code takes my initial max stop loss and uses it until the Donchian channel is greater than it and then follows the Donchian channel instead. Code below for reference:

// Initialize variables
Sell=0;
trailArray = Null;
trailStop = 0;

//Trailing stop logic
for( i = 0; i < BarCount; i++ )
{  
  if( trailstop == 0 AND Buy[ i ] ) 
  { 
	trailstop = BuyPrice[i] * (1- stopLoss/100);
  }

  if( trailstop > 0 AND Low[ i ] < trailstop )
   {   
	 Sell[ i ] = 1; 
	 SellPrice[ i ] = Min( Open[ i ], trailstop );
	 trailstop = 0;
	 Buy[i] = 0; 
   }
   
  if( trailstop > 0 )
   {
	  trailStop = Max(DonchianLower[i], trailStop); 
	  trailARRAY[ i ] = trailstop;
   }
}

Plot(trailArray, "Trailing Stop Level", colorRed, styleThick);

Now I would like to add a tighter initial Donchian channel to use as a tight stop. Once the trailing stop is in profit, I would like to use a wider channel to give the trade more breathing room. I thought I could use the IIf function to switch between the two Donchian channels depending on whether the trade is in profit or not. But when I view the plot, it continuously rides the tight channel and never moves to the looser channel even though the trailing stop is in profit. I'm obviously not doing something right here. Any assistance is appreciated.

// Initialize variables
Sell=0;
trailArray = Null;
trailStop = 0;

// Trailing stop logic trying to do a tighter stop initially until in profit
for( i = 0; i < BarCount; i++ )
{  
  if( trailstop == 0 AND Buy[ i ] ) 
  { 
	trailstop = BuyPrice[i] * (1- stopLoss/100);
  }

  if( trailstop > 0 AND Low[ i ] < trailstop )
  {   
	 Sell[ i ] = 1; 
	 SellPrice[ i ] = Min( Open[ i ], trailstop );
	 trailstop = 0;
	 Buy[i] = 0; 
  }
   
  if( trailstop > 0 )
  {
	  trailStop = IIf(BuyPrice[i] > DonchianStop[i], Max(DonchianStop[i], trailStop), DonchianLower[i]);
	  trailARRAY[ i ] = trailstop;
  }
}

Plot(trailArray, "Trailing Stop Level", colorRed, styleThick);

Your code is incomplete and has syntax errors!

Correct your code and re-post it as so others can assist you.

My apologies, I was trying to extract only the relevant parts of the original AFL file, but I see that has caused more trouble. I have re-written it so that it is functional now while still focusing on the relevant parts:

// ==========================================================================================
// === TRADING SYSTEM PARAMETERS ===
// ==========================================================================================
SetOption("InitialEquity", 100000);
SetTradeDelays( 0, 0, 0, 0 ); // 1 - Delays the trades to the next day, 0 - Trades same day via stops
SetOption("AllowPositionShrinking", True);
SetOption("AccountMargin",100); // 100 = Cash account, 75 = Using half available margin
SetOption("MaxOpenPositions", 20);
RoundLotSize = 1;  // Disallow fractional share purchasing


// ==========================================================================================
// === RISK MANAGEMENT & POSITION SIZING ===
// ==========================================================================================
// Initial (MAX) stop loss
SetOption("ActivateStopsImmediately", True);
stopLoss = 6;
ApplyStop(stopTypeLoss, stopModePercent, stopLoss, ExitAtStop = 1, True);

// Position size based on risk and max stop loss
PositionRisk = 1;  
PosSize = 100 * PositionRisk / stopLoss;
SetPositionSize(PosSize, spsPercentOfEquity);
         

// ==========================================================================================
// === PLOT CHART & INDICATORS ===
// ==========================================================================================
// Chart
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - " + FullName() + " | {{INTERVAL}} {{DATE}}: Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

// Donchian Channel
pdsU=10;  // High channel lookback
pdsL=6;  // Low channel lookback
pdsS=3;  // Tight Stop Low channel lookback

DonchianUpper =HHV(H,pdsU);
DonchianLower = LLV(L,pdsL);
DonchianStop = LLV(L,pdsS);

Plot(DonchianUpper,"DU",color = 2,styleDashed);
Plot(DonchianLower,"DL",color = 2, styleDashed);
Plot(DonchianStop,"DS",color = colorBlueGrey, styleDashed);

  
// ==========================================================================================
// === BUY & SELL LOGIC ===
// ==========================================================================================

Buy=Cross(High, Ref(DonchianUpper, -1)); 
BuyPrice=Max(Ref(DonchianUpper, -1), Open);

// Initialize variables
Sell=0;
trailArray = Null;
trailStop = 0;
breakEven = Null;

// Trailing stop logic trying to do a tighter stop initially until in profit
for( i = 0; i < BarCount; i++ )
{  
  if( trailstop == 0 AND Buy[ i ] ) 
  { 
	trailstop = BuyPrice[i] * (1- stopLoss/100);
  }

  if( trailstop > 0 AND Low[ i ] < trailstop )
  {   
	 Sell[ i ] = 1; 
	 SellPrice[ i ] = Min( Open[ i ], trailstop );
	 trailstop = 0;
	 Buy[i] = 0; 
	 breakEven = 0;
  }
   
  if( trailstop > 0 )  // Goal is to first trail stop with max stop loss, then follow the tight DonchianStop level, then once in profit, follow DonchianLower level
  {
	  breakEven = ValueWhen(((DonchianStop[i] >= BuyPrice[i]) AND (Ref(DonchianStop[i], -1) < Ref(BuyPrice[i], -1))), DonchianStop[i], 1);
	  trailStop = IIf(BuyPrice[i] > DonchianStop[i], Max(DonchianStop[i], trailStop), Max(DonchianLower[i], breakEven[i]));
	  trailARRAY[ i ] = trailstop;
  }
}

Plot(trailArray, "Trailing Stop Level", colorRed, styleThick);

// Hide buy and sell signals if in position so that it doesn't plot extra arrows
Buy = ExRem(Buy,Sell);
Sell = ExRem(Sell,Buy);

// Plot arrows indicating trades
PlotShapes(IIf(Buy, shapeUpTriangle, shapeNone),color = colorLime, 0, L, Offset=-50);
PlotShapes(IIf(Sell, shapeDownTriangle, shapeNone),color = colorRed, 0, H, Offset=-50);

When you plot this AFL, you'll see the stop follow the shorter Donchian level (DonchianStop) like this image:
Original

My goal is to have the stopLevel move to the looser DonchianLower level once in profit as shown by this yellow line I drew in.
Goal

here is 1 way to do it. At least I think it comes close to what you like to do:

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );

// Donchian Channel
pdsU = 10; // High channel lookback
pdsL = 6; // Low channel lookback
pdsS = 3; // Tight Stop Low channel lookback
stopLoss = Param( "Stploss", 6, 1, 15, 0.1 );

DonchianUpper = HHV( H, pdsU );
DonchianLower = LLV( L, pdsL );
DonchianStop = LLV( L, pdsS );

Plot( Ref( DonchianUpper, -1 ), "DU", colorBlue, styleDashed, Null, Null, 0, 0, 1 );
Plot( Ref( DonchianLower, -1 ), "DL", colorRed, styleDashed, Null, Null, 0, 0, 1 );
Plot( Ref( DonchianStop, -1 ), "DS", colorOrange, styleDashed, Null, Null, 0, 0, 1 );

BuySetup = Cross( High, Ref( DonchianUpper, -1 ) );

// Initialize variables
Buy = Sell = 0;
trailarray = Null;
trailStop = 0;
breakEven = Null;
inlong = 0;
initialstop = buyindex = 0;

for( i = 1; i < BarCount; i++ )
{
    // enter long
    if( BuySetup[i] AND !inlong )
    {
        Buy[i] = 1;
        BuyPrice[i] = Max( DonchianUpper[i - 1], O[i] );
        inlong = 1;
        initialstop = trailarray[i] = BuyPrice[i] - BuyPrice[i] / 100 * stopLoss;
        buyindex = i;
    }
    else

        // exit long
        if( inlong AND L[i] < trailarray[i - 1] )
        {
            Sell[i] = 1;
            SellPrice[i] = Min( O[i], trailarray[i - 1] );
            inlong = 0;
            trailarray[i] = trailarray[i - 1];
        }
        else

            // update the trailarray, chose out of 3 options
            if( inlong AND L[i] >= trailarray[i - 1] )
            {
                if( L[i] <= BuyPrice[buyindex] )
                {
                    trailarray[i] = Max( trailarray[i - 1], Max( initialstop, DonchianStop[i - 1] ) );
                }
                else
                    if( L[i] > BuyPrice[buyindex] )
                    {
                        trailarray[i] = Max( trailarray[i - 1], DonchianLower[i - 1] );
                    }
            }
}

upColor = colorAqua;
dnColor = colorGold;
Plot( trailArray, "Trailing Stop Level", colorRed, styleThick );
PlotShapes( IIf( Buy, shapeSmallUpTriangle, shapeNone ), upcolor, 0,  L, -20 );
PlotShapes( IIf( Sell, shapeSmallDownTriangle, shapeNone ), dncolor, 0, H, -20 );
PlotShapes( IIf( Buy, shapeSmallCircle, shapeNone ), colorAqua, 0, BuyPrice, 0 );
PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorGold, 0, SellPrice, 0 );

BuyPrice = ValueWhen( Buy, BuyPrice );
SellPrice = ValueWhen( Sell, SellPrice );
longResult = Prec( IIf( Sell, SellPrice - ValueWhen( Buy, BuyPrice ), 0 ), 2 );

ft = "Helvetica";
clr = colorDefault;
shiftLabels = 10;
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
sz = 10;

for( i = fvb; i <= lvb; i++ )
{
    if( Buy[i] )
    {
        str = "Buy: " + BuyPrice[i];
        PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -35 - shiftLabels );
    }

    if( Sell[i] )
    {
        str = "Sell: " + SellPrice[i] + " (" + longResult[i] + ")";
        PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 25 + shiftLabels );
    }
}
3 Likes

Thanks, it's a bit different behavior, but your nested if loops give me some ideas on how to approach the problem differently.

I realized a hole in the logic of my earlier code trying to do this. My goal is to look when the tighter Donchian channel is in profit, if so, leave the stop there until the slower Donchian channel catches up, then trail with the slower channel.

That means I need a static value of the fast Donchian channel at the first candle that it is in profit (was missing this before). I can then use that value to compare it against the value of the slow channel and use the Max of those two values for the trailing stop. But I am having a really hard time getting a static value and it seems like it is something simple I'm likely overlooking.

Assigning a variable to DonchianStop[i] causes that variable to change as the DonchianStop array changes, so that doesn't work.
Using ValueWhen to try to get the value of DonchianStop when the current candle is in profit but the previous one was not seems like it should work, but the variable remains empty so I might not be doing it right.

At this point in this code I am just trying to plot a horizontal line at the DonchianStop value when it is in profit. I plan on adding the logic to compare that value to DonchianLower later, but just taking it one step at a time. Can anyone help point me in the direction of figuring out how get this value and plot this horizontal line?

// ==========================================================================================
// === TRADING SYSTEM PARAMETERS ===
// ==========================================================================================
SetOption("InitialEquity", 100000);
SetTradeDelays( 0, 0, 0, 0 ); // 1 - Delays the trades to the next day, 0 - Trades same day via stops
SetOption("AllowPositionShrinking", True);
SetOption("AccountMargin",100); // 100 = Cash account, 75 = Using half available margin
SetOption("MaxOpenPositions", 20);
RoundLotSize = 1;  // Disallow fractional share purchasing


// ==========================================================================================
// === RISK MANAGEMENT & POSITION SIZING ===
// ==========================================================================================
// Initial (MAX) stop loss
SetOption("ActivateStopsImmediately", False);
stopLoss = 7; // Change this to a small number to experience the issue with trade entries being ignored
ApplyStop(stopTypeLoss, stopModePercent, stopLoss, ExitAtStop = 1);

// Position size based on risk and max stop loss
PositionRisk = 1;  
PosSize = 100 * PositionRisk / stopLoss;
SetPositionSize(PosSize, spsPercentOfEquity);
         

// ==========================================================================================
// === PLOT CHART & INDICATORS ===
// ==========================================================================================
// Chart
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - " + FullName() + " | {{INTERVAL}} {{DATE}}: Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

// Donchian Channel
pdsU=4;  // High channel lookback
pdsL=5;  // Low channel lookback
pdsS=3;  // Tight Stop Low channel lookback

DonchianUpper =HHV(H,pdsU);
DonchianLower = LLV(L,pdsL);
DonchianStop = LLV(L,pdsS);

Plot(DonchianUpper,"DU",color = colorBlueGrey,styleDashed);
Plot(DonchianLower,"DL",color = colorBlueGrey, styleDashed);
Plot(DonchianStop,"DS",color = colorBlueGrey, styleDashed);

  
// ==========================================================================================
// === BUY & SELL LOGIC ===
// ==========================================================================================
Buy=Cross(High, Ref(DonchianUpper, -1)); 
BuyPrice=Max(Ref(DonchianUpper, -1), Open);

// === TRAILING STOP WITH JUST A SINGLE DONCHIAN CHANNEL ===
// Initialize variables
//Sell=0;
//trailArray = Null;
//trailStop = 0;

//Trailing stop logic
//for( i = 0; i < BarCount; i++ )
//{  
//  if( trailstop == 0 AND Buy[ i ] ) 
//  { 
//	trailstop = BuyPrice[i] * (1- stopLoss/100);
//	entryBar[i] = True;
//  }
//  else Buy[i] = 0; // remove excess buy signals
//  if( trailstop > 0 AND Low[ i ] < trailstop AND entryBar[i] != True)
//   {   
//	 Sell[ i ] = 1; 
//	 SellPrice[ i ] = Min( Open[ i ], trailstop );
//	 trailstop = 0;
//   }
   
//  if( trailstop > 0 )
//   {
//	  trailStop = Max(DonchianLower[i], trailStop); 
//	  trailARRAY[ i ] = trailstop;
//   }
//}

// === NEW LOGIC TRYING TO MOVE TRAILING STOP TO LOOSER DONCHIAN LEVEL ===
// Initialize variables
Sell=0;
trailArray = Null;
trailStop = 0;
breakEvenLevel = 0;
breakEvenArray = Null;
buyLevel = 0;

// Trailing stop logic trying to do a tighter stop initially until in profit
for( i = 0; i < BarCount; i++ )
{  
  if( trailstop == 0 AND Buy[ i ] ) 
  { 
	trailstop = BuyPrice[i] * (1- stopLoss/100);
	entryBar[i] = True;
	buyLevel = BuyPrice[i];
  }
  else Buy[i] = 0; // remove excess buy signals
  if( trailstop > 0 AND Low[ i ] < trailstop AND entryBar[i] != True)
  {   
	 Sell[ i ] = 1; 
	 SellPrice[ i ] = Min( Open[ i ], trailstop );
	 trailstop = 0;
	 Buy[i] = 0; 
	 buyLevel = 0;
	 breakEvenLevel = 0;

  }
   
  if( trailstop > 0 )  // Goal is to first trail stop with max stop loss, then follow the tight DonchianStop level, then once in profit, follow DonchianLower level
  {
	  if(DonchianStop[i] >= buyLevel)
	  {
		  breakEvenLevel = 340; // set this value to a price on the chart you can see to test out if the line plots correctly
		  //breakEvenLevel = ValueWhen(((DonchianStop[i] >= buyLevel[i]) AND (Ref(DonchianStop[i], -1) <  Ref(BuyLevel[i], -1))), DonchianStop[i], 0);
		  //breakEvenLevel = DonchianStop[i];  // this breakeven level moves as the DC channel moves.  Need to freeze it in at the moment it is true.
		  breakEvenArray[i] = breakEvenLevel[i];
	  }
	  trailStop = Max(DonchianStop[i], trailStop); 
	  trailArray[ i ] = trailstop;
  }
}

Plot(trailArray, "Trailing Stop Level", colorRed, styleThick);
Plot(breakEvenArray, "Break Even Level", colorBlue, styleThick);

// Hide buy and sell signals if in position so that it doesn't plot extra arrows - should not use for backtests
//Buy = ExRem(Buy,Sell);
//Sell = ExRem(Sell,Buy);

// Plot arrows indicating trades
PlotShapes(IIf(Buy, shapeUpTriangle, shapeNone),color = colorLime, 0, L, Offset=-50);
PlotShapes(IIf(Sell, shapeDownTriangle, shapeNone),color = colorRed, 0, H, Offset=-50);

// ==========================================================================================
// === EXPLORATION / SCANNING COLUMNS ===
// ==========================================================================================
Filter = 1;
AddTextColumn(FullName(), "Name");
AddColumn(Buy, "Buy Array");
AddColumn(entryBar, "BarsSince Buy", 1);


@millerrh, I've been trying to figure out what you are looking for, but I'm not sure I got it properly.

Anyway, here's a way to draw a horizontal line after a specific condition has occurred in the loop (replace your loop and delete / comment out the last line (I deleted the entryBar variable).

// === NEW LOGIC TRYING TO MOVE TRAILING STOP TO LOOSER DONCHIAN LEVEL ===
// Initialize variables
Sell = 0;
trailArray = Null;

trailStop = 0;
buyLevel = 0;
isBreakEvenLevelSet = False;

// Trailing stop logic trying to do a tighter stop initially until in profit
for( i = 0; i < BarCount; i++ )
{
    // Draw horizonal line (array) when trade is in breakeven
    if( ( i > 0 ) AND ( isBreakEvenLevelSet ) )
        breakEvenArray[i] = breakEvenArray[i - 1];
    else
        breakEvenArray[i] = Null;

    if( trailstop == 0 AND Buy[ i ] )
    {
        trailstop = BuyPrice[i] * ( 1 - stopLoss / 100 );
        buyLevel = BuyPrice[i];
    }
    else Buy[i] = 0; // remove excess buy signals

    if( trailstop > 0 AND Low[ i ] < trailstop AND Buy[i] != True )
    {
        Sell[ i ] = 4; // set to this value to have a "trail" stop exit in the report
        SellPrice[ i ] = Min( Open[ i ], trailstop );
        Buy[i] = 0;
        // Reset variables
        trailstop = 0;
        buyLevel = 0;
        isBreakEvenLevelSet = False;
    }

    if( trailstop > 0 )  // Goal is to first trail stop with max stop loss, then follow the tight DonchianStop level, then once in profit, follow DonchianLower level
    {
        if( ( buyLevel > 0 ) AND ( DonchianStop[i] >= buyLevel ) )
        {
            if( !isBreakEvenLevelSet )
                breakEvenArray[i] = DonchianStop[i];

            isBreakEvenLevelSet = True;
        }

        if( isBreakEvenLevelSet )
            trailStop = Max( DonchianStop[i], trailStop );

        trailArray[ i ] = trailstop;
    }
}

Plot(trailArray, "Trailing Stop Level", colorBlue, styleThick);
Plot(breakEvenArray, "Break Even Level", ColorRGB(255, 0, 255), styleThick);

Hope it helps.

3 Likes

This is where my thinking went for the stop - might have it wrong...

// Initialize variables
Sell = 0;
trailArray = Null;
trailStop = 0;
buyLevel = 0;

// Trailing stop logic
for( i = 0; i < BarCount; i++ )
{
    if( trailstop == 0 AND Buy[i] )
    {
        trailstop = BuyPrice[i] * ( 1 - stopLoss / 100 );  // max stop loss
        buyLevel = BuyPrice[i];
    }
    else Buy[i] = 0; // remove excess buy signals

    if( trailstop > 0 AND Low[i] < trailstop AND NOT Buy[i] )
    {
        Sell[i] = 1;
        SellPrice[i] = Min( Open[i], trailstop );
        trailstop = 0;
    }

    if( trailstop > 0 )  // follow stop at the tight DonchianStop level, then once in profit, follow DonchianLower level
    {
        trailStop = Max( Max( Min( DonchianStop[i], buyLevel ), DonchianLower[i] ), trailStop );
        trailArray[ i ] = trailstop;
    }
}

Plot( trailArray, "Trailing Stop Level", colorRed, styleThick );

2 Likes

Thanks @beppe your code isn't exactly what I was looking for but you did get me the horizontal line where I wanted it, so I think I can experiment with it and figure it out now. The trick I think is the breakEvenArray[i] = breakEvenArray[i - 1]; logic where the breakEvenArray doesn't change if it is true. I was missing how to do that before not being aware of [i - 1] being an option. Still very new to AFL and programming in general so this is a big help. Thanks!

Thanks @JohnHT the nested Max(Max(Min())) I think will be useful for the final trailing stop solution I have in my mind. Would have never thought to do that like that.

1 Like

Thank you @beppe for your help! With your code example I was able to figure out what I was trying to do.

  1. Set initial max stop level
  2. Trail stop with tighter Donchian channel until it is in profit
  3. Once in profit leave stop there until looser Donchian channel catches up
  4. Trail stop with looser Donchian channel

dctest

The theory behind why I wanted to test this out was as a way to keep risk small initially while giving winners more room to run. Now I am able to test out this idea to see if it holds water.

For anyone catching this thread later on, here's the updated code that does this.

// ==========================================================================================
// === TRADING SYSTEM PARAMETERS ===
// ==========================================================================================
SetOption("InitialEquity", 100000);
SetTradeDelays( 0, 0, 0, 0 ); // 1 - Delays the trades to the next day, 0 - Trades same day via stops
SetOption("AllowPositionShrinking", True);
SetOption("AccountMargin",100); // 100 = Cash account, 75 = Using half available margin
SetOption("MaxOpenPositions", 20);
RoundLotSize = 1;  // Disallow fractional share purchasing


// ==========================================================================================
// === RISK MANAGEMENT & POSITION SIZING ===
// ==========================================================================================
// Initial (MAX) stop loss
SetOption("ActivateStopsImmediately", False);
stopLoss = 7; // Change this to a small number to experience the issue with trade entries being ignored
ApplyStop(stopTypeLoss, stopModePercent, stopLoss, ExitAtStop = 1);

// Position size based on risk and max stop loss
PositionRisk = 1;  
PosSize = 100 * PositionRisk / stopLoss;
SetPositionSize(PosSize, spsPercentOfEquity);
         

// ==========================================================================================
// === PLOT CHART & INDICATORS ===
// ==========================================================================================
// Chart
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - " + FullName() + " | {{INTERVAL}} {{DATE}}: Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

// Donchian Channel
pdsU=4;  // High channel lookback
pdsL=5;  // Low channel lookback
pdsS=3;  // Tight Stop Low channel lookback

DonchianUpper =HHV(H,pdsU);
DonchianLower = LLV(L,pdsL);
DonchianStop = LLV(L,pdsS);

Plot(DonchianUpper,"DU",color = colorBlueGrey,styleDashed);
Plot(DonchianLower,"DL",color = colorBlueGrey, styleDashed);
Plot(DonchianStop,"DS",color = colorBlueGrey, styleDashed);

  
// ==========================================================================================
// === BUY & SELL LOGIC ===
// ==========================================================================================
Buy=Cross(High, Ref(DonchianUpper, -1)); 
BuyPrice=Max(Ref(DonchianUpper, -1), Open);

// === TRAILING STOP WITH JUST A SINGLE DONCHIAN CHANNEL ===
// Initialize variables
//Sell=0;
//trailArray = Null;
//trailStop = 0;

//Trailing stop logic
//for( i = 0; i < BarCount; i++ )
//{  
//  if( trailstop == 0 AND Buy[ i ] ) 
//  { 
//	trailstop = BuyPrice[i] * (1- stopLoss/100);
//	entryBar[i] = True;
//  }
//  else Buy[i] = 0; // remove excess buy signals
//  if( trailstop > 0 AND Low[ i ] < trailstop AND entryBar[i] != True)
//   {   
//	 Sell[ i ] = 1; 
//	 SellPrice[ i ] = Min( Open[ i ], trailstop );
//	 trailstop = 0;
//   }
   
//  if( trailstop > 0 )
//   {
//	  trailStop = Max(DonchianLower[i], trailStop); 
//	  trailARRAY[ i ] = trailstop;
//   }
//}

// === NEW LOGIC TRYING TO MOVE TRAILING STOP TO LOOSER DONCHIAN LEVEL ===
// Initialize variables
Sell=0;
trailArray = Null;
trailStop = 0;
breakEvenLevel = 0;
breakEvenArray = Null;
buyLevel = 0;
isBreakEvenLevelSet = False;

 //Trailing stop logic trying to do a tighter stop initially until in profit
for( i = 0; i < BarCount; i++ )
{  
  if( ( i > 0 ) AND ( isBreakEvenLevelSet ) )
        breakEvenArray[i] = breakEvenArray[i - 1];
  else
        breakEvenArray[i] = Null;
        
  if( trailstop == 0 AND Buy[ i ] ) 
  { 
	trailstop = BuyPrice[i] * (1- stopLoss/100);
	buyLevel = BuyPrice[i];
  }
  else Buy[i] = 0; // remove excess buy signals
  if( trailstop > 0 AND Low[ i ] < trailstop AND Buy[i] != True)
  {   
	 Sell[ i ] = 4; // set to this value to have a "trail" stop exit in the report
	 SellPrice[ i ] = Min( Open[ i ], trailstop );
	 trailstop = 0;
	 Buy[i] = 0; 
	 buyLevel = 0;
	 isBreakEvenLevelSet = False;

  }
   
  if( trailstop > 0 )  // Goal is to first trail stop with max stop loss, then follow the tight DonchianStop level, then once in profit, follow DonchianLower level
  {
	 if((buyLevel > 0) AND (DonchianStop[i] >= buyLevel))
	 {
		if( !isBreakEvenLevelSet )
			breakEvenArray[i] = DonchianStop[i];
			isBreakEvenLevelSet = True;
	 }
	 
	 trailStop = IIf(isBreakEvenLevelSet, Max(DonchianLower[i], BreakEvenArray[i]), Max(DonchianStop[i], trailStop)); 
	 trailArray[ i ] = trailstop;
  }
}

Plot(trailArray, "Trailing Stop Level", colorRed, styleThick);
Plot(breakEvenArray, "Break Even Level", colorBlue, styleThick);

// Plot arrows indicating trades
PlotShapes(IIf(Buy, shapeUpTriangle, shapeNone),color = colorLime, 0, L, Offset=-50);
PlotShapes(IIf(Sell, shapeDownTriangle, shapeNone),color = colorRed, 0, H, Offset=-50);

// ==========================================================================================
// === EXPLORATION / SCANNING COLUMNS ===
// ==========================================================================================
Filter = 1;
AddTextColumn(FullName(), "Name");
AddColumn(Buy, "Buy Array");
//AddColumn(entryBar, "BarsSince Buy", 1);


3 Likes

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.