docs(wiki): document O(1) regression update and long-stream sum reseed (R2, R7)
Three indicator pages get a short follow-up paragraph that surfaces an internal implementation detail the audit findings made user-visible: - `Indicator-LinearRegression.md` gains a "Complexity" section explaining the O(1) update (precomputed `Σx`, `Σxx`; incrementally slid `Σy`, `Σxy` via the closed-form sliding identity), and the existing "Reset" bullet mentions the additional running accumulators. The same story applies to `LinRegSlope` and `LinRegAngle` (the page now links to both rather than repeating the derivation three times). - `Indicator-Sma.md` and `Indicator-BollingerBands.md` mention the periodic reseed (`16 · period` updates) that caps floating-point drift on long-running streams. Amortised cost is still O(1) and the user-facing behaviour on benign inputs is unchanged. No behavioural claim, no API claim, no example changes — just narrative catching up with the implementation.
This commit is contained in:
@@ -23,7 +23,12 @@ SMA_t = (1 / n) * Σ_{i=0}^{n-1} price_{t-i}
|
|||||||
|
|
||||||
where `n = period`. Maintained incrementally as `sum -= window.pop_front();
|
where `n = period`. Maintained incrementally as `sum -= window.pop_front();
|
||||||
sum += new_price; out = sum / n`, so `update` is O(1) regardless of
|
sum += new_price; out = sum / n`, so `update` is O(1) regardless of
|
||||||
`period`.
|
`period`. To keep f64 rounding error bounded on long-running streams (where
|
||||||
|
catastrophic cancellation between add/subtract pairs could otherwise
|
||||||
|
accumulate), the running `sum` is reseeded from the live window every
|
||||||
|
`16 · period` updates — still amortised O(1) (`O(period)` work amortised
|
||||||
|
over `O(period)` updates), zero observable change on inputs that did not
|
||||||
|
drift to begin with.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,16 @@ step. Because `Input = f64` it can sit inside a [`Chain`](../../Indicator-Chaini
|
|||||||
`LinearRegression::new(14).warmup_period() == 14`. The first value lands once
|
`LinearRegression::new(14).warmup_period() == 14`. The first value lands once
|
||||||
the window holds a full `period` prices — on input index `period − 1`.
|
the window holds a full `period` prices — on input index `period − 1`.
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
Each `update` is **O(1)**: the `Σx` and `Σxx` terms depend only on `period`
|
||||||
|
and are precomputed once at construction, and `Σy` / `Σxy` are maintained
|
||||||
|
incrementally as the window slides via the closed-form identity
|
||||||
|
`new_Σxy = old_Σxy − old_Σy + popped_y₀` (then `Σxy += (n − 1) · new_value`
|
||||||
|
and `Σy += new_value`). The same applies to
|
||||||
|
[`LinRegSlope`](Indicator-LinRegSlope.md) and
|
||||||
|
[`LinRegAngle`](Indicator-LinRegAngle.md).
|
||||||
|
|
||||||
## Edge cases
|
## Edge cases
|
||||||
|
|
||||||
- **`period < 2`.** Rejected at construction — a regression line is undefined
|
- **`period < 2`.** Rejected at construction — a regression line is undefined
|
||||||
@@ -65,7 +75,8 @@ the window holds a full `period` prices — on input index `period − 1`.
|
|||||||
the endpoint equals the current value (`perfect_line_returns_current_value`
|
the endpoint equals the current value (`perfect_line_returns_current_value`
|
||||||
pins this).
|
pins this).
|
||||||
- **Constant series.** A flat input returns that constant.
|
- **Constant series.** A flat input returns that constant.
|
||||||
- **Reset.** `lr.reset()` clears the rolling window.
|
- **Reset.** `lr.reset()` clears the rolling window and the running `Σy` /
|
||||||
|
`Σxy` accumulators.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ lower = mean - multiplier * stddev
|
|||||||
|
|
||||||
Wickra computes `var` from the streaming sums `Σ x` and `Σ x²` as
|
Wickra computes `var` from the streaming sums `Σ x` and `Σ x²` as
|
||||||
`Σx²/n - (Σx/n)²` and clamps to `0.0` to absorb catastrophic cancellation on
|
`Σx²/n - (Σx/n)²` and clamps to `0.0` to absorb catastrophic cancellation on
|
||||||
near-constant inputs (`crates/wickra-core/src/indicators/bollinger.rs:82`).
|
near-constant inputs (`crates/wickra-core/src/indicators/bollinger.rs`). On
|
||||||
|
long-running streams the running `Σ x` and `Σ x²` are reseeded from the live
|
||||||
|
window every `16 · period` updates — amortised O(1), bounds the cancellation
|
||||||
|
drift to roughly `16 · period · ULP · max(|x|²)` (sub-picodollar on
|
||||||
|
real-world price scales).
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user