fix(apo): add PyApo + ApoNode + WasmApo bindings missed from ec269d8
The previous APO commit (ec269d8) only registered APO in the Python
__init__.py / Node index.js / Node index.d.ts / fuzz / tests / docs.
The actual PyApo pyclass, ApoNode napi class, and WasmApo wasm class
edits silently no-op'd because the underlying lib.rs files had been
touched by a branch switch between Read and Edit. The bindings were
therefore advertising APO from the Python module / Node package /
WASM module but not actually exposing it.
Fix: insert PyApo block + add_class call in bindings/python/src/lib.rs,
ApoNode block in bindings/node/src/lib.rs, WasmApo macro line in
bindings/wasm/src/lib.rs. cargo test workspace stays at 615 (no new
tests added; the existing test_known_values + indicators.test.js
references would have failed at import once the bindings rebuilt
without these classes).
This commit is contained in:
@@ -1068,6 +1068,40 @@ impl AroonNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi(js_name = "APO")]
|
||||||
|
pub struct ApoNode {
|
||||||
|
inner: wc::Apo,
|
||||||
|
}
|
||||||
|
#[napi]
|
||||||
|
impl ApoNode {
|
||||||
|
#[napi(constructor)]
|
||||||
|
pub fn new(fast: u32, slow: u32) -> napi::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
inner: wc::Apo::new(clamp_period(fast), clamp_period(slow)).map_err(map_err)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[napi]
|
||||||
|
pub fn update(&mut self, value: f64) -> Option<f64> {
|
||||||
|
self.inner.update(value)
|
||||||
|
}
|
||||||
|
#[napi]
|
||||||
|
pub fn batch(&mut self, prices: Vec<f64>) -> Vec<f64> {
|
||||||
|
flatten(self.inner.batch(&prices))
|
||||||
|
}
|
||||||
|
#[napi]
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.inner.reset();
|
||||||
|
}
|
||||||
|
#[napi(js_name = "isReady")]
|
||||||
|
pub fn is_ready(&self) -> bool {
|
||||||
|
self.inner.is_ready()
|
||||||
|
}
|
||||||
|
#[napi(js_name = "warmupPeriod")]
|
||||||
|
pub fn warmup_period(&self) -> u32 {
|
||||||
|
self.inner.warmup_period() as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[napi(js_name = "KAMA")]
|
#[napi(js_name = "KAMA")]
|
||||||
pub struct KamaNode {
|
pub struct KamaNode {
|
||||||
inner: wc::Kama,
|
inner: wc::Kama,
|
||||||
|
|||||||
@@ -812,6 +812,51 @@ impl PyKama {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================== APO ==============================
|
||||||
|
|
||||||
|
#[pyclass(name = "APO", module = "wickra._wickra", skip_from_py_object)]
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct PyApo {
|
||||||
|
inner: wc::Apo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl PyApo {
|
||||||
|
#[new]
|
||||||
|
#[pyo3(signature = (fast=12, slow=26))]
|
||||||
|
fn new(fast: usize, slow: usize) -> PyResult<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
inner: wc::Apo::new(fast, slow).map_err(map_err)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn update(&mut self, value: f64) -> Option<f64> {
|
||||||
|
self.inner.update(value)
|
||||||
|
}
|
||||||
|
fn batch<'py>(
|
||||||
|
&mut self,
|
||||||
|
py: Python<'py>,
|
||||||
|
prices: PyReadonlyArray1<'py, f64>,
|
||||||
|
) -> PyResult<Bound<'py, PyArray1<f64>>> {
|
||||||
|
let s = prices
|
||||||
|
.as_slice()
|
||||||
|
.map_err(|_| PyValueError::new_err(NON_CONTIGUOUS))?;
|
||||||
|
Ok(flatten(self.inner.batch(s)).into_pyarray(py))
|
||||||
|
}
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.inner.reset();
|
||||||
|
}
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
self.inner.is_ready()
|
||||||
|
}
|
||||||
|
fn warmup_period(&self) -> usize {
|
||||||
|
self.inner.warmup_period()
|
||||||
|
}
|
||||||
|
fn __repr__(&self) -> String {
|
||||||
|
let (f, s) = self.inner.periods();
|
||||||
|
format!("APO(fast={f}, slow={s})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ============================== CCI ==============================
|
// ============================== CCI ==============================
|
||||||
|
|
||||||
#[pyclass(name = "CCI", module = "wickra._wickra", skip_from_py_object)]
|
#[pyclass(name = "CCI", module = "wickra._wickra", skip_from_py_object)]
|
||||||
@@ -4494,6 +4539,7 @@ fn _wickra(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|||||||
m.add_class::<PyTema>()?;
|
m.add_class::<PyTema>()?;
|
||||||
m.add_class::<PyHma>()?;
|
m.add_class::<PyHma>()?;
|
||||||
m.add_class::<PyKama>()?;
|
m.add_class::<PyKama>()?;
|
||||||
|
m.add_class::<PyApo>()?;
|
||||||
m.add_class::<PyCci>()?;
|
m.add_class::<PyCci>()?;
|
||||||
m.add_class::<PyRoc>()?;
|
m.add_class::<PyRoc>()?;
|
||||||
m.add_class::<PyWilliamsR>()?;
|
m.add_class::<PyWilliamsR>()?;
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ wasm_scalar_indicator!(WasmPmo, "PMO", wc::Pmo, smoothing1: usize, smoothing2: u
|
|||||||
wasm_scalar_indicator!(WasmStochRsi, "StochRSI", wc::StochRsi, rsi_period: usize, stoch_period: usize);
|
wasm_scalar_indicator!(WasmStochRsi, "StochRSI", wc::StochRsi, rsi_period: usize, stoch_period: usize);
|
||||||
wasm_scalar_indicator!(WasmDpo, "DPO", wc::Dpo, period: usize);
|
wasm_scalar_indicator!(WasmDpo, "DPO", wc::Dpo, period: usize);
|
||||||
wasm_scalar_indicator!(WasmPpo, "PPO", wc::Ppo, fast: usize, slow: usize);
|
wasm_scalar_indicator!(WasmPpo, "PPO", wc::Ppo, fast: usize, slow: usize);
|
||||||
|
wasm_scalar_indicator!(WasmApo, "APO", wc::Apo, fast: usize, slow: usize);
|
||||||
wasm_scalar_indicator!(WasmCoppock, "Coppock", wc::Coppock, roc_long: usize, roc_short: usize, wma_period: usize);
|
wasm_scalar_indicator!(WasmCoppock, "Coppock", wc::Coppock, roc_long: usize, roc_short: usize, wma_period: usize);
|
||||||
wasm_scalar_indicator!(WasmStdDev, "StdDev", wc::StdDev, period: usize);
|
wasm_scalar_indicator!(WasmStdDev, "StdDev", wc::StdDev, period: usize);
|
||||||
wasm_scalar_indicator!(WasmUlcerIndex, "UlcerIndex", wc::UlcerIndex, period: usize);
|
wasm_scalar_indicator!(WasmUlcerIndex, "UlcerIndex", wc::UlcerIndex, period: usize);
|
||||||
|
|||||||
Reference in New Issue
Block a user