def sinwma(candles: np.ndarray, period: int = 14, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Sine Weighted Moving Average (SINWMA) :param candles: np.ndarray :param period: int - default: 14 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ # Accept normal array too. if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) sines = np.array( [np.sin((i + 1) * np.pi / (period + 1)) for i in range(period)]) w = sines / sines.sum() swv = sliding_window_view(source, window_shape=period) res = np.average(swv, weights=w, axis=-1) return same_length(candles, res) if sequential else res[-1]
def swma(candles: np.ndarray, period: int = 5, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Symmetric Weighted Moving Average (SWMA) :param candles: np.ndarray :param period: int - default: 5 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ # Accept normal array too. if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) triangle = symmetric_triangle(period) swv = sliding_window_view(source, window_shape=period) res = np.average(swv, weights=triangle, axis=-1) return same_length(candles, res) if sequential else res[-1]
def high_pass(candles: np.ndarray, period: int = 48, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ (1 pole) high-pass filter indicator by John F. Ehlers :param candles: np.ndarray :param period: int - default=48 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) hpf = high_pass_fast(source, period) if sequential: return hpf else: return None if np.isnan(hpf[-1]) else hpf[-1]
def vwmacd(candles: np.ndarray, fast_period: int = 12, slow_period: int = 26, signal_period: int = 9, sequential: bool = False) -> VWMACD: """ VWMACD - Volume Weighted Moving Average Convergence/Divergence :param candles: np.ndarray :param fast_period: int - default: 12 :param slow_period: int - default: 26 :param signal_period: int - default: 9 :param sequential: bool - default: False :return: VWMACD(macd, signal, hist) """ candles = slice_candles(candles, sequential) vwma_slow = talib.SMA(candles[:, 2] * candles[:, 5], slow_period) / talib.SMA(candles[:, 5], slow_period) vwma_fast = talib.SMA(candles[:, 2] * candles[:, 5], fast_period) / talib.SMA(candles[:, 5], fast_period) vwmacd = vwma_fast - vwma_slow signal = talib.EMA(vwmacd, signal_period) hist = vwmacd - signal if sequential: return VWMACD(vwmacd, signal, hist) else: return VWMACD(vwmacd[-1], signal[-1], hist[-1])
def kaufmanstop(candles: np.ndarray, period: int = 22, mult: float = 2, direction: str = "long", sequential: bool = False) -> Union[float, np.ndarray]: """ Perry Kaufman's Stops :param candles: np.ndarray :param period: int - default: 22 :param mult: float - default: 2 :param direction: str - default: long :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) high = candles[:, 3] low = candles[:, 4] hl_diff = talib.SMA(high - low, period) if direction == "long": res = hl_diff * mult - low else: res = hl_diff * mult + high return res if sequential else res[-1]
def stochf(candles: np.ndarray, fastk_period: int = 5, fastd_period: int = 3, fastd_matype: int = 0, sequential: bool = False) -> StochasticFast: """ Stochastic Fast :param candles: np.ndarray :param fastk_period: int - default=5 :param fastd_period: int - default=3 :param fastd_matype: int - default=0 :param sequential: bool - default=False :return: StochasticFast(k, d) """ candles = slice_candles(candles, sequential) candles_close = candles[:, 2] candles_high = candles[:, 3] candles_low = candles[:, 4] hh = talib.MAX(candles_high, fastk_period) ll = talib.MIN(candles_low, fastk_period) k = 100 * (candles_close - ll) / (hh - ll) d = ma(k, period=fastd_period, matype=fastd_matype, sequential=True) if sequential: return StochasticFast(k, d) else: return StochasticFast(k[-1], d[-1])
def tsi(candles: np.ndarray, long_period: int = 25, short_period: int = 13, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ True strength index (TSI) :param candles: np.ndarray :param long_period: int - default: 25 :param short_period: int - default: 13 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) r = 100 * (talib.EMA( (talib.EMA(talib.MOM(source, 1), long_period)), short_period)) / (talib.EMA( (talib.EMA(np.absolute(talib.MOM(source, 1)), long_period)), short_period)) return r if sequential else r[-1]
def emd(candles: np.ndarray, period: int = 20, delta=0.5, fraction=0.1, sequential: bool = False) -> EMD: """ Empirical Mode Decomposition by John F. Ehlers and Ric Way :param candles: np.ndarray :param period: int - default: 20 :param delta: float - default: 0.5 :param fraction: float - default: 0.1 :param sequential: bool - default: False :return: EMD(upperband, middleband, lowerband) """ candles = slice_candles(candles, sequential) price = (candles[:, 3] + candles[:, 4]) / 2 bp = bp_fast(price, period, delta) mean = talib.SMA(bp, timeperiod=2 * period) peak, valley = peak_valley_fast(bp, price) avg_peak = fraction * talib.SMA(peak, timeperiod=50) avg_valley = fraction * talib.SMA(valley, timeperiod=50) if sequential: return EMD(avg_peak, mean, avg_valley) else: return EMD(avg_peak[-1], mean[-1], avg_valley[-1])
def supersmoother_3_pole(candles: np.ndarray, period: int = 14, source_type: str = "close", sequential: bool = False) -> \ Union[ float, np.ndarray]: """ Super Smoother Filter 3pole Butterworth This indicator was described by John F. Ehlers :param candles: np.ndarray :param period: int - default=14 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) # Accept normal array too. if len(candles.shape) == 1: source = candles else: source = get_candle_source(candles, source_type=source_type) res = supersmoother_fast(source, period) return res if sequential else res[-1]
def jma(candles: np.ndarray, period: int = 7, phase: float = 50, power: int = 2, source_type: str = 'close', sequential: bool = False) -> Union[float, np.ndarray]: """ Jurik Moving Average Port of: https://tradingview.com/script/nZuBWW9j-Jurik-Moving-Average/ """ if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) phaseRatio = 0.5 if phase < -100 else ( 2.5 if phase > 100 else phase / 100 + 1.5) beta = 0.45 * (period - 1) / (0.45 * (period - 1) + 2) alpha = pow(beta, power) res = jma_helper(source, phaseRatio, beta, alpha) return res if sequential else res[-1]
def devstop(candles: np.ndarray, period: int = 20, mult: float = 0, direction: str = "long", sequential: bool = False) -> Union[ float, np.ndarray]: """ Kase Dev Stops :param candles: np.ndarray :param period: int - default=20 :param mult: float - default=0 :param direction: str - default=long :param sequential: bool - default=False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) high = candles[:, 3] low = candles[:, 4] AVTR = talib.SMA(talib.MAX(high, 2) - talib.MIN(low, 2), period) SD = talib.STDDEV(talib.MAX(high, 2) - talib.MIN(low, 2), period) if direction == "long": res = talib.MAX(high - AVTR - mult * SD, period) else: res = talib.MIN(low + AVTR + mult * SD, period) return res if sequential else res[-1]
def ift_rsi(candles: np.ndarray, rsi_period: int = 5, wma_period: int = 9, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Modified Inverse Fisher Transform applied on RSI :param candles: np.ndarray :param rsi_period: int - default: 5 :param wma_period: int - default: 9 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) v1 = 0.1 * (talib.RSI(source, rsi_period) - 50) v2 = talib.WMA(v1, wma_period) res = (((2 * v2)**2 - 1) / ((2 * v2)**2 + 1)) return same_length(candles, res) if sequential else res[-1]
def cc(candles: np.ndarray, wma_period: int = 10, roc_short_period: int = 11, roc_long_period: int = 14, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ CC - Coppock Curve :param candles: np.ndarray :param wma_period: int - default: 10 :param roc_short_period: int - default: 11 :param roc_long_period: int - default: 14 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) res = talib.WMA(talib.ROC(source, timeperiod=roc_long_period) + talib.ROC(source, timeperiod=roc_short_period), timeperiod=wma_period) return res if sequential else res[-1]
def er(candles: np.ndarray, period: int = 5, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ ER - The Kaufman Efficiency indicator :param candles: np.ndarray :param period: int - default: 5 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) change = np.abs(np.diff(source, period)) abs_dif = np.abs(np.diff(source)) swv = sliding_window_view(abs_dif, window_shape=period) volatility = swv.sum() res = change / volatility return same_length(candles, res) if sequential else res[-1]
def zscore(candles: np.ndarray, period: int = 14, matype: int = 0, nbdev: float = 1, devtype: int = 0, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ zScore :param candles: np.ndarray :param period: int - default: 14 :param matype: int - default: 0 :param nbdev: float - default: 1 :param devtype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) means = ma(source, period=period, matype=matype, sequential=True) if devtype == 0: sigmas = talib.STDDEV(source, period) * nbdev elif devtype == 1: sigmas = mean_ad(source, period, sequential=True) * nbdev elif devtype == 2: sigmas = median_ad(source, period, sequential=True) * nbdev zScores = (source - means) / sigmas return zScores if sequential else zScores[-1]
def frama(candles: np.ndarray, window: int = 10, FC: int = 1, SC: int = 300, sequential: bool = False) -> Union[float, np.ndarray]: """ Fractal Adaptive Moving Average (FRAMA) :param candles: np.ndarray :param window: int - default: 10 :param FC: int - default: 1 :param SC: int - default: 300 :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) n = window # n must be even if n % 2 == 1: print("FRAMA n must be even. Adding one") n += 1 res = frame_fast(candles, n, SC, FC) if sequential: return res else: return res[-1]
def cfo(candles: np.ndarray, period: int = 14, scalar: float = 100, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ CFO - Chande Forcast Oscillator :param candles: np.ndarray :param period: int - default: 14 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) cfo = scalar * (source - talib.LINEARREG(source, timeperiod=period)) cfo /= source if sequential: return cfo else: return None if np.isnan(cfo[-1]) else cfo[-1]
def di(candles: np.ndarray, period: int = 14, sequential: bool = False) -> DI: """ DI - Directional Indicator :param candles: np.ndarray :param period: int - default: 14 :param sequential: bool - default: False :return: DI(plus, minus) """ candles = slice_candles(candles, sequential) MINUS_DI = talib.MINUS_DI(candles[:, 3], candles[:, 4], candles[:, 2], timeperiod=period) PLUS_DI = talib.PLUS_DI(candles[:, 3], candles[:, 4], candles[:, 2], timeperiod=period) if sequential: return DI(PLUS_DI, MINUS_DI) else: return DI(PLUS_DI[-1], MINUS_DI[-1])
def vwap(candles: np.ndarray, source_type: str = "hlc3", anchor: str = "D", sequential: bool = False) -> Union[float, np.ndarray]: """ VWAP :param candles: np.ndarray :param source_type: str - default: "close" :param anchor: str - default: "D" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) group_idx = candles[:, 0].astype('datetime64[ms]').astype( f'datetime64[{anchor}]').astype('int') vwap_values = aggregate(group_idx, candles[:, 5] * source, func='cumsum') vwap_values /= aggregate(group_idx, candles[:, 5], func='cumsum') if sequential: return vwap_values else: return None if np.isnan(vwap_values[-1]) else vwap_values[-1]
def correlation_cycle(candles: np.ndarray, period: int = 20, threshold: int = 9, source_type: str = "close", sequential: bool = False) -> CC: """ "Correlation Cycle, Correlation Angle, Market State - John Ehlers :param candles: np.ndarray :param period: int - default: 20 :param threshold: int - default: 9 :param source_type: str - default: "close" :param sequential: bool - default: False :return: CC(real, imag) """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) realPart, imagPart, angle = go_fast(source, period, threshold) priorAngle = np_shift(angle, 1, fill_value=np.nan) angle = np.where(np.logical_and(priorAngle > angle, priorAngle - angle < 270.0), priorAngle, angle) # Market State Function state = np.where(np.abs(angle - priorAngle) < threshold, np.where(angle >= 0.0, 1, np.where(angle < 0.0, -1, 0)), 0) if sequential: return CC(realPart, imagPart, angle, state) else: return CC(realPart[-1], imagPart[-1], angle[-1], state[-1])
def reflex(candles: np.ndarray, period: int = 20, source_type: str = "close", sequential: bool = False) -> Union[ float, np.ndarray]: """ Reflex indicator by John F. Ehlers :param candles: np.ndarray :param period: int - default=20 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) ssf = supersmoother_fast(source, period / 2) rf = reflex_fast(ssf, period) if sequential: return rf else: return None if np.isnan(rf[-1]) else rf[-1]
def supertrend(candles: np.ndarray, period: int = 10, factor: float = 3, sequential: bool = False) -> SuperTrend: """ SuperTrend :param candles: np.ndarray :param period: int - default=14 :param factor: float - default=3 :param sequential: bool - default=False :return: SuperTrend(trend, changed) """ candles = slice_candles(candles, sequential) # calculation of ATR using TALIB function atr = talib.ATR(candles[:, 3], candles[:, 4], candles[:, 2], timeperiod=period) super_trend, changed = supertrend_fast(candles, atr, factor, period) if sequential: return SuperTrend(super_trend, changed) else: return SuperTrend(super_trend[-1], changed[-1])
def ultosc(candles: np.ndarray, timeperiod1: int = 7, timeperiod2: int = 14, timeperiod3: int = 28, sequential: bool = False) -> Union[float, np.ndarray]: """ ULTOSC - Ultimate Oscillator :param candles: np.ndarray :param timeperiod1: int - default: 7 :param timeperiod2: int - default: 14 :param timeperiod3: int - default: 28 :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) res = talib.ULTOSC(candles[:, 3], candles[:, 4], candles[:, 2], timeperiod1=timeperiod1, timeperiod2=timeperiod2, timeperiod3=timeperiod3) return res if sequential else res[-1]
def chande(candles: np.ndarray, period: int = 22, mult: float = 3.0, direction: str = "long", sequential: bool = False) -> Union[float, np.ndarray]: """ Chandelier Exits :param candles: np.ndarray :param period: int - default: 22 :param mult: float - default: 3.0 :param direction: str - default: "long" :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) candles_close = candles[:, 2] candles_high = candles[:, 3] candles_low = candles[:, 4] atr = talib.ATR(candles_high, candles_low, candles_close, timeperiod=period) if direction == 'long': maxp = filter1d_same(candles_high, period, 'max') result = maxp - atr * mult elif direction == 'short': maxp = filter1d_same(candles_low, period, 'min') result = maxp + atr * mult else: print('The last parameter must be \'short\' or \'long\'') return result if sequential else result[-1]
def vidya(candles: np.ndarray, short_period: int = 2, long_period: int = 5, alpha: float = 0.2, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ VIDYA - Variable Index Dynamic Average :param candles: np.ndarray :param short_period: int - default: 2 :param long_period: int - default: 5 :param alpha: float - default: 0.2 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) res = ti.vidya(np.ascontiguousarray(source), short_period=short_period, long_period=long_period, alpha=alpha) return same_length(candles, res) if sequential else res[-1]
def pfe(candles: np.ndarray, period: int = 10, smoothing: int = 5, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Polarized Fractal Efficiency (PFE) :param candles: np.ndarray :param period: int - default: 10 :param smoothing: int - default: 5 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) ln = period - 1 diff = np.diff(source, ln) a = np.sqrt(np.power(diff, 2) + np.power(period, 2)) b = talib.SUM(np.sqrt(1 + np.power(np.diff(source, 1), 2)), ln) pfetmp = 100 * same_length(source, a) / same_length(source, b) res = talib.EMA(np.where(same_length(source, diff) > 0, pfetmp, -pfetmp), smoothing) return res if sequential else res[-1]
def cwma(candles: np.ndarray, period: int = 14, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Cubed Weighted Moving Average :param candles: np.ndarray :param period: int - default: 14 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ # Accept normal array too. if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) res = vpwma_fast(source, period) return res if sequential else res[-1]
def apo(candles: np.ndarray, fast_period: int = 12, slow_period: int = 26, matype: int = 0, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ APO - Absolute Price Oscillator :param candles: np.ndarray :param fast_period: int - default: 12 :param slow_period: int - default: 26 :param matype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default=False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) res = talib.APO(source, fastperiod=fast_period, slowperiod=slow_period, matype=matype) return res if sequential else res[-1]
def edcf(candles: np.ndarray, period: int = 15, source_type: str = "hl2", sequential: bool = False) -> Union[float, np.ndarray]: """ Ehlers Distance Coefficient Filter :param candles: np.ndarray :param period: int - default: 15 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ # Accept normal array too. if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) res = edcf_fast(source, period) return res if sequential else res[-1]
def hurst_exponent(candles: np.ndarray, min_chunksize: int = 8, max_chunksize: int = 200, num_chunksize:int=5, method:int=1, source_type: str = "close") -> float: """ Hurst Exponent :param candles: np.ndarray :param min_chunksize: int - default: 8 :param max_chunksize: int - default: 200 :param num_chunksize: int - default: 5 :param method: int - default: 1 - 0: RS | 1: DMA | 2: DSOD :param source_type: str - default: "close" :return: float """ if len(candles.shape) == 1: source = candles else: candles = slice_candles(candles, False) source = get_candle_source(candles, source_type=source_type) if method == 0: if no_numba: raise ValueError("This hurst method is only supported with installed numba.") h = hurst_rs(np.diff(source), min_chunksize, max_chunksize, num_chunksize) elif method == 1: h = hurst_dma(source, min_chunksize, max_chunksize, num_chunksize) elif method == 2: h = hurst_dsod(source) else: raise NotImplementedError('The method choose is not implemented.') return None if np.isnan(h) else h