5aa0949bce
Two new indicators in a brand-new "Ichimoku & alternative charts" family: - `Ichimoku` (Ichimoku Kinko Hyo): the full five-line cloud system (Tenkan-sen, Kijun-sen, Senkou Span A/B, Chikou Span). Classic (9, 26, 52, 26) defaults; configurable. Forward displacement is handled in an O(1) ring buffer so the visible Senkou A/B at bar n are the values computed at bar n-displacement. - `HeikinAshi`: recursive candle smoothing transform emitting a four-field synthetic candle. Seeds ha_open from (open+close)/2 on the first bar. Touchpoints: core + unit tests, mod.rs/lib.rs re-exports, Python + Node + WASM bindings (multi-output via PyArray2 / interleaved Vec<f64> / Object+Float64Array), Python tests across smoke/new-indicators/ input-validation, Node parity tests, fuzz target (Candle), benches, README family table + counter (71 -> 73, 8 -> 9 families), CHANGELOG. Note: Renko, Kagi, and Point & Figure from the family-13 ideas list are intentionally skipped. They are bar generators (the bar boundary is defined by price moves, not by a fixed time interval) rather than indicators that consume a candle stream, and belong in wickra-data as candle/tick transforms alongside the existing tick-to-candle aggregator and resampler.
81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
"""Smoke tests: every public class can be constructed and emits the right shape."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import wickra as ta
|
|
|
|
|
|
def test_version_is_a_nonempty_string():
|
|
assert isinstance(ta.__version__, str)
|
|
assert ta.__version__
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"cls, args",
|
|
[
|
|
(ta.SMA, (14,)),
|
|
(ta.EMA, (14,)),
|
|
(ta.WMA, (14,)),
|
|
(ta.RSI, (14,)),
|
|
],
|
|
)
|
|
def test_scalar_batch_returns_same_length(cls, args, sine_prices):
|
|
out = cls(*args).batch(sine_prices)
|
|
assert out.shape == sine_prices.shape
|
|
assert out.dtype == np.float64
|
|
|
|
|
|
def test_macd_batch_returns_n_by_3(sine_prices):
|
|
out = ta.MACD().batch(sine_prices)
|
|
assert out.shape == (sine_prices.size, 3)
|
|
|
|
|
|
def test_bollinger_batch_returns_n_by_4(sine_prices):
|
|
out = ta.BollingerBands().batch(sine_prices)
|
|
assert out.shape == (sine_prices.size, 4)
|
|
|
|
|
|
def test_atr_batch_shape(ohlc_series):
|
|
high, low, close = ohlc_series
|
|
out = ta.ATR(14).batch(high, low, close)
|
|
assert out.shape == close.shape
|
|
|
|
|
|
def test_stochastic_batch_shape(ohlc_series):
|
|
high, low, close = ohlc_series
|
|
out = ta.Stochastic(14, 3).batch(high, low, close)
|
|
assert out.shape == (close.size, 2)
|
|
|
|
|
|
def test_obv_batch_shape(ohlc_series):
|
|
_, _, close = ohlc_series
|
|
volume = np.ones_like(close)
|
|
out = ta.OBV().batch(close, volume)
|
|
assert out.shape == close.shape
|
|
|
|
|
|
def test_ichimoku_batch_returns_n_by_5(ohlc_series):
|
|
high, low, close = ohlc_series
|
|
out = ta.Ichimoku().batch(high, low, close)
|
|
assert out.shape == (close.size, 5)
|
|
|
|
|
|
def test_heikin_ashi_batch_returns_n_by_4(ohlc_series):
|
|
high, low, close = ohlc_series
|
|
open_ = (high + low) / 2.0
|
|
out = ta.HeikinAshi().batch(open_, high, low, close)
|
|
assert out.shape == (close.size, 4)
|
|
|
|
|
|
def test_ehlers_super_smoother_batch_shape(sine_prices):
|
|
out = ta.SuperSmoother(10).batch(sine_prices)
|
|
assert out.shape == sine_prices.shape
|
|
|
|
|
|
def test_mama_batch_shape(sine_prices):
|
|
out = ta.MAMA().batch(sine_prices)
|
|
assert out.shape == (sine_prices.size, 2)
|