''' FSP history synchronization regressions. ''' from collections.abc import AsyncIterator from typing import cast import numpy as np import pytest import trio from piker.fsp._momo import ( rsi, wma, ) from piker.fsp._volume import ( tina_vwap, ) from piker.data._sharedmem import NDTokenMsg from piker.data.ticktools import FeedQuote from piker.fsp._api import Fsp from tractor.ipc._shm import ( NDToken, ShmArray, ) class Value: def __init__(self, value: int) -> None: self.value: int = value class Shm: def __init__( self, first: int, last: int, token: str = 'fsp', ) -> None: self._first: Value = Value(first) self._last: Value = Value(last) self._array: np.ndarray = np.ones(4096) self._len: int = len(self._array) self._token: NDToken = NDToken( shm_name=token, shm_first_index_name=f'{token}_first', shm_last_index_name=f'{token}_last', dtype_descr=(('value', ' np.ndarray: return self._array[ self._first.value:self._last.value ] @property def token(self) -> NDTokenMsg: return cast(NDTokenMsg, self._token.as_msg()) @property def index(self) -> int: return self._last.value % len(self._array) def last(self, length: int = 1) -> np.ndarray: return self.array[-length:] class OhlcvShm(Shm): def __init__(self, length: int = 32) -> None: dtype = np.dtype([ ('index', ' None: ''' Keep every registered scalar FSP on the engine's yield protocol. The momentum operators previously had incompatible call signatures, short historical arrays, and bare realtime yields, all hidden by an engine-side cast. Run each against one OHLCV snapshot and one trade, proving the first yield is a source-aligned array and the next yield is a named realtime field/value pair. ''' shm = cast(ShmArray, OhlcvShm()) async def source() -> AsyncIterator[FeedQuote]: yield { 'ticks': [{ 'type': 'trade', 'price': 42.0, 'size': 1.0, }], } async def main() -> None: stream = target.func(source(), shm) history = await anext(stream) assert isinstance(history, np.ndarray) assert len(history) == len(shm.array) realtime = await anext(stream) assert isinstance(realtime, tuple) assert realtime[0] == target.name await stream.aclose() trio.run(main)