Skip to content
Open RaamTrade

PercentRank — Percent Rank

What fraction of the last N values the current one exceeds, 0–100. Distribution-free: it makes no assumption about normality, which is what makes it a better “unusually high” test than a z-score on anything with fat tails.

Signature

PercentRank(period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Comparison window. Default 50, bounds 2–400.
on= symbol, OHLCV field, or indicator No Source. Defaults to the trade symbol’s close.

Formula

$$ \text{PercentRank} = 100,\frac{#{x_i < x_t,\ i < t}}{n - 1} $$

Warmup

period bars to a full window; before that it ranks against the bars available.

Reading the value

pr.value
pr > 95

Example

class RankBreakout(Strategy):
"""Enter when the close ranks in the top 5% of its recent history."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
pr = PercentRank(50, on=self.trade)
if pr.value > 95 and self.trade.is_flat:
self.buy(self.trade, reason=f"Rank {pr.value:.0f}")
if pr.value < 50 and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="Rank faded")

Variants

PercentRank(100, on=atr) # is today's volatility unusual?

Notes

  • Counts strictly-less-than, so a repeated value does not inflate the rank.
  • Proven by an assert-via-trade run on SPY daily (matched a strategy-side count exactly on every bar; zero alarm trades).
  • Useful on any single-value indicator, not just price — that is where it earns its place.