Percentile
systemic:core-percStatisticsfunction1 crInputs
| Name | Type | Description |
|---|---|---|
| Percentile | integer | The quantile level (1–100) to compute on each filtered subset. |
| Data | floatarray | The numerical series over which the conditional quantile is computed. |
Outputs
| Name | Type | Description |
|---|---|---|
| Percentile | floatarray | The computed conditional quantile for each input value. |
The Percentile module computes a conditional quantile for each data point in a series. For every value, it filters the entire dataset to include only values less than or equal to the current value, then calculates the specified percentile of that filtered subset.
Where represents the -th quantile (with specified by the Percentile parameter from 1 to 100).
How It Works
flowchart TD
subgraph Input["Input Data"]
D["Data: [10, 25, 15, 30, 20]"]
P["Percentile: 50"]
end
subgraph Process["For Each Value"]
V["Current value = 25"]
F["Filter: values ≤ 25<br/>[10, 25, 15, 20]"]
Q["Compute 50th percentile<br/>of filtered set"]
end
subgraph Output["Result"]
R["Output = 17.5"]
end
D --> V
P --> Q
V --> F --> Q --> R
Step-by-step for a single data point:
- Take the current value (e.g., 25)
- Filter the entire dataset to values ≤ 25: [10, 25, 15, 20]
- Compute the specified percentile (e.g., 50th) of that filtered subset
- Result: 17.5 (the median of [10, 15, 20, 25])
This process repeats for every data point in the series.
Understanding the Percentile Parameter
The Percentile parameter (1–100) specifies which quantile to compute on the filtered subset:
| Percentile | Meaning |
|---|---|
| 25 | First quartile of values ≤ current |
| 50 | Median of values ≤ current |
| 75 | Third quartile of values ≤ current |
| 100 | Maximum of values ≤ current (equals current value) |
⚠️ Important: This is not a percentile ranking (how the current value ranks relative to history). Instead, it computes a quantile of a dynamically filtered dataset.
Practical Applications
1. Dynamic Support Level Detection
When the percentile parameter is set low (e.g., 25), the output approximates dynamic support levels—the lower quartile of all values that don't exceed the current price:
flowchart LR
subgraph Concept["Support Level Logic"]
Price["Current Price"]
Filter["Values ≤ Price"]
Q25["25th Percentile"]
Support["Dynamic Support"]
end
Price --> Filter --> Q25 --> Support
2. Distribution Analysis
By comparing outputs at different percentile settings:
| Setting | Interpretation |
|---|---|
| PERC(25) vs PERC(75) | Spread of lower values indicates distribution skew |
| PERC(50) | Central tendency of filtered distribution |
| PERC(100) | Always equals the input (identity transformation) |
3. Conditional Median Tracking
Using PERC(50) gives you the median of all values up to and including each point—useful for understanding how the "typical" value evolves relative to each observation:
flowchart TD
subgraph Strategy["Conditional Median Strategy"]
Data["Price Series"]
PERC50["PERC(50)"]
Compare{"Price > PERC(50)?"}
Above["Above conditional median<br/>Relative strength"]
Below["At or below<br/>conditional median"]
end
Data --> PERC50 --> Compare
Compare -->|Yes| Above
Compare -->|No| Below
Example Walkthrough
Consider data series: [100, 80, 120, 90, 110] with Percentile = 50
| Index | Current Value | Filtered Set (≤ current) | 50th Percentile | Output |
|---|---|---|---|---|
| 0 | 100 | [100, 80, 90] | 90 | 90.0 |
| 1 | 80 | [80] | 80 | 80.0 |
| 2 | 120 | [100, 80, 120, 90, 110] | 100 | 100.0 |
| 3 | 90 | [80, 90] | 85 | 85.0 |
| 4 | 110 | [100, 80, 90, 110] | 95 | 95.0 |
Note: The filter considers the entire dataset, not just preceding values.
Key Characteristics
Whole-series analysis: The filter examines all data points, not a rolling window. Each output depends on the entire input series.
Non-monotonic relationship: Higher input values don't necessarily produce higher outputs—it depends on the distribution of the filtered subset.
Boundary behavior:
- At Percentile = 100, output always equals input (maximum of set ≤ value is the value itself)
- At Percentile = 1, output approaches the minimum value in the dataset for most inputs
Advantages
- Context-aware — Output reflects distribution characteristics relative to each observation
- Flexible — Different percentile settings reveal different aspects of the data
- Non-parametric — No distributional assumptions required
Limitations
- Non-intuitive — The conditional filtering logic differs from standard percentile ranking
- Non-causal by design — see Non-Causality below
- Sensitive to outliers — Extreme values affect filtered subset compositions
Non-Causality
This module is not a running/rolling percentile. Every output is computed against the full analyzed series, including bars that occur after it — a historical value's output can change if later data changes the filtered subset. Historical outputs are ranked against later data and are not tradeable signals; only the newest bar's output (live, or the last bar of a backfill) is causal, because at that point there is no later data left to influence it. Do not backtest a strategy that reacts to a historical PERC value expecting it to reproduce what was knowable at that time — build a causal running-percentile module for that use case instead.
Missing Data
A missing (null) value in the data series is excluded from every reference sample it would otherwise fall into — it never fabricates a zero or a carried-forward value. A missing pivot itself produces a null output at that position; every other position's calculation is unaffected. Live execution returns exactly one datapoint (the newest bar), null when that bar's value is missing.