mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-05 20:47:43 +00:00
135 lines
7.8 KiB
Markdown
135 lines
7.8 KiB
Markdown
# POLYFIT: Polynomial Fitting
|
||
|
||
> *Polynomial fitting bends a curve through price data, capturing nonlinear trends that a straight line cannot.*
|
||
|
||
| Property | Value |
|
||
| ---------------- | -------------------------------- |
|
||
| **Category** | Statistic |
|
||
| **Inputs** | Source (close) |
|
||
| **Parameters** | `period`, `degree` (default 2) |
|
||
| **Outputs** | Single series (Polyfit) |
|
||
| **Output range** | Varies (see docs) |
|
||
| **Warmup** | `period` bars |
|
||
| **PineScript** | [polyfit.pine](polyfit.pine) |
|
||
|
||
- Polynomial Fitting computes a rolling polynomial regression of configurable degree over a lookback window, returning the fitted value at the curren...
|
||
- **Similar:** [LinReg](../linreg/LinReg.md), [TSF](../../trends_FIR/tsf/Tsf.md) | **Trading note:** Polynomial curve fitting; captures non-linear trends. Higher order = more responsive but risk of overfitting.
|
||
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
|
||
|
||
Polynomial Fitting computes a rolling polynomial regression of configurable degree over a lookback window, returning the fitted value at the current bar. Degree 1 produces a linear regression endpoint (identical to LSQR), degree 2 produces a quadratic fit that captures curvature, and degree 3 produces a cubic fit that captures inflection points. The implementation solves the normal equations $\mathbf{X}^T\mathbf{X}\mathbf{a} = \mathbf{X}^T\mathbf{y}$ via Gauss-Jordan elimination with partial pivoting, evaluating the resulting polynomial at $x = 1$ (the current bar position). With $O(Nd + d^3)$ complexity per bar where $N$ is the period and $d$ is the degree, POLYFIT provides a general-purpose curve-fitting tool that subsumes linear regression and extends it to arbitrary polynomial order.
|
||
|
||
## Historical Context
|
||
|
||
Polynomial regression traces to Adrien-Marie Legendre (1805) and Carl Friedrich Gauss (1809), who independently developed the method of least squares. The normal equations formulation provides the minimum-sum-of-squares solution in closed form, though numerical stability requires careful implementation. Gauss-Jordan elimination with partial pivoting (Jordan, 1873) is the standard approach for small systems like those arising in polynomial fitting with degrees 1-6.
|
||
|
||
In technical analysis, linear regression (degree 1) is well established via the Linear Regression Channel and LSQR indicators. Higher-degree fits are less common due to overfitting concerns, but degree 2 (quadratic) is useful for detecting acceleration/deceleration in trends, and degree 3 (cubic) can capture reversal patterns. The key insight is that higher degrees track price more closely but also amplify noise; the optimal degree depends on the signal-to-noise ratio and the lookback period.
|
||
|
||
The x-normalization step (mapping time indices to $[0, 1]$) is critical for numerical stability: without it, the Vandermonde matrix entries $x^d$ would span many orders of magnitude for typical lookback periods, causing catastrophic cancellation in the normal equations. With normalization, the matrix condition number remains manageable up to degree 6.
|
||
|
||
## Architecture and Physics
|
||
|
||
The implementation uses a circular buffer to maintain the last `period` values, with NaN substitution via last-valid-value tracking.
|
||
|
||
**Matrix assembly**: Constructs the $(d+1) \times (d+1)$ Gram matrix $\mathbf{G} = \mathbf{X}^T\mathbf{X}$ and right-hand side $\mathbf{r} = \mathbf{X}^T\mathbf{y}$ in a single pass over the data. The Vandermonde basis vectors are $[1, x, x^2, \ldots, x^d]$ where $x_i = i/(n-1)$ is the normalized time position. The matrix is symmetric so only the upper triangle needs explicit computation (mirrored to lower).
|
||
|
||
**Solver**: Gauss-Jordan elimination with partial pivoting transforms the augmented matrix $[\mathbf{G} | \mathbf{r}]$ into $[\mathbf{I} | \mathbf{a}]$. Partial pivoting selects the row with the largest absolute value in the current column to minimize round-off error. Singular or near-singular matrices (pivot $< 10^{-30}$) abort gracefully.
|
||
|
||
**Evaluation**: The polynomial $P(x) = a_0 + a_1 x + a_2 x^2 + \cdots + a_d x^d$ is evaluated at $x = 1.0$ (current bar, since time is normalized to $[0, 1]$). This gives the fitted value at the most recent observation.
|
||
|
||
**Degree clamping**: If `degree` exceeds `period - 1`, it is automatically reduced to prevent underdetermined systems.
|
||
|
||
## Mathematical Foundation
|
||
|
||
The polynomial model:
|
||
|
||
$$P(x) = \sum_{j=0}^{d} a_j x^j = a_0 + a_1 x + a_2 x^2 + \cdots + a_d x^d$$
|
||
|
||
The **normal equations** for least-squares fitting:
|
||
|
||
$$\mathbf{X}^T\mathbf{X}\,\mathbf{a} = \mathbf{X}^T\mathbf{y}$$
|
||
|
||
where $\mathbf{X}$ is the $n \times (d+1)$ Vandermonde matrix:
|
||
|
||
$$X_{ij} = x_i^j, \quad x_i = \frac{i}{n-1} \in [0, 1]$$
|
||
|
||
The Gram matrix elements:
|
||
|
||
$$G_{jk} = \sum_{i=0}^{n-1} x_i^{j+k}$$
|
||
|
||
The right-hand side:
|
||
|
||
$$r_j = \sum_{i=0}^{n-1} x_i^j \cdot y_i$$
|
||
|
||
**Gauss-Jordan with partial pivoting** reduces $[\mathbf{G} | \mathbf{r}]$ to $[\mathbf{I} | \mathbf{a}]$:
|
||
|
||
1. For each column $c$: find the row $p$ in $[c, d]$ with maximum $|G_{pc}|$
|
||
2. Swap rows $c$ and $p$
|
||
3. Scale row $c$ so the pivot becomes 1
|
||
4. Subtract multiples of row $c$ from all other rows
|
||
|
||
**Output**: $\hat{y}_{\text{current}} = P(1.0) = \sum_{j=0}^{d} a_j$
|
||
|
||
**Parameter constraints**: `period` $\ge 2$, `degree` $\ge 1$ (clamped to `period - 1`). Computational complexity: $O(nd + d^3)$.
|
||
|
||
```
|
||
POLYFIT(source, period, degree):
|
||
d = min(degree, period - 1)
|
||
m = d + 1
|
||
normalize x_i = i / (n-1) for i in [0, n-1]
|
||
|
||
// Build normal equations
|
||
G = (m x m) matrix of zeros
|
||
r = m-vector of zeros
|
||
for each (x_i, y_i) in window:
|
||
for j = 0 to d:
|
||
r[j] += x_i^j * y_i
|
||
for k = j to d:
|
||
G[j][k] += x_i^(j+k)
|
||
G[k][j] = G[j][k] // symmetric
|
||
|
||
// Gauss-Jordan with partial pivoting
|
||
for col = 0 to d:
|
||
pivot_row = argmax |G[row][col]| for row in [col, d]
|
||
swap rows col and pivot_row in G and r
|
||
scale row col by 1/G[col][col]
|
||
eliminate col from all other rows
|
||
|
||
// Evaluate at x = 1.0 (current bar)
|
||
return sum(r[j] for j = 0 to d)
|
||
```
|
||
|
||
|
||
## Performance Profile
|
||
|
||
### Operation Count (Streaming Mode)
|
||
|
||
Polyfit uses a running-sum approach via Vandermonde normal equations for degree-1 (linear) regression, updated O(1) per bar with a sliding window ring buffer.
|
||
|
||
| Operation | Count | Cost (cycles) | Subtotal |
|
||
| :--- | :---: | :---: | :---: |
|
||
| Ring buffer add/evict | 1 | 3 cy | ~3 cy |
|
||
| Update running sums (Sx, Sy, Sxx, Sxy) | 4 | 2 cy | ~8 cy |
|
||
| Solve 2x2 normal system | 1 | 6 cy | ~6 cy |
|
||
| FMA for slope/intercept | 2 | 1 cy | ~2 cy |
|
||
| NaN guard + state update | 1 | 2 cy | ~2 cy |
|
||
| **Total** | **O(1)** | — | **~21 cy** |
|
||
|
||
O(1) per update for linear (degree-1) fit using online normal equations. Higher-degree fits require O(degree^2) matrix solve per bar.
|
||
|
||
### Batch Mode (SIMD Analysis)
|
||
|
||
| Operation | Vectorizable? | Notes |
|
||
| :--- | :---: | :--- |
|
||
| Running sum accumulation | Yes | Vector<double> reduces 4 sums in parallel |
|
||
| Normal equation solve | Partial | 2×2 system trivially unrolled |
|
||
| Output projection | Yes | FMA for y = a*x + b across output span |
|
||
|
||
Batch span path can vectorize sum accumulation and output projection. Inner loop SIMD-friendly for degree-1 case.
|
||
|
||
## Resources
|
||
|
||
- Legendre, A.M. "Nouvelles methodes pour la determination des orbites des cometes." 1805.
|
||
- Gauss, C.F. "Theoria Motus Corporum Coelestium." 1809.
|
||
- Golub, G. & Van Loan, C. "Matrix Computations." 4th edition, Johns Hopkins University Press, 2013.
|
||
- Press, W.H. et al. "Numerical Recipes: The Art of Scientific Computing." 3rd edition, Cambridge University Press, 2007. Chapter 15 (Modeling of Data).
|
||
- Draper, N. & Smith, H. "Applied Regression Analysis." 3rd edition, Wiley, 1998. |