def rsmk(candles: np.ndarray, candles_compare: np.ndarray, lookback: int = 90, period: int = 3, signal_period: int = 20, matype: int = 1, signal_matype: int = 1, source_type: str = "close", sequential: bool = False) -> RSMK: """ RSMK - Relative Strength :param candles: np.ndarray :param candles_compare: np.ndarray :param period: int - default: 3 :param source_type: str - default: "close" :param sequential: bool - default: False :return: float | np.ndarray """ if not sequential and candles.shape[0] > 240: candles = candles[-240:] candles_compare = candles_compare[-240:] source = get_candle_source(candles, source_type=source_type) source_compare = get_candle_source(candles_compare, source_type=source_type) a = np.log(source / source_compare) b = talib.MOM(a, timeperiod=lookback) res = ma(b, period=period, matype=matype, sequential=True) * 100 signal = ma(res, period=signal_period, matype=signal_matype, sequential=True) if sequential: return RSMK(res, signal) else: return RSMK(res[-1], signal[-1])
def ppo(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]: """ PPO - Percentage 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) fast_ma = ma(source, period=fast_period, matype=matype, sequential=True) slow_ma = ma(source, period=slow_period, matype=matype, sequential=True) res = 100 * (fast_ma - slow_ma) / slow_ma return res if sequential else res[-1]
def mab(candles: np.ndarray, fast_period: int = 10, slow_period: int = 50, devup: float = 1, devdn: float = 1, fast_matype: int = 0, slow_matype: int = 0, source_type: str = "close", sequential: bool = False) -> MAB: """ Moving Average Bands :param candles: np.ndarray :param fast_period: int - default: 10 :param slow_period: int - default: 50 :param devup: float - default: 1 :param devdn: float - default: 1 :param fast_matype: int - default: 0 :param slow_matype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default: False :return: MAB(upperband, middleband, lowerband) """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) fastEma = ma(source, period=fast_period, matype=fast_matype, sequential=True) slowEma = ma(source, period=slow_period, matype=slow_matype, sequential=True) sqAvg = talib.SUM(np.power(fastEma - slowEma, 2), fast_period) / fast_period dev = np.sqrt(sqAvg) middlebands = fastEma upperbands = slowEma + devup * dev lowerbands = slowEma - devdn * dev if sequential: return MAB(upperbands, middlebands, lowerbands) else: return MAB(upperbands[-1], middlebands[-1], lowerbands[-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 eri(candles: np.ndarray, period: int = 13, matype: int = 1, source_type: str = "close", sequential: bool = False) -> ERI: """ Elder Ray Index (ERI) :param candles: np.ndarray :param period: int - default: 13 :param matype: int - default: 1 :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) ema = ma(source, period=period, matype=matype, sequential=True) bull = candles[:, 3] - ema bear = candles[:, 4] - ema if sequential: return ERI(bull, bear) else: return ERI(bull[-1], bear[-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 kaufmanstop(candles: np.ndarray, period: int = 22, mult: float = 2, direction: str = "long", matype: int = 0, 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 matype: int - default: 0 :param sequential: bool - default: False :return: float | np.ndarray """ candles = slice_candles(candles, sequential) high = candles[:, 3] low = candles[:, 4] hl_diff = ma(high - low, period=period, matype=matype, sequential=True) res = low - hl_diff * mult if direction == "long" else high + hl_diff * mult return res if sequential else res[-1]
def keltner(candles: np.ndarray, period: int = 20, multiplier: float = 2, matype: int = 1, source_type: str = "close", sequential: bool = False) -> KeltnerChannel: """ Keltner Channels :param candles: np.ndarray :param period: int - default: 20 :param multiplier: float - default: 2 :param matype: int - default: 1 :param source_type: str - default: "close" :param sequential: bool - default=False :return: KeltnerChannel(upperband, middleband, lowerband) """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) e = ma(source, period=period, matype=matype, sequential=True) a = talib.ATR(candles[:, 3], candles[:, 4], candles[:, 2], timeperiod=period) up = e + a * multiplier mid = e low = e - a * multiplier if sequential: return KeltnerChannel(up, mid, low) else: return KeltnerChannel(up[-1], mid[-1], low[-1])
def macdext(candles: np.ndarray, fast_period: int = 12, fast_matype: int = 0, slow_period: int = 26, slow_matype: int = 0, signal_period: int = 9, signal_matype: int = 0, source_type: str = "close", sequential: bool = False) -> MACDEXT: """ MACDEXT - MACD with controllable MA type :param candles: np.ndarray :param fast_period: int - default: 12 :param fast_matype: int - default: 0 :param slow_period: int - default: 26 :param slow_matype: int - default: 0 :param signal_period: int - default: 9 :param signal_matype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default: False :return: MACDEXT(macd, signal, hist) """ candles = slice_candles(candles, sequential) if fast_matype == 29 or slow_matype == 29 or signal_matype == 29: raise ValueError("VWAP not supported in macdext.") ma_fast = ma(candles, period=fast_period, matype=fast_matype, source_type=source_type, sequential=True) ma_slow = ma(candles, period=slow_period, matype=slow_matype, source_type=source_type, sequential=True) macd = ma_fast - ma_slow if signal_matype == 24: # volume needed. candles[:, 2] = macd candles_without_nan = candles[~np.isnan(candles).any(axis=1)] macdsignal = ma(candles_without_nan, period=signal_period, matype=signal_matype, source_type="close", sequential=True) else: macd_without_nan = macd[~np.isnan(macd)] macdsignal = ma(macd_without_nan, period=signal_period, matype=signal_matype, sequential=True) macdsignal = same_length(candles, macdsignal) macdhist = macd - macdsignal if sequential: return MACDEXT(macd, macdsignal, macdhist) else: return MACDEXT(macd[-1], macdsignal[-1], macdhist[-1])
def stc(candles: np.ndarray, fast_period: int = 23, fast_matype: int = 1, slow_period: int = 50, slow_matype: int = 1, k_period: int = 10, d_period: int = 3, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ STC - Schaff Trend Cycle (Oscillator) :param candles: np.ndarray :param fast_period: int - default: 23 :param fastmatype: int - default: 1 :param slow_period: int - default: 50 :param slowmatype: int - default: 1 :param k_period: int - default: 10 :param d_period: int - default: 3 :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) macd = ma( source, period=fast_period, matype=fast_matype, sequential=True) - ma( source, period=slow_period, matype=slow_matype, sequential=True) stok = (macd - talib.MIN(macd, k_period)) / ( talib.MAX(macd, k_period) - talib.MIN(macd, k_period)) * 100 d = talib.EMA(stok, d_period) kd = (d - talib.MIN(d, k_period)) / (talib.MAX(d, k_period) - talib.MIN(d, k_period)) * 100 res = talib.EMA(kd, d_period) return res if sequential else res[-1]
def macdext(candles: np.ndarray, fast_period: int = 12, fast_matype: int = 0, slow_period: int = 26, slow_matype: int = 0, signal_period: int = 9, signal_matype: int = 0, source_type: str = "close", sequential: bool = False) -> MACDEXT: """ MACDEXT - MACD with controllable MA type :param candles: np.ndarray :param fast_period: int - default: 12 :param fastmatype: int - default: 0 :param slow_period: int - default: 26 :param slowmatype: int - default: 0 :param signal_period: int - default: 9 :param signalmatype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default: False :return: MACDEXT(macd, signal, hist) """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) macd = ma( source, period=fast_period, matype=fast_matype, sequential=True) - ma( source, period=slow_period, matype=slow_matype, sequential=True) macdsignal = ma(macd, period=signal_period, matype=signal_matype, sequential=True) macdhist = macd - macdsignal if sequential: return MACDEXT(macd, macdsignal, macdhist) else: return MACDEXT(macd[-1], macdsignal[-1], macdhist[-1])
def rvi(candles: np.ndarray, period: int = 10, ma_len: int = 14, matype: int = 1, devtype: int = 0, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ RVI - Relative Volatility Index :param candles: np.ndarray :param period: int - default: 10 :param ma_len: int - default: 14 :param matype: int - default: 1 :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) if devtype == 0: dev = talib.STDDEV(source, period) elif devtype == 1: dev = mean_ad(source, period, sequential=True) elif devtype == 2: dev = median_ad(source, period, sequential=True) diff = np.diff(source) diff = same_length(source, diff) up = np.nan_to_num(np.where(diff <= 0, 0, dev)) down = np.nan_to_num(np.where(diff > 0, 0, dev)) up_avg = ma(up, period=ma_len, matype=matype, sequential=True) down_avg = ma(down, period=ma_len, matype=matype, sequential=True) result = 100 * (up_avg / (up_avg + down_avg)) return result if sequential else result[-1]
def stoch(candles: np.ndarray, fastk_period: int = 14, slowk_period: int = 3, slowk_matype: int = 0, slowd_period: int = 3, slowd_matype: int = 0, sequential: bool = False) -> Stochastic: """ The Stochastic Oscillator :param candles: np.ndarray :param fastk_period: int - default: 14 :param slowk_period: int - default: 3 :param slowk_matype: int - default: 0 :param slowd_period: int - default: 3 :param slowd_matype: int - default: 0 :param sequential: bool - default: False :return: Stochastic(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) stoch_val = 100 * (candles_close - ll) / (hh - ll) k = ma(stoch_val, period=slowk_period, matype=slowk_matype, sequential=True) d = ma(k, period=slowd_period, matype=slowd_matype, sequential=True) if sequential: return Stochastic(k, d) else: return Stochastic(k[-1], d[-1])
def kdj(candles: np.ndarray, fastk_period: int = 9, slowk_period: int = 3, slowk_matype: int = 0, slowd_period: int = 3, slowd_matype: int = 0, sequential: bool = False) -> KDJ: """ The KDJ Oscillator :param candles: np.ndarray :param fastk_period: int - default: 9 :param slowk_period: int - default: 3 :param slowk_matype: int - default: 0 :param slowd_period: int - default: 3 :param slowd_matype: int - default: 0 :param sequential: bool - default: False :return: KDJ(k, d, j) """ 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) stoch = 100 * (candles_close - ll) / (hh - ll) k = ma(stoch, period=slowk_period, matype=slowk_matype, sequential=True) d = ma(k, period=slowd_period, matype=slowd_matype, sequential=True) j = 3 * k - 2 * d if sequential: return KDJ(k, d, j) else: return KDJ(k[-1], d[-1], j[-1])
def vlma(candles: np.ndarray, min_period: int = 5, max_period: int = 50, matype: int = 0, devtype: int = 0, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ Variable Length Moving Average :param candles: np.ndarray :param min_period: int - default: 5 :param max_period: int - default: 50 :param matype: int - default: 0 :param devtype: int - default: 0 :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) mean = ma(source, period=max_period, matype=matype, sequential=True) if devtype == 0: stdDev = talib.STDDEV(source, max_period) elif devtype == 1: stdDev = mean_ad(source, max_period, sequential=True) elif devtype == 2: stdDev = median_ad(source, max_period, sequential=True) a = mean - (1.75 * stdDev) b = mean - (0.25 * stdDev) c = mean + (0.25 * stdDev) d = mean + (1.75 * stdDev) res = vlma_fast(source, a, b, c, d, min_period, max_period) return res if sequential else res[-1]
def bollinger_bands_width( candles: np.ndarray, period: int = 20, devup: float = 2, devdn: float = 2, matype: int = 0, devtype: int = 0, source_type: str = "close", sequential: bool = False) -> Union[float, np.ndarray]: """ BBW - Bollinger Bands Width - Bollinger Bands Bandwidth :param candles: np.ndarray :param period: int - default: 20 :param devup: float - default: 2 :param devdn: float - default: 2 :param matype: int - default: 0 :param devtype: int - default: 0 :param source_type: str - default: "close" :param sequential: bool - default: False :return: BollingerBands(upperband, middleband, lowerband) """ candles = slice_candles(candles, sequential) source = get_candle_source(candles, source_type=source_type) if devtype == 0: dev = talib.STDDEV(source, period) elif devtype == 1: dev = mean_ad(source, period, sequential=True) elif devtype == 2: dev = median_ad(source, period, sequential=True) middlebands = ma(source, period=period, matype=matype, sequential=True) upperbands = middlebands + devup * dev lowerbands = middlebands - devdn * dev if sequential: return (upperbands - lowerbands) / middlebands else: return (upperbands[-1] - lowerbands[-1]) / middlebands[-1]
def signal_line(series: np.ndarray, period: int = 10, matype: int = 0) -> np.ndarray: from jesse.indicators.ma import ma return ma(series, period=period, matype=matype, sequential=True)