br_maths/
ma.rs

1use json::{array, JsonValue};
2
3/// 简单移动平均 SMA
4/// 移动平均
5///
6/// * data 数据列表
7/// * n 统计周期
8/// * value 返回结果值 或者列表
9pub fn sma(data: JsonValue, n: usize, decimal: usize) -> JsonValue {
10    let mut list = vec![];
11    let mut value = vec![];
12    for item in data.members() {
13        let i = item.as_f64().unwrap();
14        list.push(i);
15        if list.len() == n {
16            let res: f64 = list.iter().sum();
17            let v = res / n as f64;
18            let v = format!("{:.1$}", v, decimal).parse::<f64>().unwrap();
19            value.push(v);
20            list.remove(0);
21        } else {
22            value.push(0.0);
23        }
24    }
25    value.into()
26}
27
28/// 加权移动平均
29///
30/// * data 计算数据组
31/// * n 移动周期
32/// * decimal 小数位
33/// ````rust
34/// use json::array;
35/// use br_maths::ma;
36/// let data = array![38,45,35,49,70,43,46,55,45,68,64];
37/// let res = ma::wma(data, 3, 2);
38/// ````
39pub fn wma(data: JsonValue, n: usize, decimal: usize) -> JsonValue {
40    let mut list = array![];
41    let mut index = 1;
42    for _ in data.members() {
43        let mut x = 0.0;
44        let mut a = 0.0;
45        let y = {
46            if index >= n {
47                for i in 0..n {
48                    x += data[(index - n) + i].as_f64().unwrap() * (i as f64 + 1.0);
49                    a += i as f64 + 1.0;
50                }
51                x / a
52            } else {
53                0.0
54            }
55        };
56        index += 1;
57        let y = format!("{:.1$}", y, decimal).parse::<f64>().unwrap();
58        list.push(y).unwrap();
59    }
60    list
61}
62
63
64/// 指数移动平均 EMA
65///
66/// * data 数据列表
67/// * n 统计周期
68/// * decimal 小数位
69/// * alpha 指数
70pub fn ema(data: JsonValue, n: usize, decimal: usize, mut alpha: f64) -> JsonValue {
71    let mut list = vec![];
72    let mut value = vec![];
73
74    if alpha == 0.0 {
75        alpha = 2f64 / (n as f64 + 1.0);
76    }
77    for item in data.members() {
78        list.push(item.as_f64().unwrap());
79        if list.len() >= n {
80            let mut nn = list.len() as f64;
81            let fz: f64 = list.iter().map(|x| {
82                let t = if nn - 1.0 == 0.0 {
83                    *x
84                } else {
85                    (1.0 - alpha).powf(nn - 1.0) * x
86                };
87                nn -= 1.0;
88                t
89            }).sum();
90            let mut nn = list.len() as f64;
91            let fm: f64 = list.iter().map(|_x| {
92                let t = if nn - 1.0 == 0.0 {
93                    1.0
94                } else {
95                    (1.0 - alpha).powf(nn - 1.0)
96                };
97                nn -= 1.0;
98                t
99            }).sum();
100            let v = fz / fm;
101            let v = format!("{:.1$}", v, decimal).parse::<f64>().unwrap();
102            value.push(v);
103        } else {
104            value.push(0.0);
105        }
106    }
107    value.into()
108}
109
110
111/// 指数平滑移动平均 EXPMEMA
112///
113/// * data 数据列表
114/// * n 阻尼系数 区间 [0,1]
115pub fn expmema(data: JsonValue, n: f64) -> JsonValue {
116    let mut index = 0.0;
117    let mut y = 0.0;
118    let mut list = array![];
119    for item in data.members() {
120        let x = item.as_f64().unwrap();
121        if index == 0.0 {
122            y = x * (1.0 - n) + 0.0 * n;
123            list.push(y).unwrap();
124        } else {
125            let x = data[(index) as usize].as_f64().unwrap();
126            y = x * (1.0 - n) + y * n;
127            list.push(y).unwrap();
128        }
129        index += 1.0;
130    }
131    list
132}
133
134/// 修正指数移动平均 XEXPMEMA
135///
136/// * data 数据列表
137/// * n 阻尼系数 区间 [0,1]
138pub fn xexpmema(data: JsonValue, n: f64) -> JsonValue {
139    let mut index = 0.0;
140    let mut list = array![];
141    for item in data.members() {
142        let x = item.as_f64().unwrap();
143        if index == 0.0 {
144            list.push(x).unwrap();
145        } else {
146            let y = x / (1.0 - n.powf(index + 1.0));
147            list.push(y).unwrap();
148        }
149        index += 1.0;
150    }
151    list
152}