Multi-year highs, lows and returns
The highest high, lowest low, distance from either, and percentage return over any window of sessions. The 52-week versions are the stored special case, and any other span from a week to five years is computed at scan time from the same bars.
Every fixed-window price field on this site is the stored period of one of these. `high_52w` is `highest_high(1y)`, `pct_from_52w_low` is `pct_from_low(1y)`, `return_1m` is `return(1mo)`, and the bare names keep working. Writing the function with a different period, `highest_high(3y)` or `lowest_low(6mo)` or `return(2y)`, computes the same thing over that many sessions at scan time. The result is null until a stock has that much history, so a two-year-old listing never reports a five-year high it does not have.
A period is a bar count or a duration, converted at 252 sessions a year. `52w`, `12mo` and `1y` are all 252 bars. That makes `max(high, 52w)`, `highest_high(1y)` and `high_52w` one number. Five years, 1260 bars, is the ceiling for any window. Only a scan that asks for a long window reads the extra history, so `close is highest in 3y` costs about three times a 52-week scan and nothing else does.
The longer windows change the meaning of the same shape. A 52-week high is a momentum condition. A three-year high is a stock emerging from a whole cycle, and `close is highest in 5y and rel_volume > 1.5` is the version that catches a long base resolving. On the other side, `close within 5% of lowest_low(5y)` lists stocks the market has given up on for half a decade, which is a starting point for a reversal hunt. `pct_from_low(3y) > 50 and close > sma(200)` is a recovery already under way. `return(2y) > 100` is a two-year doubler, and `return(3y) < 0` in an uptrend is a laggard turning.
The caveats are the same as for the 52-week forms, stretched. A multi-year high on thin volume is a drift, and the volume conditions matter more the longer the window. Highs and lows use intraday `high` and `low`, while `close is highest in` compares closes, so the two can disagree on the day of a wick. The windows count sessions rather than calendar days, so a long trading halt shortens the calendar span a window covers.
In Sift
Written as highest_high(n) / lowest_low(n) — a price; pct_from_high(n) / pct_from_low(n) — a percentage, negative below the high; return(n) — percentage change over n bars; n is bars or a duration, up to 5y. A working scan — the highest close in three years, on real volume:
where close is highest in 3y and rel_volume > 1.51
of the 500 most-traded NSE stocks match today, as of 6 Oct 2026
Scans that use it
Prebuilt scans in the library whose query reads this value — each with a hit-rate replay over the last 250 sessions.
Near a five-year low
Within 5% of the lowest low in five years with RSI under 35. The most abandoned names on the exchange, for a reversal hunt.
Recovering from a three-year low
Up more than 50% off the three-year low, back above the 200-day average, with a three-month return over 10%.
Two-year doublers
Up more than 100% over two years and still above the 50-day average.
Three-year laggards turning up
Below where they were three years ago, but back above the 200-day average. The names the bull market has not reached.
Yield after a sell-off
More than 20% below the 52-week high, yielding over 3%, and paid in each of the last three years.
Common questions
How is highest_high(252) different from high_52w?
It is not. 252 is the stored period, so `highest_high(252)`, `highest_high(1y)` and `high_52w` all read the same precomputed column. Any other period is computed at scan time over the same bars, and a parity test holds the two paths to agree exactly.
How far back can a window reach?
Five years, or 1260 sessions. `lowest_low(5y)` and `return(5y)` compile; `6y` is refused with a message that says so. Dividend spans are counted separately in years, up to ten, because they read a dated record rather than the bar history.
Why does 52w now equal 1y?
Durations convert at 252 sessions a year for every unit, so a week is 4.85 sessions before rounding and fifty-two of them are 252. The older conversion made `52w` 260 bars, which meant `max(high, 52w)` and the stored `high_52w` column quietly disagreed by a week and a half.