diff --git a/quantwave-py/python/quantwave/__init__.py b/quantwave-py/python/quantwave/__init__.py index 40663c43e..1d0c7948f 100644 --- a/quantwave-py/python/quantwave/__init__.py +++ b/quantwave-py/python/quantwave/__init__.py @@ -33,6 +33,8 @@ ``StreamingError``, and ``InternalError`` (native FFI). See ``quantwave._errors``. """ +from __future__ import annotations # PEP 604 (str | None) annotations on Python 3.9 + from typing import List, Dict, Any import warnings diff --git a/quantwave-py/python/quantwave/talib.py b/quantwave-py/python/quantwave/talib.py index b98a1d16f..53d2a7704 100644 --- a/quantwave-py/python/quantwave/talib.py +++ b/quantwave-py/python/quantwave/talib.py @@ -25,10 +25,12 @@ import inspect from typing import Any, Callable, Dict, List, Optional -import numpy as np - from quantwave._talib_map_generated import TALIB_SLUG_TO_NAME as _TALIB_MAP +# numpy is imported lazily (inside the wrappers) so that `import quantwave` — and the +# rest of quantwave.talib's discovery API (list_functions) — work without numpy +# installed. Calling a talib function does require numpy (classic array in/out). + # Canonical TA-Lib price-input order. Multi-input functions receive their arrays in # this order (subset), matching classic talib (e.g. ATR(high, low, close)). _OHLCV = ["open", "high", "low", "close", "volume"] @@ -148,6 +150,8 @@ def _make_wrapper(talib_name: str, method_name: str) -> Callable[..., Any]: spec = _Signature(method_name) def wrapper(*arrays, **kwargs): + import numpy as np # lazy: classic talib API is numpy-based + if len(arrays) != len(spec.input_roles): raise TypeError( f"{talib_name} expects {len(spec.input_roles)} input array(s) "