piker/tests/test_fsp_momo.py

65 lines
2.1 KiB
Python
Raw Normal View History

'''
Momentum FSP numerical regressions.
'''
import numpy as np
import pytest
from piker.fsp._momo import ema
@pytest.mark.parametrize(
'args,kwargs,expected',
[
((), {}, [1., 1.5, 2.25]),
((None,), {}, [1., 1.5, 2.25]),
((None, None), {}, [1., 1.5, 2.25]),
((0.25,), {}, [1., 1.25, 1.6875]),
((), {'alpha': 0.25}, [1., 1.25, 1.6875]),
((), {'ylast': 4.}, [4., 3., 3.]),
((None, 4.), {}, [4., 3., 3.]),
((0.5, 4.), {}, [4., 3., 3.]),
],
)
def test_ema_optional_arguments(
args: tuple[float|None, ...],
kwargs: dict[str, float],
expected: list[float],
) -> None:
'''
Accept omitted EMA defaults through the real Numba dispatcher.
`ema()` exposed optional smoothing and seed arguments, but its
eager signature accepted only explicit values or `None`.
Numba's omitted-argument types therefore raised `TypeError`
before the numerical kernel ran. Exercise positional and keyword
omissions as well as explicit arguments, checking the resulting
recurrence against hand-computed values. Import the production
dispatcher so this catches signature regressions that a call to
`ema.py_func` would miss.
'''
signal: np.ndarray = np.array([1., 2., 3.])
result: np.ndarray = ema(signal, *args, **kwargs)
np.testing.assert_allclose(result, expected)
assert result.dtype == np.float64
def test_ema_single_sample_continuation() -> None:
'''
Preserve the previous EMA when advancing one realtime sample.
The old one-sample path multiplied an absent seed by a float,
failing instead of initializing from the sample. Removing the
eager Numba signature must retain the existing initialization
fix and the previous-value update used by realtime RSI. Use a
distinct seed and smoothing factor so copying either the seed
or sample fails; verify an omitted seed uses the sole sample.
'''
signal: np.ndarray = np.array([3.])
np.testing.assert_allclose(ema(signal), [3.])
np.testing.assert_allclose(ema(signal, 0.25, 7.), [6.])