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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use ;
use crate::;
use ExponentialMovingAverage;
/// # Moving Average Convergence Divergence
/// Container for Moving Average Convergence Divergence (MACD) aggregation
///
/// The aggregation will begin producing values immediately, the first value
/// will be zero as both EMAs will use the input as the first value, after
/// which the following formula is applied:
/// <br>
/// <br>
/// <math display="block" style="font-size: 20px;">
/// <semantics>
/// <mrow>
/// <msub>
/// <mi>o</mi>
/// <mn>n</mn>
/// </msub>
/// <mo>=</mo>
/// <mrow>
/// <msub>
/// <mi>EMA</mi>
/// <mn>S</mn>
/// </msub>
/// <mo>(</mo>
/// <msub>
/// <mi>i</mi>
/// <mn>n</mn>
/// </msub>
/// <mo>)</mo>
/// <mo>-</mo>
/// <msub>
/// <mi>EMA</mi>
/// <mn>L</mn>
/// </msub>
/// <mo>(</mo>
/// <msub>
/// <mi>i</mi>
/// <mn>n</mn>
/// </msub>
/// <mo>)</mo>
/// </mrow>
/// </mrow>
/// </semantics>
/// </math>
/// <br>
/// Where `o` is the output, `n` is the current step, `EMA` is the Exponential Moving Average, `S` is the short period, `L` is the long period and `i` is the input.
///
/// _NB._ This will not produce a signal line, you will need to produce your own signal line from the MACD output.
///
/// # Example Usage
/// ```
/// use indicato_rs::signals::MovingAverageConvergenceDivergence;
/// use indicato_rs::traits::{Apply, Evaluate, Current};
///
/// #[macro_use]
/// use approx::assert_abs_diff_eq;
///
/// let mut macd = MovingAverageConvergenceDivergence::new(2, 4).unwrap();
///
/// // apply some values and check their output
/// assert_eq!(macd.apply(3.0), 0.0);
/// assert_abs_diff_eq!(macd.apply(4.8), 0.48, epsilon = 10e-7);
/// assert_abs_diff_eq!(macd.apply(6.3), 0.848, epsilon = 10e-7);
/// assert_abs_diff_eq!(macd.apply(5.0), 0.3488, epsilon = 10e-7);
///
/// // evaluate some values, these won't affect the internal state of the MACD
/// assert_abs_diff_eq!(macd.evaluate(10.0), 1.48928, epsilon = 10e-7);
///
/// // fetch the current value of the MACD
/// assert_abs_diff_eq!(macd.current(), 0.3488, epsilon = 10e-7);
/// ```