修复 rust 引用问题

This commit is contained in:
YuWuKunCheng
2026-05-28 01:07:16 +08:00
parent 4908870245
commit 52823e6c75
19 changed files with 1777 additions and 323 deletions
+95 -46
View File
@@ -28,8 +28,8 @@ use std::rc::Rc;
use crate::business_py::Py;
use crate::config_py::Py;
use crate::kline_py::K线Py;
use crate::structure_py::{Py, 线Py};
use crate::kline_py::{K线Py, K线Py};
use crate::structure_py::{Py, 线Py, 线Py};
use crate::types_py::Py;
// ========== 背驰分析 ==========
@@ -61,7 +61,7 @@ impl 背驰分析Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K线序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::algorithm::divergence::::MACD背驰(
&.borrow().inner,
@@ -105,7 +105,7 @@ impl 背驰分析Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::algorithm::divergence::::(
&.borrow().inner,
@@ -124,7 +124,7 @@ impl 背驰分析Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::algorithm::divergence::::(
&.borrow().inner,
@@ -144,7 +144,7 @@ impl 背驰分析Py {
) -> PyResult<bool> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
let config = .borrow().to_rust_config(py)?;
Ok(chanlun::algorithm::divergence::::(
@@ -165,7 +165,7 @@ impl 背驰分析Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::algorithm::divergence::::(
&.borrow().inner,
@@ -186,7 +186,7 @@ impl 背驰分析Py {
) -> PyResult<bool> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
let config = .borrow().to_rust_config(py)?;
Ok(chanlun::algorithm::divergence::::(
@@ -251,7 +251,7 @@ impl 笔Py {
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
.collect();
chanlun::algorithm::bi::::(&ck_list, )
.map(|inner| crate::kline_py::K线Py { inner })
.map(|inner| crate::kline_py::K线Py::from_rc(inner))
}
#[classmethod]
@@ -266,7 +266,7 @@ impl 笔Py {
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
.collect();
chanlun::algorithm::bi::::(&ck_list, )
.map(|inner| crate::kline_py::K线Py { inner })
.map(|inner| crate::kline_py::K线Py::from_rc(inner))
}
#[classmethod]
@@ -281,7 +281,7 @@ impl 笔Py {
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
.collect();
chanlun::algorithm::bi::::(&ck_list, )
.map(|inner| crate::kline_py::K线Py { inner })
.map(|inner| crate::kline_py::K线Py::from_rc(inner))
}
#[classmethod]
@@ -296,7 +296,7 @@ impl 笔Py {
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
.collect();
chanlun::algorithm::bi::::(&ck_list, )
.map(|inner| crate::kline_py::K线Py { inner })
.map(|inner| crate::kline_py::K线Py::from_rc(inner))
}
#[classmethod]
@@ -361,16 +361,20 @@ impl 笔Py {
}
#[classmethod]
#[pyo3(signature = (当前分型, 分型序列, 笔序列, 缠K序列, 普K序列, 递归层次, 配置))]
fn (
_cls: &Bound<'_, PyType>,
: &Bound<'_, Py>,
: Option<&Bound<'_, Py>>,
: Vec<Py<Py>>,
: Vec<Py<线Py>>,
K序列: Vec<Py<crate::kline_py::K线Py>>,
K序列: Vec<Py<K线Py>>,
: i64,
: &Bound<'_, Py>,
py: Python<'_>,
) -> PyResult<i64> {
let _ = ; // Python API 兼容参数,核心从0开始计数
let _rc = .map(|f| Rc::clone(&f.borrow().inner));
let mut fr_seq: Vec<Rc<chanlun::structure::fractal_obj::>> =
.iter()
.map(|f| Rc::clone(&f.bind(py).borrow().inner))
@@ -385,17 +389,20 @@ impl 笔Py {
.collect();
let bar_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
let config = .borrow().to_rust_config(py)?;
Ok(chanlun::algorithm::bi::::(
Rc::clone(&.borrow().inner),
&mut fr_seq,
&mut bi_seq,
&ck_list,
&bar_list,
&config,
))
match _rc {
Some(fr) => Ok(chanlun::algorithm::bi::::(
fr,
&mut fr_seq,
&mut bi_seq,
&ck_list,
&bar_list,
&config,
)),
None => Ok(),
}
}
#[classmethod]
@@ -424,7 +431,7 @@ impl 笔Py {
.collect();
let bar_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
let config = .borrow().to_rust_config(py)?;
Ok(chanlun::algorithm::bi::::(
@@ -468,12 +475,12 @@ impl 笔Py {
_cls: &Bound<'_, PyType>,
: &Bound<'_, 线Py>,
: &Bound<'_, Py>,
) -> Vec<Py> {
) -> Vec<K线Py> {
let obs = .borrow();
let obs_ref = obs.obs();
chanlun::algorithm::bi::::(&.borrow().inner, &*obs_ref)
.into_iter()
.map(|f| Py { inner: f })
.map(|ck| K线Py::from_rc(ck))
.collect()
}
}
@@ -620,10 +627,26 @@ impl 线段Py {
: &Bound<'_, PyAny>,
: u32,
) -> PyResult<()> {
// 特征序列 contains Option<Rc<线段特征>>, skip for now
let seq: Vec<Option<Rc<chanlun::structure::segment_feat::线>>> = if .is_none() {
vec![]
} else if let Ok(list) = .downcast::<pyo3::types::PyList>() {
let mut result = Vec::with_capacity(list.len());
for item in list.iter() {
if item.is_none() {
result.push(None);
} else {
let feat: PyRef<'_, 线Py> = item.extract()?;
result.push(Some(Rc::clone(&feat.inner)));
}
}
result
} else {
return Err(pyo3::exceptions::PyTypeError::new_err(
"序列 必须是 list 或 None",
));
};
let mut ref_mut = .borrow_mut();
// Just pass empty vec for now — 线段特征Py not fully integrated
chanlun::algorithm::segment::线::(&mut ref_mut.inner, vec![], );
chanlun::algorithm::segment::线::(&mut ref_mut.inner, seq, );
Ok(())
}
@@ -658,9 +681,17 @@ impl 线段Py {
Vec<Py<线Py>>,
Option<Py<线Py>>,
)> {
// 所属中枢 extraction is complex — pass None for now
let (a, b, c, d) =
chanlun::algorithm::segment::线::(&.borrow().inner, None);
let borrowed = .borrow();
let (a, b, c, d) = if let Some(hub_bound) = {
if let Ok(mut hub_ref) = hub_bound.extract::<PyRefMut<'_, Py>>() {
let inner_mut = Rc::make_mut(&mut hub_ref.inner);
chanlun::algorithm::segment::线::(&borrowed.inner, Some(inner_mut))
} else {
chanlun::algorithm::segment::线::(&borrowed.inner, None)
}
} else {
chanlun::algorithm::segment::线::(&borrowed.inner, None)
};
let wrap = |v: Vec<Rc<chanlun::structure::dash_line::线>>| -> PyResult<Vec<Py<线Py>>> {
let mut result = Vec::new();
for x in v {
@@ -945,20 +976,17 @@ impl 线段Py {
}
#[classmethod]
fn (
fn (
_cls: &Bound<'_, PyType>,
: &Bound<'_, 线Py>,
: &Bound<'_, Py>,
) -> Vec<线Py> {
let obs = .borrow();
let obs_ref = obs.obs();
chanlun::algorithm::segment::线::(
&.borrow().inner,
&*obs_ref,
)
.into_iter()
.map(|d| 线Py { inner: Rc::new(d) })
.collect()
chanlun::algorithm::segment::线::(&.borrow().inner, &*obs_ref)
.into_iter()
.map(|d| 线Py { inner: Rc::new(d) })
.collect()
}
#[classmethod]
@@ -966,12 +994,12 @@ impl 线段Py {
_cls: &Bound<'_, PyType>,
: &Bound<'_, 线Py>,
: &Bound<'_, Py>,
) -> Vec<Py> {
) -> Vec<K线Py> {
let obs = .borrow();
let obs_ref = obs.obs();
chanlun::algorithm::segment::线::(&.borrow().inner, &*obs_ref)
.into_iter()
.map(|f| Py { inner: f })
.map(|ck| K线Py::from_rc(ck))
.collect()
}
}
@@ -1153,7 +1181,14 @@ impl 中枢Py {
self.inner.()
}
fn (&mut self, : Vec<Py<线Py>>, py: Python<'_>) -> bool {
#[pyo3(signature = (序列, 中枢序列 = None))]
fn (
&mut self,
: Vec<Py<线Py>>,
: Option<Vec<Py<线Py>>>,
py: Python<'_>,
) -> bool {
let _ = ; // Python 版声明了此参数但未使用
let rc_list: Vec<Rc<chanlun::structure::dash_line::线>> =
.iter()
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
@@ -1167,18 +1202,21 @@ impl 中枢Py {
self.inner.()
}
fn (&self, : Vec<Py<Self>>, py: Python<'_>) -> PyResult<()> {
fn (
&self,
: Vec<Py<Self>>,
: &Bound<'_, crate::config_py::Py>,
py: Python<'_>,
) -> PyResult<()> {
let mut hub_seq: Vec<Rc<chanlun::algorithm::hub::>> =
.iter()
.map(|h| Rc::clone(&h.bind(py).borrow().inner))
.collect();
// Need config for this call — use default
let config = chanlun::config::::default();
let config = .borrow().to_rust_config(.py())?;
self.inner.(&mut hub_seq, &config);
Ok(())
}
#[getter]
fn (&self) -> String {
self.inner.().to_string()
}
@@ -1191,6 +1229,17 @@ impl 中枢Py {
self.__str__()
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
// ---- classmethods ----
#[classmethod]
+162 -53
View File
@@ -63,7 +63,7 @@ impl 基础买卖点Py {
Self {
inner: chanlun::business::bsp::::new(
.borrow().inner,
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
Rc::clone(&.borrow().inner),
,
,
@@ -76,6 +76,12 @@ impl 基础买卖点Py {
self.inner..clone()
}
#[setter]
#[pyo3(name = "备注")]
fn _备注(&mut self, value: String) {
self.inner. = value;
}
#[getter]
fn (&self) -> Py {
Py {
@@ -92,29 +98,27 @@ impl 基础买卖点Py {
#[getter]
fn K线(&self) -> K线Py {
K线Py {
inner: Rc::clone(&self.inner.K线),
}
K线Py::from_rc(Rc::clone(&self.inner.K线))
}
#[getter]
fn K线(&self) -> K线Py {
K线Py {
inner: (*self.inner.K线).clone(),
inner: self.inner.K线.clone(),
}
}
#[getter]
fn K线(&self) -> Option<K线Py> {
self.inner.K线.as_ref().map(|k| K线Py {
inner: (**k).clone(),
inner: Rc::clone(k),
})
}
#[getter]
fn K线(&self) -> Option<K线Py> {
self.inner.K线.as_ref().map(|k| K线Py {
inner: (**k).clone(),
inner: Rc::clone(k),
})
}
@@ -130,10 +134,12 @@ impl 基础买卖点Py {
.map(|f| crate::types_py::Py { inner: f })
}
#[getter]
fn (&self) -> i64 {
self.inner.()
}
#[getter]
fn (&self) -> i64 {
self.inner.()
}
@@ -187,7 +193,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -207,7 +213,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -227,7 +233,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -247,7 +253,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -267,7 +273,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -287,7 +293,7 @@ impl 买卖点Py {
Py {
inner: chanlun::business::bsp::::(
Rc::clone(&.borrow().inner),
Rc::new(K线.borrow().inner.clone()),
K线.borrow().inner.clone(),
,
,
,
@@ -370,33 +376,68 @@ impl 观察者Py {
#[pymethods]
impl Py {
/// __new__ 只分配空壳,构造逻辑在 __init__
/// __new__ 从 *args/**kwargs 中提取 (符号, 周期, 配置),完整初始化观察者。
/// 由于形参可变(子类参数各异),不依赖固定签名,而是从 args/kwargs 中按位置和名称智能提取。
#[new]
#[pyo3(signature = (*args, **kwargs))]
fn new(
args: &Bound<'_, pyo3::types::PyTuple>,
kwargs: Option<&Bound<'_, pyo3::types::PyDict>>,
) -> Self {
let _ = (args, kwargs);
Self { inner: None }
) -> PyResult<Self> {
let py = args.py();
// 提取 符号(位置 0 或关键字)
let : String = if !args.is_empty() {
args.get_item(0)?.extract()?
} else {
match kwargs.and_then(|kw| kw.get_item("符号").ok().flatten()) {
Some(val) => val.extract()?,
None => return Err(pyo3::exceptions::PyTypeError::new_err("缺少参数: 符号")),
}
};
// 提取 周期(位置 1 或关键字)
let : i64 = if args.len() >= 2 {
args.get_item(1)?.extract()?
} else {
match kwargs.and_then(|kw| kw.get_item("周期").ok().flatten()) {
Some(val) => val.extract()?,
None => return Err(pyo3::exceptions::PyTypeError::new_err("缺少参数: 周期")),
}
};
// 提取 配置(关键字优先,然后扫描剩余位置参数)
let mut config = None;
if let Some(val) = kwargs.and_then(|kw| kw.get_item("配置").ok().flatten()) {
let cfg: PyRef<'_, Py> = val.extract()?;
config = Some(cfg.to_rust_config(py)?);
}
if config.is_none() {
for i in 2..args.len() {
if let Ok(cfg) = args.get_item(i)?.extract::<PyRef<'_, Py>>() {
config = Some(cfg.to_rust_config(py)?);
break;
}
}
}
let config = config.unwrap_or_else(chanlun::config::::default);
Ok(Self {
inner: Some(chanlun::business::observer::::new(
, , config,
)),
})
}
/// __init__ 执行真正的构造。子类可重写并调用 super().__init__(符号, 周期, 配置)
#[pyo3(signature = (符号, 周期, 配置 = None))]
/// __init__ 不重复构造 — __new__ 已完成初始化。
/// 接收 *args/**kwargs 是为了兼容 Python 构造函数给 __init__ 传入的任意形参。
#[pyo3(signature = (*args, **kwargs))]
fn __init__(
&mut self,
py: Python<'_>,
: String,
: i64,
: Option<&Bound<'_, Py>>,
args: &Bound<'_, pyo3::types::PyTuple>,
kwargs: Option<&Bound<'_, pyo3::types::PyDict>>,
) -> PyResult<()> {
let config = match {
Some(cfg) => cfg.borrow().to_rust_config(py)?,
None => chanlun::config::::default(),
};
self.inner = Some(chanlun::business::observer::::new(
, , config,
));
let _ = (args, kwargs);
Ok(())
}
@@ -413,15 +454,15 @@ impl 观察者Py {
#[getter]
fn K线(&self) -> Option<K线Py> {
self.obs().K线().map(|k| K线Py {
inner: (**k).clone(),
inner: Rc::clone(k),
})
}
#[getter]
fn K(&self) -> Option<K线Py> {
self.obs().K().map(|k| K线Py {
inner: Rc::clone(k),
})
self.obs()
.K()
.map(|k| K线Py::from_rc(Rc::clone(k)))
}
#[getter]
@@ -444,7 +485,35 @@ impl 观察者Py {
}
fn K线(&mut self, K: &Bound<'_, K线Py>) {
self.obs_mut().K线(K.borrow().inner.clone());
self.obs_mut().K线((*K.borrow().inner).clone());
}
/// 加载本地数据 — 从 .nb 文件加载K线数据(先重置,再通过 Python dispatch 逐根投喂,
/// 确保子类重写的 增加原始K线 被正确调用)。
fn (slf: &Bound<'_, Self>, : &str) -> PyResult<()> {
let py = slf.py();
// 重置基础序列
slf.borrow_mut().obs_mut().();
// 解析文件得到 K线 列表
let bars = slf
.borrow()
.obs()
.()
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e))?;
// 通过 Python dispatch 逐根投喂,确保子类重写生效
for k线 in bars {
let k线_py = Py::new(
py,
K线Py {
inner: Rc::new(k线),
},
)?;
slf.call_method1("增加原始K线", (k线_py,))?;
}
Ok(())
}
fn (&mut self) {
@@ -456,19 +525,61 @@ impl 观察者Py {
}
#[classmethod]
#[pyo3(signature = (文件路径, 配置 = None))]
fn (
_cls: &Bound<'_, PyType>,
cls: &Bound<'_, PyType>,
: &str,
: Option<&Bound<'_, Py>>,
py: Python<'_>,
) -> PyResult<Self> {
) -> PyResult<Py<PyAny>> {
let config = match {
Some(cfg) => Some(cfg.borrow().to_rust_config(py)?),
None => None,
Some(cfg) => cfg.borrow().to_rust_config(py)?,
None => chanlun::config::::default(),
};
chanlun::business::observer::::(, config)
.map(|inner| Self { inner: Some(inner) })
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e))
// 从文件名解析 符号/周期: "btcusd-300-1761327300-1776327900.nb"
let path = std::path::Path::new();
let name = path
.file_stem()
.and_then(|n| n.to_str())
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("invalid filename"))?;
let parts: Vec<&str> = name.split('-').collect();
if parts.len() < 4 {
return Err(pyo3::exceptions::PyValueError::new_err(format!(
"invalid filename format: {}",
name
)));
}
let = parts[0].to_string();
let : i64 = parts[1]
.parse()
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("parse period: {}", e)))?;
// 通过 cls 构造实例(支持子类化)
let cfg_py = Py::from_rust_config(&config)?;
let cfg_obj = Py::new(py, cfg_py)?;
let obj = cls.call1((.clone(), , cfg_obj))?;
// 读取文件并通过 Python 分发逐根投喂(支持子类重写 增加原始K线)
let data = std::fs::read()
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("read file: {}", e)))?;
let size: usize = 48;
for i in 0..data.len() / size {
let offset = i * size;
if let Some(k线) =
chanlun::kline::bar::K线::from_bytes(&data[offset..offset + size], , &)
{
let k线_py = Py::new(
py,
K线Py {
inner: Rc::new(k线),
},
)?;
obj.call_method1("增加原始K线", (k线_py,))?;
}
}
Ok(obj.unbind())
}
// ---- 序列 getters ----
@@ -478,7 +589,7 @@ impl 观察者Py {
let list = pyo3::types::PyList::empty(py);
for k in &self.obs().K线序列 {
list.append(K线Py {
inner: (**k).clone(),
inner: Rc::clone(k),
})?;
}
Ok(list.into())
@@ -488,9 +599,7 @@ impl 观察者Py {
fn K线序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
let list = pyo3::types::PyList::empty(py);
for k in &self.obs().K线序列 {
list.append(K线Py {
inner: Rc::clone(k),
})?;
list.append(K线Py::from_rc(Rc::clone(k)))?;
}
Ok(list.into())
}
@@ -670,10 +779,10 @@ impl K线合成器Py {
K: &Bound<'_, K线Py>,
py: Python<'_>,
) -> PyResult<Vec<(i64, K线Py)>> {
let results = self.inner.K线(K.borrow().inner.clone());
let results = self.inner.K线((*K.borrow().inner).clone());
Ok(results
.into_iter()
.map(|(, k)| (, K线Py { inner: k }))
.map(|(, k)| (, K线Py { inner: Rc::new(k) }))
.collect())
}
@@ -701,14 +810,14 @@ impl K线合成器Py {
let results = self.inner.K线(k);
results
.into_iter()
.map(|(, k2)| (, K线Py { inner: k2 }))
.map(|(, k2)| (, K线Py { inner: Rc::new(k2) }))
.collect()
}
fn K线(&self, : i64) -> Option<K线Py> {
self.inner
.K线()
.map(|k| K线Py { inner: k.clone() })
self.inner.K线().map(|k| K线Py {
inner: Rc::new(k.clone()),
})
}
#[getter]
@@ -776,7 +885,7 @@ impl 立体分析器Py {
}
fn K线(&mut self, K: &Bound<'_, K线Py>) {
self.inner.K线(K.borrow().inner.clone());
self.inner.K线((*K.borrow().inner).clone());
}
fn (&self, : i64) -> Option<Py> {
+96 -8
View File
@@ -107,16 +107,18 @@ impl 缠论配置Py {
if let Some(kwargs) = kwargs {
for (key, value) in kwargs.iter() {
let key: String = key.extract()?;
if fields.contains_key(&key) {
fields.insert(key, value.clone().unbind());
} else {
if !fields.contains_key(&key) {
return Err(pyo3::exceptions::PyAttributeError::new_err(format!(
"缠论配置 没有字段: {key}"
)));
}
fields.insert(key, value.clone().unbind());
}
}
// 全部通过 serde_json 往返验证类型,统一处理字符串数字/布尔强制转换
let config = dict_to_rust_config(&fields)?;
let fields = config_to_field_dict(&config)?;
Ok(Self { fields })
}
@@ -132,7 +134,16 @@ impl 缠论配置Py {
fn __setattr__(&mut self, name: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
if self.fields.contains_key(name) {
self.fields.insert(name.to_string(), value.clone().unbind());
Ok(())
// 通过 serde 往返验证类型
match dict_to_rust_config(&self.fields) {
Ok(config) => {
self.fields = config_to_field_dict(&config)?;
Ok(())
}
Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!(
"配置转换失败: {e}"
))),
}
} else {
Err(pyo3::exceptions::PyAttributeError::new_err(format!(
"缠论配置 没有字段: {name}"
@@ -198,10 +209,13 @@ impl 缠论配置Py {
for (key, value) in data.iter() {
let key: String = key.extract()?;
fields.insert(key, value.clone().unbind());
if fields.contains_key(&key) {
fields.insert(key, value.clone().unbind());
}
}
dict_to_rust_config(&fields)?;
let config = dict_to_rust_config(&fields)?;
let fields = config_to_field_dict(&config)?;
Ok(Self { fields })
}
@@ -270,7 +284,8 @@ impl 缠论配置Py {
fields.insert(key, value.clone().unbind());
}
dict_to_rust_config(&fields)?;
let config = dict_to_rust_config(&fields)?;
let fields = config_to_field_dict(&config)?;
Ok(Self { fields })
}
@@ -313,11 +328,84 @@ fn dict_to_rust_config(
}
let dumps = json_mod.getattr("dumps")?;
let json_str: String = dumps.call1((dict,))?.extract()?;
serde_json::from_str(&json_str)
let mut value: serde_json::Value = serde_json::from_str(&json_str)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("配置转换失败: {e}")))?;
coerce_strings_to_numbers(&mut value);
serde_json::from_value(value)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("配置转换失败: {e}")))
})
}
/// 递归遍历 JSON Value,将数字/布尔字符串转为对应类型。
fn coerce_strings_to_numbers(value: &mut serde_json::Value) {
match value {
serde_json::Value::Object(map) => {
for (_, v) in map.iter_mut() {
coerce_strings_to_numbers(v);
}
}
serde_json::Value::Array(arr) => {
for v in arr.iter_mut() {
coerce_strings_to_numbers(v);
}
}
serde_json::Value::String(s) => {
// 先 clone 出独立副本,避免借用冲突
let cloned = s.clone();
if let Ok(n) = cloned.parse::<i64>() {
*value = serde_json::Value::Number(serde_json::Number::from(n));
} else if let Ok(n) = cloned.parse::<f64>() {
if n.is_finite() {
if let Some(num) = serde_json::Number::from_f64(n) {
*value = serde_json::Value::Number(num);
}
}
} else if cloned.eq_ignore_ascii_case("true") {
*value = serde_json::Value::Bool(true);
} else if cloned.eq_ignore_ascii_case("false") {
*value = serde_json::Value::Bool(false);
}
// 非数字非布尔的原样保留,不做任何修改
}
_ => {}
}
}
/// 将 Python 字符串数字/布尔值强制转为对应类型,非字符串保持不变。
/// 注:主代码路径现通过 serde 往返处理类型转换,此函数作为辅助保留。
#[allow(dead_code)]
fn coerce_py_value(value: &Bound<'_, PyAny>) -> PyResult<Py<PyAny>> {
let py = value.py();
let type_name: String = value.get_type().name()?.extract()?;
if type_name != "str" {
return Ok(value.clone().unbind());
}
let lower_obj = value.call_method0("lower")?;
let lower: String = lower_obj.extract()?;
if lower == "true" || lower == "false" {
let b = lower == "true";
let obj = pyo3::types::PyBool::new(py, b)
.to_owned()
.into_any()
.unbind();
return Ok(obj);
}
if let Ok(n) = lower.parse::<i64>() {
return Ok(n.into_pyobject(py)?.into_any().unbind());
}
if let Ok(n) = lower.parse::<f64>() {
if n.is_finite() {
return Ok(n.into_pyobject(py)?.into_any().unbind());
}
}
Ok(value.clone().unbind())
}
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Py>()?;
Ok(())
+157 -65
View File
@@ -25,6 +25,7 @@
use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyType};
use std::collections::HashMap;
use std::rc::Rc;
use crate::config_py::Py;
use crate::indicators_py::{线Py, Py, Py};
@@ -51,10 +52,9 @@ use crate::types_py::相对方向Py;
/// 获取MACD(K线序列, 计算方式, 快线周期?, 慢线周期?, 信号周期?) -> list[平滑异同移动平均线]
/// — 对整个K线序列批量计算 MACD
/// 截取(序列, 起点K线, 终点K线) -> list — 按时间戳截取K线区间
#[pyclass(name = "K线")]
#[derive(Clone)]
#[pyclass(name = "K线", unsendable)]
pub struct K线Py {
pub(crate) inner: chanlun::kline::bar::K线,
pub(crate) inner: Rc<chanlun::kline::bar::K线>,
}
#[pymethods]
@@ -73,7 +73,7 @@ impl K线Py {
: f64,
) -> Self {
Self {
inner: chanlun::kline::bar::K线 {
inner: Rc::new(chanlun::kline::bar::K线 {
: .to_string(),
,
,
@@ -86,7 +86,7 @@ impl K线Py {
macd: None,
rsi: None,
kdj: None,
},
}),
}
}
@@ -96,7 +96,7 @@ impl K线Py {
}
#[setter]
fn set_标识(&mut self, v: String) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -105,7 +105,7 @@ impl K线Py {
}
#[setter]
fn set_序号(&mut self, v: i64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -114,7 +114,7 @@ impl K线Py {
}
#[setter]
fn set_周期(&mut self, v: i64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -123,7 +123,7 @@ impl K线Py {
}
#[setter]
fn set_时间戳(&mut self, v: i64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -132,7 +132,7 @@ impl K线Py {
}
#[setter]
fn set_高(&mut self, v: f64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -141,7 +141,7 @@ impl K线Py {
}
#[setter]
fn set_低(&mut self, v: f64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -150,7 +150,7 @@ impl K线Py {
}
#[setter]
fn set_开盘价(&mut self, v: f64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -159,7 +159,7 @@ impl K线Py {
}
#[setter]
fn set_收盘价(&mut self, v: f64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -168,7 +168,7 @@ impl K线Py {
}
#[setter]
fn set_成交量(&mut self, v: f64) {
self.inner. = v;
Rc::make_mut(&mut self.inner). = v;
}
#[getter]
@@ -179,7 +179,7 @@ impl K线Py {
}
#[getter]
fn MACD(&self) -> Option<线Py> {
fn macd(&self) -> Option<线Py> {
self.inner
.macd
.as_ref()
@@ -187,7 +187,7 @@ impl K线Py {
}
#[getter]
fn RSI(&self) -> Option<Py> {
fn rsi(&self) -> Option<Py> {
self.inner
.rsi
.as_ref()
@@ -195,7 +195,7 @@ impl K线Py {
}
#[getter]
fn KDJ(&self) -> Option<Py> {
fn kdj(&self) -> Option<Py> {
self.inner
.kdj
.as_ref()
@@ -214,6 +214,17 @@ impl K线Py {
PyBytes::new(py, &self.inner.to_bytes()).into()
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
#[classmethod]
#[pyo3(signature = (标识, 时间戳, 开盘价, 最高价, 最低价, 收盘价, 成交量, 序号 = None, 周期 = None))]
fn K(
@@ -229,7 +240,7 @@ impl K线Py {
: Option<i64>,
) -> Self {
Self {
inner: chanlun::kline::bar::K线::K(
inner: Rc::new(chanlun::kline::bar::K线::K(
,
,
,
@@ -239,7 +250,7 @@ impl K线Py {
,
.unwrap_or(0),
.unwrap_or(60),
),
)),
}
}
@@ -251,7 +262,7 @@ impl K线Py {
py: Python<'_>,
) -> PyResult<()> {
let refs: Vec<_> = K线序列.iter().map(|k| k.bind(py).borrow()).collect();
let bars: Vec<&chanlun::kline::bar::K线> = refs.iter().map(|r| &r.inner).collect();
let bars: Vec<&chanlun::kline::bar::K线> = refs.iter().map(|r| r.inner.as_ref()).collect();
chanlun::kline::bar::K线::DAT文件(, &bars)
.map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))
}
@@ -263,8 +274,11 @@ impl K线Py {
: i64,
: &str,
) -> Option<Self> {
chanlun::kline::bar::K线::(.as_bytes(), , )
.map(|inner| Self { inner })
chanlun::kline::bar::K线::(.as_bytes(), , ).map(|inner| {
Self {
inner: Rc::new(inner),
}
})
}
#[classmethod]
@@ -276,7 +290,7 @@ impl K线Py {
py: Python<'_>,
) -> HashMap<String, f64> {
let refs: Vec<_> = k线序列.iter().map(|k| k.bind(py).borrow()).collect();
let bars: Vec<&chanlun::kline::bar::K线> = refs.iter().map(|r| &r.inner).collect();
let bars: Vec<&chanlun::kline::bar::K线> = refs.iter().map(|r| r.inner.as_ref()).collect();
chanlun::kline::bar::K线::MACD(&bars, &.borrow().inner, &.borrow().inner)
}
@@ -285,22 +299,33 @@ impl K线Py {
: Vec<Py<Self>>,
: &Bound<'_, Self>,
: &Bound<'_, Self>,
) -> Option<Vec<Py<Self>>> {
let start_ptr = .as_ptr();
let end_ptr = .as_ptr();
let start_idx = .iter().position(|k| k.as_ptr() == start_ptr)?;
let end_idx = .iter().position(|k| k.as_ptr() == end_ptr)?;
if start_idx <= end_idx {
Some(
.into_iter()
.skip(start_idx)
.take(end_idx - start_idx + 1)
.collect(),
)
} else {
None
py: Python<'_>,
) -> PyResult<Vec<Py<Self>>> {
let start_ptr = Rc::as_ptr(&.borrow().inner);
let end_ptr = Rc::as_ptr(&.borrow().inner);
let start_ts = .borrow().inner.;
let end_ts = .borrow().inner.;
let start_idx =
.iter()
.position(|k| {
Rc::as_ptr(&k.borrow(py).inner) == start_ptr
|| k.borrow(py).inner. == start_ts
})
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("始 不在序列中"))?;
let end_idx =
.iter()
.position(|k| {
Rc::as_ptr(&k.borrow(py).inner) == end_ptr || k.borrow(py).inner. == end_ts
})
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("终 不在序列中"))?;
if start_idx > end_idx {
return Err(pyo3::exceptions::PyValueError::new_err("始 排序在 终 之后"));
}
Ok(
.into_iter()
.skip(start_idx)
.take(end_idx - start_idx + 1)
.collect())
}
}
@@ -324,9 +349,27 @@ impl K线Py {
/// — 分析分型形成结果
/// 截取(序列, 起点分型, 终点分型) -> list — 截取分型间的缠K子序列
#[pyclass(name = "缠论K线", unsendable)]
#[derive(Clone)]
pub struct K线Py {
pub(crate) inner: std::rc::Rc<chanlun::kline::chan_kline::K线>,
bsp_set: std::cell::RefCell<Option<Py<pyo3::types::PySet>>>,
}
impl K线Py {
pub(crate) fn from_rc(inner: std::rc::Rc<chanlun::kline::chan_kline::K线>) -> Self {
Self {
inner,
bsp_set: std::cell::RefCell::new(None),
}
}
}
impl Clone for K线Py {
fn clone(&self) -> Self {
Self {
inner: std::rc::Rc::clone(&self.inner),
bsp_set: std::cell::RefCell::new(None),
}
}
}
#[pymethods]
@@ -398,7 +441,7 @@ impl 缠论K线Py {
#[getter]
fn K线(&self) -> K线Py {
K线Py {
inner: (*self.inner.K线).clone(),
inner: self.inner.K线.clone(),
}
}
@@ -410,10 +453,32 @@ impl 缠论K线Py {
self.__str__()
}
fn (&self) -> Self {
Self {
inner: std::rc::Rc::new(self.inner.()),
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
#[getter]
fn (&self, py: Python<'_>) -> Self {
let mut mirror = Self {
inner: std::rc::Rc::new(self.inner.()),
bsp_set: std::cell::RefCell::new(None),
};
if let Some(ref src_set) = *self.bsp_set.borrow() {
if let Ok(new_set) = pyo3::types::PySet::empty(py) {
for item in src_set.bind(py).iter() {
let _ = new_set.add(item);
}
mirror.bsp_set = std::cell::RefCell::new(Some(new_set.into()));
}
}
mirror
}
#[getter]
@@ -431,6 +496,24 @@ impl 缠论K线Py {
self.inner.KDJ匹配()
}
#[getter]
fn (&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
if self.bsp_set.borrow().is_none() {
let set = pyo3::types::PySet::empty(py)?;
for s in self.inner..borrow().iter() {
set.add(s.clone())?;
}
*self.bsp_set.borrow_mut() = Some(set.into());
}
Ok(self
.bsp_set
.borrow()
.as_ref()
.unwrap()
.clone_ref(py)
.into_any())
}
#[classmethod]
fn (
_cls: &Bound<'_, PyType>,
@@ -466,12 +549,10 @@ impl 缠论K线Py {
.borrow().inner,
.map(|s| s.borrow().inner),
,
std::rc::Rc::new(k.borrow().inner.clone()),
k.borrow().inner.clone(),
prev_inner,
);
Self {
inner: std::rc::Rc::new(inner),
}
Self::from_rc(std::rc::Rc::new(inner))
}
#[classmethod]
@@ -493,7 +574,7 @@ impl 缠论K线Py {
&K.borrow().inner,
&config,
);
Ok((result.map(|rc| Self { inner: rc }), mode))
Ok((result.map(Self::from_rc), mode))
}
#[classmethod]
@@ -505,7 +586,7 @@ impl 缠论K线Py {
: &Bound<'_, Py>,
py: Python<'_>,
) -> PyResult<(String, Option<Py<PyAny>>)> {
let ck_inner = K线.borrow().inner.clone();
let ck_inner = (*K线.borrow().inner).clone();
let config = .borrow().to_rust_config(py)?;
let mut ck_seq: Vec<_> = K序列
@@ -514,7 +595,7 @@ impl 缠论K线Py {
.collect();
let mut bar_seq: Vec<_> = K序列
.iter()
.map(|k| std::rc::Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
let (status, _fractal) = chanlun::kline::chan_kline::K线::(
@@ -532,22 +613,33 @@ impl 缠论K线Py {
: Vec<Py<Self>>,
: &Bound<'_, Self>,
: &Bound<'_, Self>,
) -> Option<Vec<Py<Self>>> {
let start_ptr = .as_ptr();
let end_ptr = .as_ptr();
let start_idx = .iter().position(|k| k.as_ptr() == start_ptr)?;
let end_idx = .iter().position(|k| k.as_ptr() == end_ptr)?;
if start_idx <= end_idx {
Some(
.into_iter()
.skip(start_idx)
.take(end_idx - start_idx + 1)
.collect(),
)
} else {
None
py: Python<'_>,
) -> PyResult<Vec<Py<Self>>> {
let start_ptr = Rc::as_ptr(&.borrow().inner);
let end_ptr = Rc::as_ptr(&.borrow().inner);
let start_ts = .borrow().inner.;
let end_ts = .borrow().inner.;
let start_idx =
.iter()
.position(|k| {
Rc::as_ptr(&k.borrow(py).inner) == start_ptr
|| k.borrow(py).inner. == start_ts
})
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("始 不在序列中"))?;
let end_idx =
.iter()
.position(|k| {
Rc::as_ptr(&k.borrow(py).inner) == end_ptr || k.borrow(py).inner. == end_ts
})
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("终 不在序列中"))?;
if start_idx > end_idx {
return Err(pyo3::exceptions::PyValueError::new_err("始 排序在 终 之后"));
}
Ok(
.into_iter()
.skip(start_idx)
.take(end_idx - start_idx + 1)
.collect())
}
}
+40
View File
@@ -51,3 +51,43 @@ fn _chanlun(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
business_py::register(m)?;
Ok(())
}
#[cfg(test)]
mod tests {
use crate::*;
use pyo3::prelude::*;
#[test]
fn test_rc_pointer_across_getters() {
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let module = PyModule::new(py, "test_module").unwrap();
module.add_class::<business_py::Py>().unwrap();
module.add_class::<business_py::Py>().unwrap();
module.add_class::<business_py::Py>().unwrap();
module.add_class::<kline_py::K线Py>().unwrap();
module.add_class::<kline_py::K线Py>().unwrap();
module.add_class::<structure_py::Py>().unwrap();
module.add_class::<structure_py::线Py>().unwrap();
module.add_class::<config_py::Py>().unwrap();
let config = config_py::Py::from_rust_config(&Default::default()).unwrap();
let obs = business_py::Py::new_impl("btcusd".into(), 300, config, py).unwrap();
// Feed one K line
let kline = kline_py::K线Py::new_impl(
"btcusd".into(),
1000,
100.0,
105.0,
99.0,
103.0,
1000.0,
0,
300,
);
let kline_ref = kline.into_ref(py);
// ... this is too complex
});
}
}
+181 -52
View File
@@ -72,23 +72,23 @@ impl 分型Py {
#[getter]
fn (&self) -> Option<K线Py> {
self.inner..as_ref().map(|k| K线Py {
inner: Rc::clone(k),
})
self.inner
.
.as_ref()
.map(|k| K线Py::from_rc(Rc::clone(k)))
}
#[getter]
fn (&self) -> K线Py {
K线Py {
inner: Rc::clone(&self.inner.),
}
K线Py::from_rc(Rc::clone(&self.inner.))
}
#[getter]
fn (&self) -> Option<K线Py> {
self.inner..as_ref().map(|k| K线Py {
inner: Rc::clone(k),
})
self.inner
.
.as_ref()
.map(|k| K线Py::from_rc(Rc::clone(k)))
}
#[getter]
@@ -116,6 +116,17 @@ impl 分型Py {
self.__str__()
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
#[getter]
fn (&self) -> Option<(Py, Py, Py)> {
self.inner.().map(|(a, b, c)| {
@@ -208,8 +219,8 @@ impl 分型Py {
/// 方法:
/// 之前是(其他虚线) -> bool — 判断当前虚线是否紧接在另一虚线之前
/// 之后是(其他虚线) -> bool — 判断当前虚线是否紧接在另一虚线之后
/// 获取普K序列(普K序列) -> list[K线] — 截取该虚线的原始K线范围
/// 获取缠K序列(缠K序列) -> list[缠论K线] — 截取该虚线的缠K范围
/// 获取普K序列(观察员) -> list[K线] — 截取该虚线的原始K线范围
/// 获取缠K序列(观察员) -> list[缠论K线] — 截取该虚线的缠K范围
/// 获取数据文本() -> str
///
/// 类方法(算法辅助):
@@ -294,6 +305,25 @@ impl 虚线Py {
self.inner._特征序列_显示
}
#[getter]
fn (&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
let list = pyo3::types::PyList::empty(py);
for item in &self.inner. {
match item {
Some(feat) => list.append(Py::new(
py,
线Py {
inner: Rc::clone(feat),
},
)?)?,
None => {
list.append(py.None())?;
}
}
}
Ok(list.into())
}
#[getter]
fn (&self) -> bool {
self.inner.
@@ -301,9 +331,10 @@ impl 虚线Py {
#[getter]
fn K线(&self) -> Option<K线Py> {
self.inner.K线.as_ref().map(|k| K线Py {
inner: Rc::clone(k),
})
self.inner
.K线
.as_ref()
.map(|k| K线Py::from_rc(Rc::clone(k)))
}
#[getter]
@@ -413,39 +444,43 @@ impl 虚线Py {
self.inner.(&.borrow().inner)
}
fn K序列(&self, K序列: Vec<Py<K线Py>>, py: Python<'_>) -> PyResult<Py<PyAny>> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.collect();
let result = self.inner.K序列(&rc_list);
let list = pyo3::types::PyList::empty(py);
fn K序列(
&self,
: &Bound<'_, crate::business_py::Py>,
) -> PyResult<Py<PyAny>> {
let obs_ref = .borrow();
let observer_inner = obs_ref.obs();
let result = self.inner.K序列(&observer_inner.K线序列);
let list = pyo3::types::PyList::empty(.py());
for k in &result {
list.append(K线Py {
inner: (**k).clone(),
})?;
}
Ok(list.into())
}
fn K序列(
&self, K序列: Vec<Py<K线Py>>, py: Python<'_>
) -> PyResult<Py<PyAny>> {
let rc_list: Vec<Rc<chanlun::kline::chan_kline::K线>> = K序列
.iter()
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
.collect();
let result = self.inner.K序列(&rc_list);
let list = pyo3::types::PyList::empty(py);
for k in &result {
list.append(K线Py {
inner: Rc::clone(k),
})?;
}
Ok(list.into())
}
#[getter]
fn K序列(
&self,
: &Bound<'_, crate::business_py::Py>,
) -> PyResult<Py<PyAny>> {
let obs_ref = .borrow();
let observer_inner = obs_ref.obs();
let result = self.inner.K序列(&observer_inner.K线序列);
let list = pyo3::types::PyList::empty(.py());
for k in &result {
list.append(K线Py::from_rc(Rc::clone(k)))?;
}
Ok(list.into())
}
#[classmethod]
fn _武(_cls: &Bound<'_, PyType>, 线: &Bound<'_, Self>) -> Py {
Py {
inner: 线.borrow().inner._武(),
}
}
fn (&self) -> String {
self.inner.()
}
@@ -458,6 +493,17 @@ impl 虚线Py {
self.__str__()
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
// ---- 静态工厂方法 ----
#[classmethod]
@@ -547,7 +593,7 @@ impl 虚线Py {
) -> f64 {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD柱子均值(
&rc_list,
@@ -564,7 +610,7 @@ impl 虚线Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD均值(
&rc_list,
@@ -581,7 +627,7 @@ impl 虚线Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD均值(&rc_list, &线.borrow().inner)
}
@@ -595,7 +641,7 @@ impl 虚线Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD极值(&rc_list, &线.borrow().inner)
}
@@ -609,7 +655,7 @@ impl 虚线Py {
) -> Option<f64> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD柱子均值_阴(
&rc_list,
@@ -626,7 +672,7 @@ impl 虚线Py {
) -> Option<f64> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD柱子均值_阳(
&rc_list,
@@ -643,7 +689,7 @@ impl 虚线Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD均值_阴(&rc_list, &线.borrow().inner)
}
@@ -657,7 +703,7 @@ impl 虚线Py {
) -> bool {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD均值_阳(&rc_list, &线.borrow().inner)
}
@@ -671,7 +717,7 @@ impl 虚线Py {
) -> [bool; 3] {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::K线序列MACD趋向背驰(
&rc_list,
@@ -687,7 +733,7 @@ impl 虚线Py {
) -> Vec<Vec<f64>> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = k线序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD柱子分段(&rc_list)
}
@@ -713,12 +759,37 @@ impl 虚线Py {
: usize,
: usize,
py: Python<'_>,
) -> HashMap<String, String> {
) -> PyResult<Py<PyAny>> {
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K序列
.iter()
.map(|k| Rc::new(k.bind(py).borrow().inner.clone()))
.map(|k| k.bind(py).borrow().inner.clone())
.collect();
chanlun::structure::dash_line::线::MACD行为(&rc_list, , )
let result =
chanlun::structure::dash_line::线::MACD行为(&rc_list, , );
let dict = pyo3::types::PyDict::new(py);
dict.set_item("DIF上穿0", result.DIF上穿0)?;
dict.set_item("DIF下穿0", result.DIF下穿0)?;
dict.set_item("DEA上穿0", result.DEA上穿0)?;
dict.set_item("DEA下穿0", result.DEA下穿0)?;
dict.set_item("金叉次数", result.)?;
dict.set_item("死叉次数", result.)?;
let : Vec<Py<PyAny>> = result
.
.iter()
.map(|(a, b, c)| {
let tup = pyo3::types::PyTuple::new(
py,
[
(*a).into_pyobject(py)?.into_any().unbind(),
(*b).into_pyobject(py)?.into_any().unbind(),
(*c).into_pyobject(py)?.into_any().unbind(),
],
)?;
Ok(tup.into_any().unbind())
})
.collect::<PyResult<Vec<_>>>()?;
dict.set_item("密集交叉区域", )?;
Ok(dict.into())
}
#[classmethod]
@@ -821,6 +892,53 @@ impl 线段特征Py {
self.__str__()
}
fn __len__(&self) -> usize {
self.inner..len()
}
fn __getitem__(&self, index: isize, py: Python<'_>) -> PyResult<Py<PyAny>> {
let len = self.inner..len() as isize;
let idx = if index < 0 { index + len } else { index };
if idx < 0 || idx >= len {
return Err(pyo3::exceptions::PyIndexError::new_err(format!(
"线段特征 index {index} out of range (len={len})"
)));
}
let dash = &self.inner.[idx as usize];
let obj: Py<PyAny> = Py::new(
py,
线Py {
inner: Rc::clone(dash),
},
)?
.into();
Ok(obj)
}
fn __iter__(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
let list = pyo3::types::PyList::empty(py);
for d in &self.inner. {
list.append(Py::new(
py,
线Py {
inner: Rc::clone(d),
},
)?)?;
}
list.call_method0("__iter__").map(|iter| iter.into())
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
// ---- instance methods ----
#[getter]
@@ -1004,6 +1122,17 @@ impl 特征分型Py {
fn __repr__(&self) -> String {
self.__str__()
}
fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {
if let Ok(other) = other.extract::<PyRef<'_, Self>>() {
return Rc::as_ptr(&self.inner) == Rc::as_ptr(&other.inner);
}
false
}
fn __hash__(&self) -> u64 {
Rc::as_ptr(&self.inner) as u64
}
}
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
-5
View File
@@ -135,27 +135,22 @@ impl 相对方向Py {
}
}
#[getter]
fn (&self) -> bool {
self.inner.()
}
#[getter]
fn (&self) -> bool {
self.inner.()
}
#[getter]
fn (&self) -> bool {
self.inner.()
}
#[getter]
fn (&self) -> bool {
self.inner.()
}
#[getter]
fn (&self) -> bool {
self.inner.()
}