第一版

This commit is contained in:
YuWuKunCheng
2026-05-25 02:16:35 +08:00
parent ff4e6ae570
commit f92eef11fb
37 changed files with 11615 additions and 0 deletions
+149
View File
@@ -0,0 +1,149 @@
use serde::{Deserialize, Serialize};
/// 平滑异同移动平均线 (MACD)
///
/// 使用 EMA 递推算法进行增量计算
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct 线 {
pub : i64,
pub : f64,
pub 线: i64,
pub 线: i64,
pub : i64,
pub DIF: Option<f64>,
pub DEA: Option<f64>,
#[serde(rename = "MACD柱")]
#[serde(default)]
pub MACD柱: f64,
pub 线EMA: Option<f64>,
pub 线EMA: Option<f64>,
pub DEA_EMA: Option<f64>,
}
impl Default for 线 {
fn default() -> Self {
Self {
: 0,
: 0.0,
线: 12,
线: 26,
: 9,
DIF: None,
DEA: None,
MACD柱: 0.0,
线EMA: None,
线EMA: None,
DEA_EMA: None,
}
}
}
fn (: i64) -> f64 {
2.0 / ( as f64 + 1.0)
}
impl 线 {
/// 首次计算 MACD 指标(无历史数据时使用)
pub fn (: f64, : i64, 线: i64, 线: i64, : i64) -> Self {
let 线EMA = ;
let 线EMA = ;
let DIF = 线EMA - 线EMA;
let DEA_EMA = DIF;
let MACD柱 = DIF - DEA_EMA;
Self {
: ,
: ,
线,
线,
,
DIF: Some(DIF),
DEA: Some(DEA_EMA),
MACD柱,
线EMA: Some(线EMA),
线EMA: Some(线EMA),
DEA_EMA: Some(DEA_EMA),
}
}
/// 基于前一个 MACD 指标增量计算当前 MACD
pub fn (MACD: &Self, : f64, : i64) -> Self {
// 快线 EMA
let 线EMA = match MACD.线EMA {
Some(prev) => {
* (MACD.线)
+ prev * ((MACD.线 - 1) as f64 / (MACD.线 + 1) as f64)
}
None => ,
};
// 慢线 EMA
let 线EMA = match MACD.线EMA {
Some(prev) => {
* (MACD.线)
+ prev * ((MACD.线 - 1) as f64 / (MACD.线 + 1) as f64)
}
None => ,
};
// DIF
let DIF = 线EMA - 线EMA;
// DEA_EMA
let DEA_EMA = match MACD.DEA_EMA {
Some(prev) => {
DIF * (MACD.)
+ prev * ((MACD. - 1) as f64 / (MACD. + 1) as f64)
}
None => DIF,
};
// MACD 柱 (注意: Python 版没有 ×2)
let MACD柱 = DIF - DEA_EMA;
Self {
: ,
: ,
线: MACD.线,
线: MACD.线,
: MACD.,
DIF: Some(DIF),
DEA: Some(DEA_EMA),
MACD柱,
线EMA: Some(线EMA),
线EMA: Some(线EMA),
DEA_EMA: Some(DEA_EMA),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_first_calc() {
let macd = 线::(100.0, 1000, 12, 26, 9);
assert_eq!(macd.DIF, Some(0.0));
assert_eq!(macd.MACD柱, 0.0);
assert_eq!(macd.线EMA, Some(100.0));
assert_eq!(macd.线EMA, Some(100.0));
}
#[test]
fn test_incremental_calc() {
let first = 线::(100.0, 1000, 12, 26, 9);
// 价格上升
let second = 线::(&first, 102.0, 1001);
assert!(second.DIF.unwrap() > 0.0);
// 快线EMA 应该比慢线EMA 变化更快
assert!(second.线EMA.unwrap() > second.线EMA.unwrap());
// 价格下降
let third = 线::(&second, 98.0, 1002);
// DIF 应该变小
assert!(third.DIF.unwrap() < second.DIF.unwrap());
}
}