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.valuepr > 95Example
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.