第八版
This commit is contained in:
+177
-148
@@ -22,9 +22,37 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::kline_py::chan_kline_to_py;
|
||||
use crate::structure_py::{dashed_to_py, fractal_to_py};
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDict, PyType};
|
||||
use std::rc::Rc;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
thread_local! {
|
||||
static HUB_IDENTITY: RwLock<HashMap<usize, Py<中枢Py>>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub(crate) fn hub_to_py(
|
||||
py: Python<'_>, inner: Arc<chanlun::algorithm::hub::中枢>
|
||||
) -> Py<中枢Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
HUB_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
HUB_IDENTITY.with(|c| {
|
||||
c.write().unwrap().retain(|_, v| v.get_refcnt(py) > 1);
|
||||
});
|
||||
let obj = Py::new(py, 中枢Py { inner }).unwrap();
|
||||
HUB_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
use crate::business_py::观察者Py;
|
||||
use crate::config_py::缠论配置Py;
|
||||
@@ -60,7 +88,7 @@ impl 背驰分析Py {
|
||||
方式: &str,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = K线序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = K线序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -107,7 +135,7 @@ impl 背驰分析Py {
|
||||
普K序列: Vec<Py<K线Py>>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -127,7 +155,7 @@ impl 背驰分析Py {
|
||||
普K序列: Vec<Py<K线Py>>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -148,7 +176,7 @@ impl 背驰分析Py {
|
||||
配置: &Bound<'_, 缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -170,7 +198,7 @@ impl 背驰分析Py {
|
||||
普K序列: Vec<Py<K线Py>>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -192,7 +220,7 @@ impl 背驰分析Py {
|
||||
模式: &str,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -234,13 +262,13 @@ impl 笔Py {
|
||||
配置: &Bound<'_, 缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<usize> {
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let bi_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let bi_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::bi::笔::获取缠K数量(
|
||||
@@ -255,13 +283,13 @@ impl 笔Py {
|
||||
缠K序列: Vec<Py<crate::kline_py::缠论K线Py>>,
|
||||
取舍: bool,
|
||||
py: Python<'_>,
|
||||
) -> Option<crate::kline_py::缠论K线Py> {
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
) -> Option<Py<crate::kline_py::缠论K线Py>> {
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::次高(&ck_list, 取舍)
|
||||
.map(|inner| crate::kline_py::缠论K线Py::from_rc(inner))
|
||||
.map(|inner| crate::kline_py::chan_kline_to_py(py, inner))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -271,13 +299,13 @@ impl 笔Py {
|
||||
缠K序列: Vec<Py<crate::kline_py::缠论K线Py>>,
|
||||
取舍: bool,
|
||||
py: Python<'_>,
|
||||
) -> Option<crate::kline_py::缠论K线Py> {
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
) -> Option<Py<crate::kline_py::缠论K线Py>> {
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::次低(&ck_list, 取舍)
|
||||
.map(|inner| crate::kline_py::缠论K线Py::from_rc(inner))
|
||||
.map(|inner| crate::kline_py::chan_kline_to_py(py, inner))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -287,13 +315,13 @@ impl 笔Py {
|
||||
缠K序列: Vec<Py<crate::kline_py::缠论K线Py>>,
|
||||
取舍: bool,
|
||||
py: Python<'_>,
|
||||
) -> Option<crate::kline_py::缠论K线Py> {
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
) -> Option<Py<crate::kline_py::缠论K线Py>> {
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::实际高点(&ck_list, 取舍)
|
||||
.map(|inner| crate::kline_py::缠论K线Py::from_rc(inner))
|
||||
.map(|inner| crate::kline_py::chan_kline_to_py(py, inner))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -303,13 +331,13 @@ impl 笔Py {
|
||||
缠K序列: Vec<Py<crate::kline_py::缠论K线Py>>,
|
||||
取舍: bool,
|
||||
py: Python<'_>,
|
||||
) -> Option<crate::kline_py::缠论K线Py> {
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
) -> Option<Py<crate::kline_py::缠论K线Py>> {
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::实际低点(&ck_list, 取舍)
|
||||
.map(|inner| crate::kline_py::缠论K线Py::from_rc(inner))
|
||||
.map(|inner| crate::kline_py::chan_kline_to_py(py, inner))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -335,9 +363,9 @@ impl 笔Py {
|
||||
文: &Bound<'_, 分型Py>,
|
||||
py: Python<'_>,
|
||||
) -> Option<虚线Py> {
|
||||
let bi_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let bi_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::以文会友(&bi_list, &文.borrow().inner)
|
||||
.map(|inner| 虚线Py { inner })
|
||||
@@ -351,9 +379,9 @@ impl 笔Py {
|
||||
武: &Bound<'_, 分型Py>,
|
||||
py: Python<'_>,
|
||||
) -> Option<虚线Py> {
|
||||
let bi_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let bi_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::以武会友(&bi_list, &武.borrow().inner)
|
||||
.map(|inner| 虚线Py { inner })
|
||||
@@ -369,9 +397,9 @@ impl 笔Py {
|
||||
偏移: i64,
|
||||
py: Python<'_>,
|
||||
) -> Option<虚线Py> {
|
||||
let bi_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let bi_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::bi::笔::根据缠K找笔(&bi_list, &缠K.borrow().inner, 偏移)
|
||||
.map(|inner| 虚线Py { inner })
|
||||
@@ -392,20 +420,20 @@ impl 笔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::分型>> = 分型序列
|
||||
let 当前分型_rc = 当前分型.map(|f| Arc::clone(&f.borrow().inner));
|
||||
let mut fr_seq: Vec<Arc<chanlun::structure::fractal_obj::分型>> = 分型序列
|
||||
.iter()
|
||||
.map(|f| Rc::clone(&f.bind(py).borrow().inner))
|
||||
.map(|f| Arc::clone(&f.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut bi_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let mut bi_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let bar_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let bar_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -435,25 +463,25 @@ impl 笔Py {
|
||||
配置: &Bound<'_, 缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<i64> {
|
||||
let mut fr_seq: Vec<Rc<chanlun::structure::fractal_obj::分型>> = 分型序列
|
||||
let mut fr_seq: Vec<Arc<chanlun::structure::fractal_obj::分型>> = 分型序列
|
||||
.iter()
|
||||
.map(|f| Rc::clone(&f.bind(py).borrow().inner))
|
||||
.map(|f| Arc::clone(&f.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut bi_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let mut bi_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let ck_list: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
let ck_list: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let bar_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let bar_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::bi::笔::分析递归(
|
||||
Rc::clone(&当前分型.borrow().inner),
|
||||
Arc::clone(&当前分型.borrow().inner),
|
||||
&mut fr_seq,
|
||||
&mut bi_seq,
|
||||
&ck_list,
|
||||
@@ -486,7 +514,7 @@ impl 笔Py {
|
||||
let obs_ref = obs.obs();
|
||||
chanlun::algorithm::bi::笔::获取所有停顿位置(&筆.borrow().inner, &*obs_ref)
|
||||
.into_iter()
|
||||
.map(|d| 虚线Py { inner: Rc::new(d) })
|
||||
.map(|d| 虚线Py { inner: Arc::new(d) })
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -496,12 +524,13 @@ impl 笔Py {
|
||||
_cls: &Bound<'_, PyType>,
|
||||
当前筆: &Bound<'_, 虚线Py>,
|
||||
观察员: &Bound<'_, 观察者Py>,
|
||||
) -> Vec<缠论K线Py> {
|
||||
py: Python<'_>,
|
||||
) -> Vec<Py<缠论K线Py>> {
|
||||
let obs = 观察员.borrow();
|
||||
let obs_ref = obs.obs();
|
||||
chanlun::algorithm::bi::笔::是否背驰过(&当前筆.borrow().inner, &*obs_ref)
|
||||
.into_iter()
|
||||
.map(|ck| 缠论K线Py::from_rc(ck))
|
||||
.map(|ck| chan_kline_to_py(py, ck))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -538,7 +567,7 @@ impl 线段Py {
|
||||
段: &Bound<'_, 虚线Py>,
|
||||
筆: &Bound<'_, 虚线Py>,
|
||||
) -> PyResult<()> {
|
||||
let bi_rc = Rc::clone(&筆.borrow().inner);
|
||||
let bi_rc = Arc::clone(&筆.borrow().inner);
|
||||
let mut ref_mut = 段.borrow_mut();
|
||||
chanlun::algorithm::segment::线段::添加虚线(&mut ref_mut.inner, bi_rc);
|
||||
Ok(())
|
||||
@@ -555,7 +584,7 @@ impl 线段Py {
|
||||
let mut ref_mut = 段.borrow_mut();
|
||||
chanlun::algorithm::segment::线段::武斗(
|
||||
&mut ref_mut.inner,
|
||||
&Rc::clone(&武.borrow().inner),
|
||||
&Arc::clone(&武.borrow().inner),
|
||||
行号,
|
||||
);
|
||||
Ok(())
|
||||
@@ -578,9 +607,9 @@ impl 线段Py {
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let mut ref_mut = 段.borrow_mut();
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::segment::线段::验证序列(&mut ref_mut.inner, &rc_list);
|
||||
Ok(())
|
||||
@@ -595,9 +624,9 @@ impl 线段Py {
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let mut ref_mut = 段.borrow_mut();
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::segment::线段::序列重置(&mut ref_mut.inner, &rc_list);
|
||||
Ok(())
|
||||
@@ -659,7 +688,8 @@ impl 线段Py {
|
||||
序列: &Bound<'_, PyAny>,
|
||||
行号: u32,
|
||||
) -> PyResult<()> {
|
||||
let seq: Vec<Option<Rc<chanlun::structure::segment_feat::线段特征>>> = if 序列.is_none() {
|
||||
let seq: Vec<Option<Arc<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());
|
||||
@@ -668,7 +698,7 @@ impl 线段Py {
|
||||
result.push(None);
|
||||
} else {
|
||||
let feat: PyRef<'_, 线段特征Py> = item.extract()?;
|
||||
result.push(Some(Rc::clone(&feat.inner)));
|
||||
result.push(Some(Arc::clone(&feat.inner)));
|
||||
}
|
||||
}
|
||||
result
|
||||
@@ -704,6 +734,7 @@ impl 线段Py {
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (段, 所属中枢 = None))]
|
||||
/// 将线段基础序列分割为前/后/第三买卖/贯穿伤四部分
|
||||
fn 分割序列(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -719,7 +750,7 @@ impl 线段Py {
|
||||
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);
|
||||
let inner_mut = Arc::make_mut(&mut hub_ref.inner);
|
||||
chanlun::algorithm::segment::线段::分割序列(&borrowed.inner, Some(inner_mut))
|
||||
} else {
|
||||
chanlun::algorithm::segment::线段::分割序列(&borrowed.inner, None)
|
||||
@@ -727,7 +758,7 @@ impl 线段Py {
|
||||
} else {
|
||||
chanlun::algorithm::segment::线段::分割序列(&borrowed.inner, None)
|
||||
};
|
||||
let wrap = |v: Vec<Rc<chanlun::structure::dash_line::虚线>>| -> PyResult<Vec<Py<虚线Py>>> {
|
||||
let wrap = |v: Vec<Arc<chanlun::structure::dash_line::虚线>>| -> PyResult<Vec<Py<虚线Py>>> {
|
||||
let mut result = Vec::new();
|
||||
for x in v {
|
||||
result.push(Py::new(py, 虚线Py { inner: x })?);
|
||||
@@ -770,7 +801,7 @@ impl 线段Py {
|
||||
&mut ref_mut.inner,
|
||||
&config,
|
||||
);
|
||||
let pk_list = |v: Vec<Rc<chanlun::algorithm::hub::中枢>>| -> PyResult<Py<PyAny>> {
|
||||
let pk_list = |v: Vec<Arc<chanlun::algorithm::hub::中枢>>| -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in v {
|
||||
list.append(Py::new(py, 中枢Py { inner: h })?)?;
|
||||
@@ -791,10 +822,10 @@ impl 线段Py {
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = vec![];
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = vec![];
|
||||
chanlun::algorithm::segment::线段::_添加线段(
|
||||
&mut seg_seq,
|
||||
Rc::clone(&待添加线段.borrow().inner),
|
||||
Arc::clone(&待添加线段.borrow().inner),
|
||||
&config,
|
||||
行号,
|
||||
);
|
||||
@@ -812,10 +843,10 @@ impl 线段Py {
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Option<虚线Py>> {
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = vec![];
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = vec![];
|
||||
let result = chanlun::algorithm::segment::线段::_弹出线段(
|
||||
&mut seg_seq,
|
||||
&Rc::clone(&待弹出线段.borrow().inner),
|
||||
&Arc::clone(&待弹出线段.borrow().inner),
|
||||
&config,
|
||||
行号,
|
||||
);
|
||||
@@ -831,9 +862,9 @@ impl 线段Py {
|
||||
层级: i64,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::segment::线段::_缺口突破(
|
||||
@@ -852,9 +883,9 @@ impl 线段Py {
|
||||
层级: i64,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::segment::线段::_非缺口下穿刺(
|
||||
@@ -873,9 +904,9 @@ impl 线段Py {
|
||||
层级: i64,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::segment::线段::_缺口后紧急修正(
|
||||
@@ -894,9 +925,9 @@ impl 线段Py {
|
||||
层级: i64,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<bool> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
Ok(chanlun::algorithm::segment::线段::_修正(
|
||||
@@ -918,13 +949,13 @@ impl 线段Py {
|
||||
关系序列: Option<Vec<相对方向Py>>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let bi_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
let bi_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 笔序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
let default_rel = vec![
|
||||
@@ -953,13 +984,13 @@ impl 线段Py {
|
||||
行号: u32,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::segment::线段::_添加扩展线段(
|
||||
&mut seg_seq,
|
||||
Rc::clone(&待添加线段.borrow().inner),
|
||||
Arc::clone(&待添加线段.borrow().inner),
|
||||
行号,
|
||||
);
|
||||
Ok(())
|
||||
@@ -974,13 +1005,13 @@ impl 线段Py {
|
||||
行号: u32,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Option<虚线Py>> {
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let result = chanlun::algorithm::segment::线段::_弹出扩展线段(
|
||||
&mut seg_seq,
|
||||
&Rc::clone(&待弹出线段.borrow().inner),
|
||||
&Arc::clone(&待弹出线段.borrow().inner),
|
||||
行号,
|
||||
);
|
||||
Ok(result.map(|inner| 虚线Py { inner }))
|
||||
@@ -995,13 +1026,13 @@ impl 线段Py {
|
||||
配置: &Bound<'_, 缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let dash_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let dash_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut seg_seq: Vec<Rc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
let mut seg_seq: Vec<Arc<chanlun::structure::dash_line::虚线>> = 线段序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
chanlun::algorithm::segment::线段::扩展分析(&dash_list, &mut seg_seq, &config);
|
||||
@@ -1034,7 +1065,7 @@ impl 线段Py {
|
||||
let obs_ref = obs.obs();
|
||||
chanlun::algorithm::segment::线段::获取所有停顿位置(&段.borrow().inner, &*obs_ref)
|
||||
.into_iter()
|
||||
.map(|d| 虚线Py { inner: Rc::new(d) })
|
||||
.map(|d| 虚线Py { inner: Arc::new(d) })
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -1044,12 +1075,13 @@ impl 线段Py {
|
||||
_cls: &Bound<'_, PyType>,
|
||||
当前段: &Bound<'_, 虚线Py>,
|
||||
观察员: &Bound<'_, 观察者Py>,
|
||||
) -> Vec<缠论K线Py> {
|
||||
py: Python<'_>,
|
||||
) -> Vec<Py<缠论K线Py>> {
|
||||
let obs = 观察员.borrow();
|
||||
let obs_ref = obs.obs();
|
||||
chanlun::algorithm::segment::线段::是否背驰过(&当前段.borrow().inner, &*obs_ref)
|
||||
.into_iter()
|
||||
.map(|ck| 缠论K线Py::from_rc(ck))
|
||||
.map(|ck| chan_kline_to_py(py, ck))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -1093,10 +1125,10 @@ impl 线段Py {
|
||||
/// 向中枢序列尾部添加(中枢序列, 新中枢) — 维护中枢序列顺序
|
||||
/// 从中枢序列尾部弹出(中枢序列, 配置) — 弹出最后一个中枢并更新相邻中枢
|
||||
/// 分析(虚线序列, 中枢序列容器, 允许重叠?, 标识前缀?, ...) — 中枢分析主流程
|
||||
#[pyclass(name = "中枢", module = "chanlun._chanlun", unsendable, from_py_object)]
|
||||
#[pyclass(name = "中枢", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 中枢Py {
|
||||
pub(crate) inner: Rc<chanlun::algorithm::hub::中枢>,
|
||||
pub(crate) inner: Arc<chanlun::algorithm::hub::中枢>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -1105,12 +1137,12 @@ impl 中枢Py {
|
||||
fn new(
|
||||
序号: i64, 标识: String, 级别: i64, 基础序列: Vec<Py<虚线Py>>, py: Python<'_>
|
||||
) -> Self {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 基础序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 基础序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
Self {
|
||||
inner: Rc::new(chanlun::algorithm::hub::中枢::new(
|
||||
inner: Arc::new(chanlun::algorithm::hub::中枢::new(
|
||||
序号, 标识, 级别, rc_list,
|
||||
)),
|
||||
}
|
||||
@@ -1118,48 +1150,51 @@ impl 中枢Py {
|
||||
|
||||
#[getter]
|
||||
fn 序号(&self) -> i64 {
|
||||
self.inner.序号
|
||||
self.inner.序号.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 标识(&self) -> String {
|
||||
self.inner.标识.clone()
|
||||
self.inner.标识.read().unwrap().clone()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 级别(&self) -> i64 {
|
||||
self.inner.级别
|
||||
self.inner.级别.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 基础序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.inner.基础序列 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
for d in self.inner.基础序列.read().unwrap().iter() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 第三买卖线(&self) -> Option<虚线Py> {
|
||||
self.inner.第三买卖线.as_ref().map(|d| 虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})
|
||||
fn 第三买卖线(&self, py: Python<'_>) -> Option<Py<虚线Py>> {
|
||||
self.inner
|
||||
.第三买卖线
|
||||
.read()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(|d| dashed_to_py(py, Arc::clone(d)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 本级_第三买卖线(&self) -> Option<虚线Py> {
|
||||
self.inner.本级_第三买卖线.as_ref().map(|d| 虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})
|
||||
fn 本级_第三买卖线(&self, py: Python<'_>) -> Option<Py<虚线Py>> {
|
||||
self.inner
|
||||
.本级_第三买卖线
|
||||
.read()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(|d| dashed_to_py(py, Arc::clone(d)))
|
||||
}
|
||||
|
||||
/// 向中枢添加新虚线(延伸),重置第三买卖线
|
||||
fn 添加虚线(&mut self, 实线: &Bound<'_, 虚线Py>) {
|
||||
let inner = Rc::make_mut(&mut self.inner);
|
||||
inner.添加虚线(Rc::clone(&实线.borrow().inner));
|
||||
fn 添加虚线(&self, 实线: &Bound<'_, 虚线Py>) {
|
||||
self.inner.添加虚线(Arc::clone(&实线.borrow().inner));
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -1170,10 +1205,8 @@ impl 中枢Py {
|
||||
|
||||
#[getter]
|
||||
/// :return: 最后一条虚线
|
||||
fn 离开段(&self) -> 虚线Py {
|
||||
虚线Py {
|
||||
inner: self.inner.离开段(),
|
||||
}
|
||||
fn 离开段(&self, py: Python<'_>) -> Py<虚线Py> {
|
||||
dashed_to_py(py, self.inner.离开段())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -1210,24 +1243,20 @@ impl 中枢Py {
|
||||
|
||||
#[getter]
|
||||
/// :return: 起点分型
|
||||
fn 文(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: self.inner.文(),
|
||||
}
|
||||
fn 文(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, self.inner.文())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// :return: 终点分型
|
||||
fn 武(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: self.inner.武(),
|
||||
}
|
||||
fn 武(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, self.inner.武())
|
||||
}
|
||||
|
||||
/// 设置第三类买卖点关联虚线
|
||||
fn 设置第三买卖线(&mut self, 线: &Bound<'_, 虚线Py>) {
|
||||
let inner = Rc::make_mut(&mut self.inner);
|
||||
inner.设置第三买卖线(Rc::clone(&线.borrow().inner));
|
||||
let inner = Arc::make_mut(&mut self.inner);
|
||||
inner.设置第三买卖线(Arc::clone(&线.borrow().inner));
|
||||
}
|
||||
|
||||
/// 获取中枢的完整虚线序列(基础序列+第三买卖线)
|
||||
@@ -1253,11 +1282,11 @@ impl 中枢Py {
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let _ = 中枢序列; // Python 版声明了此参数但未使用
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let inner = Rc::make_mut(&mut self.inner);
|
||||
let inner = Arc::make_mut(&mut self.inner);
|
||||
inner.校验合法性(&rc_list)
|
||||
}
|
||||
|
||||
@@ -1274,9 +1303,9 @@ impl 中枢Py {
|
||||
配置: &Bound<'_, crate::config_py::缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let mut hub_seq: Vec<Rc<chanlun::algorithm::hub::中枢>> = 扩展中枢
|
||||
let mut hub_seq: Vec<Arc<chanlun::algorithm::hub::中枢>> = 扩展中枢
|
||||
.iter()
|
||||
.map(|h| Rc::clone(&h.bind(py).borrow().inner))
|
||||
.map(|h| Arc::clone(&h.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let config = 配置.borrow().to_rust_config(配置.py())?;
|
||||
self.inner.获取扩展中枢(&mut hub_seq, &config);
|
||||
@@ -1315,13 +1344,13 @@ impl 中枢Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
// ---- classmethods ----
|
||||
@@ -1353,10 +1382,10 @@ impl 中枢Py {
|
||||
标识: &str,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::algorithm::hub::中枢::创建(
|
||||
Rc::clone(&左.borrow().inner),
|
||||
Rc::clone(&中.borrow().inner),
|
||||
Rc::clone(&右.borrow().inner),
|
||||
inner: Arc::new(chanlun::algorithm::hub::中枢::创建(
|
||||
Arc::clone(&左.borrow().inner),
|
||||
Arc::clone(&中.borrow().inner),
|
||||
Arc::clone(&右.borrow().inner),
|
||||
级别,
|
||||
标识,
|
||||
)),
|
||||
@@ -1372,9 +1401,9 @@ impl 中枢Py {
|
||||
标识: &str,
|
||||
py: Python<'_>,
|
||||
) -> Option<Self> {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::hub::中枢::从序列中获取中枢(
|
||||
&rc_list,
|
||||
@@ -1391,7 +1420,7 @@ impl 中枢Py {
|
||||
中枢序列: &Bound<'_, PyAny>,
|
||||
待添加中枢: &Bound<'_, Self>,
|
||||
) -> PyResult<()> {
|
||||
let inner = Rc::clone(&待添加中枢.borrow().inner);
|
||||
let inner = Arc::clone(&待添加中枢.borrow().inner);
|
||||
let wrapper = Py::new(中枢序列.py(), Self { inner })?;
|
||||
中枢序列.call_method1("append", (wrapper,))?;
|
||||
Ok(())
|
||||
@@ -1410,7 +1439,7 @@ impl 中枢Py {
|
||||
}
|
||||
let bound: Bound<'_, Self> = result.extract()?;
|
||||
Ok(Some(Self {
|
||||
inner: Rc::clone(&bound.borrow().inner),
|
||||
inner: Arc::clone(&bound.borrow().inner),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1426,13 +1455,13 @@ impl 中枢Py {
|
||||
层级: i64,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<()> {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut hub_seq: Vec<Rc<chanlun::algorithm::hub::中枢>> = 中枢序列
|
||||
let mut hub_seq: Vec<Arc<chanlun::algorithm::hub::中枢>> = 中枢序列
|
||||
.iter()
|
||||
.map(|h| Rc::clone(&h.bind(py).borrow().inner))
|
||||
.map(|h| Arc::clone(&h.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::algorithm::hub::中枢::分析(&rc_list, &mut hub_seq, 跳过首部, 标识, 层级);
|
||||
Ok(())
|
||||
|
||||
@@ -24,9 +24,13 @@
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDict, PyType};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use crate::algorithm_py::hub_to_py;
|
||||
use crate::kline_py::bar_to_py;
|
||||
use crate::structure_py::{dashed_to_py, fractal_to_py};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::algorithm_py::中枢Py;
|
||||
use crate::config_py::缠论配置Py;
|
||||
@@ -44,12 +48,7 @@ use crate::types_py::买卖点类型Py;
|
||||
/// 有效性: bool — 买卖点是否仍有效
|
||||
/// 与MACD柱子匹配: bool|None — 是否与MACD柱状图方向匹配
|
||||
/// 与MACD柱子分型匹配: bool|None — 是否与MACD柱分型匹配
|
||||
#[pyclass(
|
||||
name = "基础买卖点",
|
||||
module = "chanlun._chanlun",
|
||||
unsendable,
|
||||
from_py_object
|
||||
)]
|
||||
#[pyclass(name = "基础买卖点", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 基础买卖点Py {
|
||||
pub(crate) inner: chanlun::business::bsp::基础买卖点,
|
||||
@@ -69,7 +68,7 @@ impl 基础买卖点Py {
|
||||
inner: chanlun::business::bsp::基础买卖点::new(
|
||||
类型.borrow().inner,
|
||||
当前K线.borrow().inner.clone(),
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
备注,
|
||||
中枢破位值,
|
||||
),
|
||||
@@ -97,35 +96,35 @@ impl 基础买卖点Py {
|
||||
#[getter]
|
||||
fn 买卖点分型(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: Rc::clone(&self.inner.买卖点分型),
|
||||
inner: Arc::clone(&self.inner.买卖点分型),
|
||||
}
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 买卖点K线(&self) -> 缠论K线Py {
|
||||
缠论K线Py::from_rc(Rc::clone(&self.inner.买卖点K线))
|
||||
fn 买卖点K线(&self, py: Python<'_>) -> Py<缠论K线Py> {
|
||||
crate::kline_py::chan_kline_to_py(py, Arc::clone(&self.inner.买卖点K线))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// 当前K线
|
||||
fn 当前K线(&self) -> K线Py {
|
||||
K线Py {
|
||||
inner: self.inner.当前K线.clone(),
|
||||
}
|
||||
fn 当前K线(&self, py: Python<'_>) -> Py<K线Py> {
|
||||
bar_to_py(py, self.inner.当前K线.clone())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 失效K线(&self) -> Option<K线Py> {
|
||||
self.inner.失效K线.as_ref().map(|k| K线Py {
|
||||
inner: Rc::clone(k),
|
||||
})
|
||||
fn 失效K线(&self, py: Python<'_>) -> Option<Py<K线Py>> {
|
||||
self.inner
|
||||
.失效K线
|
||||
.as_ref()
|
||||
.map(|k| bar_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 终结K线(&self) -> Option<K线Py> {
|
||||
self.inner.终结K线.as_ref().map(|k| K线Py {
|
||||
inner: Rc::clone(k),
|
||||
})
|
||||
fn 终结K线(&self, py: Python<'_>) -> Option<Py<K线Py>> {
|
||||
self.inner
|
||||
.终结K线
|
||||
.as_ref()
|
||||
.map(|k| bar_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -223,7 +222,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::一卖点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -244,7 +243,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::一买点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -265,7 +264,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::二卖点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -286,7 +285,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::二买点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -307,7 +306,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::三卖点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -328,7 +327,7 @@ impl 买卖点Py {
|
||||
) -> 基础买卖点Py {
|
||||
基础买卖点Py {
|
||||
inner: chanlun::business::bsp::买卖点::三买点(
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
当前K线.borrow().inner.clone(),
|
||||
标识,
|
||||
备注,
|
||||
@@ -352,8 +351,8 @@ impl 买卖点Py {
|
||||
特征,
|
||||
序号,
|
||||
级别,
|
||||
Rc::clone(&买卖点分型.borrow().inner),
|
||||
Rc::clone(&当前缠K.borrow().inner),
|
||||
Arc::clone(&买卖点分型.borrow().inner),
|
||||
Arc::clone(&当前缠K.borrow().inner),
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -390,24 +389,30 @@ impl 买卖点Py {
|
||||
/// 调试方法:
|
||||
/// 测试_保存数据(root?) — 将各层级序列保存到文件,用于与Python版对比
|
||||
/// 读取数据文件(文件路径, 配置) -> 观察者 (classmethod) — 从 .nb 文件加载数据
|
||||
#[pyclass(name = "观察者", module = "chanlun._chanlun", subclass, unsendable)]
|
||||
#[pyclass(name = "观察者", module = "chanlun._chanlun", subclass)]
|
||||
pub struct 观察者Py {
|
||||
pub(crate) inner: Option<Rc<RefCell<chanlun::business::observer::观察者>>>,
|
||||
pub(crate) inner: Option<Arc<RwLock<chanlun::business::observer::观察者>>>,
|
||||
}
|
||||
|
||||
impl 观察者Py {
|
||||
pub(crate) fn obs(&self) -> std::cell::Ref<'_, chanlun::business::observer::观察者> {
|
||||
pub(crate) fn obs(
|
||||
&self,
|
||||
) -> std::sync::RwLockReadGuard<'_, chanlun::business::observer::观察者> {
|
||||
self.inner
|
||||
.as_ref()
|
||||
.expect("观察者 尚未初始化,请通过 __init__(符号, 周期, 配置) 构造")
|
||||
.borrow()
|
||||
.read()
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
|
||||
pub(crate) fn obs_mut(&self) -> std::cell::RefMut<'_, chanlun::business::observer::观察者> {
|
||||
pub(crate) fn obs_mut(
|
||||
&self,
|
||||
) -> std::sync::RwLockWriteGuard<'_, chanlun::business::observer::观察者> {
|
||||
self.inner
|
||||
.as_ref()
|
||||
.expect("观察者 尚未初始化,请通过 __init__(符号, 周期, 配置) 构造")
|
||||
.borrow_mut()
|
||||
.write()
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,18 +497,16 @@ impl 观察者Py {
|
||||
|
||||
#[getter]
|
||||
/// :return: 最后一根原始K线
|
||||
fn 当前K线(&self) -> Option<K线Py> {
|
||||
self.obs().当前K线().map(|k| K线Py {
|
||||
inner: Rc::clone(k),
|
||||
})
|
||||
fn 当前K线(&self, py: Python<'_>) -> Option<Py<K线Py>> {
|
||||
self.obs().当前K线().map(|k| bar_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// :return: 最后一根缠论K线
|
||||
fn 当前缠K(&self) -> Option<缠论K线Py> {
|
||||
fn 当前缠K(&self, py: Python<'_>) -> Option<Py<缠论K线Py>> {
|
||||
self.obs()
|
||||
.当前缠K()
|
||||
.map(|k| 缠论K线Py::from_rc(Rc::clone(k)))
|
||||
.map(|k| crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -551,7 +554,7 @@ impl 观察者Py {
|
||||
let k线_py = Py::new(
|
||||
py,
|
||||
K线Py {
|
||||
inner: Rc::new(k线),
|
||||
inner: Arc::new(k线),
|
||||
},
|
||||
)?;
|
||||
slf.call_method1("增加原始K线", (k线_py,))?;
|
||||
@@ -564,6 +567,7 @@ impl 观察者Py {
|
||||
self.obs_mut().静态重新分析();
|
||||
}
|
||||
|
||||
#[pyo3(signature = (root = None))]
|
||||
/// 拆分各序列数据,单独存文件,文件名为对应变量名
|
||||
fn 测试_保存数据(&self, root: Option<&str>) {
|
||||
self.obs().测试_保存数据(root);
|
||||
@@ -618,7 +622,7 @@ impl 观察者Py {
|
||||
let k线_py = Py::new(
|
||||
py,
|
||||
K线Py {
|
||||
inner: Rc::new(k线),
|
||||
inner: Arc::new(k线),
|
||||
},
|
||||
)?;
|
||||
obj.call_method1("增加原始K线", (k线_py,))?;
|
||||
@@ -634,18 +638,38 @@ 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(bar_to_py(py, Arc::clone(k)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 基础缠K序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for k in &self.obs().基础缠K序列 {
|
||||
list.append(crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
#[setter]
|
||||
#[pyo3(name = "基础缠K序列")]
|
||||
fn 设置_基础缠K序列(&mut self, value: &Bound<'_, PyAny>) -> PyResult<()> {
|
||||
let list: &Bound<'_, pyo3::types::PyList> = value.cast()?;
|
||||
let mut vec = Vec::new();
|
||||
for item in list {
|
||||
let 缠k: PyRef<'_, 缠论K线Py> = item.extract()?;
|
||||
vec.push(Arc::clone(&缠k.inner));
|
||||
}
|
||||
self.obs_mut().基础缠K序列 = vec;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
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::from_rc(Rc::clone(k)))?;
|
||||
list.append(crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -654,9 +678,7 @@ impl 观察者Py {
|
||||
fn 分型序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for f in &self.obs().分型序列 {
|
||||
list.append(分型Py {
|
||||
inner: Rc::clone(f),
|
||||
})?;
|
||||
list.append(fractal_to_py(py, Arc::clone(f)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -665,9 +687,7 @@ impl 观察者Py {
|
||||
fn 笔序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().笔序列 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -676,9 +696,7 @@ impl 观察者Py {
|
||||
fn 笔_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().笔_中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -687,9 +705,7 @@ impl 观察者Py {
|
||||
fn 线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().线段序列 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -698,9 +714,7 @@ impl 观察者Py {
|
||||
fn 中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -709,9 +723,7 @@ impl 观察者Py {
|
||||
fn 扩展线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -720,9 +732,7 @@ impl 观察者Py {
|
||||
fn 扩展中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -731,9 +741,7 @@ impl 观察者Py {
|
||||
fn 扩展线段序列_线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列_线段 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -742,9 +750,7 @@ impl 观察者Py {
|
||||
fn 扩展中枢序列_线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列_线段 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -753,9 +759,7 @@ impl 观察者Py {
|
||||
fn 线段_线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().线段_线段序列 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -764,9 +768,7 @@ impl 观察者Py {
|
||||
fn 线段_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().线段_中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -775,9 +777,7 @@ impl 观察者Py {
|
||||
fn 扩展线段序列_扩展线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列_扩展线段 {
|
||||
list.append(虚线Py {
|
||||
inner: Rc::clone(d),
|
||||
})?;
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -786,9 +786,7 @@ impl 观察者Py {
|
||||
fn 扩展中枢序列_扩展线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列_扩展线段 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -806,7 +804,7 @@ impl 观察者Py {
|
||||
/// 投喂(时间戳, 开盘价, 最高价, 最低价, 收盘价, 成交量) -> list[(周期, K线)]
|
||||
/// — 快捷入口,免去构造K线对象
|
||||
/// 获取当前K线(周期) -> K线|None — 获取指定周期的当前合成结果
|
||||
#[pyclass(name = "K线合成器", module = "chanlun._chanlun", unsendable)]
|
||||
#[pyclass(name = "K线合成器", module = "chanlun._chanlun")]
|
||||
pub struct K线合成器Py {
|
||||
pub(crate) inner: chanlun::business::synthesizer::K线合成器,
|
||||
}
|
||||
@@ -829,7 +827,7 @@ impl K线合成器Py {
|
||||
let results = self.inner.投喂K线((*普K.borrow().inner).clone());
|
||||
Ok(results
|
||||
.into_iter()
|
||||
.map(|(周期, k)| (周期, K线Py { inner: Rc::new(k) }))
|
||||
.map(|(周期, k)| (周期, K线Py { inner: Arc::new(k) }))
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -858,14 +856,21 @@ impl K线合成器Py {
|
||||
let results = self.inner.投喂K线(k);
|
||||
results
|
||||
.into_iter()
|
||||
.map(|(周期, k2)| (周期, K线Py { inner: Rc::new(k2) }))
|
||||
.map(|(周期, k2)| {
|
||||
(
|
||||
周期,
|
||||
K线Py {
|
||||
inner: Arc::new(k2),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// 获取指定周期当前正在合成的K线
|
||||
fn 获取当前K线(&self, 周期: i64) -> Option<K线Py> {
|
||||
self.inner.获取当前K线(周期).map(|k| K线Py {
|
||||
inner: Rc::new(k.clone()),
|
||||
inner: Arc::new(k.clone()),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -893,7 +898,7 @@ impl K线合成器Py {
|
||||
/// 方法:
|
||||
/// 投喂K线(普K) — 喂入最小周期K线,自动合成大周期并分发给各周期观察者
|
||||
/// 测试_保存数据(root?) — 保存各周期的分析数据到文件
|
||||
#[pyclass(name = "立体分析器", module = "chanlun._chanlun", unsendable)]
|
||||
#[pyclass(name = "立体分析器", module = "chanlun._chanlun")]
|
||||
pub struct 立体分析器Py {
|
||||
pub(crate) inner: chanlun::business::multi_frame::立体分析器,
|
||||
}
|
||||
|
||||
@@ -183,20 +183,16 @@ impl 缠论配置Py {
|
||||
}
|
||||
|
||||
/// 保存配置到 JSON 文件(默认路径 "缠论配置.json")。
|
||||
fn 保存配置(&self, py: Python<'_>, path: Option<&str>) -> PyResult<()> {
|
||||
let path = path.unwrap_or("缠论配置.json");
|
||||
#[pyo3(signature = (path = "缠论配置.json"))]
|
||||
fn 保存配置(&self, py: Python<'_>, path: &str) -> PyResult<()> {
|
||||
let json = self.to_json(py)?;
|
||||
std::fs::write(path, json).map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))
|
||||
}
|
||||
|
||||
/// 从 JSON 文件加载配置(默认路径 "缠论配置.json")。
|
||||
#[classmethod]
|
||||
fn 加载配置(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
py: Python<'_>,
|
||||
path: Option<&str>,
|
||||
) -> PyResult<Self> {
|
||||
let path = path.unwrap_or("缠论配置.json");
|
||||
#[pyo3(signature = (path = "缠论配置.json"))]
|
||||
fn 加载配置(_cls: &Bound<'_, PyType>, py: Python<'_>, path: &str) -> PyResult<Self> {
|
||||
let json_str = std::fs::read_to_string(path)
|
||||
.map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))?;
|
||||
Self::from_json_str(py, &json_str)
|
||||
@@ -336,11 +332,104 @@ fn dict_to_rust_config(
|
||||
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)
|
||||
|
||||
// 获取默认配置的 JSON 表示作为 schema
|
||||
let default_config = chanlun::config::缠论配置::default();
|
||||
let default_json = serde_json::to_value(&default_config)
|
||||
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("配置转换失败: {e}")))?;
|
||||
|
||||
// 用默认值做基准,只合并类型匹配的字段
|
||||
let mut merged = default_json.clone();
|
||||
if let serde_json::Value::Object(ref input_map) = value {
|
||||
if let serde_json::Value::Object(ref default_map) = default_json {
|
||||
for (key, input_val) in input_map {
|
||||
if let Some(default_val) = default_map.get(key) {
|
||||
match validate_field(key, input_val, default_val) {
|
||||
Ok(()) => {
|
||||
merged[key] = input_val.clone();
|
||||
}
|
||||
Err(msg) => {
|
||||
eprintln!("\x1b[33m[配置警告]\x1b[m {key}: {msg},已使用默认值 {default_val}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serde_json::from_value(merged)
|
||||
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("配置转换失败: {e}")))
|
||||
})
|
||||
}
|
||||
|
||||
/// 字符串字段的有效值集合
|
||||
fn valid_string_values(field: &str) -> Option<&'static [&'static str]> {
|
||||
match field {
|
||||
"指标计算方式" => Some(&[
|
||||
"开",
|
||||
"高",
|
||||
"低",
|
||||
"收",
|
||||
"高低均值",
|
||||
"高低收均值",
|
||||
"开高低收均值",
|
||||
]),
|
||||
"买卖点_指标模式" => Some(&["任意", "配置", "全量", "相对"]),
|
||||
"线段内部背驰_模式" => Some(&["任意", "配置", "全量", "相对"]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 验证单个字段的值是否与默认值类型兼容
|
||||
fn validate_field(
|
||||
key: &str,
|
||||
input: &serde_json::Value,
|
||||
default: &serde_json::Value,
|
||||
) -> Result<(), String> {
|
||||
use serde_json::Value;
|
||||
|
||||
// 输入为 null → 跳过(保留默认)
|
||||
if input.is_null() {
|
||||
return Err("值为 null".into());
|
||||
}
|
||||
|
||||
// 字符串字段:检查有效值白名单
|
||||
if default.is_string() && input.is_string() {
|
||||
if let Some(valid) = valid_string_values(key) {
|
||||
let s = input.as_str().unwrap();
|
||||
if !valid.contains(&s) {
|
||||
return Err(format!("\"{s}\" 不在有效值 {valid:?} 内"));
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 类型匹配:直接通过
|
||||
match (default, input) {
|
||||
(Value::Bool(_), Value::Bool(_)) => return Ok(()),
|
||||
(Value::Number(_), Value::Number(_)) => return Ok(()),
|
||||
(Value::String(_), Value::String(_)) => return Ok(()),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// 类型不匹配
|
||||
let type_name = match input {
|
||||
Value::Bool(_) => "布尔",
|
||||
Value::Number(_) => "数值",
|
||||
Value::String(_) => "字符串",
|
||||
Value::Array(_) => "数组",
|
||||
Value::Object(_) => "字典",
|
||||
Value::Null => "null",
|
||||
};
|
||||
let expected = match default {
|
||||
Value::Bool(_) => "布尔",
|
||||
Value::Number(_) => "数值",
|
||||
Value::String(_) => "字符串",
|
||||
_ => "其他",
|
||||
};
|
||||
Err(format!("类型不匹配(需要 {expected},收到 {type_name})"))
|
||||
}
|
||||
|
||||
/// 递归遍历 JSON Value,将数字/布尔字符串转为对应类型。
|
||||
fn coerce_strings_to_numbers(value: &mut serde_json::Value) {
|
||||
match value {
|
||||
|
||||
+104
-94
@@ -25,7 +25,9 @@
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyDict, PyType};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use crate::config_py::缠论配置Py;
|
||||
use crate::indicators_py::{平滑异同移动平均线Py, 相对强弱指数Py, 随机指标Py};
|
||||
@@ -52,9 +54,9 @@ use crate::types_py::相对方向Py;
|
||||
/// 获取MACD(K线序列, 计算方式, 快线周期?, 慢线周期?, 信号周期?) -> list[平滑异同移动平均线]
|
||||
/// — 对整个K线序列批量计算 MACD
|
||||
/// 截取(序列, 起点K线, 终点K线) -> list — 按时间戳截取K线区间
|
||||
#[pyclass(name = "K线", module = "chanlun._chanlun", unsendable)]
|
||||
#[pyclass(name = "K线", module = "chanlun._chanlun")]
|
||||
pub struct K线Py {
|
||||
pub(crate) inner: Rc<chanlun::kline::bar::K线>,
|
||||
pub(crate) inner: Arc<chanlun::kline::bar::K线>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -73,7 +75,7 @@ impl K线Py {
|
||||
成交量: f64,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::kline::bar::K线 {
|
||||
inner: Arc::new(chanlun::kline::bar::K线 {
|
||||
标识: 标识.to_string(),
|
||||
序号,
|
||||
周期,
|
||||
@@ -94,82 +96,46 @@ impl K线Py {
|
||||
fn 标识(&self) -> String {
|
||||
self.inner.标识.clone()
|
||||
}
|
||||
#[setter]
|
||||
fn set_标识(&mut self, v: String) {
|
||||
Rc::make_mut(&mut self.inner).标识 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 序号(&self) -> i64 {
|
||||
self.inner.序号
|
||||
}
|
||||
#[setter]
|
||||
fn set_序号(&mut self, v: i64) {
|
||||
Rc::make_mut(&mut self.inner).序号 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 周期(&self) -> i64 {
|
||||
self.inner.周期
|
||||
}
|
||||
#[setter]
|
||||
fn set_周期(&mut self, v: i64) {
|
||||
Rc::make_mut(&mut self.inner).周期 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 时间戳(&self) -> i64 {
|
||||
self.inner.时间戳
|
||||
}
|
||||
#[setter]
|
||||
fn set_时间戳(&mut self, v: i64) {
|
||||
Rc::make_mut(&mut self.inner).时间戳 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 高(&self) -> f64 {
|
||||
self.inner.高
|
||||
}
|
||||
#[setter]
|
||||
fn set_高(&mut self, v: f64) {
|
||||
Rc::make_mut(&mut self.inner).高 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 低(&self) -> f64 {
|
||||
self.inner.低
|
||||
}
|
||||
#[setter]
|
||||
fn set_低(&mut self, v: f64) {
|
||||
Rc::make_mut(&mut self.inner).低 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 开盘价(&self) -> f64 {
|
||||
self.inner.开盘价
|
||||
}
|
||||
#[setter]
|
||||
fn set_开盘价(&mut self, v: f64) {
|
||||
Rc::make_mut(&mut self.inner).开盘价 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 收盘价(&self) -> f64 {
|
||||
self.inner.收盘价
|
||||
}
|
||||
#[setter]
|
||||
fn set_收盘价(&mut self, v: f64) {
|
||||
Rc::make_mut(&mut self.inner).收盘价 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 成交量(&self) -> f64 {
|
||||
self.inner.成交量
|
||||
}
|
||||
#[setter]
|
||||
fn set_成交量(&mut self, v: f64) {
|
||||
Rc::make_mut(&mut self.inner).成交量 = v;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// :return: 相对方向.向上(开盘<收盘)或 相对方向.向下(开盘>收盘)
|
||||
@@ -243,13 +209,13 @@ impl K线Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -268,7 +234,7 @@ impl K线Py {
|
||||
周期: Option<i64>,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::kline::bar::K线::创建普K(
|
||||
inner: Arc::new(chanlun::kline::bar::K线::创建普K(
|
||||
标识,
|
||||
时间戳,
|
||||
开盘价,
|
||||
@@ -306,7 +272,7 @@ impl K线Py {
|
||||
) -> Option<Self> {
|
||||
chanlun::kline::bar::K线::读取大端字节数组(字节组.as_bytes(), 周期, 标识).map(|inner| {
|
||||
Self {
|
||||
inner: Rc::new(inner),
|
||||
inner: Arc::new(inner),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -333,21 +299,21 @@ impl K线Py {
|
||||
终: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Vec<Py<Self>>> {
|
||||
let start_ptr = Rc::as_ptr(&始.borrow().inner);
|
||||
let end_ptr = Rc::as_ptr(&终.borrow().inner);
|
||||
let start_ptr = Arc::as_ptr(&始.borrow().inner);
|
||||
let end_ptr = Arc::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
|
||||
Arc::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
|
||||
Arc::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 {
|
||||
@@ -380,31 +346,71 @@ impl K线Py {
|
||||
/// 分析(缠K序列, 配置, 可以逆序包含?, 忽视顺序包含?, 可以逆序包含新?) -> (str, 分型|None)
|
||||
/// — 分析分型形成结果
|
||||
/// 截取(序列, 起点分型, 终点分型) -> list — 截取分型间的缠K子序列
|
||||
#[pyclass(
|
||||
name = "缠论K线",
|
||||
module = "chanlun._chanlun",
|
||||
unsendable,
|
||||
from_py_object
|
||||
)]
|
||||
#[pyclass(name = "缠论K线", module = "chanlun._chanlun", from_py_object)]
|
||||
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>>>,
|
||||
pub(crate) inner: std::sync::Arc<chanlun::kline::chan_kline::缠论K线>,
|
||||
bsp_set: std::sync::RwLock<Option<Py<pyo3::types::PySet>>>,
|
||||
}
|
||||
|
||||
impl 缠论K线Py {
|
||||
pub(crate) fn from_rc(inner: std::rc::Rc<chanlun::kline::chan_kline::缠论K线>) -> Self {
|
||||
pub(crate) fn from_rc(inner: std::sync::Arc<chanlun::kline::chan_kline::缠论K线>) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
bsp_set: std::cell::RefCell::new(None),
|
||||
bsp_set: std::sync::RwLock::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
/// 对象标识缓存:Rc 地址 → 规范 Python 对象
|
||||
/// 确保同一底层 Rc 指针在 Python 侧始终映射到同一 PyObject
|
||||
|
||||
static BAR_IDENTITY: RwLock<HashMap<usize, Py<K线Py>>> = RwLock::new(HashMap::new());
|
||||
|
||||
static KLINE_IDENTITY: RwLock<HashMap<usize, Py<缠论K线Py>>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
|
||||
/// 将 Rc<K线> 转为 Py<K线Py>,确保同一 Rc 地址总是返回同一 Python 对象
|
||||
pub(crate) fn bar_to_py(
|
||||
py: Python<'_>,
|
||||
inner: std::sync::Arc<chanlun::kline::bar::K线>,
|
||||
) -> Py<K线Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
BAR_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
let obj = Py::new(py, K线Py { inner }).unwrap();
|
||||
BAR_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
/// 将 Rc<缠论K线> 转为 Py<缠论K线Py>,确保同一 Rc 地址总是返回同一 Python 对象
|
||||
pub(crate) fn chan_kline_to_py(
|
||||
py: Python<'_>,
|
||||
inner: std::sync::Arc<chanlun::kline::chan_kline::缠论K线>,
|
||||
) -> Py<缠论K线Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
KLINE_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
let obj = Py::new(py, 缠论K线Py::from_rc(inner)).unwrap();
|
||||
KLINE_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
impl Clone for 缠论K线Py {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: std::rc::Rc::clone(&self.inner),
|
||||
bsp_set: std::cell::RefCell::new(None),
|
||||
inner: std::sync::Arc::clone(&self.inner),
|
||||
bsp_set: std::sync::RwLock::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,28 +424,28 @@ impl 缠论K线Py {
|
||||
|
||||
#[getter]
|
||||
fn 序号(&self) -> i64 {
|
||||
self.inner.序号
|
||||
self.inner.序号.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 时间戳(&self) -> i64 {
|
||||
self.inner.时间戳
|
||||
self.inner.时间戳.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 高(&self) -> f64 {
|
||||
self.inner.高
|
||||
self.inner.高.get()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 低(&self) -> f64 {
|
||||
self.inner.低
|
||||
self.inner.低.get()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 方向(&self) -> 相对方向Py {
|
||||
相对方向Py {
|
||||
inner: self.inner.方向,
|
||||
inner: *self.inner.方向.read().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,6 +453,8 @@ impl 缠论K线Py {
|
||||
fn 分型(&self) -> Option<crate::types_py::分型结构Py> {
|
||||
self.inner
|
||||
.分型
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| crate::types_py::分型结构Py { inner: f })
|
||||
}
|
||||
|
||||
@@ -462,7 +470,7 @@ impl 缠论K线Py {
|
||||
|
||||
#[getter]
|
||||
fn 分型特征值(&self) -> f64 {
|
||||
self.inner.分型特征值
|
||||
self.inner.分型特征值.get()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -472,14 +480,12 @@ impl 缠论K线Py {
|
||||
|
||||
#[getter]
|
||||
fn 原始结束序号(&self) -> i64 {
|
||||
self.inner.原始结束序号
|
||||
self.inner.原始结束序号.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 标的K线(&self) -> K线Py {
|
||||
K线Py {
|
||||
inner: self.inner.标的K线.clone(),
|
||||
}
|
||||
fn 标的K线(&self, py: Python<'_>) -> Py<K线Py> {
|
||||
bar_to_py(py, self.inner.标的K线.read().unwrap().clone())
|
||||
}
|
||||
|
||||
/// pandas 兼容 — 返回所有字段构成的字典
|
||||
@@ -516,28 +522,28 @@ impl 缠论K线Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// 创建当前缠K的浅拷贝副本
|
||||
fn 镜像(&self, py: Python<'_>) -> Self {
|
||||
let mut mirror = Self {
|
||||
inner: std::rc::Rc::new(self.inner.镜像()),
|
||||
bsp_set: std::cell::RefCell::new(None),
|
||||
inner: std::sync::Arc::new(self.inner.镜像()),
|
||||
bsp_set: std::sync::RwLock::new(None),
|
||||
};
|
||||
if let Some(ref src_set) = *self.bsp_set.borrow() {
|
||||
if let Some(ref src_set) = *self.bsp_set.read().unwrap() {
|
||||
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.bsp_set = std::sync::RwLock::new(Some(new_set.into()));
|
||||
}
|
||||
}
|
||||
mirror
|
||||
@@ -563,16 +569,17 @@ impl 缠论K线Py {
|
||||
|
||||
#[getter]
|
||||
fn 买卖点信息(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
if self.bsp_set.borrow().is_none() {
|
||||
if self.bsp_set.read().unwrap().is_none() {
|
||||
let set = pyo3::types::PySet::empty(py)?;
|
||||
for s in self.inner.买卖点信息.borrow().iter() {
|
||||
for s in self.inner.买卖点信息.read().unwrap().iter() {
|
||||
set.add(s.clone())?;
|
||||
}
|
||||
*self.bsp_set.borrow_mut() = Some(set.into());
|
||||
*self.bsp_set.write().unwrap() = Some(set.into());
|
||||
}
|
||||
Ok(self
|
||||
.bsp_set
|
||||
.borrow()
|
||||
.read()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone_ref(py)
|
||||
@@ -589,12 +596,13 @@ impl 缠论K线Py {
|
||||
) -> i64 {
|
||||
let rc_list: Vec<_> = 基线
|
||||
.iter()
|
||||
.map(|k| std::rc::Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| std::sync::Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::kline::chan_kline::缠论K线::时间戳对齐(&rc_list, &k线.borrow().inner)
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (时间戳, 高, 低, 方向, 结构, 原始序号, 普k, 之前 = None))]
|
||||
/// 创建新的缠论K线
|
||||
fn 创建缠K(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -606,7 +614,8 @@ impl 缠论K线Py {
|
||||
原始序号: i64,
|
||||
普k: &Bound<'_, K线Py>,
|
||||
之前: Option<&Bound<'_, Self>>,
|
||||
) -> Self {
|
||||
py: Python<'_>,
|
||||
) -> Py<Self> {
|
||||
let prev_ref = 之前.map(|prev| prev.borrow());
|
||||
let prev_inner = prev_ref.as_ref().map(|r| r.inner.as_ref());
|
||||
let inner = chanlun::kline::chan_kline::缠论K线::创建缠K(
|
||||
@@ -619,7 +628,7 @@ impl 缠论K线Py {
|
||||
普k.borrow().inner.clone(),
|
||||
prev_inner,
|
||||
);
|
||||
Self::from_rc(std::rc::Rc::new(inner))
|
||||
chan_kline_to_py(py, std::sync::Arc::new(inner))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -631,7 +640,7 @@ impl 缠论K线Py {
|
||||
当前普K: &Bound<'_, K线Py>,
|
||||
配置: &Bound<'_, 缠论配置Py>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<(Option<Self>, Option<String>)> {
|
||||
) -> PyResult<(Option<Py<Self>>, Option<String>)> {
|
||||
let mut ck_inner = (*当前缠K.borrow().inner).clone();
|
||||
let config = 配置.borrow().to_rust_config(py)?;
|
||||
let prev_ref = 之前缠K.map(|prev| prev.borrow());
|
||||
@@ -642,7 +651,7 @@ impl 缠论K线Py {
|
||||
&当前普K.borrow().inner,
|
||||
&config,
|
||||
);
|
||||
Ok((result.map(Self::from_rc), mode))
|
||||
Ok((result.map(|rc| chan_kline_to_py(py, rc)), mode))
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
@@ -660,7 +669,7 @@ impl 缠论K线Py {
|
||||
|
||||
let mut ck_seq: Vec<_> = 缠K序列
|
||||
.iter()
|
||||
.map(|k| std::rc::Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| std::sync::Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
let mut bar_seq: Vec<_> = 普K序列
|
||||
.iter()
|
||||
@@ -685,21 +694,22 @@ impl 缠论K线Py {
|
||||
终: &Bound<'_, Self>,
|
||||
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_ptr = Arc::as_ptr(&始.borrow().inner);
|
||||
let end_ptr = Arc::as_ptr(&终.borrow().inner);
|
||||
let start_ts = 始.borrow().inner.时间戳.load(Ordering::Relaxed);
|
||||
let end_ts = 终.borrow().inner.时间戳.load(Ordering::Relaxed);
|
||||
let start_idx = 序列
|
||||
.iter()
|
||||
.position(|k| {
|
||||
Rc::as_ptr(&k.borrow(py).inner) == start_ptr
|
||||
|| k.borrow(py).inner.时间戳 == start_ts
|
||||
Arc::as_ptr(&k.borrow(py).inner) == start_ptr
|
||||
|| k.borrow(py).inner.时间戳.load(Ordering::Relaxed) == 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
|
||||
Arc::as_ptr(&k.borrow(py).inner) == end_ptr
|
||||
|| k.borrow(py).inner.时间戳.load(Ordering::Relaxed) == end_ts
|
||||
})
|
||||
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("终 不在序列中"))?;
|
||||
if start_idx > end_idx {
|
||||
|
||||
+233
-185
@@ -25,11 +25,103 @@
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDict, PyType};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use crate::algorithm_py::中枢Py;
|
||||
use crate::algorithm_py::{hub_to_py, 中枢Py};
|
||||
use crate::config_py::缠论配置Py;
|
||||
use crate::kline_py::{缠论K线Py, K线Py};
|
||||
|
||||
// ---- 身份缓存 (弱引用:通过 refcnt 检测存活,仅缓存持有则视为过期) ----
|
||||
|
||||
thread_local! {
|
||||
static FRACTAL_IDENTITY: RwLock<HashMap<usize, Py<分型Py>>> = RwLock::new(HashMap::new());
|
||||
static DASHED_IDENTITY: RwLock<HashMap<usize, Py<虚线Py>>> = RwLock::new(HashMap::new());
|
||||
static SEGFEAT_IDENTITY: RwLock<HashMap<usize, Py<线段特征Py>>> = RwLock::new(HashMap::new());
|
||||
static FEATFRAC_IDENTITY: RwLock<HashMap<usize, Py<特征分型Py>>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub(crate) fn fractal_to_py(
|
||||
py: Python<'_>,
|
||||
inner: Arc<chanlun::structure::fractal_obj::分型>,
|
||||
) -> Py<分型Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
FRACTAL_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
// 清理 refcnt==1 的过期条目(仅缓存持有,Python 侧已无引用)
|
||||
FRACTAL_IDENTITY.with(|c| {
|
||||
c.write().unwrap().retain(|_, v| v.get_refcnt(py) > 1);
|
||||
});
|
||||
let obj = Py::new(py, 分型Py { inner }).unwrap();
|
||||
FRACTAL_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
pub(crate) fn dashed_to_py(
|
||||
py: Python<'_>,
|
||||
inner: Arc<chanlun::structure::dash_line::虚线>,
|
||||
) -> Py<虚线Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
DASHED_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
DASHED_IDENTITY.with(|c| {
|
||||
c.write().unwrap().retain(|_, v| v.get_refcnt(py) > 1);
|
||||
});
|
||||
let obj = Py::new(py, 虚线Py { inner }).unwrap();
|
||||
DASHED_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
pub(crate) fn segfeat_to_py(
|
||||
py: Python<'_>,
|
||||
inner: Arc<chanlun::structure::segment_feat::线段特征>,
|
||||
) -> Py<线段特征Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
SEGFEAT_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
SEGFEAT_IDENTITY.with(|c| {
|
||||
c.write().unwrap().retain(|_, v| v.get_refcnt(py) > 1);
|
||||
});
|
||||
let obj = Py::new(py, 线段特征Py { inner }).unwrap();
|
||||
SEGFEAT_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
|
||||
pub(crate) fn featfrac_to_py(
|
||||
py: Python<'_>,
|
||||
inner: Arc<chanlun::structure::feat_fractal::特征分型>,
|
||||
) -> Py<特征分型Py> {
|
||||
let key = Arc::as_ptr(&inner) as usize;
|
||||
if let Some(cached) =
|
||||
FEATFRAC_IDENTITY.with(|c| c.read().unwrap().get(&key).map(|p| p.clone_ref(py)))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
FEATFRAC_IDENTITY.with(|c| {
|
||||
c.write().unwrap().retain(|_, v| v.get_refcnt(py) > 1);
|
||||
});
|
||||
let obj = Py::new(py, 特征分型Py { inner }).unwrap();
|
||||
FEATFRAC_IDENTITY.with(|c| {
|
||||
c.write().unwrap().insert(key, obj.clone_ref(py));
|
||||
});
|
||||
obj
|
||||
}
|
||||
use crate::types_py::{分型结构Py, 相对方向Py, 缺口Py};
|
||||
|
||||
// ========== 分型 ==========
|
||||
@@ -47,10 +139,10 @@ use crate::types_py::{分型结构Py, 相对方向Py, 缺口Py};
|
||||
/// 判断分型(缠K序列, 索引, 配置) -> 分型|None — 在缠K序列中指定位置尝试创建分型
|
||||
/// 从缠K序列中获取分型(缠K序列, 配置) -> list[分型] — 扫描全序列提取所有分型
|
||||
/// 向序列中添加(分型序列, 新分型) — 维护分型序列的顺序一致性
|
||||
#[pyclass(name = "分型", module = "chanlun._chanlun", unsendable, from_py_object)]
|
||||
#[pyclass(name = "分型", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 分型Py {
|
||||
pub(crate) inner: Rc<chanlun::structure::fractal_obj::分型>,
|
||||
pub(crate) inner: Arc<chanlun::structure::fractal_obj::分型>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -62,33 +154,33 @@ impl 分型Py {
|
||||
右: Option<&Bound<'_, 缠论K线Py>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::fractal_obj::分型::new(
|
||||
左.map(|k| Rc::clone(&k.borrow().inner)),
|
||||
Rc::clone(&中.borrow().inner),
|
||||
右.map(|k| Rc::clone(&k.borrow().inner)),
|
||||
inner: Arc::new(chanlun::structure::fractal_obj::分型::new(
|
||||
左.map(|k| Arc::clone(&k.borrow().inner)),
|
||||
Arc::clone(&中.borrow().inner),
|
||||
右.map(|k| Arc::clone(&k.borrow().inner)),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 左(&self) -> Option<缠论K线Py> {
|
||||
fn 左(&self, py: Python<'_>) -> Option<Py<缠论K线Py>> {
|
||||
self.inner
|
||||
.左
|
||||
.as_ref()
|
||||
.map(|k| 缠论K线Py::from_rc(Rc::clone(k)))
|
||||
.map(|k| crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 中(&self) -> 缠论K线Py {
|
||||
缠论K线Py::from_rc(Rc::clone(&self.inner.中))
|
||||
fn 中(&self, py: Python<'_>) -> Py<缠论K线Py> {
|
||||
crate::kline_py::chan_kline_to_py(py, Arc::clone(&self.inner.中))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 右(&self) -> Option<缠论K线Py> {
|
||||
fn 右(&self, py: Python<'_>) -> Option<Py<缠论K线Py>> {
|
||||
self.inner
|
||||
.右
|
||||
.as_ref()
|
||||
.map(|k| 缠论K线Py::from_rc(Rc::clone(k)))
|
||||
.map(|k| crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -118,13 +210,13 @@ impl 分型Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -160,11 +252,11 @@ impl 分型Py {
|
||||
dict.set_item("分型特征值", self.分型特征值())?;
|
||||
dict.set_item("强度", self.强度())?;
|
||||
dict.set_item("与MACD柱子分型匹配", self.与MACD柱子分型匹配())?;
|
||||
if let Some(v) = self.左() {
|
||||
if let Some(v) = self.左(py) {
|
||||
dict.set_item("左", v)?;
|
||||
}
|
||||
dict.set_item("中", self.中())?;
|
||||
if let Some(v) = self.右() {
|
||||
dict.set_item("中", self.中(py))?;
|
||||
if let Some(v) = self.右(py) {
|
||||
dict.set_item("右", v)?;
|
||||
}
|
||||
if let Some(v) = self.关系组() {
|
||||
@@ -196,16 +288,16 @@ impl 分型Py {
|
||||
中: &Bound<'_, 缠论K线Py>,
|
||||
py: Python<'_>,
|
||||
) -> Option<Self> {
|
||||
let ck_seq: Vec<Rc<chanlun::kline::chan_kline::缠论K线>> = K线序列
|
||||
let ck_seq: Vec<Arc<chanlun::kline::chan_kline::缠论K线>> = K线序列
|
||||
.iter()
|
||||
.map(|k| Rc::clone(&k.bind(py).borrow().inner))
|
||||
.map(|k| Arc::clone(&k.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::structure::fractal_obj::分型::从缠K序列中获取分型(
|
||||
&ck_seq,
|
||||
&中.borrow().inner,
|
||||
)
|
||||
.map(|inner| Self {
|
||||
inner: Rc::new(inner),
|
||||
inner: Arc::new(inner),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -215,13 +307,7 @@ impl 分型Py {
|
||||
分型序列: &Bound<'_, PyAny>, 当前分型: &Bound<'_, Self>
|
||||
) -> PyResult<()> {
|
||||
let py = 分型序列.py();
|
||||
let inner = Rc::clone(&当前分型.borrow().inner);
|
||||
let wrapper = Py::new(
|
||||
py,
|
||||
Self {
|
||||
inner: Rc::clone(&inner),
|
||||
},
|
||||
)?;
|
||||
let wrapper = fractal_to_py(py, Arc::clone(&当前分型.borrow().inner));
|
||||
分型序列.call_method1("append", (wrapper,))?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -257,10 +343,10 @@ impl 分型Py {
|
||||
/// 计算MACD柱子均值 / 武之全量MACD均值 / 武之MACD均值 / 武之MACD极值
|
||||
/// 计算K线序列MACD趋向背驰 / 买卖意义 / 计算MACD柱子分段
|
||||
/// 密集区域按间隔 / 统计MACD行为
|
||||
#[pyclass(name = "虚线", module = "chanlun._chanlun", unsendable, from_py_object)]
|
||||
#[pyclass(name = "虚线", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 虚线Py {
|
||||
pub(crate) inner: Rc<chanlun::structure::dash_line::虚线>,
|
||||
pub(crate) inner: Arc<chanlun::structure::dash_line::虚线>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -276,11 +362,11 @@ impl 虚线Py {
|
||||
有效性: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::dash_line::虚线::new(
|
||||
inner: Arc::new(chanlun::structure::dash_line::虚线::new(
|
||||
序号,
|
||||
标识,
|
||||
Rc::clone(&文.borrow().inner),
|
||||
Rc::clone(&武.borrow().inner),
|
||||
Arc::clone(&文.borrow().inner),
|
||||
Arc::clone(&武.borrow().inner),
|
||||
级别,
|
||||
有效性,
|
||||
)),
|
||||
@@ -291,59 +377,50 @@ impl 虚线Py {
|
||||
|
||||
#[getter]
|
||||
fn 标识(&self) -> String {
|
||||
self.inner.标识.clone()
|
||||
self.inner.标识.read().unwrap().clone()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 序号(&self) -> i64 {
|
||||
self.inner.序号
|
||||
self.inner.序号.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 级别(&self) -> i64 {
|
||||
self.inner.级别
|
||||
self.inner.级别.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 文(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: Rc::clone(&self.inner.文),
|
||||
}
|
||||
fn 文(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, Arc::clone(&self.inner.文))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 武(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: Rc::clone(&self.inner.武),
|
||||
}
|
||||
fn 武(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, Arc::clone(&*self.inner.武.read().unwrap()))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 有效性(&self) -> bool {
|
||||
self.inner.有效性
|
||||
self.inner.有效性.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 模式(&self) -> String {
|
||||
self.inner.模式.clone()
|
||||
self.inner.模式.read().unwrap().clone()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn _特征序列_显示(&self) -> bool {
|
||||
self.inner._特征序列_显示
|
||||
self.inner._特征序列_显示.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 特征序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for item in &self.inner.特征序列 {
|
||||
for item in self.inner.特征序列.read().unwrap().iter() {
|
||||
match item {
|
||||
Some(feat) => list.append(Py::new(
|
||||
py,
|
||||
线段特征Py {
|
||||
inner: Rc::clone(feat),
|
||||
},
|
||||
)?)?,
|
||||
Some(feat) => list.append(segfeat_to_py(py, Arc::clone(feat)))?,
|
||||
None => {
|
||||
list.append(py.None())?;
|
||||
}
|
||||
@@ -354,27 +431,38 @@ impl 虚线Py {
|
||||
|
||||
#[getter]
|
||||
fn 短路修正(&self) -> bool {
|
||||
self.inner.短路修正
|
||||
self.inner.短路修正.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 确认K线(&self) -> Option<缠论K线Py> {
|
||||
fn 确认K线(&self, py: Python<'_>) -> Option<Py<缠论K线Py>> {
|
||||
self.inner
|
||||
.确认K线
|
||||
.read()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(|k| 缠论K线Py::from_rc(Rc::clone(k)))
|
||||
.map(|k| crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 前一缺口(&self) -> Option<缺口Py> {
|
||||
self.inner.前一缺口.map(|q| 缺口Py { inner: q })
|
||||
self.inner
|
||||
.前一缺口
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|q| 缺口Py { inner: q })
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 前一结束位置(&self) -> Option<Self> {
|
||||
self.inner.前一结束位置.as_ref().map(|d| Self {
|
||||
inner: Rc::clone(d),
|
||||
})
|
||||
self.inner
|
||||
.前一结束位置
|
||||
.read()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(|d| Self {
|
||||
inner: Arc::clone(d),
|
||||
})
|
||||
}
|
||||
|
||||
// ---- 序列 getters ----
|
||||
@@ -382,11 +470,11 @@ impl 虚线Py {
|
||||
#[getter]
|
||||
fn 基础序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.inner.基础序列 {
|
||||
for d in self.inner.基础序列.read().unwrap().iter() {
|
||||
list.append(Py::new(
|
||||
py,
|
||||
Self {
|
||||
inner: Rc::clone(d),
|
||||
inner: Arc::clone(d),
|
||||
},
|
||||
)?)?;
|
||||
}
|
||||
@@ -396,10 +484,8 @@ impl 虚线Py {
|
||||
#[getter]
|
||||
fn 实_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.inner.实_中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
for h in self.inner.实_中枢序列.read().unwrap().iter() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -407,10 +493,8 @@ impl 虚线Py {
|
||||
#[getter]
|
||||
fn 虚_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.inner.虚_中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
for h in self.inner.虚_中枢序列.read().unwrap().iter() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -418,10 +502,8 @@ impl 虚线Py {
|
||||
#[getter]
|
||||
fn 合_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.inner.合_中枢序列 {
|
||||
list.append(中枢Py {
|
||||
inner: Rc::clone(h),
|
||||
})?;
|
||||
for h in self.inner.合_中枢序列.read().unwrap().iter() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -432,11 +514,11 @@ impl 虚线Py {
|
||||
/// 笔序列
|
||||
fn 笔序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in self.inner.笔序列() {
|
||||
for d in self.inner.基础序列.read().unwrap().iter() {
|
||||
list.append(Py::new(
|
||||
py,
|
||||
Self {
|
||||
inner: Rc::clone(d),
|
||||
inner: Arc::clone(d),
|
||||
},
|
||||
)?)?;
|
||||
}
|
||||
@@ -490,7 +572,7 @@ impl 虚线Py {
|
||||
let list = pyo3::types::PyList::empty(观察员.py());
|
||||
for k in &result {
|
||||
list.append(K线Py {
|
||||
inner: Rc::clone(k),
|
||||
inner: Arc::clone(k),
|
||||
})?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -502,21 +584,21 @@ impl 虚线Py {
|
||||
观察员: &Bound<'_, crate::business_py::观察者Py>,
|
||||
) -> PyResult<Py<PyAny>> {
|
||||
let obs_ref = 观察员.borrow();
|
||||
let py = 观察员.py();
|
||||
let observer_inner = obs_ref.obs();
|
||||
let result = self.inner.获取缠K序列(&observer_inner.缠论K线序列);
|
||||
let list = pyo3::types::PyList::empty(观察员.py());
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for k in &result {
|
||||
list.append(缠论K线Py::from_rc(Rc::clone(k)))?;
|
||||
list.append(crate::kline_py::chan_kline_to_py(py, Arc::clone(k)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
/// 递归获取虚线的终点分型(笔直接返回武,线段递归到底层笔的武)
|
||||
fn 获取_武(_cls: &Bound<'_, PyType>, 实线: &Bound<'_, Self>) -> 分型Py {
|
||||
分型Py {
|
||||
inner: 实线.borrow().inner.获取_武(),
|
||||
}
|
||||
fn 获取_武(_cls: &Bound<'_, PyType>, 实线: &Bound<'_, Self>) -> Py<分型Py> {
|
||||
let py = _cls.py();
|
||||
fractal_to_py(py, 实线.borrow().inner.获取_武())
|
||||
}
|
||||
|
||||
/// 获取用于保存的数据文本
|
||||
@@ -535,8 +617,8 @@ impl 虚线Py {
|
||||
dict.set_item("模式", self.模式())?;
|
||||
dict.set_item("短路修正", self.短路修正())?;
|
||||
dict.set_item("图表标题", self.图表标题())?;
|
||||
dict.set_item("文_时间戳", self.文().时间戳())?;
|
||||
dict.set_item("武_时间戳", self.武().时间戳())?;
|
||||
dict.set_item("文_时间戳", self.文(py).bind(py).borrow().时间戳())?;
|
||||
dict.set_item("武_时间戳", self.武(py).bind(py).borrow().时间戳())?;
|
||||
Ok(dict.into())
|
||||
}
|
||||
|
||||
@@ -550,18 +632,19 @@ impl 虚线Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
// ---- 静态工厂方法 ----
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (文, 武, 有效性 = true))]
|
||||
/// :param 文: 起点分型
|
||||
fn 创建笔(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -570,9 +653,9 @@ impl 虚线Py {
|
||||
有效性: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::dash_line::虚线::创建笔(
|
||||
Rc::clone(&文.borrow().inner),
|
||||
Rc::clone(&武.borrow().inner),
|
||||
inner: Arc::new(chanlun::structure::dash_line::虚线::创建笔(
|
||||
Arc::clone(&文.borrow().inner),
|
||||
Arc::clone(&武.borrow().inner),
|
||||
有效性,
|
||||
)),
|
||||
}
|
||||
@@ -581,12 +664,12 @@ impl 虚线Py {
|
||||
#[classmethod]
|
||||
/// :param 虚线序列: 构成线段的虚线列表(笔)
|
||||
fn 创建线段(_cls: &Bound<'_, PyType>, 虚线序列: Vec<Py<Self>>, py: Python<'_>) -> Self {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::dash_line::虚线::创建线段(
|
||||
inner: Arc::new(chanlun::structure::dash_line::虚线::创建线段(
|
||||
&rc_list,
|
||||
)),
|
||||
}
|
||||
@@ -654,7 +737,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> f64 {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -672,7 +755,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -690,7 +773,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -705,7 +788,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -720,7 +803,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> Option<f64> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -738,7 +821,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> Option<f64> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -756,7 +839,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -771,7 +854,7 @@ impl 虚线Py {
|
||||
实线: &Bound<'_, Self>,
|
||||
py: Python<'_>,
|
||||
) -> bool {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -786,7 +869,7 @@ impl 虚线Py {
|
||||
方向: &Bound<'_, 相对方向Py>,
|
||||
py: Python<'_>,
|
||||
) -> [bool; 3] {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -803,7 +886,7 @@ impl 虚线Py {
|
||||
k线序列: Vec<Py<K线Py>>,
|
||||
py: Python<'_>,
|
||||
) -> Vec<Vec<f64>> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = k线序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = k线序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -811,6 +894,7 @@ impl 虚线Py {
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (交叉标记, 最大间隔 = 5usize, 最少交叉数 = 3usize))]
|
||||
/// 交叉标记: 长度为len(macd_list)的列表,0=无交叉, 1=金叉, -1=死叉
|
||||
fn 密集区域按间隔(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -826,6 +910,7 @@ impl 虚线Py {
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (普K序列, 最大间隔 = 8usize, 最少交叉数 = 3usize))]
|
||||
/// :param 普K序列: K线序列
|
||||
fn 统计MACD行为(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -834,7 +919,7 @@ impl 虚线Py {
|
||||
最少交叉数: usize,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Py<PyAny>> {
|
||||
let rc_list: Vec<Rc<chanlun::kline::bar::K线>> = 普K序列
|
||||
let rc_list: Vec<Arc<chanlun::kline::bar::K线>> = 普K序列
|
||||
.iter()
|
||||
.map(|k| k.bind(py).borrow().inner.clone())
|
||||
.collect();
|
||||
@@ -898,15 +983,10 @@ impl 虚线Py {
|
||||
/// 新建(序号, 文, 武, 基础序列?) -> 线段特征
|
||||
/// 静态分析(虚线序列, 配置) -> 线段特征|None
|
||||
/// 获取分型序列(虚线序列, 配置) -> list[线段特征]
|
||||
#[pyclass(
|
||||
name = "线段特征",
|
||||
module = "chanlun._chanlun",
|
||||
unsendable,
|
||||
from_py_object
|
||||
)]
|
||||
#[pyclass(name = "线段特征", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 线段特征Py {
|
||||
pub(crate) inner: Rc<chanlun::structure::segment_feat::线段特征>,
|
||||
pub(crate) inner: Arc<chanlun::structure::segment_feat::线段特征>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -918,12 +998,12 @@ impl 线段特征Py {
|
||||
线段方向: &Bound<'_, 相对方向Py>,
|
||||
py: Python<'_>,
|
||||
) -> Self {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 基础序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 基础序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::segment_feat::线段特征::new(
|
||||
inner: Arc::new(chanlun::structure::segment_feat::线段特征::new(
|
||||
标识,
|
||||
rc_list,
|
||||
线段方向.borrow().inner,
|
||||
@@ -954,12 +1034,7 @@ impl 线段特征Py {
|
||||
fn 元素(&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.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
@@ -985,38 +1060,27 @@ impl 线段特征Py {
|
||||
)));
|
||||
}
|
||||
let dash = &self.inner.元素[idx as usize];
|
||||
let obj: Py<PyAny> = Py::new(
|
||||
py,
|
||||
虚线Py {
|
||||
inner: Rc::clone(dash),
|
||||
},
|
||||
)?
|
||||
.into();
|
||||
let obj: Py<PyAny> = dashed_to_py(py, Arc::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.append(dashed_to_py(py, Arc::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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
|
||||
/// pandas 兼容 — 返回关键标量字段构成的字典
|
||||
@@ -1040,18 +1104,14 @@ impl 线段特征Py {
|
||||
|
||||
#[getter]
|
||||
/// 起点分型(向上线段取高高中的最大者,向下线段取低低中的最小者)
|
||||
fn 文(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: self.inner.文(),
|
||||
}
|
||||
fn 文(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, self.inner.文())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
/// 终点分型(向上线段取高高中的最大者,向下线段取低低中的最小者)
|
||||
fn 武(&self) -> 分型Py {
|
||||
分型Py {
|
||||
inner: self.inner.武(),
|
||||
}
|
||||
fn 武(&self, py: Python<'_>) -> Py<分型Py> {
|
||||
fractal_to_py(py, self.inner.武())
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -1076,17 +1136,17 @@ impl 线段特征Py {
|
||||
|
||||
/// :param 待添加虚线: 待添加的虚线
|
||||
fn 添加(&mut self, 待添加虚线: &Bound<'_, 虚线Py>) -> PyResult<()> {
|
||||
let inner = Rc::make_mut(&mut self.inner);
|
||||
let inner = Arc::make_mut(&mut self.inner);
|
||||
inner
|
||||
.添加(Rc::clone(&待添加虚线.borrow().inner))
|
||||
.添加(Arc::clone(&待添加虚线.borrow().inner))
|
||||
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e))
|
||||
}
|
||||
|
||||
/// :param 待删除虚线: 待删除的虚线
|
||||
fn 删除(&mut self, 待删除虚线: &Bound<'_, 虚线Py>) -> PyResult<()> {
|
||||
let inner = Rc::make_mut(&mut self.inner);
|
||||
let inner = Arc::make_mut(&mut self.inner);
|
||||
inner
|
||||
.删除(&Rc::clone(&待删除虚线.borrow().inner))
|
||||
.删除(&Arc::clone(&待删除虚线.borrow().inner))
|
||||
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e))
|
||||
}
|
||||
|
||||
@@ -1100,12 +1160,12 @@ impl 线段特征Py {
|
||||
线段方向: &Bound<'_, 相对方向Py>,
|
||||
py: Python<'_>,
|
||||
) -> Self {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::segment_feat::线段特征::新建(
|
||||
inner: Arc::new(chanlun::structure::segment_feat::线段特征::新建(
|
||||
rc_list,
|
||||
线段方向.borrow().inner,
|
||||
)),
|
||||
@@ -1113,6 +1173,7 @@ impl 线段特征Py {
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (虚线序列, 线段方向, 四象, 是否忽视 = false))]
|
||||
/// 静态分析虚线序列,生成特征序列
|
||||
fn 静态分析(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
@@ -1122,9 +1183,9 @@ impl 线段特征Py {
|
||||
是否忽视: bool,
|
||||
py: Python<'_>,
|
||||
) -> Vec<Self> {
|
||||
let rc_list: Vec<Rc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
let rc_list: Vec<Arc<chanlun::structure::dash_line::虚线>> = 虚线序列
|
||||
.iter()
|
||||
.map(|d| Rc::clone(&d.bind(py).borrow().inner))
|
||||
.map(|d| Arc::clone(&d.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::structure::segment_feat::线段特征::静态分析(
|
||||
&rc_list,
|
||||
@@ -1143,16 +1204,14 @@ impl 线段特征Py {
|
||||
_cls: &Bound<'_, PyType>,
|
||||
特征序列: Vec<Py<Self>>,
|
||||
py: Python<'_>,
|
||||
) -> Vec<特征分型Py> {
|
||||
let rc_list: Vec<Rc<chanlun::structure::segment_feat::线段特征>> = 特征序列
|
||||
) -> Vec<Py<特征分型Py>> {
|
||||
let rc_list: Vec<Arc<chanlun::structure::segment_feat::线段特征>> = 特征序列
|
||||
.iter()
|
||||
.map(|s| Rc::clone(&s.bind(py).borrow().inner))
|
||||
.map(|s| Arc::clone(&s.bind(py).borrow().inner))
|
||||
.collect();
|
||||
chanlun::structure::segment_feat::线段特征::获取分型序列(&rc_list)
|
||||
.into_iter()
|
||||
.map(|inner| 特征分型Py {
|
||||
inner: Rc::new(inner),
|
||||
})
|
||||
.map(|inner| featfrac_to_py(py, Arc::new(inner)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -1164,15 +1223,10 @@ impl 线段特征Py {
|
||||
/// 属性 (只读):
|
||||
/// 左: 线段特征|None / 中: 线段特征 / 右: 线段特征|None
|
||||
/// 结构: 分型结构 — 顶/底分型判定结果
|
||||
#[pyclass(
|
||||
name = "特征分型",
|
||||
module = "chanlun._chanlun",
|
||||
unsendable,
|
||||
from_py_object
|
||||
)]
|
||||
#[pyclass(name = "特征分型", module = "chanlun._chanlun", from_py_object)]
|
||||
#[derive(Clone)]
|
||||
pub struct 特征分型Py {
|
||||
pub(crate) inner: Rc<chanlun::structure::feat_fractal::特征分型>,
|
||||
pub(crate) inner: Arc<chanlun::structure::feat_fractal::特征分型>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -1185,34 +1239,28 @@ impl 特征分型Py {
|
||||
结构: &Bound<'_, 分型结构Py>,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(chanlun::structure::feat_fractal::特征分型::new(
|
||||
Rc::clone(&左.borrow().inner),
|
||||
Rc::clone(&中.borrow().inner),
|
||||
Rc::clone(&右.borrow().inner),
|
||||
inner: Arc::new(chanlun::structure::feat_fractal::特征分型::new(
|
||||
Arc::clone(&左.borrow().inner),
|
||||
Arc::clone(&中.borrow().inner),
|
||||
Arc::clone(&右.borrow().inner),
|
||||
结构.borrow().inner,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 左(&self) -> 线段特征Py {
|
||||
线段特征Py {
|
||||
inner: Rc::clone(&self.inner.左),
|
||||
}
|
||||
fn 左(&self, py: Python<'_>) -> Py<线段特征Py> {
|
||||
segfeat_to_py(py, Arc::clone(&self.inner.左))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 中(&self) -> 线段特征Py {
|
||||
线段特征Py {
|
||||
inner: Rc::clone(&self.inner.中),
|
||||
}
|
||||
fn 中(&self, py: Python<'_>) -> Py<线段特征Py> {
|
||||
segfeat_to_py(py, Arc::clone(&self.inner.中))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 右(&self) -> 线段特征Py {
|
||||
线段特征Py {
|
||||
inner: Rc::clone(&self.inner.右),
|
||||
}
|
||||
fn 右(&self, py: Python<'_>) -> Py<线段特征Py> {
|
||||
segfeat_to_py(py, Arc::clone(&self.inner.右))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
@@ -1240,13 +1288,13 @@ impl 特征分型Py {
|
||||
|
||||
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);
|
||||
return Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn __hash__(&self) -> u64 {
|
||||
Rc::as_ptr(&self.inner) as u64
|
||||
Arc::as_ptr(&self.inner) as u64
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -286,17 +286,15 @@ impl 分型结构Py {
|
||||
/// 返回:
|
||||
/// 分型结构 或 None — 无法判定时返回 None
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (左, 中, 右, 可以逆序包含 = false, 忽视顺序包含 = false))]
|
||||
fn 分析(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
左: &Bound<'_, PyAny>,
|
||||
中: &Bound<'_, PyAny>,
|
||||
右: &Bound<'_, PyAny>,
|
||||
可以逆序包含: Option<bool>,
|
||||
忽视顺序包含: Option<bool>,
|
||||
可以逆序包含: bool,
|
||||
忽视顺序包含: bool,
|
||||
) -> PyResult<Option<Self>> {
|
||||
let 可以逆序包含 = 可以逆序包含.unwrap_or(false);
|
||||
let 忽视顺序包含 = 忽视顺序包含.unwrap_or(false);
|
||||
|
||||
let get_hl = |obj: &Bound<'_, PyAny>| -> PyResult<(f64, f64)> {
|
||||
Ok((
|
||||
obj.getattr("高")?.extract::<f64>()?,
|
||||
@@ -456,13 +454,13 @@ impl 缺口Py {
|
||||
/// 返回:
|
||||
/// 缺口 或 None — 起点==终点时返回 None
|
||||
#[classmethod]
|
||||
#[pyo3(signature = (起点, 终点, 比例 = 0.15))]
|
||||
fn 居中截取区间(
|
||||
_cls: &Bound<'_, PyType>,
|
||||
起点: f64,
|
||||
终点: f64,
|
||||
比例: Option<f64>,
|
||||
比例: f64,
|
||||
) -> Option<Self> {
|
||||
let 比例 = 比例.unwrap_or(0.15);
|
||||
chanlun::types::缺口::居中截取区间(起点, 终点, 比例).map(|inner| Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user