wickra_core/indicators/
funding_rate.rs1use crate::derivatives::DerivativesTick;
4use crate::traits::Indicator;
5
6#[derive(Debug, Clone, Default)]
35pub struct FundingRate {
36 has_emitted: bool,
37}
38
39impl FundingRate {
40 #[must_use]
42 pub const fn new() -> Self {
43 Self { has_emitted: false }
44 }
45}
46
47impl Indicator for FundingRate {
48 type Input = DerivativesTick;
49 type Output = f64;
50
51 fn update(&mut self, tick: DerivativesTick) -> Option<f64> {
52 self.has_emitted = true;
53 Some(tick.funding_rate)
54 }
55
56 fn reset(&mut self) {
57 self.has_emitted = false;
58 }
59
60 fn warmup_period(&self) -> usize {
61 1
62 }
63
64 fn is_ready(&self) -> bool {
65 self.has_emitted
66 }
67
68 fn name(&self) -> &'static str {
69 "FundingRate"
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::traits::BatchExt;
77
78 fn tick(funding_rate: f64) -> DerivativesTick {
79 DerivativesTick::new_unchecked(
80 funding_rate,
81 100.0,
82 100.0,
83 100.0,
84 0.0,
85 0.0,
86 0.0,
87 0.0,
88 0.0,
89 0.0,
90 0.0,
91 0,
92 )
93 }
94
95 #[test]
96 fn accessors_and_metadata() {
97 let fr = FundingRate::new();
98 assert_eq!(fr.name(), "FundingRate");
99 assert_eq!(fr.warmup_period(), 1);
100 assert!(!fr.is_ready());
101 }
102
103 #[test]
104 fn passes_through_funding_rate() {
105 let mut fr = FundingRate::new();
106 assert_eq!(fr.update(tick(0.0001)), Some(0.0001));
107 assert_eq!(fr.update(tick(-0.0003)), Some(-0.0003));
108 assert!(fr.is_ready());
109 }
110
111 #[test]
112 fn batch_equals_streaming() {
113 let ticks: Vec<DerivativesTick> =
114 (0..20).map(|i| tick(0.0001 * f64::from(i - 10))).collect();
115 let mut a = FundingRate::new();
116 let mut b = FundingRate::new();
117 assert_eq!(
118 a.batch(&ticks),
119 ticks.iter().map(|x| b.update(*x)).collect::<Vec<_>>()
120 );
121 }
122
123 #[test]
124 fn reset_clears_state() {
125 let mut fr = FundingRate::new();
126 fr.update(tick(0.0001));
127 assert!(fr.is_ready());
128 fr.reset();
129 assert!(!fr.is_ready());
130 }
131}