a3a1ae4dba
Adds ten pairwise `(f64, f64)` indicators to the **Price Statistics** family, completing the A1 stat-arb expansion block.
## Indicators
**Scalar output:**
- **RollingCorrelation** — rolling Pearson correlation of period-over-period *returns* (distinct from level-based `PearsonCorrelation`).
- **RollingCovariance** — rolling covariance of returns.
- **OuHalfLife** — Ornstein–Uhlenbeck half-life of mean reversion of the spread `a − b`.
- **SpreadHurst** — Hurst exponent of the spread (variance-of-lagged-differences fit) for regime detection.
- **DistanceSsd** — Gatev sum-of-squared-deviations between two start-normalised series.
- **BetaNeutralSpread** — rolling OLS regression residual `a − (α + β·b)`.
- **VarianceRatio** — Lo–MacKinlay variance-ratio test on the spread (two params: `period`, `q`).
- **GrangerCausality** — F-statistic for whether `b` predicts `a` (two params: `period`, `lag`).
**Struct output (custom bindings):**
- **KalmanHedgeRatio** — dynamic hedge ratio via a Kalman filter → `{ hedgeRatio, intercept, spread }`.
- **SpreadBollingerBands** — Bollinger bands on the spread → `{ middle, upper, lower, percentB }`.
## Notes
- No new traits or input families: all use the native `Indicator<Input = (f64, f64)>` (precedent `Beta`, `Cointegration`).
- Adds `Error::InvalidParameter` for floating-point constructor parameters (Kalman `delta`/`observation_var`, `num_std`).
- Full Python/Node/WASM bindings; the two struct-output indicators are hand-written, the rest use the pair macros.
- Indicator count 315 → 325; README, family rows, `__init__`, fuzz target, and CHANGELOG updated.
## Verification
- `cargo test --workspace --all-features` — green (2676 core lib + 308 doc).
- `cargo clippy --workspace --all-targets --all-features -- -D warnings` — clean.
- Node: `npm run build && npm test` — 410 passing (`index.d.ts`/`index.js` regenerated).
- Python: `pytest` — 684 passing.
74 lines
3.4 KiB
Rust
74 lines
3.4 KiB
Rust
//! Error types used across `wickra-core`.
|
|
|
|
use thiserror::Error;
|
|
|
|
/// Errors that can occur when constructing or operating on an indicator.
|
|
#[derive(Debug, Clone, PartialEq, Eq, Error)]
|
|
pub enum Error {
|
|
/// A period (window length) must be at least one.
|
|
#[error("period must be greater than zero")]
|
|
PeriodZero,
|
|
|
|
/// A specific minimum period requirement was not met (e.g. MACD needs slow > fast).
|
|
#[error("invalid period: {message}")]
|
|
InvalidPeriod { message: &'static str },
|
|
|
|
/// A non-finite value (NaN or infinity) was passed where a finite price was expected.
|
|
#[error("input value must be finite (got NaN or infinity)")]
|
|
NonFiniteInput,
|
|
|
|
/// A candle whose components do not form a valid bar (e.g. high < low) was provided.
|
|
#[error("invalid candle: {message}")]
|
|
InvalidCandle { message: &'static str },
|
|
|
|
/// A tick whose components do not satisfy the tick invariants (e.g. negative
|
|
/// volume) was provided. Ticks are a different concept from candles and
|
|
/// surface as their own variant so consumers of a tick-stream pipeline
|
|
/// can match on a semantically-correct error instead of `InvalidCandle`.
|
|
#[error("invalid tick: {message}")]
|
|
InvalidTick { message: &'static str },
|
|
|
|
/// A multiplier or factor must be strictly positive.
|
|
#[error("multiplier must be greater than zero")]
|
|
NonPositiveMultiplier,
|
|
|
|
/// An order-book snapshot whose levels do not satisfy the book invariants
|
|
/// (e.g. a crossed book, non-finite price, negative size, or mis-sorted
|
|
/// levels) was provided. Order books are a microstructure input distinct
|
|
/// from candles and ticks, so they surface as their own variant.
|
|
#[error("invalid order book: {message}")]
|
|
InvalidOrderBook { message: &'static str },
|
|
|
|
/// A trade whose components do not satisfy the trade invariants (e.g.
|
|
/// non-finite price or negative size) was provided.
|
|
#[error("invalid trade: {message}")]
|
|
InvalidTrade { message: &'static str },
|
|
|
|
/// A derivatives tick whose components do not satisfy the tick invariants
|
|
/// (e.g. a non-positive price, a non-finite funding rate, or a negative
|
|
/// size/volume/liquidation) was provided. Derivatives ticks (funding /
|
|
/// open-interest / liquidation feeds) are a perpetual-futures input
|
|
/// distinct from candles, order books and trades, so they surface as their
|
|
/// own variant.
|
|
#[error("invalid derivatives tick: {message}")]
|
|
InvalidDerivatives { message: &'static str },
|
|
|
|
/// A market-breadth cross-section whose members do not satisfy the
|
|
/// cross-section invariants (an empty universe, a non-finite change, or a
|
|
/// negative / non-finite volume) was provided. A cross-section is a
|
|
/// breadth input distinct from candles, ticks, order books and trades, so
|
|
/// it surfaces as its own variant.
|
|
#[error("invalid cross-section: {message}")]
|
|
InvalidCrossSection { message: &'static str },
|
|
|
|
/// A real-valued configuration parameter was outside its admissible range
|
|
/// (e.g. a non-positive standard-deviation multiplier, or a Kalman filter
|
|
/// covariance that is not strictly positive). This is the floating-point
|
|
/// analogue of [`Error::InvalidPeriod`], which only covers integer windows.
|
|
#[error("invalid parameter: {message}")]
|
|
InvalidParameter { message: &'static str },
|
|
}
|
|
|
|
/// Convenience alias for `Result<T, wickra_core::Error>`.
|
|
pub type Result<T> = core::result::Result<T, Error>;
|