def vhf(close, length=None, drift=None, offset=None, **kwargs): """Indicator: Vertical Horizontal Filter (VHF)""" # Validate arguments length = int(length) if length and length > 0 else 28 close = verify_series(close, length) drift = get_drift(drift) offset = get_offset(offset) if close is None: return # Calculate Result hcp = close.rolling(length).max() lcp = close.rolling(length).min() diff = npFabs(close.diff(drift)) vhf = npFabs(non_zero_range(hcp, lcp)) / diff.rolling(length).sum() # Offset if offset != 0: vhf = vhf.shift(offset) # Handle fills if "fillna" in kwargs: vhf.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: vhf.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it vhf.name = f"VHF_{length}" vhf.category = "trend" return vhf
def fibonacci(n: int = 2, **kwargs: dict) -> npNdArray: """Fibonacci Sequence as a numpy array""" n = int(npFabs(n)) if n >= 0 else 2 zero = kwargs.pop("zero", False) if zero: a, b = 0, 1 else: n -= 1 a, b = 1, 1 result = npArray([a]) for _ in range(0, n): a, b = b, a + b result = npAppend(result, a) weighted = kwargs.pop("weighted", False) if weighted: fib_sum = npSum(result) if fib_sum > 0: return result / fib_sum else: return result else: return result
def combination(**kwargs: dict) -> int: """https://stackoverflow.com/questions/4941753/is-there-a-math-ncr-function-in-python""" n = int(npFabs(kwargs.pop("n", 1))) r = int(npFabs(kwargs.pop("r", 0))) if kwargs.pop("repetition", False) or kwargs.pop("multichoose", False): n = n + r - 1 # if r < 0: return None r = min(n, n - r) if r == 0: return 1 numerator = reduce(mul, range(n, n - r, -1), 1) denominator = reduce(mul, range(1, r + 1), 1) return numerator // denominator
def symmetric_triangle(n: int = None, **kwargs: dict) -> Optional[List[int]]: """Symmetric Triangle with n >= 2 Returns a numpy array of the nth row of Symmetric Triangle. n=4 => triangle: [1, 2, 2, 1] => weighted: [0.16666667 0.33333333 0.33333333 0.16666667] """ n = int(npFabs(n)) if n is not None else 2 triangle = None if n == 2: triangle = [1, 1] if n > 2: if n % 2 == 0: front = [i + 1 for i in range(0, mfloor(n / 2))] triangle = front + front[::-1] else: front = [i + 1 for i in range(0, mfloor(0.5 * (n + 1)))] triangle = front.copy() front.pop() triangle += front[::-1] if kwargs.pop("weighted", False) and isinstance(triangle, list): triangle_sum = npSum(triangle) triangle_weights = triangle / triangle_sum return triangle_weights return triangle
def pascals_triangle(n: int = None, **kwargs: dict) -> npNdArray: """Pascal's Triangle Returns a numpy array of the nth row of Pascal's Triangle. n=4 => triangle: [1, 4, 6, 4, 1] => weighted: [0.0625, 0.25, 0.375, 0.25, 0.0625] => inverse weighted: [0.9375, 0.75, 0.625, 0.75, 0.9375] """ n = int(npFabs(n)) if n is not None else 0 # Calculation triangle = npArray([combination(n=n, r=i) for i in range(0, n + 1)]) triangle_sum = npSum(triangle) triangle_weights = triangle / triangle_sum inverse_weights = 1 - triangle_weights weighted = kwargs.pop("weighted", False) inverse = kwargs.pop("inverse", False) if weighted and inverse: return inverse_weights if weighted: return triangle_weights if inverse: return None return triangle