System Trader Success
Share It!

A Flexible Trailing Stop Function

The Anatomy of a Stop

A stop can be defined by specifying four basic parameters, illustrated in Figure 1 below:

Price Reference: The price from which the stop is offset (white line) to create a stop value.

Stop Offset: The distance from the Price Reference to the stop value.

Price Trigger: The value of price that will trigger the stop. Usually this is the low or the high of a price bar. However, more sophisticated stops can be created by setting the trigger to a custom function of price, such as Average(Low, 3) to make the stop less vulnerable to isolated tall tails.

Reset Padding: The distance the stop should be reset away from the Price Trigger when the stop has been hit. Resetting the stop level serves two purposes: (1) it is much easier to see when a stop is hit, especially when the price trigger comes very close to but not quite touches the stop level, and (2) if a trade is re-entered in the same direction after stopping out, this reset padding can serve as the initial stop loss.

With these parameters defined, the following stop values can be calculated:

Stop Value: The value of the stop (yellow line). The stop is hit when the Price Trigger touches or crosses the Stop Value.

Ratchet Stop Value: The value of the ratchet stop (red line) is the Stop Value when it is constrained to move only in the direction toward the price action. The ratchet stop is hit when the Price Trigger touches or crosses the Ratchet Stop Value.

Fig. 1. Chandelier 5% Ratchet Trailing Stop (red line).

In this case, the Price Reference is the high of the bar, shown in white. The Stop Value is the yellow line, a distance of 5% below the Price Reference. The red line is the ratchet stop, which is the Stop Value constrained to always move in a direction closer to the price and never away from the price (unless the stop is hit and reset).

The Price Trigger is the low of the bar. The cyan dots indicate the points at which the Price Trigger has crossed below the Ratchet Stop Value, triggering the stop.

Generating Many Stops from a Single Function (or Method)

By manipulating the the four basic parameters that define a stop, a multitude of different stops can be generated:

Price Reference can be defined to be the high, low or average price of a bar. It could also be defined as some custom function of price, such as a Linear Regression function of price.

Stop Offset can be defined in terms of points, price percentage, ATR units or some custom function of price or volatility.

Trigger Price is usually set to the last trading price or the closing price for the bar. However, an alternative definition based on a custom formula of price, such as Average(Avgprice, 2), can be used to make the stop less vulnerable to tall tails and isolated bars extending beyond historical support or resistance.

Stop Directional Constraints can allow the stop to vary up and down, as in a yo-yo stop, or can force the stop to move only in a direction toward the current price, as in a ratchet stop.

Each unique type of stop could be coded into a separate function. However, since much of the code in each of these functions would be duplicated it makes sense to create a single unified stop generating function that could specify any type of stop by manipulating its input parameters.

This would serve to reduce coding errors and encourage consistency when using stops in indicators and strategies. There is, however, an even greater motivation for using such a function. When used to generate stops within strategies, the optimizer could vary not only the value of the stop, but the type of stop as well, to determine which type of stop extracts the greatest profit from a trading system.

It is with these goals in mind that the superfunction (or method), StopsFlexible, was created. This single function (or method) can be used to create almost any type of stop desired.

Advantages of Using Function: StopsFlexible

  1. Coding duplication is markedly reduced, lessening the possibility of errors and making code maintenance more efficient.
  2. When used in a chart, the type of stop can be varied by simply changing an input parameter. This is more convenient than manually locating and inserting a new indicator from a large collection of stop indicators.
  3. Indicators using function StopsFlexible can display the differences in behavior of several different types of stops simultaneously, giving the user a graphical representation of each on the chart and visually revealing their unique behaviors. Such a graphical comparison assists in the selection of the most appropriate stop without the need for formal backtesting.
  4. When used in a strategy, optimization can exercise many types of stops using StopsFlexible, not just a single type of stop. In this manner, the best type of stop can be determined for the trading system being tested rather than only varying the “distance” of a single type of stop from the price reference.
  5. Blended Stops can can easily be created. For example, one blended stop could be: the sum of 1% of price plus 1.5 ATR units. Optimization can test blended stops efficiently to determine if the unique characteristics of blended stops can extract more profit from a trading system than traditional stops.

Advantages of Converting the Function: StopsFlexible to a Method

The function StopsFlexible is a series function, not a simple function. Therefore, when called by a indicator or strategy formatted “Update each tick”, the function MUST execute with every tick, even if it is desirable to re-calculate only once per bar. Bracketing the call to the function with If BarStatus(1) = 2 condition, will NOT prevent a series function from executing with each tick, since this is the behavior of all series function within EasyLanguage.

Since the calculation in StopsFlexible needs to occur only once per bar, the inefficiency forced upon the programmer by using a series function can be eliminated by recoding the function as a Method. Method calls, in contrast to series function calls, CAN be restricted to occur only once per bar when the indicator or strategy must be formatted to “Update each tick”.

This technique is used in the current version of indicator StopsFlexible, bracketing the method StopsFlexible call by an If BarStatus(1) = 2 condition.

More Sophisticated Stops

Reference Point for a Stop

Although the reference point for a trailing stop is usually defined as the high of the bar for long trades, there is nothing that prevents an alternative definition. For example, the reference point could be the Low rather than the High of the bar. This would make the stop less sensitive to unusually tall bars or tall tails which might pull the stop up abruptly and cause a trade to stop out of a continuing trend prematurely.

An alternative approach to make the stop movement less sensitive to bars with “tall tails” would be to define a chandelier stop to be based on the reference point of Average(high, length) or MinList(high, high[1]) rather than simply the high of the bar.

More sophisticated stops may be created by referencing them to custom functions of price, such as linear regression or Kaufman Adaptive Moving Average of the price.

Stop Offset Variations

In addition to stop offsets being based on points, price percentage, and ATR units, other offset definitions are possible.

For example, blended stops formed by adding a price percentage offset and an ATR unit offset can be created, inheriting some of the characteristics of each. Such blended stops can be optimized to extract additional profit from trading systems.

Stops can also be made to react dynamically to the acceleration of price movement by tightening the stop to capture additional profit in the event of rapid price thrust before a signifcant price retracement can occur.

Stops can also use custom volatility functions, such as Standard Error, in place of the standard ATR unit, as illustrated below:

Figure 2. 6 StdErr Trailing Stop vs 1.5 ATR Trailing Stop.

Why choose Standard Error? The goal here is to tighten the stop whenever the price moves in a very well-behaved trend for at least n-bars. Well-behaved, in this case, means a consistent trend with low volatility.

The StdError(Price, N) function measures the degree to which price deviates from a linear regression line through the most recent “n” price bars. Notice that the minimums of the StdError function above (yellow arrows) correspond to intervals when the price moved in a consistent trend with low volatility for a period of at least 6 bars. A high standard error indicates that the price action is not moving consistently along a straight linear regression line, and maximums in the standard error typically occur at points where the trend abruptly changes direction.

You can also see at each relative minimum in the StdError function value, the 6 StdError Trailing Stop tightened while the 1.5 ATR Trailing Stop remained about the same distance from the price.

The StdError Trailing Stop can sqeeze a few more dollars out of a trend trade, as shown in the three instances illustrated above, as it will tighten further after a consistent price move has occurred.

Trigger Reference Modification

Instead of using the last trade price or the low of the bar as a trigger for a stop, a custom trigger reference could be created as an input parameter to StopsFlexible. The screen shot to the right shows a Trigger Reference (white line) defined as Average(AvgPrice, 2). This moving average must hit the stop level to trigger the stop. Note that the bar crossing the ratchet trailing stop (red line) did NOT trigger the stop.

This is an example of a custom trigger reference that makes the stop less sensitive to isolated bars extending just below or above a historical level of support or resistance.

Such a trigger definition might be useful when using a stop order for a breakout entry, either long or short. It prevents an isolated tall tail from triggering a stop prematurely and protects to some extent against stop running and head fakes by larger traders.

StopsFlexible Indicator Input Parameters

HighRef is the Price Reference for the high stop (positioned above the price). LowRef is the Price Reference for the low stop (positioned below the price).

Length is used to delay changes in the price reference by “Length” bars by adjusting the HighRef and LowRef values to MaxList(high, Length) and MinList(low, Length), respectively.

UseKAMA is used to apply a KAMA (Kaufman adaptive moving average) filter to HighRef and LowRef values. Default value is false. EffRatioLength, FastAvgLength and SlowAvgLength are all parameters that determine the degree of KAMA filtering.

StopOffset is the offset to the bar used to calculate the stop for the current bar. Usually should be set = 1 (since strategy orders use the format: Buy/Sell NEXT bar at Value Limit).

TradeDir indicates if stops will be displayed below the price (+1), above the price (-1) or both (0). Similarly, AlertDir indicates if the corresponding low (+1), high (-1) or both (0) stops will generate an alert.

ATRLength, JATRLength and StdErrLength are the lengths used to calculate the Average True Range, Jurik Average True Range and Standard Error.

StopPts, StopPct, StopATR, StopJurikATR and StopStdErr are the multipliers used for the stop offset expressed in points, price percentage, ATR units, Jurik ATR units and standard error units, respectively. All specified values are calculated and added together to form the final stop value. For example, to create a pure 2 ATR stop, StopATR should be 2 and all other values 0. To create a stop that is a blend of 1 ATR unit and 1%, set StopATR = 1, StopPct = 1 and all other values to 0.

HighRefTrig and LowRefTrig are the price references triggering the stop. Normally, HighRefTrig = high and LowRefTrigger = low indicating the high or low of the bar will trigger stops above and below the price, respectively.

SmoothTrigRef is the length of the simple moving average applied to the HighRefTrig and LowRefTrig values.

ResetPts, ResetPct, ResetATR, ResetJATR and ResetStdErr are the amounts the stop will be offset each time it is hit. Moving the stop value when hit makes it easier to determine if a stop that comes very close to the low or high of a bar was hit or not.

ShowRef, ShowStops, ShowRatchet, ShowRefTrigger and ShowStopTriggered are set to true or false to indicate whether these values are to be displayed on the chart.

PlotWidth indicates the width of all lines plotted. UsePlotWidth indicates whether the PlotWidth value will be used, or if the user will be free to specify line formatting manually.

ShowHitsOffsetATR is the amount of vertical offset (in ATR units) the ShowMe dot, indicating a stop has been hit, will be displayed. This offset moves the dot away from the price action to make it more easily visible. If ShowHitsOffsetATR = 0, then the dot appears at the HighRefTrig or LowRefTrig value.

NOTE: The Jurik moving average function used to calculate the Jurik Average True Range is disabled in StopsFlexible, as this is a third party add-in that must be purchased from Jurik Research. Those users that have purchased this add-in may uncomment out the appropriate section of code.


The download package is a zip file that contains the following three EasyLanguage files:

  1. StopFlexable Indicator
  2. StopFlexable Function
  3. StopFlexable Method

StopFlexable Zip File 

— by Mark Krisburg from HighTick Trading. Do you have a custom indicator or function you would like to use, but don’t have the programming experience to create it? We provide custom programming services, as well as a variety of useful add-on functions and screening tools to find profitable trades in any market condition, while controlling risk.

About the Author System Trader Success Contributor

Contributing authors are active participants in the financial markets and fully engrossed in technical or quantitative analysis. They desire to share their stories, insights and discovers on System Trader Success and hope to make you a better system trader. Contact us if you would like to be a contributing author and share your message with the world.

Leave a Comment:

1 comment
Add Your Reply