Stops and Reversals
All functions · nseries package
ATRTrailingStop
func (s Series) ATRTrailingStop(h, l Series, n int, k float64) Series
ATRTrailingStop returns the close-anchored ATR trailing stop, Vervoort’s SVE_Stop_trail_ATR. It is not TradingView’s built-in Volatility Stop (VolatilityStop), which anchors on the highest or lowest close since the flip, tests the updated stop and goes long on a tie. The receiver is the close: the anchor of the candidate stops, the trigger, and the close passed to ATRWilder. h and l are the highs and lows, n is the length of the ATR and k its multiple; Vervoort’s defaults are n = 5 and k = 3.5. The line is a price.
From bar n it is FlipStop on the close with the long candidate k times ATRWilder(h, l, s, n) below the close and the short candidate the same distance above it, so ATRTrailingStop(h, l, n, k)[n:] equals s[n:].FlipStop(longStop[n:], shortStop[n:]) bit for bit. Its start t0 is the first bar from n on at which the close and both candidates are finite: usually bar n, but later when ATRWilder with n = 1 recovers after a bad bar or when the distance or a candidate overflows. Bars n to t0-1 are NaN, and after t0 a non-finite value makes its bar and every later bar NaN, as in FlipStop. (SuperTrendLine instead has a fixed start at bar n, so that a bad value there poisons every later bar.)
The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. If n < 1, n >= len(s), or k is negative or not finite, the result is len(s) zeros; if h or l is not as long as the receiver, it is an empty series.
Vervoort’s own ATR is an exponential moving average of the true range of length 2n-1 and MetaStock’s is Wilder’s, so the values differ from those on his platform until the seeds decay, and also wherever FlipStop departs from his code.
The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its position can differ from that of the full series; while both hold the same position from the same flip its line differs by at most k times the ATR-seed difference on the flip bar (the ratchet can hold that difference unchanged while the seed difference itself decays by the factor 1 - 1/n per bar), and a close that lands between the two lines flips them on different bars, so the positions can differ again after a common flip.
Source: Vervoort, “Average True Range Trailing Stops”, Technical Analysis of Stocks & Commodities, June 2009 (part 2 of a series running May to July 2009).
ATRTrailingStopDirection
func (s Series) ATRTrailingStopDirection(h, l Series, n int, k float64) Series
ATRTrailingStopDirection returns the position of ATRTrailingStop with the same arguments: +1 while long and -1 while short. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. There 0 means no position yet. Bars n to t0-1, where t0 is the start described for ATRTrailingStop, are NaN, as are the bar of a later non-finite value and every bar after it. Invalid parameters give len(s) zeros and a length mismatch an empty series, as in ATRTrailingStop. The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its position can differ from that of the full series, and even after both flip the same way on the same bar a close that lands between their two lines (which differ by up to k times the ATR-seed difference on the flip bar, a difference the ratchet can hold) flips them on different bars.
FlipStop
func (s Series) FlipStop(longStop, shortStop Series) Series
FlipStop returns a generic ratchet-and-flip trailing stop: the recursion of Vervoort’s SVE_Stop_Trail% and SVE_Stop_trail_ATR, with an explicit direction state. The receiver is the trigger price (usually the close); longStop and shortStop are the candidate stops for a long and a short position on each bar. The candidates are taken as given: a long candidate above the trigger or a short candidate below it is not rejected, and simply flips the position on the next bar unless the trigger moves past it.
The position starts long at the first bar t0 at which the trigger and both candidates are finite, with line[t0] = longStop[t0]. The bars before t0 are NaN, so a leading run of NaN inputs (such as another indicator’s NaN warm-up) propagates; if there is no such bar, every bar is NaN. While long, the line only rises: it is the running maximum of the long candidates since the last flip, and the position flips to short, with that bar’s short candidate as its line, when the trigger falls to or through the previous bar’s line. While short, the line only falls: it is the running minimum of the short candidates since the last flip, and the position flips to long, with that bar’s long candidate as its line, when the trigger rises above the previous bar’s line. So on a tie a long position flips (Vervoort: “lower than or equal to the previous value”) and a short position stays short. Vervoort’s MetaStock code loosens a short line to C + loss (the close plus the stop distance) on an exact tie; this method keeps the short line. It also departs from his code where a bar’s stop distance is zero, which his two-close test cannot resolve, and at the start, where his PREV starts at 0, so his first line is Max(0, C - loss).
line[t-1] is the stop in force during bar t, computed at the close of bar t-1; a flip happens at the close of bar t (a close-basis fill), and line[t] on a flip bar is the first stop of the new position. If the trigger or a candidate is not finite at a bar after t0, that bar and every later bar are NaN: the recursion does not recover. If longStop or shortStop is not as long as the receiver, the result is an empty series.
FlipStop has no warm-up of its own beyond the NaN start. The +0 warm-up of a house indicator is finite and would start the recursion inside the warm-up, so mask such a warm-up with NaN first, for example with SetN(n, math.NaN()).
The method is recursive (path-dependent): a slice of the history that starts later can differ from the full series until both hold the same position with the same line on the same bar (as after both flip the same way on the same bar), after which they agree.
Source: Vervoort, “Using Initial And Trailing Stops” and its sequels “Average True Range Trailing Stops” and “Trailing Resistance And Support Stops”, Technical Analysis of Stocks & Commodities, May to July 2009.
FlipStopDirection
func (s Series) FlipStopDirection(longStop, shortStop Series) Series
FlipStopDirection returns the position of FlipStop with the same arguments and rules: +1 while long and -1 while short. The bars before the start (the first bar at which the trigger and both candidates are finite) are NaN, as are the bar of a later non-finite input and every bar after it; a length mismatch gives an empty series. A flip at the close of bar t shows as a change of sign from bar t-1 to bar t. The method is recursive (path-dependent): a slice of the history that starts later can differ from the full series until both hold the same position with the same line on the same bar, after which they agree.
ParabolicSAR
func (s Series) ParabolicSAR(h, l Series, afStart, afStep, afMax float64) Series
ParabolicSAR returns Wilder’s Parabolic time/price system, the stop and reverse level (SAR), of the highs h and lows l, in TA-Lib’s state machine (TA_SAR). Index 0 is the oldest bar and the last index the most recent. The system is always in the market, long or short. While long, the SAR trails below price and accelerates towards the trade’s extreme point (EP, the highest high since the trade began); the short side mirrors it with the lowest low. afStart is the initial acceleration factor (AF), afStep its increment and afMax its cap; Wilder’s defaults are 0.02, 0.02 and 0.2. The AF steps only on a bar that makes a new extreme (a new high while long, a new low while short) and is capped at afMax. After each bar the next SAR is clamped outside the ranges of the last two bars: while long it is not above their lows, while short it is not below their highs. At bar 1 both clamp bars are bar 1, as in TA-Lib, so bar 0’s range does not clamp.
The start is TA-Lib’s minus-DM rule over bars 0 and 1: with up = h[1] - h[0] and dn = l[0] - l[1], the system starts short if dn > 0 and up < dn, otherwise long, so a tie starts long. A long start has sar = l[0] and ep = h[1]; a short start has sar = h[0] and ep = l[1]. Other platforms start differently (Tulip compares h+l, TradingView compares closes, pandas-ta seeds the EP from bar 0), so their values differ from these at least until the first common reversal. They can also differ after it, because those platforms reverse and clamp differently (pandas-ta clamps on one bar, and pandas-ta and TradingView test the stop before clamping it) and do not use a fused multiply-add.
A touch reverses: while long, a bar whose low is at or below the SAR reverses the position to short; while short, a bar whose high is at or above the SAR reverses it to long. Tulip, pandas-ta and TradingView reverse only on a strict penetration. On a reversal bar the output is the new stop of the opposite position (as in TA-Lib, Tulip, pandas-ta and TradingView): the old trade’s EP, moved if need be so that it is not inside the ranges of that bar and the one before (at bar 1, of bar 1 only). It uses the bar’s own high or low, so it is known only at that bar’s close. The stop that was hit, the fill, is not one of the outputs: it is the stop computed at the previous bar’s close, which in general differs from the previous bar’s value (the two are equal when a clamp holds the stop). From bar 2 on, detect reversals from a change in ParabolicSARDirection; a reversal on bar 1 does not show, because bar 0 reads 0. FlipStop, ATRTrailingStop, SuperTrendLine, WilderVolatilityStop and VolatilityStop time their lines differently: on every bar they return the stop computed at that bar’s close, in force during the next bar.
The warm-up reads 0, not NaN: bar 0 is 0 and the first valid index is 1.
Invalid parameters give aligned zeros, one 0 per bar of h: afStart, afStep and afMax must all be finite, with afStart > 0, afStep >= 0 and afMax > 0. As TA-Lib corrects incoherent values, an afStart or afStep above afMax is set to afMax. If h and l differ in length the result is an empty Series, and that check comes first. The receiver s is not used, as in ParkinsonVolatility.
With valid parameters and equal lengths, if h or l holds NaN or an infinity, the result is NaN from the first bad bar on, because the recursion does not recover; a bad bar 0 or 1 makes every bar from 1 NaN (bar 0 still reads 0). The result is also NaN from the bar after the internal stop, after its clamps, is not finite, and from a bar whose output is not finite (possible only on overflow near ±1.8e308).
The stop update uses a fused multiply-add, as current TA-Lib does, so the bits match TA-Lib on every platform. The method is recursive, and each reversal carries the previous trade’s EP into the new stop, so a slice of the history that starts later can differ from the full series until both reverse on the same bar with the same new stop.
Sources: Wilder, New Concepts in Technical Trading Systems (1978), through Hartle, “The Parabolic Trading System”, Technical Analysis of Stocks & Commodities, November 1993; Aan, “Parabolic Stop/Reversal”, Technical Analysis of Stocks & Commodities, November 1989, for the AF step and maximum ranges; TA-Lib TA_SAR and TA_SAREXT; Tulip psar; pandas-ta psar; TradingView ta.sar.
ParabolicSARDirection
func (s Series) ParabolicSARDirection(h, l Series, afStart, afStep, afMax float64) Series
ParabolicSARDirection returns the position of Wilder’s Parabolic time/price system after each bar: +1 while long and -1 while short. It runs the same state machine as ParabolicSAR, TA-Lib’s TA_SAR, with the same parameters: afStart is the initial acceleration factor (AF), afStep its increment and afMax its cap; Wilder’s defaults are 0.02, 0.02 and 0.2. The AF steps only on a bar that makes a new extreme (a new high while long, a new low while short) and is capped at afMax, and each next stop is clamped outside the ranges of the last two bars (at bar 1 both are bar 1, as in TA-Lib, so bar 0’s range does not clamp).
The start is TA-Lib’s minus-DM rule over bars 0 and 1: with up = h[1] - h[0] and dn = l[0] - l[1], the system starts short if dn > 0 and up < dn, otherwise long, so a tie starts long. The stop starts at bar 0’s low (long) or high (short) and the EP at bar 1’s high (long) or low (short). Other platforms start differently (Tulip compares h+l, TradingView compares closes, pandas-ta seeds the EP from bar 0), so values differ at least until the first common reversal, and can differ after it because those platforms reverse and clamp differently and do not use a fused multiply-add.
A touch reverses: while long, a bar whose low is at or below the stop reverses the position to short; while short, a bar whose high is at or above the stop reverses it to long. Tulip, pandas-ta and TradingView reverse only on a strict penetration. On a reversal bar the direction is the new position, which pairs with the new stop that ParabolicSAR returns on that bar. The stop that was hit, the fill, is not one of the outputs: it is the stop computed at the previous bar’s close, which in general differs from the previous bar’s SAR (the two are equal when a clamp holds the stop). From bar 2 on, a reversal shows as a change in the direction; a reversal on bar 1 does not show, because bar 0 reads 0. The direction views of FlipStop, ATRTrailingStop, SuperTrendLine, WilderVolatilityStop and VolatilityStop share this timing (the position held after each bar’s close), though their lines are timed differently from ParabolicSAR: on every bar they return the stop computed at that bar’s close, in force during the next bar.
The warm-up reads 0, not NaN: bar 0 is 0 and the first valid index is 1. For the direction, 0 means no position yet.
Invalid parameters give aligned zeros, one 0 per bar of h: afStart, afStep and afMax must all be finite, with afStart > 0, afStep >= 0 and afMax > 0. As TA-Lib corrects incoherent values, an afStart or afStep above afMax is set to afMax. If h and l differ in length the result is an empty Series, and that check comes first. The receiver s is not used, as in ParkinsonVolatility.
With valid parameters and equal lengths, if h or l holds NaN or an infinity, the result is NaN from the first bad bar on, because the recursion does not recover; a bad bar 0 or 1 makes every bar from 1 NaN (bar 0 still reads 0). The direction is NaN wherever the SAR is NaN, including where the internal stop, after its clamps, or an output is not finite (possible only on overflow near ±1.8e308).
The stop update uses a fused multiply-add, as current TA-Lib does, so the bits match TA-Lib on every platform. The method is recursive, and each reversal carries the previous trade’s EP into the new stop, so a slice of the history that starts later can differ from the full series until both reverse on the same bar with the same new stop.
Sources: Wilder, New Concepts in Technical Trading Systems (1978), through Hartle, “The Parabolic Trading System”, Technical Analysis of Stocks & Commodities, November 1993; Aan, “Parabolic Stop/Reversal”, Technical Analysis of Stocks & Commodities, November 1989, for the AF step and maximum ranges; TA-Lib TA_SAR and TA_SAREXT; Tulip psar; pandas-ta psar; TradingView ta.sar.
ParabolicSARExt
func (s Series) ParabolicSARExt(h, l Series, start, offsetOnReverse, afInitLong, afLong, afMaxLong, afInitShort, afShort, afMaxShort float64) Series
ParabolicSARExt returns the Parabolic SAR as TA-Lib’s TA_SAREXT computes it: the system of ParabolicSAR with separate long and short acceleration parameters, a chosen start and an offset on reversal, and with the SAR negated while the position is short. The negation applies on every bar that ends short, including the reversal bar into short; the SAR is not negated while long, so for positive prices it is negative while short and positive while long. The sign therefore carries the direction only for positive prices; use ParabolicSARDirection when prices can be zero or negative. With start 0, offsetOnReverse 0 and equal parameters on both sides the result equals ParabolicSAR multiplied by ParabolicSARDirection, bit for bit, on finite inputs.
Each side has an initial acceleration factor (AF), a step and a cap: afInitLong, afLong and afMaxLong, and afInitShort, afShort and afMaxShort. Wilder’s defaults are 0.02, 0.02 and 0.2. The AF steps only on a bar that makes a new extreme (a new high while long, a new low while short) and is capped at that side’s maximum. After each bar the next SAR is clamped outside the ranges of the last two bars: while long it is not above their lows, while short it is not below their highs. At bar 1 both clamp bars are bar 1, as in TA-Lib, so bar 0’s range does not clamp.
start selects the first position. Zero uses TA-Lib’s minus-DM rule over bars 0 and 1: with up = h[1] - h[0] and dn = l[0] - l[1], the system starts short if dn > 0 and up < dn, otherwise long, so a tie starts long; the SAR starts at bar 0’s low (long) or high (short) and the EP at bar 1’s high (long) or low (short). A positive start goes long with the SAR at start and the EP at bar 1’s high; a negative start goes short with the SAR at -start and the EP at bar 1’s low. Other platforms start differently (Tulip compares h+l, TradingView compares closes, pandas-ta seeds the EP from bar 0), so values differ from theirs at least until the first common reversal, and can differ after it because those platforms reverse and clamp differently and do not use a fused multiply-add.
offsetOnReverse is a fraction of the SAR added to the new stop on a reversal into short and subtracted from it on a reversal into long.
A touch reverses: while long, a bar whose low is at or below the SAR reverses the position to short; while short, a bar whose high is at or above the SAR reverses it to long. Tulip, pandas-ta and TradingView reverse only on a strict penetration. On a reversal bar the output is the new stop of the opposite position (as in TA-Lib, Tulip, pandas-ta and TradingView), negated when that position is short. It uses the bar’s own high or low, so it is known only at that bar’s close. The stop that was hit, the fill, is not one of the outputs: it is the stop computed at the previous bar’s close, which in general differs from the previous bar’s value (the two are equal when a clamp holds the stop). From bar 2 on, detect reversals with ParabolicSARDirection; a reversal on bar 1 does not show, because bar 0 reads 0.
The warm-up reads 0, not NaN: bar 0 is 0 and the first valid index is 1.
Invalid parameters give aligned zeros, one 0 per bar of h: start, offsetOnReverse and the six acceleration parameters must all be finite, offsetOnReverse must be >= 0, and on each side the initial AF must be > 0, the step >= 0 and the maximum > 0. start may be any finite value, including a negative one. As TA-Lib corrects incoherent values, an initial AF or step above its side’s maximum is set to that maximum. If h and l differ in length the result is an empty Series, and that check comes first. The receiver s is not used, as in ParkinsonVolatility.
With valid parameters and equal lengths, if h or l holds NaN or an infinity, the result is NaN from the first bad bar on, because the recursion does not recover; a bad bar 0 or 1 makes every bar from 1 NaN (bar 0 still reads 0). The result is also NaN from the bar after the internal stop, after its clamps, is not finite, and from a bar whose output is not finite (possible only on overflow near ±1.8e308).
The stop update uses a fused multiply-add, as current TA-Lib does, so with offsetOnReverse 0 the bits match TA-Lib on every platform. The offset is fused here too, but TA-Lib writes it as a separate multiply and add, so with a non-zero offset TA-Lib’s own bits depend on whether its compiler fuses that line; these match a fused build. The method is recursive, and each reversal carries the previous trade’s EP into the new stop, so a slice of the history that starts later can differ from the full series until both reverse on the same bar with the same new stop.
Sources: Wilder, New Concepts in Technical Trading Systems (1978), through Hartle, “The Parabolic Trading System”, Technical Analysis of Stocks & Commodities, November 1993; Aan, “Parabolic Stop/Reversal”, Technical Analysis of Stocks & Commodities, November 1989, for the AF step and maximum ranges; TA-Lib TA_SAR and TA_SAREXT; Tulip psar; pandas-ta psar; TradingView ta.sar.
SuperTrendDirection
func (s Series) SuperTrendDirection(h, l, c Series, mult float64, n int) Series
SuperTrendDirection returns the trend of SuperTrendLine with the same arguments: +1 in an uptrend, where the line is the lower band, and -1 in a downtrend, where it is the upper band, as TA-Lib and pandas-ta sign it. TradingView’s ta.supertrend uses the opposite sign and returns -1 for an uptrend. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. There 0 means no trend yet. The bar of a non-finite value and every bar after it are NaN, invalid parameters give len(s) zeros and a length mismatch an empty series, as in SuperTrendLine. The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its trend can differ from that of the full series, and even after both flip the same way on the same bar a close that lands between their two lines (which differ by a multiple of the ATR-seed difference that the ratchet can hold) flips them on different bars.
SuperTrendLine
func (s Series) SuperTrendLine(h, l, c Series, mult float64, n int) Series
SuperTrendLine returns Olivier Seban’s SuperTrend in its ratcheting and flipping form, as TradingView’s ta.supertrend, Golson’s MetaStock code and TA-Lib’s TA_SUPERTREND compute it. The receiver is the basis, by convention the median price h.Add(l).Div(2); h, l and c are the highs, lows and closes, n is the length of ATRWilder(h, l, c, n) and mult its multiple. Seban’s defaults are n = 10 and mult = 3 (pandas-ta uses 7 and 3). The line is a price level. The existing SuperTrend method is the unratcheted band.
The raw bands lie mult times the ATR above and below the basis, and each ratchets on its own on every bar, the inactive one included: the lower band only rises unless the previous close fell below it, and the upper band only falls unless the previous close rose above it. The trend starts up at bar n, as in TA-Lib (TradingView and MetaStock start down). An uptrend turns down when the close falls below the lower band, and a downtrend turns up when the close rises above the upper band, both as updated on that bar; a close equal to the lower band stays up and one equal to the upper band stays down. The line is the lower band in an uptrend and the upper band in a downtrend.
The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. If n < 1, n >= len(s), or mult is negative or not finite, the result is len(s) zeros; if h, l, c and the receiver do not all have the same length, it is an empty series. Unlike ATRTrailingStop, the start is fixed at bar n: if the basis, the close or the ATR is not finite at a bar from n on, or the line computed there is not finite, that bar and every later bar are NaN (the recursion does not recover), so a bad value at bar n leaves no valid bar. A NaN high, low or close reaches the ATR as ATRWilder documents.
TA-Lib’s TA_SUPERTREND uses the same band and flip rules, the same start and the same ATR seed, but writes Wilder’s step as a different fused expression, so the line agrees with it to rounding, not bit for bit, and the trend agrees except where a close lies within rounding of a band.
The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its trend can differ from that of the full series. Its line differs from the full series’ by mult times an ATR-seed difference: the raw bands’ difference decays by the factor 1 - 1/n per bar, but the ratchet holds a band’s difference unchanged until the band next moves, and the band in force after a flip can carry a difference from before the flip. A close that lands between the two lines flips them on different bars, so the trends can differ again after a common flip.
Sources: Star, “Stay On Track With The Supertrend Indicator”, Technical Analysis of Stocks & Commodities, July 2023, with Golson’s MetaStock code; Unger, “Developing A Trading System For Crude Oil Using The SuperTrend Indicator”, Technical Analysis of Stocks & Commodities, August 2025; TradingView ta.supertrend; TA-Lib TA_SUPERTREND.
VolatilityStop
func (s Series) VolatilityStop(h, l Series, n int, k float64) Series
VolatilityStop returns the volatility stop as TradingView’s built-in “Volatility Stop” (VStop) computes it, a stop-and-reverse line that is always in the market. The stop trails the significant close (SIC), the highest close since the last reversal while long and the lowest while short, by k times the average true range (ATR). At the close of bar t, in this order: the SIC is updated with the close; the stop is ratcheted, moving to the SIC minus k times the ATR of bar t (long) or the SIC plus that distance (short) only when that is in the position’s favour, so it does not move against the position; the close is tested against this updated stop (the same-bar test); and if the close is below a long stop, or at or above a short stop, the position reverses, the SIC restarts at the close and the stop resets, unratcheted, to the close minus or plus k times the ATR of bar t. So a long holds on a close equal to its stop and a short reverses, whereas ATRTrailingStop tests the close against the previous bar’s line, reversing a long on a close equal to it and holding a short. Because the test uses the stop already updated with the bar’s ATR, a fall in the ATR alone can lift a long stop above an unchanged close and reverse the position. With k = 0 a short lasts one bar: the next close always equals or exceeds the updated stop (the lowest close), so the position reverses to long at that close; this is the recursion’s behaviour, not a special case.
The receiver s is the close: the trigger, the source of the SIC and the close passed to ATRWilder(h, l, s, n). h and l are the highs and lows, n is the ATR length and k its multiple. TradingView’s defaults are n = 20 and k = 2.
The value on bar t is the stop computed at the close of bar t, in force during bar t+1, so the stop in force during bar t is the value on bar t-1, and on a reversal bar the value is the new position’s first stop (the reversal fills at the close of bar t). This is the convention of FlipStop, ATRTrailingStop, SuperTrendLine and TradingView’s plotted VStop. ParabolicSAR instead follows TA-Lib: on a bar without a reversal its value is the stop in force during that bar, computed at the previous close, and on a reversal bar it is the new position’s first stop.
The start is fixed at bar n, long (TradingView also starts long), with the SIC at s[n] and the stop k times the ATR below it. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. If n < 1, n >= len(s), or k is negative or not finite, the result is len(s) zeros (k = -0 is valid). If h or l is not the same length as s, the result is an empty series, whatever n and k. If the close or the ATR of bar n or of a later bar, or the stop stored for that bar, is not finite, the result is NaN from that bar on: the recursion does not recover, even with n = 1, where ATRWilder does. Only the stored stop is tested: a non-finite candidate that the ratchet rejects leaves the previous stop in place.
TradingView’s script uses ta.atr, which includes bar 0’s true range h[0] - l[0] and seeds at bar n-1; it starts at bar 0, where its stop falls back to the source itself, and uses the unmultiplied true range as the distance on bars 1 to n-2, before the ATR exists, so its first value is at bar 0, not bar n; and it computes in its own arithmetic. Its values are therefore not reproduced exactly: after both hold the same position from the same reversal, the stops differ by at most k times the ATR-seed difference on the reversal bar, which the ratchet can hold unchanged while the seed difference itself decays by the factor 1 - 1/n per bar, and a close that lands between the two stops reverses them on different bars.
ATRTrailingStop anchors on the current close, not the SIC, and Vakkur’s “volatility stop” (Technical Analysis of Stocks & Commodities, October 1999), a stop ratcheted from the entry close and hit by the low (its short side by the high; his system is long-only), is a different construction. WilderVolatilityStop is Wilder’s original stop, unratcheted and tested against the stop computed at the previous close. The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its position can differ from that of the full series; while both hold the same position from the same reversal its stop differs by at most k times the ATR-seed difference on the reversal bar (the ratchet can hold that difference unchanged while the seed difference itself decays by the factor 1 - 1/n per bar), and a close that lands between the two stops reverses them on different bars.
Sources: TradingView’s built-in Volatility Stop; J. Welles Wilder, New Concepts in Technical Trading Systems (1978), as restated by Peter Aan, “Volatility System”, Technical Analysis of Stocks & Commodities, July 1989; Abraham, “Trading The Trend”, Technical Analysis of Stocks & Commodities, September 1998, for the re-anchoring on a reversal.
VolatilityStopDirection
func (s Series) VolatilityStopDirection(h, l Series, n int, k float64) Series
VolatilityStopDirection returns the position of VolatilityStop held after the close of each bar: +1 long and -1 short (TradingView’s uptrend flag). A reversal at the close of bar t shows as a change of sign from bar t-1 to the bar itself. The timing is that of the line and not that of ParabolicSAR, whose value on a bar without a reversal is the stop in force during that bar. A long holds on a close equal to its updated stop and a short reverses. The receiver s is the close, h and l are the highs and lows, n is the ATR length and k its multiple. The start is fixed at bar n, long, so bar n is +1. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. There 0 means no position yet. Invalid parameters give len(s) zeros and mismatched lengths an empty series, and a non-finite close, ATR or stored stop on bar n or a later bar makes the result NaN from that bar on, with no recovery, as in VolatilityStop. The position is path-dependent: a slice of the history that starts later, or TradingView’s differently seeded ATR, can give a different position, and even after both reverse the same way on the same bar a close that lands between their two stops reverses them on different bars until the ATR seeds have decayed. See VolatilityStop for the construction, the settings and the sources.
WilderVolatilityStop
func (s Series) WilderVolatilityStop(h, l Series, n int, k float64) Series
WilderVolatilityStop returns the stop of Wilder’s Volatility System, a stop-and-reverse line that is always in the market. The stop trails the significant close (SIC), the highest close since the last reversal while long and the lowest while short, by k times the average true range (ATR): at the close of bar t it is the SIC minus k times the ATR of bar t while long and the SIC plus that distance while short. It is rebuilt from the SIC and the ATR at each close and is not ratcheted, so it loosens when the ATR rises (Aan: “the trailing stop loosens”). Each close is tested against the stop computed at the previous close, strictly both ways (Aan’s stop “is activated only on the close”; Abraham’s “closes below” and “closes above”): a long reverses on a close below it, a short on a close above it, and on a reversal the SIC restarts at the close. A close equal to the stop holds the position, long or short, whereas ATRTrailingStop reverses a long on a close equal to its line and holds a short. VolatilityStop is the ratcheted variant, in TradingView’s construction.
The receiver s is the close: the trigger, the source of the SIC and the close passed to ATRWilder(h, l, s, n). h and l are the highs and lows, n is the ATR length and k its multiple. Aan tested n from 6 to 20 and constants from 1.0 to 4.0; in his example an ATR of 200 points times a constant of 3.5 puts a long position’s stop 700 points below the highest close of the trade.
The value on bar t is the stop computed at the close of bar t, in force during bar t+1, so the stop in force during bar t is the value on bar t-1, and on a reversal bar the value is the new position’s first stop (the reversal fills at the close of bar t). This is the convention of FlipStop, ATRTrailingStop and SuperTrendLine. ParabolicSAR instead follows TA-Lib: on a bar without a reversal its value is the stop in force during that bar, computed at the previous close, and on a reversal bar it is the new position’s first stop.
The start is fixed at bar n, long (a convention: the sources do not fix the first position, and TradingView also starts long), with the SIC at s[n] and the stop k times the ATR below it. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. If n < 1, n >= len(s), or k is negative or not finite, the result is len(s) zeros (k = -0 is valid). If h or l is not the same length as s, the result is an empty series, whatever n and k. If the close or the ATR of bar n or of a later bar is not finite, or the stop computed for that bar is not finite (an overflow), the result is NaN from that bar on: the recursion does not recover, even with n = 1, where ATRWilder does.
ATRTrailingStop anchors on the current close, not the SIC, and Vakkur’s “volatility stop” (Technical Analysis of Stocks & Commodities, October 1999), a stop ratcheted from the entry close and hit by the low (its short side by the high; his system is long-only), is a different construction. The method is recursive (path-dependent): a slice of the history that starts later seeds its ATR on a later bar, so its position can differ from that of the full series; while both hold the same position from the same reversal its stop differs by k times the ATR-seed difference, whose weight falls by the factor 1 - 1/n per bar, and a close that lands between the two stops reverses them on different bars.
Sources: J. Welles Wilder, New Concepts in Technical Trading Systems (1978), as restated by Peter Aan, “Volatility System”, Technical Analysis of Stocks & Commodities, July 1989; Abraham, “Trading The Trend”, Technical Analysis of Stocks & Commodities, September 1998, for the re-anchoring on a reversal.
WilderVolatilityStopDirection
func (s Series) WilderVolatilityStopDirection(h, l Series, n int, k float64) Series
WilderVolatilityStopDirection returns the position of WilderVolatilityStop held after the close of each bar: +1 long and -1 short. A reversal at the close of bar t shows as a change of sign from bar t-1 to bar t. The timing is that of the line and not that of ParabolicSAR, whose value on a bar without a reversal is the stop in force during that bar. A close equal to the stop in force holds the position, long or short. The receiver s is the close, h and l are the highs and lows, n is the ATR length and k its multiple. The start is fixed at bar n, long, so bar n is +1. The warm-up reads 0, not NaN: bars 0 to n-1 are 0 and the first valid index is n. There 0 means no position yet. Invalid parameters give len(s) zeros and mismatched lengths an empty series, and a non-finite close, ATR or stop on bar n or a later bar makes the result NaN from that bar on, with no recovery, as in WilderVolatilityStop. The position is path-dependent: a slice of the history that starts later can hold a different position, and even after both reverse the same way on the same bar a close that lands between their two stops reverses them on different bars until the ATR seeds have decayed. See WilderVolatilityStop for the construction, the settings and the sources (Wilder through Aan, 1989; Abraham, 1998).