ux_indicators/indicators/
roc.rs1#![allow(dead_code)]
2
3use std::collections::VecDeque;
4use std::fmt;
5
6use crate::errors::*;
7use crate::traits::{Close, Next, Reset};
8
9use crate::{Factory};
10use crate::indicators::SimpleMovingAverage;
11
12pub struct RocFactory {
13}
14
15impl RocFactory {
16 pub fn new() -> Self {
17 Self{}
18 }
19}
20
21impl Factory for RocFactory {
22 fn create() -> Box<dyn Next<f64, Output = Box<[f64]>>> {
23 Box::new(SimpleMovingAverage::default())
24 }
25}
26
27#[derive(Debug, Clone)]
62pub struct RateOfChange {
63 length: u32,
64 prices: VecDeque<f64>,
65}
66
67impl RateOfChange {
68 pub fn new(length: u32) -> Result<Self> {
69 match length {
70 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
71 _ => {
72 let indicator = Self {
73 length: length,
74 prices: VecDeque::with_capacity(length as usize + 1),
75 };
76 Ok(indicator)
77 }
78 }
79 }
80}
81
82impl Next<f64> for RateOfChange {
83 type Output = f64;
84
85 fn next(&mut self, input: f64) -> f64 {
86 self.prices.push_back(input);
87
88 if self.prices.len() == 1 {
89 return 0.0;
90 }
91
92 let initial_price = if self.prices.len() > (self.length as usize) {
93 self.prices.pop_front().unwrap()
96 } else {
97 self.prices[0]
98 };
99
100 (input - initial_price) / initial_price * 100.0
101 }
102}
103
104impl<'a, T: Close> Next<&'a T> for RateOfChange {
105 type Output = f64;
106
107 fn next(&mut self, input: &'a T) -> f64 {
108 self.next(input.close())
109 }
110}
111
112impl Default for RateOfChange {
113 fn default() -> Self {
114 Self::new(9).unwrap()
115 }
116}
117
118impl fmt::Display for RateOfChange {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 write!(f, "ROC({})", self.length)
121 }
122}
123
124impl Reset for RateOfChange {
125 fn reset(&mut self) {
126 self.prices.clear();
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 use crate::test_helper::*;
134
135 #[test]
138 fn test_new() {
139 assert!(RateOfChange::new(0).is_err());
140 assert!(RateOfChange::new(1).is_ok());
141 assert!(RateOfChange::new(100_000).is_ok());
142 }
143
144 #[test]
145 fn test_next_f64() {
146 let mut roc = RateOfChange::new(3).unwrap();
147
148 assert_eq!(round(roc.next(10.0)), 0.0);
149 assert_eq!(round(roc.next(10.4)), 4.0);
150 assert_eq!(round(roc.next(10.57)), 5.7);
151 assert_eq!(round(roc.next(10.8)), 8.0);
152 assert_eq!(round(roc.next(10.9)), 4.808);
153 assert_eq!(round(roc.next(10.0)), -5.393);
154 }
155
156 #[test]
157 fn test_next_bar() {
158 fn bar(close: f64) -> Bar {
159 Bar::new().close(close)
160 }
161
162 let mut roc = RateOfChange::new(3).unwrap();
163
164 assert_eq!(round(roc.next(&bar(10.0))), 0.0);
165 assert_eq!(round(roc.next(&bar(10.4))), 4.0);
166 assert_eq!(round(roc.next(&bar(10.57))), 5.7);
167 }
168
169 #[test]
170 fn test_reset() {
171 let mut roc = RateOfChange::new(3).unwrap();
172
173 roc.next(12.3);
174 roc.next(15.0);
175
176 roc.reset();
177
178 assert_eq!(round(roc.next(10.0)), 0.0);
179 assert_eq!(round(roc.next(10.4)), 4.0);
180 assert_eq!(round(roc.next(10.57)), 5.7);
181 }
182}