From 62fcab1c861138edaca1926ba763dc08ac6261b2 Mon Sep 17 00:00:00 2001 From: kingchenc Date: Sat, 23 May 2026 10:54:51 +0200 Subject: [PATCH] docs(wiki): refresh PSAR streaming exposure and HV non-positive behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PSAR — the wiki page still claimed "Node streaming. Not exposed in the Node binding." That was true for an early release but is no longer: the Node binding has exposed `psar.update(high, low, close)` since the B1 fix in todo-detailed.md, and the WASM binding now exposes the same streaming surface (audit finding R3, this branch). The page lists all three streaming + batch shapes and adds a paragraph on the new `is_ready` convention (audit finding R6 — flips on the first non-None SAR, not on the seed candle). HistoricalVolatility — the "Non-positive prices" edge-case note still described the old behaviour ("that return is treated as 0"). The new behaviour skips the bad tick entirely (audit finding R13): the indicator's state is left untouched, the previous valid value is returned, and the next real tick re-anchors against the previous *valid* price. Updated the note to describe the new behaviour and explain why (silently treating bad ticks as "no movement" underreports realised volatility). --- .../indicators/trailing-stops/Indicator-Psar.md | 15 +++++++++++++-- .../Indicator-HistoricalVolatility.md | 7 ++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/wiki/indicators/trailing-stops/Indicator-Psar.md b/docs/wiki/indicators/trailing-stops/Indicator-Psar.md index 19e40b13..922196f4 100644 --- a/docs/wiki/indicators/trailing-stops/Indicator-Psar.md +++ b/docs/wiki/indicators/trailing-stops/Indicator-Psar.md @@ -72,13 +72,24 @@ impl Indicator for Psar { } ``` -- **Python streaming.** Returns `float | None`. +- **Python streaming.** `psar.update(candle)` returns `float | None`. - **Python batch.** `PSAR.batch(high, low, close)` returns a 1-D `np.ndarray`; the first row is `NaN` (warmup) and every subsequent row holds the SAR level for that bar. -- **Node streaming.** Not exposed in the Node binding. +- **Node streaming.** `psar.update(high, low, close)` returns `number | null`. - **Node batch.** `psar.batch(high, low, close)` returns `Array` with `NaN` for the first row. +- **WASM streaming.** `psar.update(high, low, close)` returns + `number | null` once warm. +- **WASM batch.** `psar.batch(high, low, close)` returns a + `Float64Array` with `NaN` for the first row. +- **`isReady` convention.** `psar.is_ready()` flips to `true` only once the + first non-`None` SAR has been produced (i.e. from the second candle + onwards). The first (seed) candle returns `None` and `is_ready()` stays + `false`, matching every other indicator in the library. Previous releases + flipped the flag after the seed candle even though it produced no value — + consumers that wrote `if psar.is_ready() { use(psar.update(c)?) }` would + hit an unexpected `None` on the first post-seed update; that's now fixed. ## Warmup diff --git a/docs/wiki/indicators/volatility-bands/Indicator-HistoricalVolatility.md b/docs/wiki/indicators/volatility-bands/Indicator-HistoricalVolatility.md index 1a162d99..e8f6517d 100644 --- a/docs/wiki/indicators/volatility-bands/Indicator-HistoricalVolatility.md +++ b/docs/wiki/indicators/volatility-bands/Indicator-HistoricalVolatility.md @@ -69,7 +69,12 @@ non-`None` output lands on input `period + 1`. log return; its standard deviation — and so HV — is `0` (`geometric_series_yields_zero` pins this). - **Non-positive prices.** A log return is undefined when either price is - `<= 0`; that return is treated as `0`. + `<= 0`. Such ticks are **skipped**: the previous valid value is returned, + the indicator's state (previous price, window, sums) is left untouched, and + the next real positive tick re-anchors against the previous *valid* price. + Previous releases silently treated bad ticks as a `0.0` log-return, which + underreported realised volatility on broken data feeds — that behaviour has + changed. - **Non-negative.** Volatility is a standard deviation and is never negative (`output_is_non_negative` pins this). - **NaN / infinity inputs.** Non-finite inputs are silently dropped.