2026-02-27 07:48:12 -08:00
# MPE: Mean Percentage Error
2026-03-11 20:21:52 -07:00
> *MAPE tells you how wrong you are; MPE tells you which direction you're wrong in.*
2026-02-27 07:48:12 -08:00
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Error Metric |
fix(docs): correct .md documentation across errors, dynamics, filters, forecasts, momentum, numerics, oscillators, reversals, statistics, trends, volatility, volume
2026-03-10 18:38:23 -07:00
| **Inputs** | Actual, Predicted (dual series) |
2026-02-27 07:48:12 -08:00
| **Parameters** | `period` |
| **Outputs** | Single series (MPE) |
fix(docs): correct .md documentation across errors, dynamics, filters, forecasts, momentum, numerics, oscillators, reversals, statistics, trends, volatility, volume
2026-03-10 18:38:23 -07:00
| **Output range** | Any (positive or negative) |
| **Warmup** | `period` bars |
2026-03-11 15:35:33 -07:00
| **PineScript** | [mpe.pine ](mpe.pine ) |
2026-02-27 07:48:12 -08:00
- Mean Percentage Error measures the average percentage difference between actual and predicted values while preserving the sign.
2026-03-13 13:46:52 -07:00
- **Similar:** [ME ](../me/Me.md ), [MAPE ](../mape/Mape.md ) | **Trading note:** Mean Percentage Error; reveals directional bias as percentage. Positive/negative cancellation is a feature.
2026-02-27 07:48:12 -08:00
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
2026-01-18 19:02:03 -08:00
Mean Percentage Error measures the average percentage difference between actual and predicted values while preserving the sign. Unlike MAPE, which takes absolute values, MPE reveals systematic bias in predictions—whether a model consistently over-predicts or under-predicts.
## Architecture & Physics
MPE computes the signed percentage error for each data point and averages over a rolling window:
$$\text{MPE} = \frac{100}{n} \sum_{i=1}^{n} \frac{(\text{actual}_i - \text{predicted}_i)}{\text{actual}_i}$$
The sign preservation makes MPE invaluable for bias detection:
* **Positive MPE**: Model systematically under-predicts (actual > predicted)
* **Negative MPE**: Model systematically over-predicts (actual < predicted)
* **MPE near zero**: No systematic bias (though individual errors may be large)
### Bias Detection
Consider a weather forecasting model:
* If MPE = +15%, the model consistently predicts temperatures 15% lower than actual
* If MPE = -10%, the model consistently predicts temperatures 10% higher than actual
* If MPE ≈ 0% but MAPE = 20%, errors cancel out (no bias) but magnitude is still significant
## Mathematical Foundation
### 1. Point-wise Percentage Error
For each observation:
$$e_i = 100 \times \frac{\text{actual}_i - \text{predicted}_i}{\text{actual}_i}$$
### 2. Rolling Average
Over a period $n$:
$$\text{MPE}_t = \frac{1}{n} \sum_{i=t-n+1}^{t} e_i$$
### 3. Relationship to MAPE
$$\text{MAPE} = \frac{100}{n} \sum |e_i / 100|$$
$$\text{MPE} = \frac{100}{n} \sum (e_i / 100)$$
When errors are consistently in one direction: $|\text{MPE}| \approx \text{MAPE}$
When errors alternate: $|\text{MPE}| < \text{MAPE}$
## Performance Profile
2026-02-26 22:02:52 -08:00
### Operation Count (Streaming Mode)
O(1) per bar. Single-pass scalar transformation of (actual, forecast) pair; no lookback window required.
| Operation | Count | Cost (cycles) | Subtotal |
| :--- | :---: | :---: | :---: |
| Error computation (subtract, abs/square/log) | 1-3 | ~3-8 cy | ~5-15 cy |
| Running accumulator update (EMA or sum) | 1 | ~4 cy | ~4 cy |
| **Total** | **2-4** | — | ** ~9-19 cycles** |
Streaming update requires only the current actual/forecast pair and running state. ~10-15 cycles/bar typical.
### Batch Mode (SIMD Analysis)
| Operation | Vectorizable? | Notes |
| :--- | :---: | :--- |
| Element-wise error computation | Yes | Independent per bar; fully vectorizable with `Vector<double>` |
| Reduction (sum/mean) | Yes | Parallel reduction; AVX2 gives 4x speedup |
| Log/exp components | Partial | Transcendental ops; polynomial approx for SIMD |
Batch SIMD: 4x-8x speedup for large windows. ~3-5 cy/bar amortized in vectorized batch mode.
2026-01-18 19:02:03 -08:00
| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | 15 ns/bar | O(1) via running sum |
| **Allocations** | 0 | Zero-allocation hot path |
| **Complexity** | O(1) | Constant per update |
| **Bias Detection** | 10/10 | Primary strength |
| **Magnitude Info** | 3/10 | Errors can cancel |
| **Scale Independence** | 9/10 | Percentage-based |
| **Outlier Sensitivity** | 5/10 | Linear in error magnitude |
## Usage
```csharp
// Streaming mode - bias detection in real-time
var mpe = new Mpe ( 20 );
// Actual values consistently higher than predictions
mpe . Update ( actual : 105.0 , predicted : 100.0 ); // +5%
mpe . Update ( actual : 110.0 , predicted : 100.0 ); // +10%
// MPE will be positive, indicating under-prediction bias
double currentBias = mpe . Last . Value ;
if ( currentBias > 5.0 )
Console . WriteLine ( "Model is under-predicting by {0:F1}%" , currentBias );
else if ( currentBias < - 5.0 )
Console . WriteLine ( "Model is over-predicting by {0:F1}%" , Math . Abs ( currentBias ));
else
Console . WriteLine ( "Model shows no significant bias" );
// Batch mode - analyze historical predictions
var actual = new TSeries { 100 , 105 , 98 , 102 , 101 };
var predicted = new TSeries { 95 , 100 , 95 , 100 , 100 };
var results = Mpe . Calculate ( actual , predicted , period : 3 );
// Span mode - zero-allocation bulk processing
Span < double > output = stackalloc double [ 1000 ];
Mpe . Batch ( actualSpan , predictedSpan , output , period : 20 );
```
## Interpretation Guide
| MPE Value | Interpretation | Action |
| :--- | :--- | :--- |
| ** > +10%** | Severe under-prediction | Add positive bias correction |
| ** +5% to +10%** | Moderate under-prediction | Consider model recalibration |
| ** -5% to +5%** | Acceptable bias range | Monitor for drift |
| ** -10% to -5%** | Moderate over-prediction | Consider model recalibration |
| ** < -10%** | Severe over-prediction | Add negative bias correction |
## Comparison with Related Metrics
| Metric | Formula | Preserves Sign | Use Case |
| :--- | :--- | :--- | :--- |
| **MPE** | 100 × (A-P)/A | ✓ | Bias detection |
| **MAPE** | 100 × \|A-P\|/A | ✗ | Magnitude only |
| **ME** | A - P | ✓ | Absolute bias |
| **MAE** | \|A - P\| | ✗ | Absolute magnitude |
## Common Pitfalls
### 1. Zero Actuals
MPE is undefined when actual = 0. The implementation uses epsilon fallback:
```csharp
double divisor = Math . Abs ( actual ) < 1e-10 ? 1e-10 : actual ;
```
### 2. Cancellation Effect
Errors of opposite signs cancel out. A model alternating between +50% and -50% errors would show MPE ≈ 0%, masking severe inaccuracy.
**Solution** : Use MPE alongside MAPE:
* Low MAPE + Low |MPE|: Good model
* Low MAPE + High |MPE|: Unlikely (mathematically constrained)
* High MAPE + Low |MPE|: High variance, no bias
* High MAPE + High |MPE|: High variance with bias
### 3. Asymmetric Bounds
Unlike MAPE (bounded at 0% to ∞), MPE can range from -∞ to +100%:
* Maximum positive: actual = 100, predicted = 0 → MPE = +100%
* No upper bound on negative: actual = 100, predicted = 1000 → MPE = -900%
## See Also
* [MAPE ](../mape/Mape.md ) - Unsigned percentage error for magnitude
* [ME ](../me/Me.md ) - Signed absolute error for absolute bias
2026-03-13 13:46:52 -07:00
* [MAE ](../mae/Mae.md ) - Unsigned absolute error for magnitude