Random Walk Index

All functions · nseries package

RandomWalkIndexHigh

func (s Series) RandomWalkIndexHigh(h, l, c Series, minN, maxN int) Series

RandomWalkIndexHigh returns the Random Walk Index of the highs, how far each bar’s high stands above the low of a past bar in units of the move a random walk would make over that many bars, at its largest over the lags minN to maxN.

The receiver is not used. The bars are the highs h, lows l and closes c, one bundle of bars rather than a base and a comparison series, so they are not right-aligned: if the three lengths differ, the result is an empty Series. For lag k at bar t the numerator is h[t] - l[t-k] and the denominator is AR_k times sqrt(k), with AR_k the arithmetic mean of the true ranges of lags 1 to k, the symmetric true range of TrueRange, that is max(c[j-1], h[j]) - min(c[j-1], l[j]), over bars t-k to t-1. The sum S_k of those true ranges is formed in increasing lag order and incrementally across the lags, and the lag’s value is num / ((S_k / k) * sqrt(k)), with the product rounded on its own; the result is the largest of the values of lags minN to maxN. It keeps its sign, so a high below every one of the band’s lows gives a negative value rather than 0, and a zero result is +0. A lag whose computed average range S_k / k is 0 (flat bars with no gap, or a sum so small that the division underflows, so that a longer lag can be left out while a shorter one is kept) is left out, and a bar on which every lag is left out is 0.

The source is E. Michael Poulos, “Of Trends And Random Walks”, in Stocks & Commodities V9:2 (February 1991), with the symmetric true range of his September 1992 article (V10:9). That article is “Are There Persistent Cycles?”, in the same journal. He reads a value above 1 as a move beyond a random walk: on the long band (8, 64) as a trend, an uptrend from the highs and a downtrend from the lows, and on the short band (2, 7) as an overbought or oversold reading, a short-term high or low. The threshold is uncalibrated: on driftless random-walk bars a large share of the valid bars exceed 1 on either side, for both bands.

This is the lag pairing of Poulos’s formula text and of Investor/RT: lag k pairs the low k bars ago with sqrt(k) and the mean range of the k bars before today. Not provided are the MetaStock-style documentation and the TradeStation forum code, whose averages include today, Hartle’s spreadsheet, which pairs the extreme k-1 bars ago with sqrt(k) and uses a one-sided true range, Wilder smoothing of the range, and the anchored drunkard’s walk.

The warm-up reads 0, not NaN: bars 0 to maxN are 0 and the first valid index is maxN+1. The minimum length is maxN+2, and minN < 1, maxN < minN or maxN > len(h)-2 gives len(h) zeros, so maxN = len(h)-2 gives one valid bar, the last.

At a valid bar t the method reads h of bars t-maxN to t, l of bars t-maxN to t-1 and c of bars t-maxN-1 to t-2, whatever minN is, and the bar is NaN when any value read is NaN or an infinity, checked before the zero-range rule. On finite data whose sums overflow, a lag’s value can be 0 (an infinite average range) or NaN (an infinite numerator over one), so a bar can read 0 or NaN although no value it reads is bad. Today’s and yesterday’s closes are not read, so the value can be taken intrabar. Each value depends only on the bars it reads, so the method is window-local and start-invariant bit for bit: dropping bars from the front leaves every later valid bar unchanged. The cost is O(maxN) per valid bar.

The mirror RandomWalkIndexHigh(-l, -h, -c, minN, maxN), with -x the exact negation x.Mul(-1), equals RandomWalkIndexLow(h, l, c, minN, maxN) bit for bit on every input. Where no lag of the band is left out, the band’s value is the largest of the single-lag values of lags minN to maxN, and widening the band does not lower the value at a bar valid for both bands as long as the narrower band keeps a lag there. A single lag k equals h.Sub(l.Shift(k)).Div(c.ATR(h, l, c, k).Shift(1).Mul(math.Sqrt(float64(k)))) from bar k+1 wherever the lag’s average range is not 0, bit for bit on dyadic data, where every sum is exact, and to rounding otherwise. Scaling h, l and c by a power of two leaves the result unchanged bit for bit while nothing is subnormal or overflows. RandomWalkIndexLow is the mirror for the lows.

RandomWalkIndexLow

func (s Series) RandomWalkIndexLow(h, l, c Series, minN, maxN int) Series

RandomWalkIndexLow returns the Random Walk Index of the lows, how far each bar’s low stands below the high of a past bar in units of the move a random walk would make over that many bars, at its largest over the lags minN to maxN.

The receiver is not used. The bars are the highs h, lows l and closes c, one bundle of bars rather than a base and a comparison series, so they are not right-aligned: if the three lengths differ, the result is an empty Series. For lag k at bar t the numerator is h[t-k] - l[t] and the denominator is AR_k times sqrt(k), with AR_k the arithmetic mean of the true ranges of lags 1 to k, the symmetric true range of TrueRange, that is max(c[j-1], h[j]) - min(c[j-1], l[j]), over bars t-k to t-1. The sum S_k of those true ranges is formed in increasing lag order and incrementally across the lags, and the lag’s value is num / ((S_k / k) * sqrt(k)), with the product rounded on its own; the result is the largest of the values of lags minN to maxN. It keeps its sign, so a low above every one of the band’s highs gives a negative value rather than 0, and a zero result is +0. A lag whose computed average range S_k / k is 0 (flat bars with no gap, or a sum so small that the division underflows, so that a longer lag can be left out while a shorter one is kept) is left out, and a bar on which every lag is left out is 0.

The source is E. Michael Poulos, “Of Trends And Random Walks”, in Stocks & Commodities V9:2 (February 1991), with the symmetric true range of his September 1992 article (V10:9). That article is “Are There Persistent Cycles?”, in the same journal. He reads a value above 1 as a move beyond a random walk: on the long band (8, 64) as a trend, an uptrend from the highs and a downtrend from the lows, and on the short band (2, 7) as an overbought or oversold reading, a short-term high or low. The threshold is uncalibrated: on driftless random-walk bars a large share of the valid bars exceed 1 on either side, for both bands.

This is the lag pairing of Poulos’s formula text and of Investor/RT: lag k pairs the high k bars ago with sqrt(k) and the mean range of the k bars before today. Not provided are the MetaStock-style documentation and the TradeStation forum code, whose averages include today, Hartle’s spreadsheet, which pairs the extreme k-1 bars ago with sqrt(k) and uses a one-sided true range, Wilder smoothing of the range, and the anchored drunkard’s walk. On Hartle’s ten bars, with the blank close of the last bar set to NaN since it is not read, the band (2, 8) gives 1.4504754485877898 at bar 9, the value of lag 2, where his sheet prints 1.25, the largest of its lookbacks.

The warm-up reads 0, not NaN: bars 0 to maxN are 0 and the first valid index is maxN+1. The minimum length is maxN+2, and minN < 1, maxN < minN or maxN > len(h)-2 gives len(h) zeros, so maxN = len(h)-2 gives one valid bar, the last.

At a valid bar t the method reads h of bars t-maxN to t-1, l of bars t-maxN to t and c of bars t-maxN-1 to t-2, whatever minN is, and the bar is NaN when any value read is NaN or an infinity, checked before the zero-range rule. On finite data whose sums overflow, a lag’s value can be 0 (an infinite average range) or NaN (an infinite numerator over one), so a bar can read 0 or NaN although no value it reads is bad. Today’s and yesterday’s closes are not read, so the value can be taken intrabar. Each value depends only on the bars it reads, so the method is window-local and start-invariant bit for bit: dropping bars from the front leaves every later valid bar unchanged. The cost is O(maxN) per valid bar.

The mirror RandomWalkIndexLow(-l, -h, -c, minN, maxN), with -x the exact negation x.Mul(-1), equals RandomWalkIndexHigh(h, l, c, minN, maxN) bit for bit on every input, and RandomWalkIndexHigh(-l, -h, -c, minN, maxN) equals this result. Where no lag of the band is left out, the band’s value is the largest of the single-lag values of lags minN to maxN, and widening the band does not lower the value at a bar valid for both bands as long as the narrower band keeps a lag there. A single lag k equals h.Shift(k).Sub(l).Div(c.ATR(h, l, c, k).Shift(1).Mul(math.Sqrt(float64(k)))) from bar k+1 wherever the lag’s average range is not 0, bit for bit on dyadic data, where every sum is exact, and to rounding otherwise. Scaling h, l and c by a power of two leaves the result unchanged bit for bit while nothing is subnormal or overflows. RandomWalkIndexHigh is the mirror for the highs.