Files
chanlun.rs/chanlun/src/algorithm/divergence.rs
T

188 lines
7.0 KiB
Rust
Raw Normal View History

2026-05-25 02:16:35 +08:00
use crate::config::缠论配置;
use crate::kline::bar::K线;
use crate::structure::dash_line::虚线;
2026-05-25 04:26:15 +08:00
use crate::types::相对方向;
2026-05-25 02:16:35 +08:00
use std::rc::Rc;
/// 背驰分析 — 判断进入段和离开段之间是否存在背驰
pub struct 背驰分析;
impl 背驰分析 {
2026-05-25 04:26:15 +08:00
/// MACD背驰 — MACD柱状线面积背驰
/// 方式: "总"=阳+|阴|总面积, 其他=按进入段方向选阳或阴
pub fn MACD背驰(
进入段: &虚线, 离开段: &虚线, K线序列: &[Rc<K线>], 方式: &str
) -> bool {
let 进入MACD =
Self::_获取MACD面积(K线序列, &进入段...标的K线, &进入段...标的K线);
let 离开MACD =
Self::_获取MACD面积(K线序列, &离开段...标的K线, &离开段...标的K线);
2026-05-25 02:16:35 +08:00
2026-05-25 04:26:15 +08:00
// 计算面积(绝对值求和)
let 进入面积 = if 方式 == "总" {
进入MACD.().abs()
} else if 进入段.方向() == 相对方向::向上 {
进入MACD..abs()
} else {
进入MACD..abs()
};
let 离开面积 = if 方式 == "总" {
离开MACD.().abs()
} else if 进入段.方向() == 相对方向::向上 {
离开MACD..abs()
} else {
离开MACD..abs()
};
2026-05-25 02:16:35 +08:00
2026-05-25 04:26:15 +08:00
离开面积 < 进入面积
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
/// 斜率背驰 — 价格斜率背驰
2026-05-25 02:16:35 +08:00
pub fn 斜率背驰(进入段: &虚线, 离开段: &虚线) -> bool {
2026-05-25 04:26:15 +08:00
let dx = (进入段..时间戳 - 进入段..时间戳) as f64;
let dy = 进入段..分型特征值 - 进入段..分型特征值;
let 进入斜率 = dy / dx;
2026-05-25 02:16:35 +08:00
2026-05-25 04:26:15 +08:00
let dx = (离开段..时间戳 - 离开段..时间戳) as f64;
let dy = 离开段..分型特征值 - 离开段..分型特征值;
let 离开斜率 = dy / dx;
if 进入段.方向() == 相对方向::向上 {
离开段.() > 进入段.() && 离开斜率.abs() < 进入斜率.abs()
} else {
离开段.() < 进入段.() && 离开斜率.abs() < 进入斜率.abs()
}
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
/// 测度背驰 — 价格时间测度背驰
2026-05-25 02:16:35 +08:00
pub fn 测度背驰(进入段: &虚线, 离开段: &虚线) -> bool {
2026-05-25 04:26:15 +08:00
let dx = (进入段..时间戳 - 进入段..时间戳) as f64;
let dy = 进入段..分型特征值 - 进入段..分型特征值;
let 进入测度 = (dx * dx + dy * dy).sqrt();
let dx = (离开段..时间戳 - 离开段..时间戳) as f64;
let dy = 离开段..分型特征值 - 离开段..分型特征值;
let 离开测度 = (dx * dx + dy * dy).sqrt();
if 进入段.方向() == 相对方向::向上 {
离开段.() > 进入段.() && 离开测度.abs() < 进入测度.abs()
} else {
离开段.() < 进入段.() && 离开测度.abs() < 进入测度.abs()
}
2026-05-25 02:16:35 +08:00
}
/// 全量背驰 — MACD + 斜率 + 测度 三者全满足
pub fn 全量背驰(进入段: &虚线, 离开段: &虚线, K序列: &[Rc<K线>]) -> bool {
Self::MACD背驰(进入段, 离开段, K序列, "总")
&& Self::测度背驰(进入段, 离开段)
2026-05-25 04:26:15 +08:00
&& Self::斜率背驰(进入段, 离开段)
2026-05-25 02:16:35 +08:00
}
/// 任意背驰 — 任一条件满足即可
pub fn 任意背驰(进入段: &虚线, 离开段: &虚线, K序列: &[Rc<K线>]) -> bool {
Self::MACD背驰(进入段, 离开段, K序列, "总")
|| Self::测度背驰(进入段, 离开段)
2026-05-25 04:26:15 +08:00
|| Self::斜率背驰(进入段, 离开段)
2026-05-25 02:16:35 +08:00
}
/// 配置背驰 — 根据配置选择判断方式
2026-05-25 04:26:15 +08:00
pub fn 配置背驰(
进入段: &虚线,
离开段: &虚线,
K序列: &[Rc<K线>],
配置: &缠论配置,
) -> bool {
match (
配置.线段内部背驰_MACD,
配置.线段内部背驰_测度,
配置.线段内部背驰_斜率,
) {
(true, true, true) => {
Self::MACD背驰(进入段, 离开段, K序列, "总")
&& Self::测度背驰(进入段, 离开段)
&& Self::斜率背驰(进入段, 离开段)
}
(false, false, false) => false,
(true, false, true) => {
Self::MACD背驰(进入段, 离开段, K序列, "总") && Self::斜率背驰(进入段, 离开段)
}
(false, true, false) => Self::测度背驰(进入段, 离开段),
(true, false, false) => Self::MACD背驰(进入段, 离开段, K序列, "总"),
(false, true, true) => {
Self::测度背驰(进入段, 离开段) && Self::斜率背驰(进入段, 离开段)
}
(false, false, true) => Self::斜率背驰(进入段, 离开段),
(true, true, false) => {
Self::MACD背驰(进入段, 离开段, K序列, "总") && Self::测度背驰(进入段, 离开段)
}
2026-05-25 02:16:35 +08:00
}
}
2026-05-25 04:26:15 +08:00
/// 任选背驰 — 至少两个条件满足(多数投票)
2026-05-25 02:16:35 +08:00
pub fn 任选背驰(进入段: &虚线, 离开段: &虚线, K序列: &[Rc<K线>]) -> bool {
2026-05-25 04:26:15 +08:00
let 混沌槽 = [
Self::MACD背驰(进入段, 离开段, K序列, "总"),
Self::测度背驰(进入段, 离开段),
Self::斜率背驰(进入段, 离开段),
];
混沌槽.iter().filter(|&&x| x).count() >= 2
2026-05-25 02:16:35 +08:00
}
/// 背驰模式 — 根据模式字符串选择判断方式
pub fn 背驰模式(
进入段: &虚线,
离开段: &虚线,
K序列: &[Rc<K线>],
配置: &缠论配置,
模式: &str,
) -> bool {
match 模式 {
"全量" => Self::全量背驰(进入段, 离开段, K序列),
"任意" => Self::任意背驰(进入段, 离开段, K序列),
"配置" => Self::配置背驰(进入段, 离开段, K序列, 配置),
2026-05-25 04:26:15 +08:00
"相对" => Self::任选背驰(进入段, 离开段, K序列),
_ => false,
2026-05-25 02:16:35 +08:00
}
}
// ---- 内部辅助 ----
2026-05-25 04:26:15 +08:00
fn _获取MACD面积(K线序列: &[Rc<K线>], : &Rc<K线>, : &Rc<K线>) -> MACD面积 {
let _idx = K线序列.iter().position(|k| Rc::as_ptr(k) == Rc::as_ptr());
let _idx = K线序列.iter().position(|k| Rc::as_ptr(k) == Rc::as_ptr());
2026-05-25 02:16:35 +08:00
let mut = 0.0f64;
let mut = 0.0f64;
2026-05-25 04:26:15 +08:00
if let (Some(), Some()) = (_idx, _idx) {
let (, ) = if <= { (, ) } else { (, ) };
for k in &K线序列[..=] {
if let Some(ref macd) = k.macd {
let hist = macd.MACD柱;
if hist >= 0.0 {
+= hist;
} else {
+= hist;
2026-05-25 02:16:35 +08:00
}
}
}
}
2026-05-25 04:26:15 +08:00
2026-05-25 02:16:35 +08:00
MACD面积 { , }
}
}
struct MACD面积 {
: f64,
: f64,
}
2026-05-25 04:26:15 +08:00
impl MACD面积 {
fn (&self) -> f64 {
self. + self.
}
}