The fuzz suite previously covered only `Rsi(14)` and `Ema(20)` — 2 of
71 indicators, no OHLCV coverage at all. Audit finding R9 asked for
ATR/ADX/Stochastic/PSAR as a minimum; this commit goes further and
brings every indicator under fuzz.
- `indicator_update` (rewritten): drives every scalar-input indicator
through one streaming pass + one batch call per iteration. Covers
SMA, EMA, WMA, RSI, DEMA, TEMA, HMA, ROC, TRIX, SMMA, TRIMA, ZLEMA,
KAMA, T3, MOM, CMO, TSI, PMO, StochRSI, DPO, PPO, Coppock, StdDev,
UlcerIndex, HistoricalVolatility, LinearRegression, LinRegSlope,
LinRegAngle, VHF, ZScore, MACD, BollingerBands. A `drive` helper
marked `#[inline(never)]` keeps each indicator on its own panic
backtrace frame.
- `indicator_update_candle` (new): chunks the fuzz `f64` stream into
`[open, high, low, close, volume]` tuples, builds candles via
`Candle::new` (skipping ones that fail OHLCV validation — that path
is fuzz-tested separately), then drives every candle-input indicator
through streaming + batch. Covers ATR, NATR, TrueRange,
ChaikinVolatility, Keltner, Donchian, PSAR, SuperTrend,
ChandelierExit, ChandeKrollStop, ATRTrailingStop, ADX, Aroon,
AroonOscillator, Vortex, MassIndex, ChoppinessIndex, CCI, WilliamsR,
AwesomeOscillator, AcceleratorOscillator, UltimateOscillator,
BalanceOfPower, OBV, MFI, VWAP, RollingVWAP, VWMA, ADL, VPT, CMF,
ChaikinOscillator, ForceIndex, EaseOfMovement, TypicalPrice,
MedianPrice, WeightedClose, Stochastic.
- `fuzz/Cargo.toml` registers the new target; `fuzz/README.md`
describes both expanded targets.
- A `fuzz-smoke` CI job runs each of the five targets for 30 s on
every push and pull-request — enough to catch a regression in the
harness without slowing CI to a crawl. Long fuzz campaigns belong
on dedicated infrastructure with persistent corpora.
The repository had no fuzzing setup despite several natural targets —
the CSV parser, the Binance envelope deserializer, and the stateful
indicator/aggregator update paths.
Add a fuzz/ cargo-fuzz crate (detached from the workspace via its own
[workspace] table and the parent's exclude) with four targets:
- csv_reader — CandleReader over arbitrary bytes
- binance_envelope — RawWsEnvelope deserialization from arbitrary strings
- indicator_update — RSI/EMA streaming + batch over arbitrary f64 series
- tick_aggregator — TickAggregator over arbitrary tick triples
Each target asserts the no-panic contract: malformed input must surface
as an Err. fuzz/README.md documents running them (nightly + cargo-fuzz).