PRANK -- Percentile Rank
Contents
- Format
- Understanding Percentile Rank Values
- Understanding Operators with Percentile Rank
- TOML Examples
- Tips
Overview
Percentile Rank measures where the current closing price ranks among the last N closing prices, expressed as a percentage from 0 to 100. If the current price is the lowest close in the lookback window, the Percentile Rank is 0. If it is the highest, the Percentile Rank is 100. A value of 25 means the current price is higher than 25% of the closes in the window.
The calculation is simple: count how many of the last N closes are less than or equal to the current close, divide by N, and multiply by 100. No assumptions about distribution shape, no parameters beyond the lookback period. This simplicity is its strength.
The key advantage of Percentile Rank over Z-Score: it is distribution-free. Z-Score assumes prices are approximately normally distributed to interpret its thresholds (e.g., "Z = -2 means bottom 2.5%"). Percentile Rank makes no such assumption. A Percentile Rank of 5 means "the current price is in the bottom 5% of the last N closes" regardless of whether prices are normally distributed, skewed, or have fat tails. For crypto markets, where returns are decidedly non-normal, this non-parametric property is valuable. Percentile Rank tells you exactly what it says -- no statistical assumptions required.
Format
prank_{period}
The period defines the lookback window -- how many recent closing prices are compared against the current close.
| Example | Period | Use Case |
|---|---|---|
prank_50 | 50 | Standard -- ranks price among the last 50 closes, good for short-to-medium-term context |
prank_100 | 100 | Slower -- ranks price within a broader window, better for swing trading and position sizing |
prank_200 | 200 | Long-term -- provides context against a large historical sample, fewer extremes |
Period range: 10 to 500.
Value range: 0 to 100 (always). 0 = current price is the lowest close in the window. 100 = current price is the highest close in the window.
Understanding Percentile Rank Values
Percentile Rank values are bounded between 0 and 100 and have an intuitive interpretation that does not depend on the asset or timeframe. A value of 10 means "cheaper than 90% of recent closes" whether you are looking at BTC on the hourly chart or ETH on the daily chart.
| Percentile Rank | Meaning | Trading Interpretation |
|---|---|---|
| 95 -- 100 | Price is at or near the highest close in the window | Extremely expensive relative to recent history. Potential top. Contrarian sell zone. |
| 75 -- 95 | Price is in the upper quartile | Elevated. Market has been rallying. Trend-following strategies may stay long; mean-reversion strategies may start scaling out. |
| 25 -- 75 | Price is in the middle range | Normal territory. No strong signal from percentile rank alone. |
| 5 -- 25 | Price is in the lower quartile | Depressed. Market has pulled back. Starting to get interesting for dip buyers. |
| 0 -- 5 | Price is at or near the lowest close in the window | Extremely cheap relative to recent history. Potential bottom. Contrarian buy zone. |
Percentile Rank is relative to the lookback window. A prank_50 of 5 means "bottom 5% of the last 50 closes" -- it says nothing about where price stands relative to the last 200 or 500 closes. Longer periods provide more historical context but react more slowly to recent trends.
Understanding Operators with Percentile Rank
Percentile Rank is a contrarian positioning indicator. It tells you where price sits in the context of recent history. Extreme lows suggest buying opportunities; extreme highs suggest selling opportunities.
> (Greater Than) -- State-Based
What it does: The trigger is true on every candle where Percentile Rank is above the threshold.
On the chart: Price is ranking high among recent closes. The closer to 100, the closer price is to its recent high watermark. This trigger stays active for as long as the Percentile Rank remains above the threshold.
[[actions.triggers]]
indicator = "prank_100"
operator = ">"
target = "95"
timeframe = "1h"
Typical use: "Price is near the top of its recent range -- consider taking profit or reducing exposure." When Percentile Rank exceeds 95, the current price is higher than 95% of the last 100 closes. This is a contrarian signal that the move may be overextended.
< (Less Than) -- State-Based
What it does: The trigger is true on every candle where Percentile Rank is below the threshold.
On the chart: Price is ranking low among recent closes. The closer to 0, the closer price is to its recent low point. This trigger stays active for as long as Percentile Rank remains below the threshold.
[[actions.triggers]]
indicator = "prank_100"
operator = "<"
target = "5"
timeframe = "1h"
Typical use: "Price is near the bottom of its recent range -- consider buying." When Percentile Rank drops below 5, the current price is lower than 95% of the last 100 closes. This is the core contrarian buy signal. Price is historically cheap within the lookback window.
cross_above -- Event-Based
What it does: Fires once, at the exact candle where Percentile Rank transitions from below the threshold to above it. The previous candle had Percentile Rank <= the target, and the current candle has Percentile Rank > the target.
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_above"
target = "50"
timeframe = "1h"
Typical use: Detect the moment price crosses above the median of its recent range. This can serve as an exit signal for mean-reversion trades: you bought in the bottom percentile, and now price has recovered to the middle of its range -- the reversion is complete.
cross_below -- Event-Based
What it does: Fires once, at the exact candle where Percentile Rank transitions from above the threshold to below it. The previous candle had Percentile Rank >= the target, and the current candle has Percentile Rank < the target.
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_below"
target = "10"
timeframe = "1h"
Typical use: Detect the exact moment price falls into the bottom percentile zone. Unlike < which stays active the entire time Percentile Rank is below 10, cross_below fires only at the transition -- giving you a single entry signal per dip.
= (Equal) -- Not Recommended for Percentile Rank
Why: While Percentile Rank produces integer-like values more often than Z-Score, exact matches are still unreliable for triggering. Use > or < instead.
- Use
<with a low threshold (e.g., 5 or 10) to buy when price is at the bottom of its recent range. This is the most common Percentile Rank operator. - Use
>with a high threshold (e.g., 90 or 95) to sell or take profit when price is at the top of its recent range. - Use
cross_belowto enter once per dip (fires at the moment of transition, not on every candle). - Use
cross_aboveto detect the moment price recovers to mid-range (exit signal).
TOML Examples
Buy the Bottom 5th Percentile
The classic contrarian trade: buy when the current price is lower than 95% of the last 100 closes. This is a purely statistical signal -- price is at the extreme low of its recent range. Add a trend filter to avoid buying into a sustained downtrend.
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
indicator = "prank_100"
operator = "<"
target = "5"
timeframe = "1h"
[[actions.triggers]]
indicator = "sma_50"
operator = ">"
target = "sma_200"
timeframe = "1d"
Exit at 60th Percentile
Close the position when price recovers to the 60th percentile of its recent range. This exits above the median, capturing the majority of the reversion move without waiting for price to reach the top of the range (which may never happen).
[[actions]]
type = "close_long"
amount = "100%"
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_above"
target = "60"
timeframe = "1h"
Percentile Rank with RSI Confluence
Combine Percentile Rank with RSI for double confirmation. Both indicators must agree that price is depressed: Percentile Rank says the price is in the bottom 10% of its recent range, and RSI says momentum is oversold. The confluence of two independent signals increases confidence in the entry.
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
indicator = "prank_100"
operator = "<"
target = "10"
timeframe = "1h"
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "30"
timeframe = "1h"
[[actions.triggers]]
indicator = "ema_21"
operator = ">"
target = "ema_55"
timeframe = "1d"
DCA at Different Percentile Levels
Dollar-cost average into a position at progressively lower percentile levels. The deeper the dip, the larger the allocation. This creates a tiered entry strategy that averages into a position more aggressively as price becomes cheaper relative to recent history.
# Light entry at 15th percentile
[[actions]]
type = "open_long"
amount = "50 USDC"
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_below"
target = "15"
timeframe = "4h"
# Medium entry at 8th percentile
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_below"
target = "8"
timeframe = "4h"
# Heavy entry at 3rd percentile
[[actions]]
type = "open_long"
amount = "200 USDC"
[[actions.triggers]]
indicator = "prank_100"
operator = "cross_below"
target = "3"
timeframe = "4h"
Tips
A Percentile Rank of 0 means price is the lowest close in the last N periods -- but it says nothing about whether price will continue falling. In a sustained downtrend, price can print a Percentile Rank of 0 on every new candle as it keeps making new lows. Always combine Percentile Rank with a trend filter to avoid buying into an accelerating decline.
Unlike Z-Score, which interprets its thresholds based on a normal distribution assumption, Percentile Rank is completely non-parametric. A Percentile Rank of 5 literally means "current price is lower than 95% of the last N closes." No bell curve required. For crypto markets with fat tails and skewed returns, this is an advantage -- the number means exactly what it says.
Z-Score and Percentile Rank often agree, but when they diverge, it is informative. If Z-Score says -3 (extreme) but Percentile Rank says 15 (not that extreme), it means price is far from the mean but not actually near the lowest close -- volatility has expanded the Z-Score. Combining both gives you a parametric and non-parametric view of the same question: "Is this price cheap?"
A prank_50 reaching 5 means price is the cheapest of the last ~2 days of hourly candles -- a short-term dip. A prank_200 reaching 5 means price is the cheapest of the last ~8 days of hourly candles -- a more significant pullback. Choose your period based on your holding horizon: shorter periods for quick mean-reversion trades, longer periods for swing trades that may take days to play out.