Swing Points
All functions · nseries package
SwingPointIndices
func (s Series) SwingPointIndices(opn, high, low, cls Series, opts ...any) []int
SwingPointIndices returns swing point positions as sequential signed indices. Positive values are swing high bar indices, negative values are negated swing low bar indices.
A swing high and a swing low can be reported on the same bar. A bar that reverses the trend (typically an outside bar, or a bar whose high or low equals the trend’s extreme) can itself be the trend’s extreme, reported as the swing that ends the trend; it is also where the new trend starts, so if the new trend reverses before making a new extreme, the same bar is reported again as the opposite swing. Such a pair appears as adjacent entries b, -b (or -b, b), the trend’s extreme first (at level 1; at levels 2 and above a promoted pair is listed high first).
At level 1, the default output has strictly alternating signs. Absolute bar indices never decrease and are equal only within an adjacent opposite-sign pair; no signed index repeats.
Optional arguments control behaviour (see SwingPoints for details): - int: hierarchical level (default 1) - bool: classifyOB mode (default false) - SwingOption: SwingAppendOnly (default off) skips the snap pass and makes level 1 append-only (see below); any other SwingOption value is ignored
Revision: by default a snap pass moves a confirmed swing forward to the bar that truly holds the extreme, stopping before the next swing’s bar (or at the end of the data for the latest swing). The main loop only appends, and the snap of an earlier swing reads only bars before the next swing, all present when that swing was confirmed. So when bars are appended, only the most recent swing can change at level 1. It can move forward as later bars extend it, and back again when the next swing is confirmed; a backtest that reads historical swing positions should allow for that one moving entry.
With SwingAppendOnly the snap pass is skipped and level 1 is append-only: for any inputs of length n and any m <= n, the result for the first m bars (opn[:m], high[:m], low[:m], cls[:m]) is a prefix of the result for all n bars, for either classifyOB value. Level-1 bar indices are then non-decreasing (equal only within a same-bar pair) and highs and lows strictly alternate. At levels 2 and above promotion needs the next same-type swing and flattening may replace the latest entry, so the result can still change when bars are appended.
Level construction stops once a level produces no swings, since no higher level can be derived from an empty set; there is no other cap on level.
SwingPoints
func (s Series) SwingPoints(opn, high, low, cls Series, opts ...any) []int
SwingPoints returns a slice of integers representing swing highs and lows in OHLC data, where zero indicates no swing, a positive value indicates a swing high, and a negative value indicates a swing low. The magnitude of the value indicates how many bars back from the end of the series the swing occurred.
Caveat: a swing confirmed at the very last bar has a lookback of zero, which this encoding cannot distinguish from “no swing”; such a swing is silently dropped. Use SwingPointIndices if swings at the final bar matter to the caller.
The encoding also holds only one value per bar, while a swing high and a swing low can be reported on the same bar (see SwingPointIndices). Where two entries of the SwingPointIndices result share a bar, the later entry in that list wins.
Inside bars (bars whose range falls within the prior non-inside bar) are always skipped. Outside bar direction is inferred from the open/close relationship: close > open is bullish, close < open is bearish, and close == open continues the prevailing trend.
Optional arguments control behaviour: - int: hierarchical level (default 1). Level 1 = short-term swings, Level 2 = medium-term (swings of swings), Level 3+ = progressively longer-term. - bool: classifyOB mode (default false). When true, uses outside bar direction (from open vs close) to determine which swing extreme the bar can update. A bearish outside bar in an uptrend will NOT capture a new swing high. When false, the swing point is always the bar with the most extreme price regardless of outside bar direction. - SwingOption: SwingAppendOnly (default off) skips the snap pass described below. Level-1 swings are then append-only: the SwingPointIndices result for the first m bars is a prefix of the result for all the bars, for any m, so in that list a swing once reported keeps its bar. This encoding holds one value per bar, so when a later bar completes a same-bar pair (see SwingPointIndices) the slot changes sign and the earlier swing drops out of this slice. Any other SwingOption value is ignored.
Revision: by default, after the single pass that confirms swings, a snap pass moves a confirmed swing forward to each following bar that extends it (a higher high for a swing high, a lower low for a swing low), stopping at the first bar that does not, inside bars aside, and before the next swing’s bar, so that the swing sits on the bar that truly holds the extreme. The main loop only appends, and the snap of an earlier swing reads only bars before the next swing, all present when that swing was confirmed. So when bars are appended, only the most recent swing can change at level 1. It can move forward as later bars extend it, and back again when the next swing is confirmed; a backtest that reads historical swing positions should allow for that one moving entry. SwingAppendOnly removes the snap and guarantees append-only level 1 in SwingPointIndices.
In the default level-1 SwingPointIndices list, signs strictly alternate, absolute bar indices never decrease and are equal only within an adjacent opposite-sign pair, and no signed index repeats.
Levels 2 and above can still change when bars are appended, with or without SwingAppendOnly: promotion needs the next swing of the same type, and flattening may replace the latest entry.
Level construction stops once a level produces no swings, since no higher level can be derived from an empty set; there is no other cap on level.