# ME: Mean Error (Mean Bias Error)

> "Sometimes you need to know not just how wrong you are, but which direction you're wrong in."

Mean Error (ME), also known as Mean Bias Error, measures the average error between actual and predicted values while preserving the sign. Unlike MAE, ME reveals systematic bias in predictions: whether a model consistently over-predicts or under-predicts.

## Historical Context

ME is one of the fundamental error metrics in statistics and forecasting. While MAE and MSE focus on error magnitude, ME fills the critical role of detecting directional bias. A model could have low MAE but significant ME, indicating consistent over or under-prediction that cancels out when measuring magnitude alone.

## Architecture & Physics

ME preserves the sign of errors, allowing positive and negative errors to cancel each other. This makes it ideal for detecting systematic bias but unsuitable for measuring prediction accuracy alone.

### Properties

* **Can be negative**: ME can be positive, negative, or zero
* **Positive ME**: Model under-predicts (actual > predicted on average)
* **Negative ME**: Model over-predicts (actual < predicted on average)
* **Zero ME**: No systematic bias (but not necessarily accurate)
* **Same units**: ME is in the same units as the original data
* **Cancellation**: Errors can cancel out, hiding large individual errors

## Mathematical Foundation

### 1. Error Calculation

For each observation, calculate the signed difference between actual and predicted values:

$$e_i = y_i - \hat{y}_i$$

Where:

* $y_i$ = actual value
* $\hat{y}_i$ = predicted value

### 2. Mean Calculation

Average the errors over the period:

$$ME = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)$$

### 3. Running Update (O(1))

QuanTAlib uses a ring buffer with running sum for O(1) updates:

$$S_{new} = S_{old} - e_{oldest} + e_{newest}$$

$$ME = \frac{S_{new}}{n}$$

## Implementation Details

### Usage Patterns

```csharp
// Streaming mode - update with each new observation
var me = new Me(period: 20);
var result = me.Update(actualValue, predictedValue);

// Batch mode - calculate for entire series
var results = Me.Calculate(actualSeries, predictedSeries, period: 20);

// Span mode - zero-allocation for high performance
Me.Batch(actualSpan, predictedSpan, outputSpan, period: 20);
```

### Parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| **period** | int | Lookback window for averaging (must be > 0) |

### Properties

| Property | Type | Description |
| :--- | :--- | :--- |
| **Last** | TValue | Most recent ME value |
| **IsHot** | bool | True when buffer is full |
| **Name** | string | Indicator name (e.g., "Me(20)") |
| **WarmupPeriod** | int | Number of periods before valid output |

## Performance Profile

| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | ~10 ns/bar | O(1) update complexity |
| **Allocations** | 0 | Uses pre-allocated ring buffer |
| **Complexity** | O(1) | Constant time per update |
| **Accuracy** | 10/10 | Exact calculation |
| **Timeliness** | 9/10 | No lag beyond the period |
| **Smoothness** | 7/10 | Moderate smoothing |

## Interpretation

| ME Value | Interpretation |
| :--- | :--- |
| **ME > 0** | Systematic under-prediction (actual > predicted) |
| **ME = 0** | No systematic bias |
| **ME < 0** | Systematic over-prediction (actual < predicted) |

## Comparison with Other Metrics

| Metric | Shows Bias | Units | Use Case |
| :--- | :--- | :--- | :--- |
| **ME** | Yes | Same as data | Detect systematic bias |
| **MAE** | No | Same as data | Average error magnitude |
| **MSE** | No | Squared units | Penalize large errors |
| **MPE** | Yes | Percentage | Relative bias |

## Common Use Cases

1. **Bias Detection**: Identify if a model consistently over or under-predicts
2. **Model Calibration**: Use ME to adjust model outputs
3. **Forecast Evaluation**: Distinguish between random errors and systematic bias
4. **Trading Signals**: Detect directional bias in price predictions

## Warning: Cancellation Problem

ME can be misleading when errors cancel out:

```csharp
var me = new Me(4);
me.Update(110, 100); // Error: +10
me.Update(90, 100);  // Error: -10
me.Update(110, 100); // Error: +10
me.Update(90, 100);  // Error: -10
// ME = 0, but individual errors are large!
```

Always use ME alongside MAE or MSE to get a complete picture.

## Edge Cases

* **Identical Values**: Returns 0 when actual equals predicted
* **NaN Handling**: Uses last valid value substitution
* **Single Input**: Not supported (requires two series)
* **Period = 1**: Returns current signed error
* **Balanced Errors**: Can return 0 even with large individual errors

## Related Indicators

* [MAE](../mae/Mae.md) - Mean Absolute Error (magnitude only)
* [MSE](../mse/Mse.md) - Mean Squared Error
* [MPE](../mpe/Mpe.md) - Mean Percentage Error (relative bias)
