f10b8c2e2d
* feat(family-09): add 7 trailing stops (HiLo, Volty, Yo-Yo, Donchian, Pct, Step, Renko)
Rounds out the Trailing Stops family from 5 to 12 indicators:
- HiLoActivator (Crabel): SMA-of-high/SMA-of-low trail with a one-bar
lag; emits the opposite-side SMA as the trailing stop.
- VoltyStop (Cynthia Kase): ATR trail anchored on the extreme close
since the trade was opened — tighter than AtrTrailingStop on
pullbacks.
- YoyoExit: long-only ATR trail with an explicit re-entry trigger at
trail + multiplier*ATR; exposes an in_trade flag.
- DonchianStop (Turtle): lowest low / highest high over the window;
multi-output {stop_long, stop_short}.
- PercentageTrailingStop: fixed-percent trail that scales across
instruments without per-asset tuning.
- StepTrailingStop: snaps to a step_size-aligned grid; mirrors
discretionary stop-by-hand workflow.
- RenkoTrailingStop: block-anchored trail; only moves on full-block
advances, ignores intra-block noise.
All seven are wired into wickra-core, the Python / Node / WASM
bindings, the indicator_update + indicator_update_candle fuzz targets,
the wickra bench harness, and the Python + Node test suites. README
counter bumps from 71 to 78; CHANGELOG entry under [Unreleased].
* fix(family-09): satisfy pedantic clippy lints
- hilo_activator: rewrite match-Some/None as if-let-else (single_match_else),
add backticks around the HiLo identifier in module/struct doc (doc_markdown).
- percentage / step / renko trailing stop tests: use f64::from(i32) instead
of `as f64` (cast_lossless).
- bench `benches()` is now >100 lines after Family 09 was wired in; allow
too_many_lines (matches the python pymodule fn).
Fuzzing Wickra
cargo-fuzz harnesses for
the parsing and stateful entry points of Wickra. Fuzzing requires a nightly
Rust toolchain.
Setup
cargo install cargo-fuzz
rustup toolchain install nightly
Targets
| Target | What it exercises |
|---|---|
csv_reader |
CandleReader over arbitrary bytes — headers, cells, BOM, binary noise. |
binance_envelope |
RawWsEnvelope deserialization from arbitrary strings. |
indicator_update |
Every scalar-input indicator (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 / Bollinger) streamed + batched over arbitrary f64 sequences (NaN, ±inf, jumps). |
indicator_update_candle |
Every candle-input indicator (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) streamed + batched over fuzz-derived OHLCV candles. |
tick_aggregator |
TickAggregator over arbitrary (price, volume, timestamp) triples. |
Run
# From the repository root:
cargo +nightly fuzz run csv_reader
cargo +nightly fuzz run binance_envelope
cargo +nightly fuzz run indicator_update
cargo +nightly fuzz run indicator_update_candle
cargo +nightly fuzz run tick_aggregator
Each run continues until a crash is found or it is interrupted. A short time-boxed smoke run is useful in CI:
cargo +nightly fuzz run csv_reader -- -max_total_time=60
The expectation for every target is that it never panics: malformed or
adversarial input must surface as an Err, never a crash.