feat: derivatives funding & open-interest indicators (part 1 of 3) (#126)
* feat(derivatives): DerivativesTick input type + InvalidDerivatives error * feat(derivatives): FundingRate indicator (core) * feat(derivatives): FundingRateMean indicator (core) * feat(derivatives): FundingRateZScore indicator (core) * feat(derivatives): FundingBasis indicator (core) * feat(derivatives): OpenInterestDelta indicator (core) * feat(derivatives): Python, Node and WASM bindings for funding & OI-delta indicators * test(derivatives): Python and Node tests for funding & OI-delta indicators * bench(derivatives): synthetic-tick bench + derivatives fuzz target * docs(derivatives): README family row + counter 232->237, CHANGELOG entry
This commit is contained in:
@@ -73,6 +73,13 @@ test = false
|
||||
doc = false
|
||||
bench = false
|
||||
|
||||
[[bin]]
|
||||
name = "indicator_update_derivatives"
|
||||
path = "fuzz_targets/indicator_update_derivatives.rs"
|
||||
test = false
|
||||
doc = false
|
||||
bench = false
|
||||
|
||||
[[bin]]
|
||||
name = "tick_aggregator"
|
||||
path = "fuzz_targets/tick_aggregator.rs"
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#![no_main]
|
||||
//! Fuzz derivatives `Indicator<Input = DerivativesTick>` implementations with
|
||||
//! arbitrary perpetual / futures tick streams.
|
||||
//!
|
||||
//! Each iteration consumes a byte stream, interprets it as a sequence of `f64`
|
||||
//! values (8 bytes each), and packs consecutive groups of eleven into a
|
||||
//! [`DerivativesTick`]'s numeric fields. Ticks are built with `new_unchecked`
|
||||
//! so the fuzzer can explore degenerate values (non-finite, negative, zero
|
||||
//! prices) that the validating constructor would reject — the indicators must
|
||||
//! never panic, streaming or batched.
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use wickra_core::{
|
||||
BatchExt, DerivativesTick, FundingBasis, FundingRate, FundingRateMean, FundingRateZScore,
|
||||
Indicator, OpenInterestDelta,
|
||||
};
|
||||
|
||||
#[inline(never)]
|
||||
fn drive<I>(make: impl Fn() -> I, ticks: &[DerivativesTick])
|
||||
where
|
||||
I: Indicator<Input = DerivativesTick, Output = f64> + BatchExt,
|
||||
{
|
||||
let mut streaming = make();
|
||||
for &tick in ticks {
|
||||
let _ = streaming.update(tick);
|
||||
}
|
||||
let _ = make().batch(ticks);
|
||||
}
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let floats: Vec<f64> = data
|
||||
.chunks_exact(8)
|
||||
.map(|c| f64::from_le_bytes(c.try_into().expect("8 bytes")))
|
||||
.collect();
|
||||
let ticks: Vec<DerivativesTick> = floats
|
||||
.chunks_exact(11)
|
||||
.map(|c| {
|
||||
DerivativesTick::new_unchecked(
|
||||
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], 0,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
drive(FundingRate::new, &ticks);
|
||||
drive(|| FundingRateMean::new(5).unwrap(), &ticks);
|
||||
drive(|| FundingRateZScore::new(5).unwrap(), &ticks);
|
||||
drive(FundingBasis::new, &ticks);
|
||||
drive(OpenInterestDelta::new, &ticks);
|
||||
});
|
||||
Reference in New Issue
Block a user