Files
QuanTAlib/lib/trends_FIR/pwma/Pwma.md
T

97 lines
4.1 KiB
Markdown
Raw Normal View History

# PWMA: Parabolic Weighted Moving Average
> *Linear weighting is for people who think the world is flat. PWMA squares the weights, because recent data isn't just more important—it's exponentially more important.*
2026-02-27 07:48:12 -08:00
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Pwma) |
| **Output range** | Tracks input |
| **Warmup** | `period` bars |
| **PineScript** | [pwma.pine](pwma.pine) |
| **Signature** | [pwma_signature](pwma_signature.md) |
2026-02-27 07:48:12 -08:00
- PWMA (Parabolic Weighted Moving Average) applies a parabolic ($i^2$) weighting scheme to the data window.
- **Similar:** [FWMA](../fwma/fwma.md), [WMA](../wma/wma.md) | **Complementary:** Trend filters | **Trading note:** Pascal-Weighted MA; weights from Pascals triangle for smooth, symmetric kernel.
2026-02-27 07:48:12 -08:00
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
PWMA (Parabolic Weighted Moving Average) applies a parabolic ($i^2$) weighting scheme to the data window. This assigns massive importance to the most recent data points while still technically including the older data. It's like a WMA on steroids.
## Historical Context
While the WMA uses a linear triangle window ($1, 2, 3, \dots, n$), the PWMA uses a parabolic window ($1^2, 2^2, 3^2, \dots, n^2$). This was developed for traders who found the WMA too slow but the EMA too jittery. It provides a curve that turns faster than a WMA but is smoother than an EMA at the tail.
## Architecture & Physics
The "physics" is defined by the weight function $W_i = i^2$.
This shifts the center of gravity of the filter heavily towards the right (recent data).
## Mathematical Foundation
$$ \text{PWMA} = \frac{\sum_{i=1}^{N} i^2 P_{t-N+i}}{\sum_{i=1}^{N} i^2} $$
The O(1) update logic involves cascading the sums:
$$ S1_{new} = S1_{old} - \text{Oldest} + \text{Newest} $$
$$ S2_{new} = S2_{old} - S1_{old} + N \times \text{Newest} $$
$$ S3_{new} = S3_{old} - 2 S2_{old} + S1_{old} + N^2 \times \text{Newest} $$
## Performance Profile
### Operation Count (Streaming Mode, Scalar)
The O(1) algorithm uses triple cascading sums:
| Operation | Count | Cost (cycles) | Subtotal |
| :--- | :---: | :---: | :---: |
| ADD/SUB | 9 | 1 | 9 |
| MUL | 3 | 3 | 9 |
| DIV | 1 | 15 | 15 |
| **Total** | **13** | — | **~33 cycles** |
**Hot path breakdown:**
- S1 update: `S1_new = S1_old - oldest + newest` → 2 ADD/SUB
- S2 update: `S2_new = S2_old - S1_old + N×newest` → 2 ADD/SUB + 1 MUL
- S3 update: `S3_new = S3_old - 2×S2_old + S1_old + N²×newest` → 4 ADD/SUB + 2 MUL
- Final: `PWMA = S3 / divisor` → 1 DIV (divisor precomputed)
**Comparison with naive O(N) implementation:**
| Mode | Complexity | Cycles (Period=100) |
| :--- | :---: | :---: |
| Naive (recalculate) | O(N) | ~700 cycles |
| QuanTAlib O(1) | O(1) | ~33 cycles |
| **Improvement** | **—** | **~21× faster** |
### Batch Mode (SIMD)
PWMA batch can vectorize prefix-sum cascades:
| Operation | Scalar Ops (512 bars) | SIMD Ops (AVX2) | Speedup |
| :--- | :---: | :---: | :---: |
| S1 prefix sum | 512 | 64 | 8× |
| S2 cascaded sum | 1024 | 128 | 8× |
| S3 cascaded sum | 1536 | 192 | 8× |
### Quality Metrics
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Accuracy** | 10/10 | Matches mathematical definition exactly |
| **Timeliness** | 9/10 | Very fast reaction to new data (heavy recent weighting) |
| **Overshoot** | 3/10 | Parabolic weighting can cause overshoot |
| **Smoothness** | 4/10 | Sensitive to recent noise |
## Validation
Validated against Ooples.
| Library | Status | Notes |
| :--- | :--- | :--- |
| **QuanTAlib** | ✅ | Validated. |
| **Ooples** | ✅ | Matches `CalculateParabolicWeightedMovingAverage` |
| **Skender** | N/A | Not implemented |
| **TA-Lib** | N/A | Not implemented |
| **Tulip** | N/A | Not implemented. |