第一版

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
+771
View File
@@ -0,0 +1,771 @@
use crate::algorithm::hub::;
use crate::config::;
use crate::kline::chan_kline::K线;
use crate::kline::bar::K线;
use crate::structure::fractal_obj::;
use crate::structure::segment_feat::线;
use crate::types::{, , };
use std::rc::Rc;
/// 虚线 — 笔和线段的通用数据结构
///
/// 笔和线段共享此 struct,通过 `标识` 字段区分 ("笔"/"线段"/"扩展线段"等)
#[derive(Debug, Clone)]
pub struct 线 {
pub : String,
pub : i64,
pub : i64,
pub : Rc<>,
pub : Rc<>,
pub : bool,
pub : Vec<Rc<线>>,
pub : Vec<Option<Rc<线>>>,
pub _中枢序列: Vec<Rc<>>,
pub _中枢序列: Vec<Rc<>>,
pub _中枢序列: Vec<Rc<>>,
pub K线: Option<Rc<K线>>,
pub : String,
pub _特征序列_显示: bool,
pub : Option<>,
pub : Option<Rc<线>>,
pub : bool,
}
impl 线 {
pub fn new(: i64, : String, : Rc<>, : Rc<>, : i64, : bool) -> Self {
Self {
,
,
,
,
,
,
: Vec::new(),
: Vec::new(),
_中枢序列: Vec::new(),
_中枢序列: Vec::new(),
_中枢序列: Vec::new(),
K线: None,
: "文武".into(),
_特征序列_显示: false,
: None,
: None,
: false,
}
}
/// 笔序列(基础序列的别名)
pub fn (&self) -> &Vec<Rc<线>> {
&self.
}
pub fn (&self) -> String {
format!("{}:{}:{}:{}", self..., self..., self., self.)
}
/// 方向 — 文到武的方向
pub fn (&self) -> {
match (self.., self..) {
(::, ::) => ::,
(::, ::) => ::,
(::, ::) => ::,
(::, ::) => ::,
_ => ::,
}
}
/// 虚线高 — 文和武中高的那个
pub fn (&self) -> f64 {
self...max(self..)
}
/// 虚线低 — 文和武中低的那个
pub fn (&self) -> f64 {
self...min(self..)
}
/// 判断两个虚线是否首尾相连
pub fn (&self, : &线) -> bool {
self... == ...
}
/// 判断两个虚线是否首尾相连
pub fn (&self, : &线) -> bool {
self... == ...
}
/// 获取该虚线范围内的普K序列
pub fn K序列(&self, K序列: &[Rc<K线>]) -> Vec<Rc<K线>> {
let = self... as usize;
let = self... as usize;
if < K序列.len() && < K序列.len() && <= {
K序列[..=].to_vec()
} else {
Vec::new()
}
}
/// 获取该虚线范围内的缠K序列
pub fn K序列(&self, K序列: &[Rc<K线>]) -> Vec<Rc<K线>> {
K线::(K序列, &self.., &self..).unwrap_or_default()
}
/// 获取数据文本(用于保存/调试)
pub fn (&self) -> String {
use crate::utils::format_f64_g;
if self. == "" {
return format!(
"{}, {}, {}, 文:({},{}), 武:({},{}), {}",
self.,
self.,
self.,
self..,
format_f64_g(self..),
self..,
format_f64_g(self..),
if self. { "True" } else { "False" },
);
}
// 非笔:线段/扩展线段等,完整输出
let (, , , 穿) =
crate::algorithm::segment::线::(self, None);
let (_a, _b, _c) = crate::algorithm::segment::线::(self);
let _bool = |b: bool| -> &str { if b { "True" } else { "False" } };
let _str = match &self. {
Some(g) => format!("{}", g),
None => "None".to_string(),
};
let _str = match &self. {
Some(d) => format!("{}", d),
None => "None".to_string(),
};
// Format中枢序列 as Python-style list representations
let _str = format!("[{}]", self._中枢序列.iter().map(|h| format!("{}", h)).collect::<Vec<_>>().join(", "));
let _str = format!("[{}]", self._中枢序列.iter().map(|h| format!("{}", h)).collect::<Vec<_>>().join(", "));
let _str = format!("[{}]", self._中枢序列.iter().map(|h| format!("{}", h)).collect::<Vec<_>>().join(", "));
let _str = format!("[{}]", .iter().map(|d| format!("{}", d)).collect::<Vec<_>>().join(", "));
let _str = format!("[{}]", .iter().map(|d| format!("{}", d)).collect::<Vec<_>>().join(", "));
let _str = format!("[{}]", .iter().map(|d| format!("{}", d)).collect::<Vec<_>>().join(", "));
format!(
"{}, {}, {}, 文:({},{}), 武:({},{}), {}, {}, ({}, {}, {}), (前: {}, 后: {}, 三: {}, 伤: {}), 实: {}, 虚: {}, 合: {}, {}, {}, {}, {}",
self.,
self.,
self.,
self..,
format_f64_g(self..),
self..,
format_f64_g(self..),
if self. { "True" } else { "False" },
self..len(),
_bool(_a),
_bool(_b),
_bool(_c),
_str,
_str,
_str,
match &穿 { Some(d) => format!("{}", d), None => "None".to_string() },
_str,
_str,
_str,
self.,
_str,
_str,
if self. { "True" } else { "False" },
)
}
// ---- 关联函数(静态工厂方法) ----
/// 创建笔
pub fn (: Rc<>, : Rc<>, : bool) -> Self {
Self::new(0, "".into(), , , 1, )
}
/// 创建线段
pub fn 线(线: &[Rc<线>]) -> Self {
let = Rc::clone(&线[0].);
let = Rc::clone(&线[线.len() - 1].);
let = if 线[0]. == "" {
"线段".into()
} else {
format!("线段<{}>", 线[0].)
};
let = 线[0]. + 1;
let mut = Self::new(0, , , , , true);
. = 线.to_vec();
. = "文武".into();
}
// ---- 买卖点模式匹配 ----
/// 缠K买卖点模式 — 根据模式字符串选择匹配方法
pub fn K买卖点模式(: &str, K: &K线, : &) -> bool {
match {
"全量" => Self::(K),
"任意" => Self::(K),
"配置" => Self::(K, ),
"相对" => Self::(K),
_ => false,
}
}
/// 买卖点配置匹配 — 根据配置中的指标开关组合判断
pub fn (K: &K线, : &) -> bool {
match (._指标匹配_MACD, ._指标匹配_KDJ, ._指标匹配_RSI) {
(true, true, true) => K.MACD柱子匹配() && K.KDJ匹配() && K.RSI匹配(),
(false, false, false) => false,
(true, false, true) => K.MACD柱子匹配() && K.RSI匹配(),
(false, true, false) => K.KDJ匹配(),
(true, false, false) => K.MACD柱子匹配(),
(false, true, true) => K.KDJ匹配() && K.RSI匹配(),
(false, false, true) => K.RSI匹配(),
(true, true, false) => K.MACD柱子匹配() && K.KDJ匹配(),
}
}
/// 买卖点任意匹配 — 任一指标匹配
pub fn (K: &K线) -> bool {
K.MACD柱子匹配() || K.KDJ匹配() || K.RSI匹配()
}
/// 买卖点全量匹配 — 全部指标匹配
pub fn (K: &K线) -> bool {
K.MACD柱子匹配() && K.KDJ匹配() && K.RSI匹配()
}
/// 买卖点相对匹配 — 至少两个指标匹配
pub fn (K: &K线) -> bool {
let = [
K.MACD柱子匹配(),
K.KDJ匹配(),
K.RSI匹配(),
];
.iter().filter(|&&x| x).count() >= 2
}
// ---- MACD柱子均值计算 ----
/// 计算MACD柱子均值 — 虚线范围内所有MACD柱的绝对值均值
pub fn MACD柱子均值(K序列: &[Rc<K线>], 线: &线) -> f64 {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
if K线序列.is_empty() {
return 0.0;
}
let : f64 = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
.map(|m| m.MACD柱.abs())
.sum();
/ K线序列.len() as f64
}
/// 计算MACD柱子均值_阴 — 负柱的绝对值均值
pub fn MACD柱子均值_阴(K序列: &[Rc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
.filter(|m| m.MACD柱 < 0.0)
.map(|m| m.MACD柱.abs())
.collect();
if .is_empty() {
None
} else {
Some(.iter().sum::<f64>() / .len() as f64)
}
}
/// 计算MACD柱子均值_阳 — 正柱的绝对值均值
pub fn MACD柱子均值_阳(K序列: &[Rc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
.filter(|m| m.MACD柱 > 0.0)
.map(|m| m.MACD柱.abs())
.collect();
if .is_empty() {
None
} else {
Some(.iter().sum::<f64>() / .len() as f64)
}
}
// ---- 武之MACD比较 ----
/// 武之全量MACD均值 — 武端MACD柱是否小于均值(背驰)
pub fn MACD均值(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
Some(m) => m.MACD柱.abs(),
None => return false,
};
_MACD < Self::MACD柱子均值(K序列, 线)
}
/// 武之MACD均值 — 按方向选择阴/阳均值比对
pub fn MACD均值(K序列: &[Rc<K线>], 线: &线) -> bool {
if 线.() == :: {
Self::MACD均值_阳(K序列, 线)
} else {
Self::MACD均值_阴(K序列, 线)
}
}
/// 武之MACD均值_阴 — 武端负柱是否小于阴均值
pub fn MACD均值_阴(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
Some(m) => m.MACD柱.abs(),
None => return false,
};
match Self::MACD柱子均值_阴(K序列, 线) {
Some() => _MACD < .abs(),
None => false,
}
}
/// 武之MACD均值_阳 — 武端正柱是否小于阳均值
pub fn MACD均值_阳(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
Some(m) => m.MACD柱.abs(),
None => return false,
};
match Self::MACD柱子均值_阳(K序列, 线) {
Some() => _MACD < ,
None => false,
}
}
/// 武之MACD极值 — 武端MACD柱是否为区间极值
pub fn MACD极值(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
Some(m) => m.MACD柱,
None => return false,
};
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
.map(|m| m.MACD柱)
.collect();
if .is_empty() {
return false;
}
if _MACD > 0.0 {
let = .iter().cloned().fold(f64::NEG_INFINITY, f64::max);
== _MACD
} else {
let = .iter().cloned().fold(f64::INFINITY, f64::min);
== _MACD
}
}
// ---- MACD趋向背驰 ----
/// 计算K线序列MACD趋向背驰 — 分析 MACD柱/DIF/DEA 三项背驰信号
pub fn K线序列MACD趋向背驰(K序列: &[Rc<K线>], : ) -> [bool; 3] {
if K序列.is_empty() {
return [false, false, false];
}
let = &K序列[K序列.len() - 1];
if == :: {
let : Vec<&Rc<K线>> = K序列
.iter()
.filter(|k| k.macd.as_ref().map_or(false, |m| m.MACD柱 > 0.0))
.collect();
if .is_empty() {
return [false, false, false];
}
let mut = [false; 3];
// MACD柱背驰
let =
.iter()
.max_by(|a, b| {
a.macd.as_ref().unwrap().MACD柱
.partial_cmp(&b.macd.as_ref().unwrap().MACD柱)
.unwrap()
})
.unwrap();
let mut = vec![Rc::clone(*), Rc::clone()];
.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = ([0].macd.as_ref(), [1].macd.as_ref()) {
if m0.MACD柱 > m1.MACD柱 && [0]. < [1]. {
[0] = true;
}
}
// DIF背驰
let =
.iter()
.max_by(|a, b| {
let da = a.macd.as_ref().and_then(|m| m.DIF).unwrap_or(0.0);
let db = b.macd.as_ref().and_then(|m| m.DIF).unwrap_or(0.0);
da.partial_cmp(&db).unwrap()
})
.unwrap();
let mut 2 = vec![Rc::clone(*), Rc::clone()];
2.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = (2[0].macd.as_ref(), 2[1].macd.as_ref()) {
let dif0 = m0.DIF.unwrap_or(0.0);
let dif1 = m1.DIF.unwrap_or(0.0);
if dif0 > dif1 && 2[0]. < 2[1]. {
[1] = true;
}
}
// DEA背驰
let 线 =
.iter()
.max_by(|a, b| {
let da = a.macd.as_ref().and_then(|m| m.DEA).unwrap_or(0.0);
let db = b.macd.as_ref().and_then(|m| m.DEA).unwrap_or(0.0);
da.partial_cmp(&db).unwrap()
})
.unwrap();
let mut 3 = vec![Rc::clone(*线), Rc::clone()];
3.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = (3[0].macd.as_ref(), 3[1].macd.as_ref()) {
let dea0 = m0.DEA.unwrap_or(0.0);
let dea1 = m1.DEA.unwrap_or(0.0);
if dea0 > dea1 && 3[0]. < 3[1]. {
[2] = true;
}
}
} else {
let : Vec<&Rc<K线>> = K序列
.iter()
.filter(|k| k.macd.as_ref().map_or(false, |m| m.MACD柱 < 0.0))
.collect();
if .is_empty() {
return [false, false, false];
}
let mut = [false; 3];
// MACD柱背驰 (负向: absolute value comparison)
let =
.iter()
.max_by(|a, b| {
a.macd.as_ref().unwrap().MACD柱.abs()
.partial_cmp(&b.macd.as_ref().unwrap().MACD柱.abs())
.unwrap()
})
.unwrap();
let mut = vec![Rc::clone(*), Rc::clone()];
.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = ([0].macd.as_ref(), [1].macd.as_ref()) {
if m0.MACD柱 < m1.MACD柱 && [0]. > [1]. {
[0] = true;
}
}
// DIF背驰
let =
.iter()
.max_by(|a, b| {
let da = a.macd.as_ref().and_then(|m| m.DIF).unwrap_or(0.0).abs();
let db = b.macd.as_ref().and_then(|m| m.DIF).unwrap_or(0.0).abs();
da.partial_cmp(&db).unwrap()
})
.unwrap();
let mut 2 = vec![Rc::clone(*), Rc::clone()];
2.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = (2[0].macd.as_ref(), 2[1].macd.as_ref()) {
let dif0 = m0.DIF.unwrap_or(0.0);
let dif1 = m1.DIF.unwrap_or(0.0);
if dif0 < dif1 && 2[0]. > 2[1]. {
[1] = true;
}
}
// DEA背驰
let 线 =
.iter()
.max_by(|a, b| {
let da = a.macd.as_ref().and_then(|m| m.DEA).unwrap_or(0.0).abs();
let db = b.macd.as_ref().and_then(|m| m.DEA).unwrap_or(0.0).abs();
da.partial_cmp(&db).unwrap()
})
.unwrap();
let mut 3 = vec![Rc::clone(*线), Rc::clone()];
3.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = (3[0].macd.as_ref(), 3[1].macd.as_ref()) {
let dea0 = m0.DEA.unwrap_or(0.0);
let dea1 = m1.DEA.unwrap_or(0.0);
if dea0 < dea1 && 3[0]. > 3[1]. {
[2] = true;
}
}
}
}
// ---- MACD柱子分段 ----
/// 计算MACD柱子分段 — 按正负号将MACD柱子分段
pub fn MACD柱子分段(k线序列: &[Rc<K线>]) -> Vec<Vec<f64>> {
if k线序列.is_empty() {
return Vec::new();
}
let = |x: f64| -> &str {
if x > 0.0 { "" } else { "" }
};
let _MACD = match &k线序列[0].macd {
Some(m) => m.MACD柱,
None => return Vec::new(),
};
let mut = (_MACD);
let mut = vec![_MACD];
let mut = Vec::new();
for k线 in &k线序列[1..] {
let macd = match &k线.macd {
Some(m) => m.MACD柱,
None => continue,
};
let = (macd);
if == {
.push(macd);
} else {
.push(std::mem::take(&mut ));
.push(macd);
= ;
}
}
if !.is_empty() {
.push();
}
}
// ---- 密集区域按间隔 ----
/// 密集区域按间隔 — 找出交叉标记中的密集区域
pub fn (
: &[i32],
: usize,
: usize,
) -> Vec<(usize, usize, usize)> {
let : Vec<usize> = (0...len()).filter(|&i| [i] != 0).collect();
if .is_empty() {
return Vec::new();
}
let mut = Vec::new();
let mut = [0];
let mut = 1;
for i in 1...len() {
let prev = [i - 1];
let curr = [i];
if curr - prev <= {
+= 1;
} else {
if >= {
.push((, prev, ));
}
= curr;
= 1;
}
}
if >= {
.push((, [.len() - 1], ));
}
}
// ---- 统计MACD行为 ----
/// 统计MACD行为 — 分析DIF/DEA穿零轴和金叉死叉
pub fn MACD行为(K序列: &[Rc<K线>], : usize, : usize) -> std::collections::HashMap<String, String> {
use std::collections::HashMap;
let mut dif_up = 0;
let mut dif_down = 0;
let mut dea_up = 0;
let mut dea_down = 0;
for i in 1..K序列.len() {
let pre = &K序列[i - 1].macd;
let cur = &K序列[i].macd;
if pre.is_none() || cur.is_none() {
continue;
}
let (pre_dif, cur_dif) = (pre.as_ref().unwrap().DIF, cur.as_ref().unwrap().DIF);
let (pre_dea, cur_dea) = (pre.as_ref().unwrap().DEA, cur.as_ref().unwrap().DEA);
if let (Some(pd), Some(cd)) = (pre_dif, cur_dif) {
if pd < 0.0 && cd >= 0.0 { dif_up += 1; }
if pd > 0.0 && cd <= 0.0 { dif_down += 1; }
}
if let (Some(pd), Some(cd)) = (pre_dea, cur_dea) {
if pd < 0.0 && cd >= 0.0 { dea_up += 1; }
if pd > 0.0 && cd <= 0.0 { dea_down += 1; }
}
}
let mut golden = 0;
let mut death = 0;
let mut = vec![0i32];
for i in 1..K序列.len() {
let pre = &K序列[i - 1].macd;
let cur = &K序列[i].macd;
if pre.is_none() || cur.is_none() {
.push(0);
continue;
}
let pre_dif = pre.as_ref().unwrap().DIF;
let pre_dea = pre.as_ref().unwrap().DEA;
let cur_dif = cur.as_ref().unwrap().DIF;
let cur_dea = cur.as_ref().unwrap().DEA;
if let (Some(pd), Some(cd), Some(pe), Some(ce)) = (pre_dif, cur_dif, pre_dea, cur_dea) {
if pd <= pe && cd > ce {
golden += 1;
.push(1);
} else if pd >= pe && cd < ce {
death += 1;
.push(-1);
} else {
.push(0);
}
} else {
.push(0);
}
}
let = Self::(&, , );
let mut map = HashMap::new();
map.insert("DIF上穿0".into(), dif_up.to_string());
map.insert("DIF下穿0".into(), dif_down.to_string());
map.insert("DEA上穿0".into(), dea_up.to_string());
map.insert("DEA下穿0".into(), dea_down.to_string());
map.insert("金叉次数".into(), golden.to_string());
map.insert("死叉次数".into(), death.to_string());
map.insert("密集交叉区域".into(), format!("{:?}", ));
map
}
// ---- 买卖意义 ----
/// 买卖意义 — 核心买卖点判断逻辑
///
/// 返回 (是否有意义, 原因字符串)
pub fn (线: &线, : &crate::business::observer::) -> (bool, String) {
let K序列 = &.K线序列;
let = &.;
if 线. != "" && 线. != "线段" && !线..starts_with("线段<") {
return (false, "标识不在范围内".into());
}
// KDJ指标完整性检查
match &线...K线.kdj {
Some(kdj) if kdj.K.is_some() && kdj.D.is_some() && kdj.J.is_some() => {}
_ => return (false, "KDJ指标不完整".into()),
}
let = Self::K买卖点模式(&._指标模式, &线.., );
let = false;
let : Vec<Rc<>> = if 线. == "" {
crate::algorithm::bi::::(线, )
} else {
crate::algorithm::segment::线::(线, )
};
if {
if 线. == "" {
if Self::MACD均值(K序列, 线) {
return (true, "武之MACD均值".into());
}
if Self::MACD极值(K序列, 线) && !.is_empty() {
return (true, "背驰过且极值".into());
} else if 线..MACD柱子分型匹配() {
return (
true,
format!(
"背驰过:{},极值:{},柱子分型匹配",
.len(),
Self::MACD极值(K序列, 线)
),
);
}
}
if 线. != ""
&& crate::algorithm::segment::线::线(线, )
{
return (true, "线段内部背驰".into());
}
}
if ! && && 线...MACD柱子匹配() {
if Self::MACD极值(K序列, 线) && .len() > 2 {
return (
true,
"没结果, 极值, 柱子分型匹配, 背驰过大于2次".into(),
);
}
}
(, "".into())
}
}
impl std::fmt::Display for 线 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self. == "" {
write!(
f,
"笔({}, {}, {}, {}, 周期: {}, 数量: {})",
self.,
self.(),
self.,
self.,
self...,
self... - self... + 1
)
} else {
let = crate::algorithm::segment::线::(self);
let = crate::algorithm::segment::线::(self);
let _str = match {
Some(g) => format!("{}", g),
None => "None".to_string(),
};
let K线_str = match &self.K线 {
Some(k) => format!("{}", k),
None => "None".to_string(),
};
write!(
f,
"{}<{}, {}, {}, {}, {}, 数量: {}, 缺口: {}, {}>",
self.,
self.,
,
self.(),
self.,
self.,
self..len(),
_str,
K线_str,
)
}
}
}
+24
View File
@@ -0,0 +1,24 @@
use crate::structure::segment_feat::线;
use crate::types::;
use std::rc::Rc;
/// 特征分型 — 由三个线段特征元素构成的分型
#[derive(Debug, Clone)]
pub struct {
pub : Rc<线>,
pub : Rc<线>,
pub : Rc<线>,
pub : ,
}
impl {
pub fn new(: Rc<线>, : Rc<线>, : Rc<线>, : ) -> Self {
Self { , , , }
}
}
impl std::fmt::Display for {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "特征分型<{}, {}>", self., self.)
}
}
+173
View File
@@ -0,0 +1,173 @@
use crate::kline::chan_kline::K线;
use crate::types::;
use crate::types::;
use std::rc::Rc;
/// 分型 — 由三根缠K构成(可能缺左或右)
#[derive(Debug, Clone)]
pub struct {
pub : Option<Rc<K线>>,
pub : Rc<K线>,
pub : Option<Rc<K线>>,
pub : ,
pub : i64,
pub : f64,
}
impl {
pub fn new(: Option<Rc<K线>>, : Rc<K线>, : Option<Rc<K线>>) -> Self {
let = ..unwrap_or(::);
let = .;
let = .;
Self {
,
,
,
,
,
,
}
}
/// 左中右三组关系
pub fn (&self) -> Option<(, , )> {
let = self..as_ref()?;
let = self..as_ref()?;
Some((
::(., ., self.., self..),
::(self.., self.., ., .),
::(., ., ., .),
))
}
/// 分型强度
pub fn (&self) -> f64 {
match self. {
:: | :: => {
if let Some(ref ) = self. {
self.. - .
} else {
0.0
}
}
:: | :: => {
if let Some(ref ) = self. {
. - self..
} else {
0.0
}
}
:: => 0.0,
}
}
/// MACD柱子分型匹配
pub fn MACD柱子分型匹配(&self) -> bool {
match self. {
:: | :: => {
if let Some(ref ) = self. {
.MACD柱子匹配()
} else {
false
}
}
:: | :: => {
if let Some(ref ) = self. {
.MACD柱子匹配()
} else {
false
}
}
:: => false,
}
}
/// 判断两个分型是否匹配
pub fn (: &, : &, : &str) -> bool {
match {
"" => .. == ..,
_ => false,
}
}
/// 从缠K序列中获取以指定缠K为中元素的分型
pub fn K序列中获取分型(K线序列: &[Rc<K线>], : &Rc<K线>) -> Option<Self> {
let idx = K线序列.iter().position(|k| Rc::as_ptr(k) == Rc::as_ptr())?;
let = if idx > 0 {
Some(Rc::clone(&K线序列[idx - 1]))
} else {
None
};
let = if idx + 1 < K线序列.len() {
Some(Rc::clone(&K线序列[idx + 1]))
} else {
None
};
Some(Self::new(, Rc::clone(), ))
}
/// 向分型序列中添加新分型
pub fn (: &mut Vec<Rc<>>, : Rc<>) {
if let Some() = .last() {
if . == . {
// 同一时间戳: 比较强度,保留更强的
match . {
:: | :: => {
if . >= . {
.pop();
.push();
}
return;
}
:: | :: => {
if . <= . {
.pop();
.push();
}
return;
}
:: => {}
}
}
// 相同结构只保留更强的
if . == . {
if (. == :: || . == ::)
&& . >= .
{
.pop();
.push();
} else if (. == :: || . == ::)
&& . <= .
{
.pop();
.push();
}
return;
}
}
.push();
}
}
impl crate::types::fractal:: for {
fn (&self) -> f64 {
self..
}
fn (&self) -> f64 {
self..
}
}
impl std::fmt::Display for {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}<{}, {}, None: {}, None: {}>",
self...unwrap_or(crate::types::::),
self.,
crate::utils::format_f64_g(self.),
if self..is_none() { "True" } else { "False" },
if self..is_none() { "True" } else { "False" },
)
}
}
+4
View File
@@ -0,0 +1,4 @@
pub mod dash_line;
pub mod feat_fractal;
pub mod fractal_obj;
pub mod segment_feat;
+254
View File
@@ -0,0 +1,254 @@
use crate::structure::dash_line::线;
use crate::structure::feat_fractal::;
use crate::structure::fractal_obj::;
use crate::types::{, };
use std::rc::Rc;
/// 线段特征 — 特征序列元素(内部是虚线的集合)
#[derive(Debug, Clone)]
pub struct 线 {
pub : i64,
pub : String,
pub 线: ,
pub : Vec<Rc<线>>,
}
impl 线 {
pub fn new(: String, : Vec<Rc<线>>, 线: ) -> Self {
Self {
: 0,
,
线,
: ,
}
}
pub fn (&self) -> String {
self..clone()
}
/// 文 — 取特征序列元素中分型特征值最大/最小的文分型
pub fn (&self) -> Rc<> {
if self.线.() {
// 向上 → 取最大的文
self.
.iter()
.max_by(|a, b| {
a.
.
.partial_cmp(&b..)
.unwrap_or(std::cmp::Ordering::Equal)
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
} else {
// 向下 → 取最小的文
self.
.iter()
.min_by(|a, b| {
a.
.
.partial_cmp(&b..)
.unwrap_or(std::cmp::Ordering::Equal)
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
}
}
/// 武 — 取特征序列元素中分型特征值最大/最小的武分型
pub fn (&self) -> Rc<> {
if self.线.() {
self.
.iter()
.max_by(|a, b| {
a.
.
.partial_cmp(&b..)
.unwrap_or(std::cmp::Ordering::Equal)
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
} else {
self.
.iter()
.min_by(|a, b| {
a.
.
.partial_cmp(&b..)
.unwrap_or(std::cmp::Ordering::Equal)
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
}
}
pub fn (&self) -> f64 {
let = self.();
let = self.();
..max(.)
}
pub fn (&self) -> f64 {
let = self.();
let = self.();
..min(.)
}
/// 方向 — 线段方向的翻转
pub fn (&self) -> {
self.线.()
}
/// 向特征序列元素中添加虚线
pub fn (&mut self, 线: Rc<线>) -> Result<(), String> {
if 线.() == self.线 {
return Err("添加方向与线段方向相同".into());
}
self..push(线);
Ok(())
}
/// 新建特征序列元素
pub fn (线: Vec<Rc<线>>, 线: ) -> Self {
let = format!("特征<虚线>");
Self::new(, 线, 线)
}
/// 静态分析 — 从虚线序列生成特征序列元素列表
pub fn (
线: &[Rc<线>],
线: ,
: &str,
: bool,
) -> Vec<Rc<线>> {
let mut : Vec<Rc<线>> = Vec::new();
// 需要被合并的方向集合
let : Vec<> = match {
"老阳" | "老阴" if ! => vec![::, ::, ::],
_ => vec![::, ::],
};
for 线 in 线 {
// 情况1:方向相同(可能触发分型替换)
if 线.() == 线 {
if .len() >= 3 {
let = Rc::clone(&[.len() - 3]);
let = Rc::clone(&[.len() - 2]);
let = Rc::clone(&[.len() - 1]);
if let Some() = ::(&*, &*, &*, true, true) {
let = (线 == ::
&& == ::
&& 线.() > .())
|| (线 == ::
&& == ::
&& 线.() < .());
if {
let 线 = if .[0]. < .[0]. {
&.[0]
} else {
&.[0]
};
let 线 = if ..last().unwrap().
> ..last().unwrap().
{
&.[..len() - 1]
} else {
&.[..len() - 1]
};
let fake = 线::(
Rc::clone(&线.),
Rc::clone(&线.),
false,
);
.pop();
let idx = .len() - 1;
[idx] =
Rc::new(Self::(vec![Rc::new(fake)], 线));
}
}
}
continue;
}
// 情况2:方向不同(执行特征序列的合并/添加)
if .is_empty() {
.push(Rc::new(Self::(vec![Rc::clone(线)], 线)));
continue;
}
// 检查与最后一个特征序列的方向关系
let _idx = .len() - 1;
let 线 = &*[_idx];
if .contains(&::(
线.(),
线.(),
线.(),
线.(),
)) {
// Clone-modify-replace
let mut = (*[_idx]).clone();
let _ = .(Rc::clone(线));
[_idx] = Rc::new();
} else {
.push(Rc::new(Self::(vec![Rc::clone(线)], 线)));
}
}
}
/// 获取分型序列
pub fn (: &[Rc<线>]) -> Vec<> {
let mut = Vec::new();
if .len() < 3 {
return ;
}
for i in 2...len() {
let = Rc::clone(&[i - 2]);
let = Rc::clone(&[i - 1]);
let = Rc::clone(&[i]);
if let Some() = ::_对象(
&* as &dyn crate::types::fractal::,
&* as &dyn crate::types::fractal::,
&* as &dyn crate::types::fractal::,
true,
true,
) {
.push(::new(, , , ));
}
}
}
}
impl crate::types::fractal:: for 线 {
fn (&self) -> f64 {
self.()
}
fn (&self) -> f64 {
self.()
}
}
impl std::fmt::Display for 线 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self..is_empty() {
write!(f, "{}<{}, 空>", self., self.线)
} else {
write!(
f,
"{}<{}, {}, {}, {}>",
self.,
self.线,
self.(),
self.(),
self..len()
)
}
}
}