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

897 lines
32 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::structure::dash_line::虚线;
use crate::structure::fractal_obj::分型;
use crate::types::相对方向;
2026-05-29 03:55:22 +08:00
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::{Arc, RwLock};
2026-05-25 02:16:35 +08:00
/// 中枢 — 三段虚线重叠区间构成的价格中枢
2026-05-29 03:55:22 +08:00
/// 可变字段使用 Cell/RefCell 实现内部可变性,确保 Rc 指针身份一致
#[derive(Debug)]
2026-05-25 02:16:35 +08:00
pub struct 中枢 {
2026-05-29 03:55:22 +08:00
pub 序号: AtomicI64,
pub 标识: RwLock<String>,
pub 级别: AtomicI64,
pub 基础序列: RwLock<Vec<Arc<虚线>>>,
pub 第三买卖线: RwLock<Option<Arc<虚线>>>,
pub 本级_第三买卖线: RwLock<Option<Arc<虚线>>>,
}
impl Clone for 中枢 {
fn clone(&self) -> Self {
Self {
序号: AtomicI64::new(self.序号.load(Ordering::Relaxed)),
标识: RwLock::new(self.标识.read().unwrap().clone()),
级别: AtomicI64::new(self.级别.load(Ordering::Relaxed)),
基础序列: RwLock::new(self.基础序列.read().unwrap().clone()),
第三买卖线: RwLock::new(self.第三买卖线.read().unwrap().clone()),
本级_第三买卖线: RwLock::new(self.本级_第三买卖线.read().unwrap().clone()),
}
}
2026-05-25 02:16:35 +08:00
}
impl 中枢 {
2026-05-29 03:55:22 +08:00
pub fn new(序号: i64, 标识: String, 级别: i64, 基础序列: Vec<Arc<虚线>>) -> Self {
2026-05-25 02:16:35 +08:00
Self {
2026-05-29 03:55:22 +08:00
序号: AtomicI64::new(序号),
标识: RwLock::new(标识),
级别: AtomicI64::new(级别),
基础序列: RwLock::new(基础序列.into_iter().take(3).collect()),
第三买卖线: RwLock::new(None),
本级_第三买卖线: RwLock::new(None),
2026-05-25 02:16:35 +08:00
}
}
2026-05-29 03:55:22 +08:00
pub fn 添加虚线(&self, 实线: Arc<虚线>) {
self.基础序列.write().unwrap().push(实线);
*self.本级_第三买卖线.write().unwrap() = None;
*self.第三买卖线.write().unwrap() = None;
2026-05-25 02:16:35 +08:00
}
pub fn 图表标题(&self) -> String {
format!(
"{}:{}:{}:{}",
2026-05-25 04:26:15 +08:00
self.()..标识,
self.()..周期,
2026-05-29 03:55:22 +08:00
self.标识.read().unwrap(),
self.序号.load(Ordering::Relaxed)
2026-05-25 02:16:35 +08:00
)
}
2026-05-29 03:55:22 +08:00
pub fn 离开段(&self) -> Arc<虚线> {
Arc::clone(&self.基础序列.read().unwrap()[self.基础序列.read().unwrap().len() - 1])
2026-05-25 02:16:35 +08:00
}
pub fn 方向(&self) -> 相对方向 {
2026-05-29 03:55:22 +08:00
self.基础序列.read().unwrap()[0].方向().翻转()
2026-05-25 02:16:35 +08:00
}
pub fn (&self) -> f64 {
2026-05-29 03:55:22 +08:00
self.基础序列.read().unwrap()[..3]
2026-05-25 02:16:35 +08:00
.iter()
.map(|x| x.())
.min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
.unwrap_or(0.0)
}
pub fn (&self) -> f64 {
2026-05-29 03:55:22 +08:00
self.基础序列.read().unwrap()[..3]
2026-05-25 02:16:35 +08:00
.iter()
.map(|x| x.())
.max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
.unwrap_or(0.0)
}
pub fn 高高(&self) -> f64 {
self.基础序列
2026-05-29 03:55:22 +08:00
.read()
.unwrap()
2026-05-25 02:16:35 +08:00
.iter()
.map(|x| x.())
.max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
.unwrap_or(0.0)
}
pub fn 低低(&self) -> f64 {
self.基础序列
2026-05-29 03:55:22 +08:00
.read()
.unwrap()
2026-05-25 02:16:35 +08:00
.iter()
.map(|x| x.())
.min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
.unwrap_or(0.0)
}
2026-05-29 03:55:22 +08:00
pub fn (&self) -> Arc<分型> {
Arc::clone(&self.基础序列.read().unwrap()[0].)
2026-05-25 02:16:35 +08:00
}
2026-05-29 03:55:22 +08:00
pub fn (&self) -> Arc<分型> {
Arc::clone(
&*self.基础序列.read().unwrap()[self.基础序列.read().unwrap().len() - 1]
.
.read()
.unwrap(),
)
2026-05-25 02:16:35 +08:00
}
2026-05-29 03:55:22 +08:00
pub fn 设置第三买卖线(&self, 线: Arc<虚线>) {
*self.第三买卖线.write().unwrap() = Some(线);
2026-05-25 02:16:35 +08:00
}
2026-05-25 04:26:15 +08:00
/// 获取序列 — 基础序列 + 第三买卖线(若有)
2026-05-29 03:55:22 +08:00
pub fn 获取序列(&self) -> Vec<Arc<虚线>> {
let mut 序列: Vec<Arc<虚线>> = self.基础序列.read().unwrap().clone();
if let Some(ref 三买) = *self.第三买卖线.read().unwrap() {
序列.push(Arc::clone(三买));
2026-05-25 04:26:15 +08:00
}
序列
}
2026-05-25 02:16:35 +08:00
pub fn 获取数据文本(&self) -> String {
2026-05-29 03:55:22 +08:00
let 第三买卖线_str = match &*self.第三买卖线.read().unwrap() {
2026-05-25 02:16:35 +08:00
Some(x) => format!("{}", x),
None => "None".to_string(),
};
2026-05-29 03:55:22 +08:00
let 本级_第三买卖线_str = match &*self.本级_第三买卖线.read().unwrap() {
2026-05-25 02:16:35 +08:00
Some(x) => format!("{}", x),
None => "None".to_string(),
};
format!(
"{}, {}, {}, 文:({},{}), 武:({},{}), {}, {}",
2026-05-29 03:55:22 +08:00
self.标识.read().unwrap(),
self.序号.load(Ordering::Relaxed),
self.级别.load(Ordering::Relaxed),
2026-05-29 15:43:02 +08:00
self.().时间戳(),
2026-05-25 02:16:35 +08:00
crate::utils::format_f64_g(self.().分型特征值),
2026-05-29 15:43:02 +08:00
self.().时间戳(),
2026-05-25 02:16:35 +08:00
crate::utils::format_f64_g(self.().分型特征值),
第三买卖线_str,
本级_第三买卖线_str,
)
}
/// 校验中枢合法性
2026-05-29 03:55:22 +08:00
pub fn 校验合法性(&self, 序列: &[Arc<虚线>]) -> bool {
let mut 有效序列 = self.基础序列.read().unwrap().clone();
let mut 无效序列: Vec<Arc<虚线>> = Vec::new();
for 元素 in self.基础序列.read().unwrap().iter() {
if !序列.iter().any(|x| Arc::as_ptr(x) == Arc::as_ptr(元素)) {
无效序列.push(Arc::clone(元素));
2026-05-25 04:26:15 +08:00
}
}
if !无效序列.is_empty() {
let 无效 = &无效序列[0];
if let Some(pos) = self
.基础序列
2026-05-29 03:55:22 +08:00
.read()
.unwrap()
2026-05-25 04:26:15 +08:00
.iter()
2026-05-29 03:55:22 +08:00
.position(|x| Arc::as_ptr(x) == Arc::as_ptr(无效))
2026-05-25 04:26:15 +08:00
{
2026-05-29 03:55:22 +08:00
有效序列 = self.基础序列.read().unwrap()[..pos].to_vec();
2026-05-25 04:26:15 +08:00
}
}
if 有效序列.len() < 3 {
2026-05-29 03:55:22 +08:00
*self.第三买卖线.write().unwrap() = None;
*self.本级_第三买卖线.write().unwrap() = None;
2026-05-25 04:26:15 +08:00
return false;
}
2026-05-29 03:55:22 +08:00
*self.基础序列.write().unwrap() = 有效序列;
2026-05-25 04:26:15 +08:00
let 中枢高 = self.();
let 中枢低 = self.();
有效序列 = Vec::new();
2026-05-29 03:55:22 +08:00
for 元素 in self.基础序列.read().unwrap().iter() {
2026-05-25 04:26:15 +08:00
if crate::types::相对方向::分析(中枢高, 中枢低, 元素.(), 元素.()).是否缺口()
{
break;
}
2026-05-29 03:55:22 +08:00
有效序列.push(Arc::clone(元素));
2026-05-25 04:26:15 +08:00
}
2026-05-29 03:55:22 +08:00
*self.基础序列.write().unwrap() = 有效序列;
2026-05-25 04:26:15 +08:00
2026-05-29 03:55:22 +08:00
if self.基础序列.read().unwrap().len() < 3 {
2026-05-25 04:26:15 +08:00
return false;
}
2026-05-29 03:55:22 +08:00
for i in 1..self.基础序列.read().unwrap().len() {
let = &self.基础序列.read().unwrap()[i - 1];
let = &self.基础序列.read().unwrap()[i];
2026-05-25 04:26:15 +08:00
if !.之后是() {
2026-05-25 02:16:35 +08:00
return false;
}
}
2026-05-25 04:26:15 +08:00
if !crate::types::相对方向::分析(
2026-05-29 03:55:22 +08:00
self.基础序列.read().unwrap()[0].(),
self.基础序列.read().unwrap()[0].(),
self.基础序列.read().unwrap()[2].(),
self.基础序列.read().unwrap()[2].(),
2026-05-25 04:26:15 +08:00
)
.是否缺口()
{
let 重叠高 = self.();
let 重叠低 = self.();
if 重叠低 > 重叠高 {
2026-05-25 02:16:35 +08:00
return false;
}
}
2026-05-25 04:26:15 +08:00
2026-05-29 03:55:22 +08:00
let 三买线_opt = self.第三买卖线.read().unwrap().clone();
if let Some(ref 三买线) = 三买线_opt {
if 序列.iter().any(|x| Arc::as_ptr(x) == Arc::as_ptr(三买线)) {
if !self.基础序列.read().unwrap().last().unwrap().之后是(三买线) {
*self.第三买卖线.write().unwrap() = None;
2026-05-25 04:26:15 +08:00
} else if !crate::types::相对方向::分析(
self.(),
self.(),
三买线.(),
三买线.(),
)
.是否缺口()
{
2026-05-29 03:55:22 +08:00
self.添加虚线(Arc::clone(三买线));
*self.第三买卖线.write().unwrap() = None;
2026-05-25 04:26:15 +08:00
}
} else {
2026-05-29 03:55:22 +08:00
*self.第三买卖线.write().unwrap() = None;
2026-05-25 04:26:15 +08:00
}
}
2026-05-25 02:16:35 +08:00
true
}
2026-05-25 04:26:15 +08:00
/// 完整性 — 详见教你炒股票43:有关背驰的补习课
/// 不完整时下一个中枢大概率会与当前中枢发生扩展
pub fn 完整性(&self, 虚实: &str) -> bool {
2026-05-29 03:55:22 +08:00
if *self.基础序列.read().unwrap()[0].标识.read().unwrap() == "笔" {
return self.第三买卖线.read().unwrap().is_some();
2026-05-25 04:26:15 +08:00
}
2026-05-29 03:55:22 +08:00
let 基础序列_ref = self.基础序列.read().unwrap();
let 最后段 = 基础序列_ref.last().unwrap();
let 内部中枢_vec = if 虚实 == "合" {
最后段._中枢序列.read().unwrap()
2026-05-25 04:26:15 +08:00
} else {
2026-05-29 03:55:22 +08:00
最后段._中枢序列.read().unwrap()
2026-05-25 04:26:15 +08:00
};
2026-05-29 03:55:22 +08:00
for 内部中枢 in 内部中枢_vec.iter() {
2026-05-25 04:26:15 +08:00
if crate::types::相对方向::分析(
self.(),
self.(),
内部中枢.(),
内部中枢.(),
)
.是否缺口()
{
return true;
}
}
false
}
/// 获取扩展中枢 — 当基础序列 >= 9 时生成扩展中枢
pub fn 获取扩展中枢(
2026-05-29 03:55:22 +08:00
&self,
扩展中枢: &mut Vec<Arc<中枢>>,
配置: &crate::config::缠论配置,
2026-05-25 04:26:15 +08:00
) {
2026-05-29 03:55:22 +08:00
if self.基础序列.read().unwrap().len() >= 9 {
let mut 扩展线段: Vec<Arc<虚线>> = Vec::new();
let 基础序列_ref = self.基础序列.read().unwrap();
crate::algorithm::segment::线段::扩展分析(&基础序列_ref, &mut 扩展线段, 配置);
2026-05-25 04:26:15 +08:00
中枢::分析(
&扩展线段,
扩展中枢,
false,
2026-05-29 03:55:22 +08:00
&format!("{}_扩展中枢_", self.标识.read().unwrap()),
2026-05-25 04:26:15 +08:00
0,
);
}
}
/// 当前状态 — 详见教你炒股票49:利润率最大的操作模式
/// 返回当前中枢最后一段所处的位置关系:中枢之中/中枢之上/中枢之下
pub fn 当前状态(&self) -> &str {
2026-05-29 03:55:22 +08:00
let 基础序列_ref = self.基础序列.read().unwrap();
let 最后 = Arc::clone(基础序列_ref.last().unwrap());
2026-05-28 01:07:16 +08:00
let 尾部 = 最后.获取_武();
2026-05-29 03:55:22 +08:00
let 关系 = crate::types::相对方向::分析(
self.(),
self.(),
尾部...get(),
尾部...get(),
);
2026-05-25 04:26:15 +08:00
if 关系 == crate::types::相对方向::向上缺口 {
"中枢之上"
} else if 关系 == crate::types::相对方向::向下缺口 {
"中枢之下"
} else {
"中枢之中"
}
}
2026-05-25 02:16:35 +08:00
// ---- 关联函数 ----
/// 基础检查 — 三根虚线是否能形成中枢
pub fn 基础检查(: &虚线, : &虚线, : &虚线) -> bool {
if !.之后是() || !.之后是() {
return false;
}
2026-05-25 04:26:15 +08:00
let 关系 = crate::types::相对方向::分析(.(), .(), .(), .());
matches!(
关系,
crate::types::相对方向::向下
| crate::types::相对方向::向上
| crate::types::相对方向::
| crate::types::相对方向::
| crate::types::相对方向::
)
2026-05-25 02:16:35 +08:00
}
/// 创建中枢
2026-05-25 04:26:15 +08:00
pub fn 创建(
2026-05-29 03:55:22 +08:00
: Arc<虚线>, : Arc<虚线>, : Arc<虚线>, 级别: i64, 标识: &str
2026-05-25 04:26:15 +08:00
) -> Self {
Self::new(
0,
2026-05-29 03:55:22 +08:00
format!("{}中枢<{}>", 标识, .标识.read().unwrap()),
2026-05-25 04:26:15 +08:00
级别,
vec![, , ],
)
2026-05-25 02:16:35 +08:00
}
/// 从序列中获取中枢
pub fn 从序列中获取中枢(
2026-05-29 03:55:22 +08:00
虚线序列: &[Arc<虚线>],
2026-05-25 02:16:35 +08:00
起始方向: 相对方向,
标识: &str,
2026-05-29 03:55:22 +08:00
) -> Option<Arc<中枢>> {
2026-05-25 02:16:35 +08:00
for i in 2..虚线序列.len() {
let = &虚线序列[i - 2];
let = &虚线序列[i - 1];
let = &虚线序列[i];
if Self::基础检查(, , ) && .方向() == 起始方向 {
2026-05-29 03:55:22 +08:00
let 中枢 = Self::创建(Arc::clone(), Arc::clone(), Arc::clone(), 0, 标识);
return Some(Arc::new(中枢));
2026-05-25 02:16:35 +08:00
}
}
None
}
/// 向中枢序列尾部添加
2026-05-25 04:26:15 +08:00
pub fn 向中枢序列尾部添加(
2026-05-29 03:55:22 +08:00
中枢序列: &mut Vec<Arc<中枢>>, mut 待添加中枢: Arc<中枢>
2026-05-25 04:26:15 +08:00
) {
2026-05-25 02:16:35 +08:00
if let Some(前一个) = 中枢序列.last() {
2026-05-29 03:55:22 +08:00
待添加中枢
.序号
.store(前一个.序号.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
2026-05-25 04:26:15 +08:00
// Python: assert seq[-1].获取序列()[-1].序号 <= new.获取序列()[-1].序号
let _seq = 前一个.获取序列();
2026-05-29 03:55:22 +08:00
let new_seq = 待添加中枢.获取序列();
2026-05-25 04:26:15 +08:00
if let (Some(_last), Some(new_last)) = (_seq.last(), new_seq.last()) {
2026-05-29 03:55:22 +08:00
if _last.序号.load(Ordering::Relaxed) > new_last.序号.load(Ordering::Relaxed)
{
2026-05-25 04:26:15 +08:00
panic!(
"向中枢序列尾部添加 序号错误 前last={} > new_last={}",
2026-05-29 03:55:22 +08:00
_last.序号.load(Ordering::Relaxed),
new_last.序号.load(Ordering::Relaxed)
2026-05-25 04:26:15 +08:00
);
}
2026-05-25 02:16:35 +08:00
}
}
2026-05-25 04:26:15 +08:00
中枢序列.push(待添加中枢);
2026-05-25 02:16:35 +08:00
}
/// 从中枢序列尾部弹出
2026-05-25 04:26:15 +08:00
pub fn 从中枢序列尾部弹出(
2026-05-29 03:55:22 +08:00
中枢序列: &mut Vec<Arc<中枢>>,
待弹出: &Arc<中枢>,
) -> Option<Arc<中枢>> {
if 中枢序列.last().map(|x| Arc::as_ptr(x)) == Some(Arc::as_ptr(待弹出)) {
2026-05-25 02:16:35 +08:00
中枢序列.pop()
} else {
None
}
}
/// 中枢分析 — 从虚线序列生成中枢序列(增量算法)
///
/// 每收到新的虚线序列数据后调用,更新中枢序列
pub fn 分析(
2026-05-29 03:55:22 +08:00
虚线序列: &[Arc<虚线>],
中枢序列: &mut Vec<Arc<中枢>>,
2026-05-25 02:16:35 +08:00
跳过首部: bool,
标识: &str,
层级: i64,
) {
if 虚线序列.len() < 3 {
return;
}
// 初始化第一个中枢
if 中枢序列.is_empty() {
for i in 1..虚线序列.len() - 1 {
let = &虚线序列[i - 1];
let = &虚线序列[i];
let = &虚线序列[i + 1];
if Self::基础检查(, , ) {
// Python: 序号 = 虚线序列.index(左)
2026-05-25 04:26:15 +08:00
let 序号 = 虚线序列
.iter()
2026-05-29 03:55:22 +08:00
.position(|x| Arc::as_ptr(x) == Arc::as_ptr())
2026-05-25 04:26:15 +08:00
.unwrap_or(i - 1);
2026-05-29 03:55:22 +08:00
if 跳过首部 && (.序号.load(Ordering::Relaxed) == 0 || 序号 == 0) {
2026-05-25 02:16:35 +08:00
continue;
}
if 序号 >= 2 {
let = &虚线序列[序号 - 2];
2026-05-25 04:26:15 +08:00
let 同向相对关系 =
crate::types::相对方向::分析(.(), .(), .(), .());
2026-05-25 02:16:35 +08:00
if 同向相对关系.是否向上() && .方向().是否向上() {
continue;
}
if 同向相对关系.是否向下() && .方向().是否向下() {
continue;
}
}
2026-05-29 03:55:22 +08:00
let 新中枢 = Arc::new(Self::创建(
Arc::clone(),
Arc::clone(),
Arc::clone(),
.级别.load(Ordering::Relaxed),
2026-05-25 02:16:35 +08:00
标识,
));
Self::向中枢序列尾部添加(中枢序列, 新中枢);
// Python: return 中枢递归分析(虚线序列, 中枢序列, ...)
Self::分析(虚线序列, 中枢序列, 跳过首部, 标识, 层级);
return;
}
}
return;
}
// 增量更新
2026-05-25 04:26:15 +08:00
let mut 当前中枢_idx = 中枢序列.len() - 1;
2026-05-25 02:16:35 +08:00
2026-05-29 03:55:22 +08:00
// Validate via shared reference (中枢 uses RwLock internally)
let needs_pop = !中枢序列[当前中枢_idx].校验合法性(虚线序列);
2026-05-25 04:26:15 +08:00
if needs_pop {
2026-05-29 03:55:22 +08:00
let 当前中枢 = Arc::clone(&中枢序列[当前中枢_idx]);
2026-05-25 02:16:35 +08:00
Self::从中枢序列尾部弹出(中枢序列, &当前中枢);
Self::分析(虚线序列, 中枢序列, 跳过首部, 标识, 层级);
return;
}
// 找到当前中枢最后一个元素在虚线序列中的位置
2026-05-25 04:26:15 +08:00
let 起始索引 = {
let cur = &中枢序列[当前中枢_idx];
2026-05-29 03:55:22 +08:00
let 最后元素 = &cur.基础序列.read().unwrap()[cur.基础序列.read().unwrap().len() - 1];
2026-05-25 04:26:15 +08:00
match 虚线序列
.iter()
2026-05-29 03:55:22 +08:00
.position(|x| Arc::as_ptr(x) == Arc::as_ptr(最后元素))
2026-05-25 04:26:15 +08:00
{
Some(idx) => idx + 1,
None => return,
}
2026-05-25 02:16:35 +08:00
};
2026-05-25 04:26:15 +08:00
let mut 中枢高 = 中枢序列[当前中枢_idx].();
let mut 中枢低 = 中枢序列[当前中枢_idx].();
2026-05-29 03:55:22 +08:00
let mut 候选序列: Vec<Arc<虚线>> = Vec::new();
2026-05-25 02:16:35 +08:00
for i in 起始索引..虚线序列.len() {
2026-05-29 03:55:22 +08:00
let 当前虚线 = Arc::clone(&虚线序列[i]);
2026-05-25 02:16:35 +08:00
// 检查是否超出中枢范围(缺口)
2026-05-25 04:26:15 +08:00
if crate::types::相对方向::分析(中枢高, 中枢低, 当前虚线.(), 当前虚线.()).是否缺口()
{
2026-05-25 02:16:35 +08:00
候选序列.push(当前虚线.clone());
// Python: if 当前中枢.基础序列[-1].之后是(当前虚线):
2026-05-25 04:26:15 +08:00
let needs_三买 = {
let cur = &中枢序列[当前中枢_idx];
2026-05-29 03:55:22 +08:00
cur.基础序列
.read()
.unwrap()
.last()
.unwrap()
.之后是(&当前虚线)
2026-05-25 04:26:15 +08:00
};
if needs_三买 {
2026-05-29 03:55:22 +08:00
中枢序列[当前中枢_idx].设置第三买卖线(当前虚线.clone());
2026-05-25 02:16:35 +08:00
}
} else {
if 候选序列.is_empty() {
// 仍在范围内:延伸中枢
2026-05-29 03:55:22 +08:00
中枢序列[当前中枢_idx].添加虚线(当前虚线);
2026-05-25 02:16:35 +08:00
} else {
候选序列.push(当前虚线);
}
}
// 候选序列积满3个:尝试创建新中枢
while 候选序列.len() >= 3 {
2026-05-25 04:26:15 +08:00
let 起始方向 = 中枢序列[当前中枢_idx]
.基础序列
2026-05-29 03:55:22 +08:00
.read()
.unwrap()
2026-05-25 04:26:15 +08:00
.last()
.unwrap()
.方向()
.翻转();
2026-05-25 02:16:35 +08:00
match Self::从序列中获取中枢(&候选序列, 起始方向, 标识) {
Some(新中枢) => {
Self::向中枢序列尾部添加(中枢序列, 新中枢);
2026-05-25 04:26:15 +08:00
// Python: 当前中枢 = 新中枢
当前中枢_idx = 中枢序列.len() - 1;
中枢高 = 中枢序列[当前中枢_idx].();
中枢低 = 中枢序列[当前中枢_idx].();
候选序列.clear();
2026-05-25 02:16:35 +08:00
}
None => {
候选序列.remove(0); // 滑动窗口
}
}
}
}
}
}
2026-05-29 03:55:22 +08:00
#[cfg(test)]
mod tests {
use super::*;
use crate::kline::bar::K线;
use crate::kline::chan_kline::缠论K线;
use crate::structure::fractal_obj::分型;
use crate::types::分型结构;
fn 辅助_创建K线(时间戳: i64, : f64, : f64, : f64, : f64) -> K线 {
let mut k = K线::default();
k.时间戳 = 时间戳;
k. = ;
k. = ;
k.开盘价 = ;
k.收盘价 = ;
k
}
fn 辅助_创建缠K(
时间戳: i64,
: f64,
: f64,
方向: 相对方向,
结构: Option<分型结构>,
序号: i64,
) -> Arc<缠论K线> {
let K = Arc::new(辅助_创建K线(时间戳, , , , ));
Arc::new(缠论K线::创建缠K(
时间戳, , , 方向, 结构, 序号, K, None,
))
}
fn 辅助_创建顶分型(时间戳: i64, : f64, : f64, 序号: i64) -> Arc<分型> {
let = 辅助_创建缠K(
时间戳 - 2,
- 2.0,
- 2.0,
相对方向::向上,
Some(分型结构::),
序号 - 2,
);
let = 辅助_创建缠K(时间戳, , , 相对方向::向上, Some(分型结构::), 序号);
let = 辅助_创建缠K(
时间戳 + 2,
- 1.0,
- 1.0,
相对方向::向下,
Some(分型结构::),
序号 + 2,
);
Arc::new(分型::new(Some(), , Some()))
}
fn 辅助_创建底分型(时间戳: i64, : f64, : f64, 序号: i64) -> Arc<分型> {
let = 辅助_创建缠K(
时间戳 - 2,
+ 2.0,
+ 2.0,
相对方向::向下,
Some(分型结构::),
序号 - 2,
);
let = 缠论K线::创建缠K(
时间戳,
,
,
相对方向::向下,
Some(分型结构::),
序号,
Arc::new(辅助_创建K线(时间戳, , , , )),
None,
);
.分型特征值.set();
let = Arc::new();
let = 辅助_创建缠K(
时间戳 + 2,
+ 1.0,
+ 1.0,
相对方向::向上,
Some(分型结构::),
序号 + 2,
);
Arc::new(分型::new(Some(), , Some()))
}
fn 辅助_创建笔(
文时间戳: i64,
文高: f64,
文低: f64,
武时间戳: i64,
武高: f64,
武低: f64,
) -> Arc<虚线> {
let = 辅助_创建顶分型(文时间戳, 文高, 文低, 1);
let = 辅助_创建底分型(武时间戳, 武高, 武低, 2);
Arc::new(虚线::创建笔(, , true))
}
// ============================================================
// 中枢 Cell/RefCell 字段读写
// ============================================================
#[test]
fn test_中枢创建后字段初始值正确() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 中枢 = 中枢::new(
1,
"测试中枢".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
assert_eq!(中枢.序号.load(Ordering::Relaxed), 1);
assert_eq!(*中枢.标识.read().unwrap(), "测试中枢");
assert_eq!(中枢.级别.load(Ordering::Relaxed), 1);
assert_eq!(中枢.基础序列.read().unwrap().len(), 3);
assert!(中枢.第三买卖线.read().unwrap().is_none());
assert!(中枢.本级_第三买卖线.read().unwrap().is_none());
}
#[test]
fn test_中枢CellRefCell字段读写() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 中枢 = 中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
// Cell 序号读写
中枢.序号.store(99, Ordering::Relaxed);
assert_eq!(中枢.序号.load(Ordering::Relaxed), 99);
// RefCell 第三买卖线读写
中枢.设置第三买卖线(Arc::clone(&1));
assert!(中枢.第三买卖线.read().unwrap().is_some());
assert_eq!(
Arc::as_ptr(&*中枢.第三买卖线.read().unwrap().as_ref().unwrap()),
Arc::as_ptr(&1)
);
// 本级_第三买卖线
assert!(中枢.本级_第三买卖线.read().unwrap().is_none());
*中枢.本级_第三买卖线.write().unwrap() = Some(Arc::clone(&3));
assert!(中枢.本级_第三买卖线.read().unwrap().is_some());
}
// ============================================================
// 中枢 添加虚线
// ============================================================
#[test]
fn test_中枢添加虚线后基础序列扩展() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 4 = 辅助_创建笔(400, 25.0, 15.0, 500, 60.0, 50.0);
let 中枢 = 中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
assert_eq!(中枢.基础序列.read().unwrap().len(), 3);
中枢.添加虚线(Arc::clone(&4));
assert_eq!(中枢.基础序列.read().unwrap().len(), 4);
assert_eq!(
Arc::as_ptr(&中枢.基础序列.read().unwrap()[3]),
Arc::as_ptr(&4)
);
}
#[test]
fn test_中枢添加虚线后清除第三买卖线() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 4 = 辅助_创建笔(400, 25.0, 15.0, 500, 60.0, 50.0);
let 中枢 = 中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
中枢.设置第三买卖线(Arc::clone(&1));
*中枢.本级_第三买卖线.write().unwrap() = Some(Arc::clone(&2));
assert!(中枢.第三买卖线.read().unwrap().is_some());
assert!(中枢.本级_第三买卖线.read().unwrap().is_some());
中枢.添加虚线(Arc::clone(&4));
// 添加虚线后第三买卖线被清除
assert!(中枢.第三买卖线.read().unwrap().is_none());
assert!(中枢.本级_第三买卖线.read().unwrap().is_none());
}
// ============================================================
// Clone 后 Rc 指针身份一致
// ============================================================
#[test]
fn test_中枢Clone后基础序列Rc指针一致() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 中枢 = 中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
中枢.设置第三买卖线(Arc::clone(&1));
let 克隆 = 中枢.clone();
// 基础序列中的 Rc 指针应一致
for i in 0..3 {
assert_eq!(
Arc::as_ptr(&中枢.基础序列.read().unwrap()[i]),
Arc::as_ptr(&克隆.基础序列.read().unwrap()[i])
);
}
// 第三买卖线 Rc 指针应一致
assert_eq!(
Arc::as_ptr(中枢.第三买卖线.read().unwrap().as_ref().unwrap()),
Arc::as_ptr(克隆.第三买卖线.read().unwrap().as_ref().unwrap())
);
}
// ============================================================
// 中枢 高/低/高高/低低计算
// ============================================================
#[test]
fn test_中枢高低计算正确() {
// 笔1: 顶(高=50,低=45) →底(高=40,低=30) = 向下笔, 高=50, 低=30
let 1 = 辅助_创建笔(100, 50.0, 45.0, 200, 40.0, 30.0);
// 笔2: 底(高=40,低=30) →顶(高=55,低=50) = 向上笔, 高=55, 低=30
let 2 = 辅助_创建底分型(200, 40.0, 30.0, 10);
let 2 = 辅助_创建顶分型(300, 55.0, 50.0, 15);
let 2 = Arc::new(虚线::创建笔(2, 2, true));
// 笔3: 顶(高=55,低=50) →底(高=35,低=25) = 向下笔, 高=55, 低=25
let 3 = 辅助_创建笔(300, 55.0, 50.0, 400, 35.0, 25.0);
let 中枢 = 中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
);
// 高 = min(笔1高, 笔2高, 笔3高) = min(50, 55, 55) = 50
assert!((中枢.() - 50.0).abs() < 0.01, "中枢高={}", 中枢.());
// 低 = max(笔1低, 笔2低, 笔3低) = max(30, 30, 25) = 30
assert!((中枢.() - 30.0).abs() < 0.01, "中枢低={}", 中枢.());
}
// ============================================================
// 多 Rc 共享下修改可见性
// ============================================================
#[test]
fn test_多Rc共享中枢修改对所有引用可见() {
let 1 = 辅助_创建笔(100, 50.0, 40.0, 200, 30.0, 20.0);
let 2 = 辅助_创建笔(200, 30.0, 20.0, 300, 55.0, 45.0);
let 3 = 辅助_创建笔(300, 55.0, 45.0, 400, 25.0, 15.0);
let 4 = 辅助_创建笔(400, 25.0, 15.0, 500, 60.0, 50.0);
let 中枢1 = Arc::new(中枢::new(
0,
"测试".into(),
1,
vec![Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)],
));
let 中枢2 = Arc::clone(&中枢1);
// 通过 rc1 修改序号
中枢1.序号.store(88, Ordering::Relaxed);
assert_eq!(中枢2.序号.load(Ordering::Relaxed), 88);
// 通过 rc1 添加虚线
中枢1.添加虚线(Arc::clone(&4));
assert_eq!(中枢2.基础序列.read().unwrap().len(), 4);
// 验证共享的 Arc<虚线> 指针一致
assert_eq!(
Arc::as_ptr(&中枢1.基础序列.read().unwrap()[3]),
Arc::as_ptr(&中枢2.基础序列.read().unwrap()[3])
);
}
}
2026-05-25 02:16:35 +08:00
impl std::fmt::Display for 中枢 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let 序列_str = self
.基础序列
2026-05-29 03:55:22 +08:00
.read()
.unwrap()
2026-05-25 02:16:35 +08:00
.iter()
.map(|d| format!("{}", d))
.collect::<Vec<_>>()
.join(", ");
write!(
f,
"{}({}, {}, 元素数量: {}, [{}], {} ===>>> {})",
2026-05-29 03:55:22 +08:00
self.标识.read().unwrap(),
2026-05-25 02:16:35 +08:00
crate::utils::format_f64_g(self.()),
crate::utils::format_f64_g(self.()),
2026-05-29 03:55:22 +08:00
self.基础序列.read().unwrap().len(),
2026-05-25 02:16:35 +08:00
序列_str,
self.(),
self.(),
)
}
}