quantaxis_rs/
qaindicator.rs

1
2// use std::f64::NAN;
3
4
5// use ndarray;
6// use ndarray::prelude::*;
7// use std::iter::FromIterator;
8
9
10// #[derive(Debug)]
11// pub enum Err {
12//     NotEnoughtData, // not enought data to compute requested values
13// }
14
15
16// pub fn round_array(array: &mut [f64], decimals: u8) {
17//     let divider = (10.0 as f64).powi(decimals as i32);
18//     for number in array {
19//         *number = (*number * divider).round() / divider;
20//     }
21// }
22
23
24
25
26// //pub fn HHV(data: &[f64], period: usize) -> Result<Vec<f64>, Err> {
27// //    if length <= 0 {
28// //        return Err(Err::NotEnoughtData);
29// //    }
30// //
31// //    let highest = source.get(0);
32// //
33// //    if highest.is_none() {
34// //        return Err(Err::NotEnoughtData);
35// //    }
36// //
37// //    let mut highest = highest.unwrap();
38// //
39// //    for index in 1..(length) {
40// //        match source.get(index) {
41// //            None => {}
42// //            Some(maybe_highest) => {
43// //                if maybe_highest > highest {
44// //                    highest = maybe_highest;
45// //                }
46// //            }
47// //        }
48// //    }
49// //
50// //    Ok(highest)
51// //}
52// //
53
54// pub fn ema(data: &[f64], period: usize) -> Result<Vec<f64>, Err> {
55//     if period > data.len() {
56//         return Err(Err::NotEnoughtData);
57//     }
58//     let mut ema = Vec::new();
59//     let mut j = 1;
60
61//     // get period sma first and calculate the next period period ema
62//     let sma = (data[0..period])
63//                         .iter()
64//                         .sum::<f64>() / period as f64;
65//     let multiplier: f64 = 2.0 / (1.0 + period as f64);
66//     ema.push(sma);
67
68//     // EMA(current) = ( (Price(current) - EMA(prev) ) x Multiplier) + EMA(prev)
69//     ema.push(((data[period] - sma) * multiplier) + sma);
70
71//     // now calculate the rest of the values
72//     for i in &data[period + 1..data.len()] {
73//         println!("{:#?}", i);
74//         let tmp = ((*i - ema[j]) * multiplier) + ema[j];
75//         j = j + 1;
76//         ema.push(tmp);
77//     }
78
79//     Ok(ema)
80// }
81
82// pub fn sma(data: &[f64], period: usize) -> Result<Vec<f64>, Err> {
83//     if period > data.len() {
84//         return Err(Err::NotEnoughtData);
85//     }
86
87//     let mut result = Vec::new();
88//     let mut running_total = 0.0;
89
90//     for i in 0..data.len() {
91//         running_total += data[i];
92//         if i >= period {
93//             running_total -= data[i - period];
94//         }
95//         if i >= period - 1 {
96//             result.push(running_total / period as f64);
97//         }
98//     }
99//     Ok(result)
100// }
101
102
103// pub fn psar(high: &[f64], low: &[f64], iaf: f64, maxaf: f64) -> Result<Vec<f64>, Err> {
104//     let mut psar = vec![NAN; high.len()];
105
106//     if high.len() < 2 {
107//         return Err(Err::NotEnoughtData);
108//     };
109
110//     let mut long = false;
111//     if high[0] + low[0] <= high[1] + low[1] {
112//         long = true;
113//     }
114
115//     let mut sar;
116//     let mut extreme;
117
118//     if long {
119//         extreme = high[0];
120//         sar = low[0];
121//     } else {
122//         extreme = low[0];
123//         sar = high[0];
124//     }
125
126//     psar[0] = sar;
127
128//     let mut af = iaf;
129
130//     for i in 1..high.len() {
131//         sar = (extreme - sar) * af + sar;
132
133//         if long {
134//             if i >= 2 && (sar > low[i - 2]) {
135//                 sar = low[i - 2]
136//             };
137//             if sar > low[i - 1] {
138//                 sar = low[i - 1]
139//             };
140
141//             if af < maxaf && high[i] > extreme {
142//                 af += iaf;
143//                 if af > maxaf {
144//                     af = maxaf
145//                 };
146//             }
147
148//             if high[i] > extreme {
149//                 extreme = high[i];
150//             }
151//         } else {
152//             if i >= 2 && sar < high[i - 2] {
153//                 sar = high[i - 2]
154//             };
155//             if sar < high[i - 1] {
156//                 sar = high[i - 1]
157//             };
158
159//             if af < maxaf && low[i] < extreme {
160//                 af += iaf;
161//                 if af > maxaf {
162//                     af = maxaf
163//                 };
164//             }
165
166//             if low[i] < extreme {
167//                 extreme = low[i]
168//             };
169//         }
170
171//         if long && low[i] < sar || !long && high[i] > sar {
172//             af = iaf;
173//             sar = extreme;
174
175//             long = !long;
176
177//             if !long {
178//                 extreme = low[i];
179//             } else {
180//                 extreme = high[i];
181//             }
182//         }
183
184//         psar[i] = sar;
185//     }
186
187//     Ok(psar)
188// }
189
190
191// pub fn rsi(data: &[f64], period: usize) -> Result<Vec<f64>, Err> {
192//     if period > data.len() {
193//         return Err(Err::NotEnoughtData);
194//     }
195
196//     let mut changes = Vec::new();
197//     for i in 0..data.len() - 1 {
198//         let change = data[i + 1] - data[i];
199//         changes.push(change);
200//     }
201
202//     let rsi_range = data.len() - period;
203
204//     let mut rsis = vec![NAN ; rsi_range];
205
206//     // gains & losses
207//     let mut gains = Vec::new();
208//     let mut losses = Vec::new();
209
210//     for i in 0..changes.len() {
211//         if changes[i] > 0.0 {
212//             gains.push(changes[i]);
213//             losses.push(0.0);
214//         } else if changes[i] < 0.0 {
215//             losses.push(changes[i] * -1.0);
216//             gains.push(0.0);
217//         } else {
218//             gains.push(0.0);
219//             losses.push(0.0);
220//         }
221//     }
222
223//     let mut avg_gain: f64 = gains[..period].iter().sum::<f64>() / gains[..period].len() as f64;
224//     let mut avg_loss: f64 = losses[..period].iter().sum::<f64>() / losses[..period].len() as f64;
225
226//     if avg_loss == 0.0 {
227//         rsis[0] = 100.0;
228//     } else {
229//         let rs = avg_gain / avg_loss;
230//         rsis[0] = 100.0 - (100.0 / (1.0 + rs));
231//     }
232
233//     for i in 1..rsi_range {
234//         avg_gain = (avg_gain * (period - 1) as f64 + gains[i + (period - 1)]) / period as f64;
235//         avg_loss = (avg_loss * (period - 1) as f64 + losses[i + (period - 1)]) / period as f64;
236
237//         if avg_loss == 0.0 {
238//             rsis[i] = 100.0;
239//         } else {
240//             let rs = avg_gain / avg_loss;
241//             rsis[i] = 100.0 - (100.0 / (1.0 + rs));
242//         }
243//     }
244
245//     Ok(rsis)
246// }
247
248
249
250
251// // Some randomly generated data to test against TA-Lib (see generate_data.py & correct_values.py)
252// const OPEN: &[f64] = &[1984.03, 1959.83, 2041.42, 2019.04, 1969.53, 2082.75, 2209.52, 2200.9,
253//     2364.04, 2543.32, 2423.95, 2483.28, 2604.88, 2393.81, 2231.27, 2420.82,
254//     2544.0, 2766.67, 2919.62, 2763.25];
255// const HIGH: &[f64] = &[2174.72, 2129.49, 2158.92, 2050.2, 2042.12, 2151.19, 2220.64, 2352.98,
256//     2456.25, 2691.53, 2572.81, 2494.14, 2845.93, 2682.66, 2527.13, 2455.68,
257//     2607.54, 2872.17, 3004.26, 3036.05];
258// const LOW: &[f64] = &[1934.7, 1921.02, 1793.77, 1887.36, 1919.72, 1868.23, 1991.19, 2011.08,
259//     2193.91, 2183.96, 2223.15, 2363.19, 2240.03, 2208.31, 2192.15, 2199.02,
260//     2311.16, 2463.15, 2651.8, 2749.42];
261// const CLOSE: &[f64] = &[1959.83, 2041.42, 2019.04, 1969.53, 2082.75, 2209.52, 2200.9, 2364.04,
262//     2543.32, 2423.95, 2483.28, 2604.88, 2393.81, 2231.27, 2420.82, 2544.0,
263//     2766.67, 2919.62, 2763.25, 2922.14];
264
265
266// #[test]
267// fn sma_works() {
268//     let mut result = sma(CLOSE, 4).unwrap();
269//     let expected = &[1997.455, 2028.185, 2070.21, 2115.675, 2214.3025, 2329.445, 2383.0525,
270//         2453.6475, 2513.8575, 2476.48, 2428.31, 2412.695, 2397.475, 2490.69,
271//         2662.7775, 2748.385, 2842.92];
272//     round_array(result.as_mut(), 4);
273//     assert_eq!(result, expected);
274// }
275
276// #[test]
277// fn ema_works() {
278//     let mut result = ema(CLOSE, 4).unwrap();
279//     let expected = &[1997.455, 2031.573, 2102.7518, 2142.0111, 2230.8226, 2355.8216, 2383.073,
280//         2423.1558, 2495.8455, 2455.0313, 2365.5268, 2387.6441, 2450.1864, 2576.7799,
281//         2713.9159, 2733.6496, 2809.0457];
282//     round_array(result.as_mut(), 4);
283//     assert_eq!(result, expected);
284// }
285
286// #[test]
287// fn psar_works() {
288//     let mut result = psar(HIGH, LOW, 0.02, 0.2).unwrap();
289//     let expected = &[2174.72, 2169.646, 2158.92, 2158.92, 1793.77, 1800.9184, 1817.7073,
290//         1849.8236, 1898.3377, 1977.657, 2049.0443, 2113.2928, 2201.2093, 2845.93,
291//         2832.8544, 2820.0403, 2192.15, 2205.7504, 2237.6908];
292//     round_array(result.as_mut(), 4);
293//     // For some reasons, the first values are not exactly the same but since this indicator
294//     // was not clearly described by its author, we can say that current implementation is correct.
295//     assert_eq!(result[result.len() - 16..result.len()],
296//                expected[expected.len() - 16..expected.len()]);
297// }
298
299// #[test]
300// fn rsi_works() {
301//     let mut result = rsi(CLOSE, 6).unwrap();
302//     let expected = &[79.9771, 86.5336, 90.5949, 73.0035, 75.8056, 80.7258, 56.706, 44.4766,
303//         57.3488, 63.879, 72.8847, 77.5072, 64.1009, 70.3536];
304//     round_array(result.as_mut(), 4);
305//     assert_eq!(result, expected);
306// }