Window aggregation
18 functions
HHV(X, N)Highest value of X over the last N bars. N = 0 means since the first bar.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars, including the current one. 0 scans the whole history.
// Donchian channel
DONCHIAN_UP: HHV(HIGH, 20), COLORYELLOW;
DONCHIAN_DN: LLV(LOW, 20), COLORYELLOW;
MID: (DONCHIAN_UP + DONCHIAN_DN) / 2, COLORGRAY, DOTLINE;
// breakout of the previous 20-bar high — REF avoids comparing
// the high against a window that already contains it
BREAK := HIGH > REF(HHV(HIGH, 20), 1);
DRAWICON(BREAK, LOW, 85);LLV(X, N)Lowest value of X over the last N bars.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars, including the current one.
// the raw stochastic — where price sits inside its 9-bar range
LOW9 := LLV(LOW, 9);
HIGH9 := HHV(HIGH, 9);
RSV: (CLOSE - LOW9) / (HIGH9 - LOW9) * 100;
// trailing stop for a long position
STOP: LLV(LOW, 10), COLORRED, STEPLINE;HV(X, N)Highest value excluding the current bar.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars, ending on the previous bar.
// HV is the breakout comparison you usually want:
// the current high is not part of the window it is measured against
BREAK: HIGH > HV(HIGH, 20);
// equivalent to REF(HHV(HIGH, 20), 1), just shorter
SAME: HIGH > REF(HHV(HIGH, 20), 1);LV(X, N)Lowest value excluding the current bar.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars, ending on the previous bar.
// breakdown through the prior 20-bar low
DOWN := LOW < LV(LOW, 20);
DRAWICON(DOWN, HIGH, 97);HHVBARS(X, N)Number of bars since the highest value in the last N bars.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars.
// 0 means the high is on this very bar
AGE: HHVBARS(HIGH, 60);
// fresh 60-bar high
DRAWICON(AGE = 0, LOW, 85);
// how long the market has gone without a new high
STALE: AGE > 20;LLVBARS(X, N)Number of bars since the lowest value in the last N bars.
- X(series)
- The series to scan.
- N(integer)
- Window length in bars.
// bars since the 60-bar low — a rough measure of how long
// the recovery has been running
SINCELOW: LLVBARS(LOW, 60);
DRAWTEXT(ISLASTBAR, LOW, VARCAT('bars from low: ', VAR2STR(SINCELOW, 0)));SUM(X, N)Rolling sum of X over N bars. N = 0 sums from the first bar.
- X(series)
- The series to add up.
- N(integer)
- Window length in bars. 0 accumulates from the very first bar.
// 20-bar turnover
TURNOVER: SUM(AMOUNT, 20);
// OBV — a running total that never resets, hence N = 0
DELTA := IF(CLOSE > REF(CLOSE, 1), VOL, IF(CLOSE < REF(CLOSE, 1), -VOL, 0));
OBV: SUM(DELTA, 0), COLORYELLOW;SUMBARS(X, A)How many bars back you must go for the sum of X to first reach A.
- X(series)
- The series to accumulate backwards.
- A(series)
- The target the running sum has to reach.
// how many bars it takes to accumulate today's volume —
// a small number means today traded unusually heavily
BARSNEEDED: SUMBARS(VOL, VOL);
// average price over the bars that make up 10x today's volume
N := SUMBARS(VOL, VOL * 10);
VWAP10: SUM(CLOSE * VOL, N) / SUM(VOL, N), COLORYELLOW;COUNT(COND, N)How many of the last N bars satisfy COND.
- COND(condition)
- The condition to count.
- N(integer)
- Window length in bars. 0 counts the whole history.
// PSY — share of up bars in the last 12
PSY: COUNT(CLOSE > REF(CLOSE, 1), 12) / 12 * 100;
PSYMA: MA(PSY, 6), COLORYELLOW;
// three or more heavy-volume bars in the last 10
CLUSTER: COUNT(VOL > MA(VOL, 20) * 2, 10) >= 3;MULAR(X, N)Rolling product of X over N bars.
- X(series)
- The series to multiply together.
- N(integer)
- Window length in bars. 0 multiplies from the first bar.
// compounded return over 20 bars — multiply the growth
// factors rather than adding the percentages
GROWTH := CLOSE / REF(CLOSE, 1);
COMPOUND: (MULAR(GROWTH, 20) - 1) * 100, COLORSTICK;HOD(X, N)Rank of the current X among the highest values of the last N bars.
- X(series)
- The series to rank within.
- N(integer)
- Window length in bars.
// 1 means today is the highest of the last 60 bars,
// 2 the second highest, and so on
RANK: HOD(HIGH, 60);
DRAWICON(RANK <= 3, LOW, 85); // among the three highestLOD(X, N)Rank of the current X among the lowest values of the last N bars.
- X(series)
- The series to rank within.
- N(integer)
- Window length in bars.
// today is among the three lowest closes of the last 60
OVERSOLD: LOD(CLOSE, 60) <= 3;
STICKLINE(OVERSOLD, HIGH, LOW, 8, 1), COLORLIGREEN;TOPRANGE(X)How many bars back you can go before X was last higher than it is now.
- X(series)
- The series to measure.
// the window is not fixed — it answers "a high of how many bars?"
SPAN: TOPRANGE(HIGH);
// a 250-bar high without having to guess the number first
DRAWICON(SPAN >= 250, LOW, 85);LOWRANGE(X)How many bars back you can go before X was last lower than it is now.
- X(series)
- The series to measure.
// how deep this low reaches into the past
SPAN: LOWRANGE(LOW);
DRAWTEXT(SPAN >= 120, LOW, 'multi-month low'), COLORRED, VALIGN2;FINDHIGH(X, N, M, T)The T-th highest value of X inside the M bars that end N bars ago.
- X(series)
- The series to scan.
- N(integer)
- Where the window ends, counted back from the current bar.
- M(integer)
- Length of that window, in bars.
- T(integer)
- Which ranked value to take — 1 is the highest, 2 the second highest.
// second-highest high of the 60 bars that ended 10 bars ago —
// a resistance level that ignores the most recent action
RES: FINDHIGH(HIGH, 10, 60, 2), COLORGRAY, DOTLINE;FINDHIGHBARS(X, N, M, T)Bars from that T-th highest value to the current bar.
- X(series)
- The series to scan.
- N(integer)
- Where the window ends, counted back from the current bar.
- M(integer)
- Length of that window, in bars.
- T(integer)
- Which ranked value to locate.
// where that resistance came from, and how long ago
AGE: FINDHIGHBARS(HIGH, 10, 60, 2);
DRAWTEXT(ISLASTBAR, HIGH, VARCAT('res set ', VAR2STR(AGE, 0), ' bars ago'));FINDLOW(X, N, M, T)The T-th lowest value of X inside the M bars that end N bars ago.
- X(series)
- The series to scan.
- N(integer)
- Where the window ends, counted back from the current bar.
- M(integer)
- Length of that window, in bars.
- T(integer)
- Which ranked value to take — 1 is the lowest.
// support from the 60 bars that ended 10 bars ago
SUP: FINDLOW(LOW, 10, 60, 1), COLORGRAY, DOTLINE;
// price coming back down to it
DRAWICON(LOW <= SUP AND CLOSE > SUP, LOW, 85);FINDLOWBARS(X, N, M, T)Bars from that T-th lowest value to the current bar.
- X(series)
- The series to scan.
- N(integer)
- Where the window ends, counted back from the current bar.
- M(integer)
- Length of that window, in bars.
- T(integer)
- Which ranked value to locate.
// distance back to the support low, used to fade
// levels that are getting old
AGE: FINDLOWBARS(LOW, 10, 60, 1);
FRESH: AGE < 40;