1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use ta_common::fixed_queue::FixedQueue;
use ta_common::traits::Indicator;
use ta_common::math::min::Min;
use ta_common::math::max::Max;
pub struct Fisher {
period: u32,
history: FixedQueue<[f64; 2]>,
min: Min,
max: Max,
prev_val: f64,
prev_fischer: f64,
}
impl Fisher {
pub fn new(period: u32) -> Fisher {
Self {
period,
history: FixedQueue::new(period),
max: Max::new(period),
min: Min::new(period),
prev_val: 0.0,
prev_fischer: 0.0,
}
}
}
impl Indicator<[f64; 2], Option<[f64; 2]>> for Fisher {
fn next(&mut self, input: [f64; 2]) -> Option<[f64; 2]> {
let [high, low] = input;
self.history.add(input);
let avg = (high + low) / 2.0;
let min = self.min.next(avg);
let max = self.max.next(avg);
return if self.history.is_full() {
let min = min.unwrap();
let max = max.unwrap();
let mut diff = max - min;
if diff == 0.0 {
diff = 0.001;
}
let mut val = 0.66 * (((avg - min) / diff) - 0.5) + 0.67 * self.prev_val;
let temp = (1.0 + val) / (1.0 - val);
let fisher = 0.5 * temp.ln() + 0.5 * self.prev_fischer;
let result = [fisher, self.prev_fischer];
self.prev_val = val;
self.prev_fischer = fisher;
Some(result)
} else {
None
};
}
fn reset(&mut self) {
self.history.reset();
self.max.reset();
self.min.reset();
self.prev_val=0.0;
self.prev_fischer=0.0;
}
}
#[cfg(test)]
mod tests {
use crate::Fisher;
use ta_common::traits::Indicator;
#[test]
fn it_works() {
let mut fisher = Fisher::new(5);
assert_eq!(fisher.next([82.15, 81.29]), None);
assert_eq!(fisher.next([81.89, 80.64]), None);
assert_eq!(fisher.next([83.03, 81.31]), None);
assert_eq!(fisher.next([83.30, 82.65]), None);
assert_eq!(fisher.next([83.85, 83.07]), Some([0.34282825441539394, 0.0]));
assert_eq!(fisher.next([83.90, 83.11]), Some([0.7913738721291064, 0.34282825441539394]));
assert_eq!(fisher.next([83.33, 82.49]), Some([0.8253978616040214, 0.7913738721291064]));
assert_eq!(fisher.next([84.30, 82.30]), Some([0.8057742927742315, 0.8253978616040214]));
assert_eq!(fisher.next([84.84, 84.15]), Some([1.0662328466080955, 0.8057742927742315]));
assert_eq!(fisher.next([85.00, 84.11]), Some([1.4386723332736164, 1.0662328466080955]));
assert_eq!(fisher.next([85.90, 84.03]), Some([1.851401398210955, 1.4386723332736164]));
assert_eq!(fisher.next([86.58, 85.39]), Some([2.274864111876407, 1.851401398210955]));
assert_eq!(fisher.next([86.98, 85.76]), Some([2.697820152019159, 2.274864111876407]));
assert_eq!(fisher.next([88.00, 87.17]), Some([3.1167647415593853, 2.697820152019159]));
assert_eq!(fisher.next([87.87, 87.01]), Some([3.1846885349584984, 3.1167647415593853]));
}
}