# -*- coding: utf-8 -*- from functools import partial from pandas import DataFrame, Series from pandas.api.types import is_datetime64_any_dtype from pandas_ta._typing import ( Float, Int, IntFloat, List, MaybeSeriesFrame, Optional, SeriesFrame ) __all__ = [ 'is_percent', 'v_bool', 'v_dataframe', 'v_float', 'v_int', 'v_str', 'v_ascending', 'v_datetime_ordered', 'v_drift', 'v_list', 'v_lowerbound', 'v_mamode', 'v_offset', 'v_pos_default', 'v_scalar', 'v_series', 'v_talib', 'v_tradingview', 'v_upperbound', ] def is_percent(x: IntFloat) -> bool: if isinstance(x, (int, float)): return x is not None and 0 <= x <= 100 return False def v_bool(var: bool, default: bool = True) -> bool: """Returns default=True if var is not a bool.""" if isinstance(var, bool): return bool(var) return default def v_dataframe(obj: MaybeSeriesFrame) -> None: if not isinstance(obj, (DataFrame, Series)): print("[X] Requires a Pandas Series or DataFrame.") def v_float( var: IntFloat, default: IntFloat, ne: Optional[IntFloat] = 0.0 ) -> Float: """Returns the default if var is not equal to the ne value.""" is_ne, is_var = isinstance(ne, (float, int)), isinstance(var, (float, int)) if is_ne and is_var and float(var) != float(ne): return float(var) return float(default) def v_int(var: Int, default: Int, ne: Optional[Int] = 0) -> Int: """Returns the default if var is not equal to the ne value.""" is_ne, is_var = isinstance(ne, int), isinstance(var, int) if is_ne and is_var and int(var) != int(ne): return int(var) return int(default) def v_str(var: str, default: str) -> str: """"Returns the default value if var is not a empty str""" if isinstance(var, str) and len(var) > 0: return f"{var}" return f"{default}" def v_ascending(var: bool) -> bool: """Returns True by default""" return partial(v_bool, default=True)(var=var) def v_datetime_ordered(df: SeriesFrame) -> bool: if is_datetime64_any_dtype(df.index): np_dt_index = df.index.to_numpy() if np_dt_index[0] < np_dt_index[-1]: return True return False def v_drift(var: Int) -> Int: """Defaults to 1""" return partial(v_int, default=1, ne=0)(var=var) def v_list(var: List, default: List = []) -> List: """Returns [] if not a valid list""" if isinstance(var, list) and len(var) > 0: return var return default def v_lowerbound( var: IntFloat, bound: IntFloat = 0, default: IntFloat = 0, strict: bool = True, complement: bool = False ) -> IntFloat: """Returns the default if var(iable) not greater(equal) than bound.""" var_type = None if isinstance(var, float): var_type = float if isinstance(var, int): var_type = int if var_type is None: return default valid = False if strict: valid = var_type(var) > var_type(bound) else: valid = var_type(var) >= var_type(bound) if complement: valid = not valid if valid: return var_type(var) return default def v_mamode(var: str, default: str) -> str: # Could be an alias. return v_str(var, default) def v_offset(var: Int) -> Int: """Defaults to 0""" return partial(v_int, default=0, ne=0)(var=var) def v_pos_default( var: IntFloat, default: IntFloat = 0, strict: bool = True, complement: bool = False ) -> IntFloat: return partial(v_lowerbound, bound=0) \ (var=var, default=default, strict=strict, complement=complement) def v_scalar(var: IntFloat, default: Optional[IntFloat] = 1) -> Float: """Returns the default if var is not a float.""" if isinstance(var, (float, int)): return float(var) return float(default) def v_series(series: Series, length: Optional[IntFloat] = 0) -> Optional[Series]: """Returns None if the Pandas Series does not meet the minimum length required for the indicator.""" if series is not None and isinstance(series, Series): if series.size >= v_pos_default(length, 0): return series return None def v_talib(var: bool) -> bool: """Returns True by default""" return partial(v_bool, default=True)(var=var) def v_tradingview(var: bool) -> bool: """Returns True by default""" return partial(v_bool, default=True)(var=var) def v_upperbound( var: IntFloat, bound: IntFloat = 0, default: IntFloat = 0, strict: bool = True ) -> IntFloat: return partial(v_lowerbound, complement=True)\ (var=var, bound=bound, default=default, strict=strict)