Files
chanlun.rs/chanlun/src/structure/fractal_obj.rs
T

238 lines
8.6 KiB
Rust
Raw Normal View History

2026-05-26 11:12:44 +08:00
/*
* MIT License
*
* Copyright (c) 2026 YuYuKunKun
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
2026-05-25 02:16:35 +08:00
use crate::kline::chan_kline::缠论K线;
use crate::types::分型结构;
use crate::types::相对方向;
2026-05-29 15:43:02 +08:00
use std::sync::atomic::AtomicBool;
2026-05-29 03:55:22 +08:00
use std::sync::atomic::Ordering;
use std::sync::Arc;
2026-05-25 02:16:35 +08:00
2026-05-29 15:43:02 +08:00
/// 分型模式 — True 时使用构造时缓存值(默认),False 时从 中 缠K 实时读取
pub static 分型模式: AtomicBool = AtomicBool::new(true);
2026-05-25 02:16:35 +08:00
/// 分型 — 由三根缠K构成(可能缺左或右)
#[derive(Debug, Clone)]
pub struct 分型 {
2026-05-29 03:55:22 +08:00
pub : Option<Arc<缠论K线>>,
pub : Arc<缠论K线>,
pub : Option<Arc<缠论K线>>,
2026-05-25 02:16:35 +08:00
pub 结构: 分型结构,
pub 时间戳: i64,
pub 分型特征值: f64,
}
impl 分型 {
2026-05-25 04:26:15 +08:00
pub fn new(
2026-05-29 03:55:22 +08:00
: Option<Arc<缠论K线>>, : Arc<缠论K线>, : Option<Arc<缠论K线>>
2026-05-25 04:26:15 +08:00
) -> Self {
2026-05-29 03:55:22 +08:00
let 结构 = .分型.read().unwrap().unwrap_or(分型结构::);
let 时间戳 = .时间戳.load(Ordering::Relaxed);
let 分型特征值 = .分型特征值.get();
2026-05-25 02:16:35 +08:00
Self {
,
,
,
结构,
时间戳,
分型特征值,
}
}
2026-05-29 15:43:02 +08:00
/// 时间戳 — 根据 分型模式 决定返回缓存值(True)或实时值(False)
pub fn 时间戳(&self) -> i64 {
if 分型模式.load(Ordering::Relaxed) {
self.时间戳
} else {
self..时间戳.load(Ordering::Relaxed)
}
}
2026-05-25 02:16:35 +08:00
/// 左中右三组关系
pub fn 关系组(&self) -> Option<(相对方向, 相对方向, 相对方向)> {
let = self..as_ref()?;
let = self..as_ref()?;
Some((
2026-05-29 03:55:22 +08:00
相对方向::分析(..get(), ..get(), self...get(), self...get()),
相对方向::分析(self...get(), self...get(), ..get(), ..get()),
相对方向::分析(..get(), ..get(), ..get(), ..get()),
2026-05-25 02:16:35 +08:00
))
}
2026-05-25 04:26:15 +08:00
/// 分型强度 — 返回 "强"/"中"/"弱"/"未知"
pub fn 强度(&self) -> &str {
if self.结构 != 分型结构:: && self.结构 != 分型结构:: {
return "未知";
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
if self..is_none() || self..is_none() {
return "未知";
}
if let Some(ref 关系组) = self.关系组() {
if self.结构 == 分型结构:: {
if 关系组.2.是否向下() {
return "弱";
} else if 关系组.2.是否向上() {
return "强";
} else {
return "中";
}
} else if self.结构 == 分型结构:: {
if 关系组.2.是否向上() {
return "弱";
} else if 关系组.2.是否向下() {
return "强";
} else {
return "中";
}
}
}
if let (Some(ref ), Some(ref )) = (&self., &self.) {
if self.结构 == 分型结构:: {
2026-05-29 03:55:22 +08:00
if .标的K线.read().unwrap().收盘价 > .标的K线.read().unwrap(). {
2026-05-25 04:26:15 +08:00
return "强";
2026-05-29 03:55:22 +08:00
} else if .标的K线.read().unwrap().收盘价 > self..标的K线.read().unwrap().
{
2026-05-25 04:26:15 +08:00
return "中";
} else {
return "弱";
}
} else if self.结构 == 分型结构:: {
2026-05-29 03:55:22 +08:00
if .标的K线.read().unwrap().收盘价 < .标的K线.read().unwrap(). {
2026-05-25 04:26:15 +08:00
return "强";
2026-05-29 03:55:22 +08:00
} else if .标的K线.read().unwrap().收盘价 < self..标的K线.read().unwrap().
{
2026-05-25 04:26:15 +08:00
return "中";
} else {
return "弱";
}
}
}
"未知"
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
/// MACD柱子分型匹配 — 检查左中右MACD柱形成顶/底形态
2026-05-25 02:16:35 +08:00
pub fn MACD柱子分型匹配(&self) -> bool {
2026-05-25 04:26:15 +08:00
if let (Some(ref ), Some(ref )) = (&self., &self.) {
if self.结构 == 分型结构:: {
2026-05-29 03:55:22 +08:00
let _k = .标的K线.read().unwrap();
let _k = self..标的K线.read().unwrap();
let _k = .标的K线.read().unwrap();
2026-05-25 04:26:15 +08:00
if let (Some(ref macd), Some(ref macd), Some(ref macd)) =
2026-05-29 03:55:22 +08:00
(&_k.macd, &_k.macd, &_k.macd)
2026-05-25 04:26:15 +08:00
{
return macd.MACD柱 > macd.MACD柱 && macd.MACD柱 < macd.MACD柱;
2026-05-25 02:16:35 +08:00
}
}
2026-05-25 04:26:15 +08:00
if self.结构 == 分型结构:: {
2026-05-29 03:55:22 +08:00
let _k = .标的K线.read().unwrap();
let _k = self..标的K线.read().unwrap();
let _k = .标的K线.read().unwrap();
2026-05-25 04:26:15 +08:00
if let (Some(ref macd), Some(ref macd), Some(ref macd)) =
2026-05-29 03:55:22 +08:00
(&_k.macd, &_k.macd, &_k.macd)
2026-05-25 04:26:15 +08:00
{
return macd.MACD柱 < macd.MACD柱 && macd.MACD柱 > macd.MACD柱;
2026-05-25 02:16:35 +08:00
}
}
}
2026-05-25 04:26:15 +08:00
false
2026-05-25 02:16:35 +08:00
}
/// 判断两个分型是否匹配
2026-05-29 03:55:22 +08:00
pub fn 判断分型(: &Arc<分型>, : &Arc<分型>, 模式: &str) -> bool {
2026-05-25 02:16:35 +08:00
match 模式 {
2026-05-29 03:55:22 +08:00
"中" => Arc::as_ptr() == Arc::as_ptr(),
2026-05-25 02:16:35 +08:00
_ => false,
}
}
/// 从缠K序列中获取以指定缠K为中元素的分型
2026-05-25 04:26:15 +08:00
pub fn 从缠K序列中获取分型(
2026-05-29 03:55:22 +08:00
K线序列: &[Arc<缠论K线>],
: &Arc<缠论K线>,
2026-05-25 04:26:15 +08:00
) -> Option<Self> {
let idx = K线序列
.iter()
2026-05-29 03:55:22 +08:00
.position(|k| Arc::as_ptr(k) == Arc::as_ptr())?;
2026-05-25 02:16:35 +08:00
let = if idx > 0 {
2026-05-29 03:55:22 +08:00
Some(Arc::clone(&K线序列[idx - 1]))
2026-05-25 02:16:35 +08:00
} else {
None
};
let = if idx + 1 < K线序列.len() {
2026-05-29 03:55:22 +08:00
Some(Arc::clone(&K线序列[idx + 1]))
2026-05-25 02:16:35 +08:00
} else {
None
};
2026-05-29 03:55:22 +08:00
Some(Self::new(, Arc::clone(), ))
2026-05-25 02:16:35 +08:00
}
/// 向分型序列中添加新分型
2026-05-29 03:55:22 +08:00
pub fn 向序列中添加(分型序列: &mut Vec<Arc<分型>>, 当前分型: Arc<分型>) {
2026-05-25 04:26:15 +08:00
if 分型序列.is_empty() {
if 当前分型.结构 != 分型结构:: && 当前分型.结构 != 分型结构::
{
panic!("首次添加分型不为 顶底 {:?}", 当前分型);
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
} else {
let 前一个 = &分型序列[分型序列.len() - 1];
2026-05-25 02:16:35 +08:00
if 前一个.结构 == 当前分型.结构 {
2026-05-25 04:26:15 +08:00
panic!("分型相同无法添加 {:?} {:?}", 前一个, 当前分型);
}
if 前一个..is_none() {
eprintln!("分型.向序列中添加, 分型异常 {:?}", 前一个);
2026-05-25 02:16:35 +08:00
}
}
分型序列.push(当前分型);
}
}
impl crate::types::fractal::有高低 for 分型 {
fn (&self) -> f64 {
2026-05-29 03:55:22 +08:00
self...get()
2026-05-25 02:16:35 +08:00
}
fn (&self) -> f64 {
2026-05-29 03:55:22 +08:00
self...get()
2026-05-25 02:16:35 +08:00
}
}
impl std::fmt::Display for 分型 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}<{}, {}, None: {}, None: {}>",
2026-05-29 03:55:22 +08:00
self.
.分型
.read()
.unwrap()
.unwrap_or(crate::types::分型结构::),
2026-05-29 15:43:02 +08:00
self.时间戳(),
2026-05-25 02:16:35 +08:00
crate::utils::format_f64_g(self.分型特征值),
if self..is_none() { "True" } else { "False" },
if self..is_none() { "True" } else { "False" },
)
}
}