quantaxis_rs/indicators/
rate_of_change.rs1use std::collections::VecDeque;
2use std::fmt;
3
4use crate::errors::*;
5use crate::traits::{Close, Next, Reset};
6
7#[derive(Debug, Clone)]
41pub struct RateOfChange {
42 length: u32,
43 prices: VecDeque<f64>,
44}
45
46impl RateOfChange {
47 pub fn new(length: u32) -> Result<Self> {
48 match length {
49 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
50 _ => {
51 let indicator = Self {
52 length: length,
53 prices: VecDeque::with_capacity(length as usize + 1),
54 };
55 Ok(indicator)
56 }
57 }
58 }
59}
60
61impl Next<f64> for RateOfChange {
62 type Output = f64;
63
64 fn next(&mut self, input: f64) -> f64 {
65 self.prices.push_back(input);
66
67 if self.prices.len() == 1 {
68 return 0.0;
69 }
70
71 let initial_price = if self.prices.len() > (self.length as usize) {
72 self.prices.pop_front().unwrap()
75 } else {
76 self.prices[0]
77 };
78
79 (input - initial_price) / initial_price * 100.0
80 }
81}
82
83impl<'a, T: Close> Next<&'a T> for RateOfChange {
84 type Output = f64;
85
86 fn next(&mut self, input: &'a T) -> f64 {
87 self.next(input.close())
88 }
89}
90
91impl Default for RateOfChange {
92 fn default() -> Self {
93 Self::new(9).unwrap()
94 }
95}
96
97impl fmt::Display for RateOfChange {
98 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99 write!(f, "ROC({})", self.length)
100 }
101}
102
103impl Reset for RateOfChange {
104 fn reset(&mut self) {
105 self.prices.clear();
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use crate::test_helper::*;
113 macro_rules! test_indicator {
114 ($i:tt) => {
115 #[test]
116 fn test_indicator() {
117 let bar = Bar::new();
118
119 let mut indicator = $i::default();
121
122 let first_output = indicator.next(12.3);
124
125 indicator.next(&bar);
127
128 indicator.reset();
130 assert_eq!(indicator.next(12.3), first_output);
131
132 format!("{}", indicator);
134 }
135 };
136 }
137 test_indicator!(RateOfChange);
138
139 #[test]
140 fn test_new() {
141 assert!(RateOfChange::new(0).is_err());
142 assert!(RateOfChange::new(1).is_ok());
143 assert!(RateOfChange::new(100_000).is_ok());
144 }
145
146 #[test]
147 fn test_next_f64() {
148 let mut roc = RateOfChange::new(3).unwrap();
149
150 assert_eq!(round(roc.next(10.0)), 0.0);
151 assert_eq!(round(roc.next(10.4)), 4.0);
152 assert_eq!(round(roc.next(10.57)), 5.7);
153 assert_eq!(round(roc.next(10.8)), 8.0);
154 assert_eq!(round(roc.next(10.9)), 4.808);
155 assert_eq!(round(roc.next(10.0)), -5.393);
156 }
157
158 #[test]
159 fn test_next_bar() {
160 fn bar(close: f64) -> Bar {
161 Bar::new().close(close)
162 }
163
164 let mut roc = RateOfChange::new(3).unwrap();
165
166 assert_eq!(round(roc.next(&bar(10.0))), 0.0);
167 assert_eq!(round(roc.next(&bar(10.4))), 4.0);
168 assert_eq!(round(roc.next(&bar(10.57))), 5.7);
169 }
170
171 #[test]
172 fn test_reset() {
173 let mut roc = RateOfChange::new(3).unwrap();
174
175 roc.next(12.3);
176 roc.next(15.0);
177
178 roc.reset();
179
180 assert_eq!(round(roc.next(10.0)), 0.0);
181 assert_eq!(round(roc.next(10.4)), 4.0);
182 assert_eq!(round(roc.next(10.57)), 5.7);
183 }
184}