mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-16 17:48:05 +00:00
135 lines
7.7 KiB
Markdown
135 lines
7.7 KiB
Markdown
# WINS: Winsorized Mean Moving Average
|
|
|
|
> *Winsorization clamps outliers to the nearest percentile fence, preserving sample size while taming extreme values.*
|
|
|
|
| Property | Value |
|
|
| ---------------- | -------------------------------- |
|
|
| **Category** | Statistic |
|
|
| **Inputs** | Source (close) |
|
|
| **Parameters** | `period`, `winPct` (default 10.0) |
|
|
| **Outputs** | Single series (Wins) |
|
|
| **Output range** | Varies (see docs) |
|
|
| **Warmup** | `period` bars |
|
|
| **PineScript** | [wins.pine](wins.pine) |
|
|
|
|
- The Winsorized Mean Moving Average computes a rolling average after replacing (not discarding) the most extreme values in each tail with the bounda...
|
|
- **Similar:** [Trim](../trim/Trim.md), [Percentile](../percentile/Percentile.md) | **Trading note:** Winsorized mean; replaces extreme values instead of removing them. Preserves sample size.
|
|
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
|
|
|
|
The Winsorized Mean Moving Average computes a rolling average after replacing (not discarding) the most extreme values in each tail with the boundary values at the trim point. Unlike the trimmed mean (TRIM) which removes outliers entirely, Winsorization preserves the full sample size by clamping extreme values to the nearest non-extreme observation. At `winPct = 0` it degenerates to the SMA; at `winPct = 50` all values equal the median pair. The default 10% Winsorization provides a robust central tendency estimator that dampens outlier impact while maintaining the statistical efficiency advantages of the full sample size.
|
|
|
|
## Historical Context
|
|
|
|
Winsorization is named after Charles P. Winsor, a biostatistician at Harvard, though the technique was popularized by John Tukey (1962) who credited Winsor with the idea. The concept arises naturally from the question: "what if instead of throwing away extreme values, we replace them with the most extreme non-discarded value?" This produces an estimator that is more efficient than the trimmed mean under light contamination models while retaining comparable robustness.
|
|
|
|
The distinction between trimming and Winsorizing is subtle but consequential. Consider a 20-bar window with 10% processing: TRIM discards the 2 lowest and 2 highest values, averaging the remaining 16. WINS replaces the 2 lowest with the 3rd-lowest value and the 2 highest with the 3rd-highest, averaging all 20. Both have the same breakdown point (10%), but WINS has higher asymptotic efficiency because it uses all $n$ observations in the average.
|
|
|
|
In financial applications, Winsorization is standard practice in factor modeling: Fama-French factor returns are typically Winsorized at 1% or 5% to prevent a handful of extreme observations from dominating cross-sectional regressions. The Winsorized mean is also used in the construction of robust risk measures like the Winsorized variance and the Winsorized covariance matrix.
|
|
|
|
## Architecture and Physics
|
|
|
|
The computation has three steps per bar:
|
|
|
|
**Step 1: Collection** gathers the most recent `period` values into an array, substituting 0 for NaN via `nz()`.
|
|
|
|
**Step 2: Sort and clamp** arranges values in ascending order, then replaces the lowest `winCount` values with the value at index `winCount` (the lower boundary) and the highest `winCount` values with the value at index `period - 1 - winCount` (the upper boundary):
|
|
|
|
$$\text{winCount} = \left\lfloor \frac{\text{period} \times \text{winPct}}{100} \right\rfloor$$
|
|
|
|
The clamping preserves the boundary values themselves; only values beyond them are replaced.
|
|
|
|
**Step 3: Average** computes the arithmetic mean of all `period` values (including the replaced ones). Since replaced values equal the boundary values, this is equivalent to:
|
|
|
|
$$\text{WINS} = \frac{\text{winCount} \cdot x_{(k+1)} + \sum_{i=k+1}^{n-k} x_{(i)} + \text{winCount} \cdot x_{(n-k)}}{n}$$
|
|
|
|
where $k = \text{winCount}$ and $x_{(i)}$ is the $i$-th order statistic.
|
|
|
|
**Edge case**: If `winCount` would reach or exceed `period / 2`, it is clamped to `(period - 1) / 2`, producing the median pair (two middle values) replicated across all positions.
|
|
|
|
## Mathematical Foundation
|
|
|
|
The **Winsorized mean** for a sample of size $n$ with $k$ replacements per tail:
|
|
|
|
$$\bar{x}_W = \frac{1}{n}\left[k \cdot x_{(k+1)} + \sum_{i=k+1}^{n-k} x_{(i)} + k \cdot x_{(n-k)}\right]$$
|
|
|
|
where $x_{(i)}$ is the $i$-th order statistic and $k = \lfloor \alpha n \rfloor$ with $\alpha = \text{winPct}/100$.
|
|
|
|
**Winsorized variance** (used for inference on the Winsorized mean):
|
|
|
|
$$s_W^2 = \frac{1}{n-1} \sum_{i=1}^{n} (w_i - \bar{x}_W)^2$$
|
|
|
|
where $w_i$ are the Winsorized values.
|
|
|
|
**Influence function**: Bounded like TRIM, but the boundary behavior differs:
|
|
|
|
$$\text{IF}(x; \bar{x}_W) = \begin{cases} x_{(\alpha)} - \bar{x}_W & \text{if } x \le x_{(\alpha)} \\ x - \bar{x}_W & \text{if } x_{(\alpha)} < x < x_{(1-\alpha)} \\ x_{(1-\alpha)} - \bar{x}_W & \text{if } x \ge x_{(1-\alpha)} \end{cases}$$
|
|
|
|
**Breakdown point**: $\alpha$ (the Winsorization fraction).
|
|
|
|
**Asymptotic efficiency** relative to SMA under normality (higher than TRIM at same percentage):
|
|
|
|
| Win % | WINS Efficiency | TRIM Efficiency |
|
|
|-------|----------------|-----------------|
|
|
| 0% | 100% | 100% |
|
|
| 10% | ~97% | ~95% |
|
|
| 25% | ~90% | ~85% |
|
|
|
|
**Parameter constraints**: `period` $\ge 3$, `winPct` $\in [0, 49]$.
|
|
|
|
```
|
|
WINS(source, period, winPct):
|
|
winCount = floor(period * winPct / 100)
|
|
if winCount >= period/2: winCount = (period-1)/2
|
|
|
|
// Collect and sort
|
|
vals = [source[0], source[1], ..., source[period-1]]
|
|
sort(vals, ascending)
|
|
|
|
// Replace tails with boundary values
|
|
lowerBound = vals[winCount]
|
|
upperBound = vals[period - 1 - winCount]
|
|
for i = 0 to winCount-1:
|
|
vals[i] = lowerBound
|
|
vals[period - 1 - i] = upperBound
|
|
|
|
// Average all values (full sample size)
|
|
return mean(vals)
|
|
```
|
|
|
|
|
|
## Performance Profile
|
|
|
|
### Operation Count (Streaming Mode)
|
|
|
|
Winsorized mean collects the window, sorts it, replaces the tails with boundary values, then computes the mean of all N values.
|
|
|
|
| Operation | Count | Cost (cycles) | Subtotal |
|
|
| :--- | :---: | :---: | :---: |
|
|
| Ring buffer collect | N | 1 cy | ~N cy |
|
|
| Array sort (introsort) | N log N | 2 cy | ~2N log N cy |
|
|
| Tail clamping (2k assignments) | 2k | 1 cy | ~2k cy |
|
|
| Sum all N values | N | 2 cy | ~2N cy |
|
|
| Divide for mean | 1 | 4 cy | ~4 cy |
|
|
| NaN guard + state update | 1 | 2 cy | ~2 cy |
|
|
| **Total (N=20, k=2)** | **O(N log N)** | — | **~230 cy** |
|
|
|
|
O(N log N) per update due to sort. Slightly higher total cost than TRIM because the sum includes all N values (not N-2k), but both are dominated by the sort.
|
|
|
|
### Batch Mode (SIMD Analysis)
|
|
|
|
| Operation | Vectorizable? | Notes |
|
|
| :--- | :---: | :--- |
|
|
| Window collection | Yes | Gather from ring buffer with SIMD copy |
|
|
| Sort | No | Comparison sort is sequential |
|
|
| Clamping tail values | Yes | Vector conditional-select possible post-sort |
|
|
| Full-window sum | Yes | Vector<double> sum over N values |
|
|
|
|
Sort blocks SIMD on the main path. The sum phase can use Vector<double> for modest gains. Outer loop (across M bars) has no cross-bar dependency — suitable for parallel batch.
|
|
|
|
## Resources
|
|
|
|
- Tukey, J.W. "The Future of Data Analysis." Annals of Mathematical Statistics, 1962.
|
|
- Huber, P.J. & Ronchetti, E. "Robust Statistics." 2nd edition, Wiley, 2009.
|
|
- Wilcox, R.R. "Introduction to Robust Estimation and Hypothesis Testing." 4th edition, Academic Press, 2017.
|
|
- Fama, E.F. & French, K.R. "Common Risk Factors in the Returns on Stocks and Bonds." Journal of Financial Economics, 1993.
|
|
- Dixon, W.J. & Tukey, J.W. "Approximate Behavior of the Distribution of Winsorized t." Technometrics, 1968. |