pub struct PairSpreadZScore { /* private fields */ }Expand description
Z-score of the log-spread ln(a) − β·ln(b) between two assets.
This is the canonical mean-reversion / statistical-arbitrage signal for a
pair. Each update receives one (a, b) pair of raw prices and the
indicator does two things:
- Hedge ratio. A rolling ordinary-least-squares regression of
ln(a)onln(b)over the trailingbeta_periodsamples gives the slopeβ = cov(ln a, ln b) / var(ln b). The instantaneous spread is the residual against the origin,s = ln(a) − β·ln(b). - Standardisation. The spread is then z-scored over the trailing
z_periodspreads:z = (s − mean_s) / std_s.
A large positive z means a is rich relative to b (sell the spread); a
large negative z means a is cheap (buy the spread); z near zero means
the pair is at its typical relationship. The two windows are independent:
beta_period controls how much history the hedge ratio adapts over, and
z_period controls the look-back for the mean and dispersion of the spread.
Each update is O(1): five running sums maintain the rolling OLS and two
more maintain the rolling spread mean/variance. A flat ln(b) window has
zero variance and the hedge ratio is undefined; β is then taken as 0,
reducing the spread to ln(a). A flat spread window (zero dispersion)
yields a z-score of 0 rather than NaN.
Prices must be strictly positive and finite for the logarithm to be defined; a non-positive or non-finite price is skipped (it does not enter either window), exactly as a real feed would discard a bad tick.
§Example
use wickra_core::{Indicator, PairSpreadZScore};
let mut zs = PairSpreadZScore::new(2, 2).unwrap();
// A flat benchmark gives hedge ratio 0, so the spread is just ln(a); with
// a 2-sample z-window the z-score collapses to the sign of the last move.
let mut last = None;
for a in [100.0, 100.0, 110.0, 120.0] {
last = zs.update((a, 100.0));
}
assert!((last.unwrap() - 1.0).abs() < 1e-9);Implementations§
Source§impl PairSpreadZScore
impl PairSpreadZScore
Sourcepub fn new(beta_period: usize, z_period: usize) -> Result<Self>
pub fn new(beta_period: usize, z_period: usize) -> Result<Self>
Construct a new pair spread z-score.
beta_period is the look-back for the rolling hedge ratio; z_period
is the look-back for standardising the spread.
§Errors
Returns Error::InvalidPeriod if either period is below 2
(variance needs at least two points).
Sourcepub const fn beta_period(&self) -> usize
pub const fn beta_period(&self) -> usize
Look-back of the rolling hedge-ratio regression.
Trait Implementations§
Source§impl Clone for PairSpreadZScore
impl Clone for PairSpreadZScore
Source§fn clone(&self) -> PairSpreadZScore
fn clone(&self) -> PairSpreadZScore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PairSpreadZScore
impl Debug for PairSpreadZScore
Source§impl Indicator for PairSpreadZScore
impl Indicator for PairSpreadZScore
Source§fn update(&mut self, input: (f64, f64)) -> Option<f64>
fn update(&mut self, input: (f64, f64)) -> Option<f64>
None if the indicator is still warming up.Source§fn reset(&mut self)
fn reset(&mut self)
Source§fn warmup_period(&self) -> usize
fn warmup_period(&self) -> usize
None output can be produced.Auto Trait Implementations§
impl Freeze for PairSpreadZScore
impl RefUnwindSafe for PairSpreadZScore
impl Send for PairSpreadZScore
impl Sync for PairSpreadZScore
impl Unpin for PairSpreadZScore
impl UnsafeUnpin for PairSpreadZScore
impl UnwindSafe for PairSpreadZScore
Blanket Implementations§
Source§impl<T> BatchExt for Twhere
T: Indicator,
impl<T> BatchExt for Twhere
T: Indicator,
Source§fn batch(&mut self, inputs: &[Self::Input]) -> Vec<Option<Self::Output>>
fn batch(&mut self, inputs: &[Self::Input]) -> Vec<Option<Self::Output>>
None during warmup) per input.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more