use pyo3::prelude::*;
use crate::analyze::CZSC;
use crate::analyze::utils as analyze_utils;
use crate::objects::bar::{NewBar, RawBar};
use crate::objects::bi::BI;
use crate::objects::direction::Direction;
use crate::objects::event::PyEvent;
use crate::objects::fake_bi::{FakeBI, create_fake_bis};
use crate::objects::freq::Freq;
use crate::objects::fx::FX;
use crate::objects::mark::Mark;
use crate::objects::market::Market;
use crate::objects::operate::PyOperate;
use crate::objects::position::{PyLiteBar, PyPos, PyPosition};
use crate::objects::signal::{PyParsedSignalDoc, PySignal, parse_signal_doc_py};
use crate::objects::zs::ZS;
use crate::utils::common::create_naive_pandas_timestamp;
use pyo3::types::{PyDict, PyDictMethods};
use pyo3_stub_gen::derive::gen_stub_pyfunction;
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "check_fx")]
fn check_fx_py(k1: NewBar, k2: NewBar, k3: NewBar) -> Option<FX> {
analyze_utils::check_fx(&k1, &k2, &k3)
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "check_fxs")]
fn check_fxs_py(bars: Vec<NewBar>) -> Vec<FX> {
analyze_utils::check_fxs(&bars)
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "check_bi")]
#[pyo3(signature = (bars, min_bi_len=0))]
fn check_bi_py(bars: Vec<NewBar>, min_bi_len: usize) -> Option<BI> {
let n = if min_bi_len > 0 {
min_bi_len
} else {
crate::analyze::resolve_min_bi_len(min_bi_len)
};
let (bi, _) = analyze_utils::check_bi(&bars, n);
bi
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "remove_include")]
fn remove_include_py(k1: NewBar, k2: NewBar, k3: RawBar) -> PyResult<(bool, NewBar)> {
analyze_utils::remove_include(&k1, &k2, k3)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "format_standard_kline")]
fn format_standard_kline_py(bars: Vec<RawBar>) -> Vec<RawBar> {
bars
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "create_fake_bis")]
fn create_fake_bis_py(fxs: Vec<FX>) -> PyResult<Vec<FakeBI>> {
if fxs.windows(2).any(|w| w[0].mark == w[1].mark) {
return Err(pyo3::exceptions::PyValueError::new_err(
"相邻分型标记必须不同",
));
}
Ok(create_fake_bis(&fxs))
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "get_zs_seq")]
fn get_zs_seq_py(bis: Vec<BI>) -> Vec<ZS> {
analyze_utils::get_zs_seq(&bis)
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "is_symmetry_zs", signature = (bis, th=0.3))]
fn is_symmetry_zs_py(bis: Vec<BI>, th: f64) -> bool {
analyze_utils::is_symmetry_zs(&bis, th)
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "is_bis_up")]
fn is_bis_up_py(bis: Vec<BI>) -> bool {
analyze_utils::is_bis_up(&bis)
}
#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(name = "is_bis_down")]
fn is_bis_down_py(bis: Vec<BI>) -> bool {
analyze_utils::is_bis_down(&bis)
}
#[gen_stub_pyfunction]
#[gen_stub(override_return_type(
type_repr = "builtins.list[builtins.dict[builtins.str, typing.Any]]",
imports = ("builtins", "typing")
))]
#[pyfunction]
#[pyo3(name = "check_gap_info")]
fn check_gap_info_py(py: Python<'_>, bars: Vec<RawBar>) -> PyResult<Vec<Py<PyDict>>> {
analyze_utils::check_gap_info(&bars)
.into_iter()
.map(|gap| {
let item = PyDict::new(py);
item.set_item("kind", gap.kind)?;
item.set_item("cover", gap.cover)?;
item.set_item("sdt", create_naive_pandas_timestamp(py, gap.sdt)?)?;
item.set_item("edt", create_naive_pandas_timestamp(py, gap.edt)?)?;
item.set_item("high", gap.high)?;
item.set_item("low", gap.low)?;
item.set_item("delta", gap.delta)?;
Ok(item.unbind())
})
.collect()
}
pub fn register(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Freq>()?;
m.add_class::<Market>()?;
m.add_class::<Mark>()?;
m.add_class::<Direction>()?;
m.add_class::<PyOperate>()?;
m.add_class::<PyPos>()?;
m.add_class::<RawBar>()?;
m.add_class::<NewBar>()?;
m.add_class::<PyLiteBar>()?;
m.add_class::<FX>()?;
m.add_class::<FakeBI>()?;
m.add_class::<BI>()?;
m.add_class::<ZS>()?;
m.add_class::<PySignal>()?;
m.add_class::<PyParsedSignalDoc>()?;
m.add_class::<PyEvent>()?;
m.add_class::<PyPosition>()?;
m.add_class::<CZSC>()?;
m.add_function(wrap_pyfunction!(parse_signal_doc_py, m)?)?;
m.add_function(wrap_pyfunction!(check_fx_py, m)?)?;
m.add_function(wrap_pyfunction!(check_fxs_py, m)?)?;
m.add_function(wrap_pyfunction!(check_bi_py, m)?)?;
m.add_function(wrap_pyfunction!(remove_include_py, m)?)?;
m.add_function(wrap_pyfunction!(format_standard_kline_py, m)?)?;
m.add_function(wrap_pyfunction!(create_fake_bis_py, m)?)?;
m.add_function(wrap_pyfunction!(get_zs_seq_py, m)?)?;
m.add_function(wrap_pyfunction!(is_symmetry_zs_py, m)?)?;
m.add_function(wrap_pyfunction!(is_bis_up_py, m)?)?;
m.add_function(wrap_pyfunction!(is_bis_down_py, m)?)?;
m.add_function(wrap_pyfunction!(check_gap_info_py, m)?)?;
Ok(())
}