def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: Relative Strength Index (RSI)""" # Validate arguments close = verify_series(close) length = int(length) if length and length > 0 else 14 scalar = float(scalar) if scalar else 100 drift = get_drift(drift) offset = get_offset(offset) # Calculate Result negative = close.diff(drift) positive = negative.copy() positive[positive < 0] = 0 # Make negatives 0 for the postive series negative[negative > 0] = 0 # Make postives 0 for the negative series positive_avg = positive.ewm(com=length, adjust=False).mean() negative_avg = negative.ewm(com=length, adjust=False).mean().abs() rsi = scalar * positive_avg / (positive_avg + negative_avg) # Offset if offset != 0: rsi = rsi.shift(offset) # Handle fills if 'fillna' in kwargs: rsi.fillna(kwargs['fillna'], inplace=True) if 'fill_method' in kwargs: rsi.fillna(method=kwargs['fill_method'], inplace=True) # Name and Categorize it rsi.name = f"RSI_{length}" rsi.category = 'momentum' signal_indicators = kwargs.pop('signal_indicators', False) if signal_indicators: signalsdf = concat( [ DataFrame( {rsi.name: rsi} ), signals( indicator=rsi, xa=kwargs.pop('xa', 80), xb=kwargs.pop('xb', 20), xserie=kwargs.pop('xserie', None), xserie_a=kwargs.pop('xserie_a', None), xserie_b=kwargs.pop('xserie_b', None), cross_values=kwargs.pop('cross_values', False), cross_series=kwargs.pop('cross_series', True), offset=offset, ), ], axis=1 ) return signalsdf else: return rsi
def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: Relative Strength Index (RSI)""" # Validate arguments length = int(length) if length and length > 0 else 14 scalar = float(scalar) if scalar else 100 close = verify_series(close, length) drift = get_drift(drift) offset = get_offset(offset) if close is None: return # Calculate Result negative = close.diff(drift) positive = negative.copy() positive[positive < 0] = 0 # Make negatives 0 for the postive series negative[negative > 0] = 0 # Make postives 0 for the negative series positive_avg = rma(positive, length=length) negative_avg = rma(negative, length=length) rsi = scalar * positive_avg / (positive_avg + negative_avg.abs()) # Offset if offset != 0: rsi = rsi.shift(offset) # Handle fills if "fillna" in kwargs: rsi.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: rsi.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it rsi.name = f"RSI_{length}" rsi.category = "momentum" signal_indicators = kwargs.pop("signal_indicators", False) if signal_indicators: signalsdf = concat( [ DataFrame({rsi.name: rsi}), signals( indicator=rsi, xa=kwargs.pop("xa", 80), xb=kwargs.pop("xb", 20), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", False), cross_series=kwargs.pop("cross_series", True), offset=offset, ), ], axis=1, ) return signalsdf else: return rsi
def er(close, length=None, drift=None, offset=None, **kwargs): """Indicator: Efficiency Ratio (ER)""" # Validate arguments length = int(length) if length and length > 0 else 10 close = verify_series(close, length) offset = get_offset(offset) drift = get_drift(drift) if close is None: return # Calculate Result abs_diff = close.diff(length).abs() abs_volatility = close.diff(drift).abs() er = abs_diff er /= abs_volatility.rolling(window=length).sum() # Offset if offset != 0: er = er.shift(offset) # Handle fills if "fillna" in kwargs: er.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: er.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it er.name = f"ER_{length}" er.category = "momentum" signal_indicators = kwargs.pop("signal_indicators", False) if signal_indicators: signalsdf = concat( [ DataFrame({er.name: er}), signals( indicator=er, xa=kwargs.pop("xa", 80), xb=kwargs.pop("xb", 20), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", False), cross_series=kwargs.pop("cross_series", True), offset=offset, ), ], axis=1, ) return signalsdf else: return er
def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs): """Indicator: Moving Average, Convergence/Divergence (MACD)""" # Validate arguments close = verify_series(close) fast = int(fast) if fast and fast > 0 else 12 slow = int(slow) if slow and slow > 0 else 26 signal = int(signal) if signal and signal > 0 else 9 if slow < fast: fast, slow = slow, fast offset = get_offset(offset) # Calculate Result fastma = ema(close, length=fast) slowma = ema(close, length=slow) macd = fastma - slowma signalma = ema(close=macd, length=signal) histogram = macd - signalma # Offset if offset != 0: macd = macd.shift(offset) histogram = histogram.shift(offset) signalma = signalma.shift(offset) # Handle fills if "fillna" in kwargs: macd.fillna(kwargs["fillna"], inplace=True) histogram.fillna(kwargs["fillna"], inplace=True) signalma.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: macd.fillna(method=kwargs["fill_method"], inplace=True) histogram.fillna(method=kwargs["fill_method"], inplace=True) signalma.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it _props = f"_{fast}_{slow}_{signal}" macd.name = f"MACD{_props}" histogram.name = f"MACDh{_props}" signalma.name = f"MACDs{_props}" macd.category = histogram.category = signalma.category = "momentum" # Prepare DataFrame to return data = {macd.name: macd, histogram.name: histogram, signalma.name: signalma} df = DataFrame(data) df.name = f"MACD{_props}" df.category = macd.category signal_indicators = kwargs.pop("signal_indicators", False) if signal_indicators: signalsdf = concat( [ df, signals( indicator=histogram, xa=kwargs.pop("xa", 0), xb=kwargs.pop("xb", None), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", True), cross_series=kwargs.pop("cross_series", True), offset=offset, ), signals( indicator=macd, xa=kwargs.pop("xa", 0), xb=kwargs.pop("xb", None), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", False), cross_series=kwargs.pop("cross_series", True), offset=offset, ), ], axis=1, ) return signalsdf else: return df
def rsx(close, length=None, drift=None, offset=None, **kwargs): """Indicator: Relative Strength Xtra (inspired by Jurik RSX)""" # Validate arguments length = int(length) if length and length > 0 else 14 close = verify_series(close, length) drift = get_drift(drift) offset = get_offset(offset) if close is None: return # variables vC, v1C = 0, 0 v4, v8, v10, v14, v18, v20 = 0, 0, 0, 0, 0, 0 f0, f8, f10, f18, f20, f28, f30, f38 = 0, 0, 0, 0, 0, 0, 0, 0 f40, f48, f50, f58, f60, f68, f70, f78 = 0, 0, 0, 0, 0, 0, 0, 0 f80, f88, f90 = 0, 0, 0 # Calculate Result m = close.size result = [npNaN for _ in range(0, length - 1)] + [0] for i in range(length, m): if f90 == 0: f90 = 1.0 f0 = 0.0 if length - 1.0 >= 5: f88 = length - 1.0 else: f88 = 5.0 f8 = 100.0 * close.iloc[i] f18 = 3.0 / (length + 2.0) f20 = 1.0 - f18 else: if f88 <= f90: f90 = f88 + 1 else: f90 = f90 + 1 f10 = f8 f8 = 100 * close.iloc[i] v8 = f8 - f10 f28 = f20 * f28 + f18 * v8 f30 = f18 * f28 + f20 * f30 vC = 1.5 * f28 - 0.5 * f30 f38 = f20 * f38 + f18 * vC f40 = f18 * f38 + f20 * f40 v10 = 1.5 * f38 - 0.5 * f40 f48 = f20 * f48 + f18 * v10 f50 = f18 * f48 + f20 * f50 v14 = 1.5 * f48 - 0.5 * f50 f58 = f20 * f58 + f18 * abs(v8) f60 = f18 * f58 + f20 * f60 v18 = 1.5 * f58 - 0.5 * f60 f68 = f20 * f68 + f18 * v18 f70 = f18 * f68 + f20 * f70 v1C = 1.5 * f68 - 0.5 * f70 f78 = f20 * f78 + f18 * v1C f80 = f18 * f78 + f20 * f80 v20 = 1.5 * f78 - 0.5 * f80 if f88 >= f90 and f8 != f10: f0 = 1.0 if f88 == f90 and f0 == 0.0: f90 = 0.0 if f88 < f90 and v20 > 0.0000000001: v4 = (v14 / v20 + 1.0) * 50.0 if v4 > 100.0: v4 = 100.0 if v4 < 0.0: v4 = 0.0 else: v4 = 50.0 result.append(v4) rsx = Series(result, index=close.index) # Offset if offset != 0: rsx = rsx.shift(offset) # Handle fills if "fillna" in kwargs: rsx.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: rsx.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it rsx.name = f"RSX_{length}" rsx.category = "momentum" signal_indicators = kwargs.pop("signal_indicators", False) if signal_indicators: signalsdf = concat([ DataFrame({rsx.name: rsx}), signals( indicator=rsx, xa=kwargs.pop("xa", 80), xb=kwargs.pop("xb", 20), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", False), cross_series=kwargs.pop("cross_series", True), offset=offset, ), ], axis=1) return signalsdf else: return rsx
def macd(close, fast=None, slow=None, signal=None, talib=None, offset=None, **kwargs): """Indicator: Moving Average, Convergence/Divergence (MACD)""" # Validate arguments fast = int(fast) if fast and fast > 0 else 12 slow = int(slow) if slow and slow > 0 else 26 signal = int(signal) if signal and signal > 0 else 9 if slow < fast: fast, slow = slow, fast close = verify_series(close, max(fast, slow, signal)) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True if close is None: return as_mode = kwargs.setdefault("asmode", False) # Calculate Result if Imports["talib"] and mode_tal: from talib import MACD macd, signalma, histogram = MACD(close, fast, slow, signal) else: fastma = ema(close, length=fast) slowma = ema(close, length=slow) macd = fastma - slowma signalma = ema(close=macd.loc[macd.first_valid_index():, ], length=signal) histogram = macd - signalma if as_mode: macd = macd - signalma signalma = ema(close=macd.loc[macd.first_valid_index():, ], length=signal) histogram = macd - signalma # Offset if offset != 0: macd = macd.shift(offset) histogram = histogram.shift(offset) signalma = signalma.shift(offset) # Handle fills if "fillna" in kwargs: macd.fillna(kwargs["fillna"], inplace=True) histogram.fillna(kwargs["fillna"], inplace=True) signalma.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: macd.fillna(method=kwargs["fill_method"], inplace=True) histogram.fillna(method=kwargs["fill_method"], inplace=True) signalma.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it _asmode = "AS" if as_mode else "" _props = f"_{fast}_{slow}_{signal}" macd.name = f"MACD{_asmode}{_props}" histogram.name = f"MACD{_asmode}h{_props}" signalma.name = f"MACD{_asmode}s{_props}" macd.category = histogram.category = signalma.category = "momentum" # Prepare DataFrame to return data = { macd.name: macd, histogram.name: histogram, signalma.name: signalma } df = DataFrame(data) df.name = f"MACD{_asmode}{_props}" df.category = macd.category signal_indicators = kwargs.pop("signal_indicators", False) if signal_indicators: signalsdf = concat( [ df, signals( indicator=histogram, xa=kwargs.pop("xa", 0), xb=kwargs.pop("xb", None), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", True), cross_series=kwargs.pop("cross_series", True), offset=offset, ), signals( indicator=macd, xa=kwargs.pop("xa", 0), xb=kwargs.pop("xb", None), xserie=kwargs.pop("xserie", None), xserie_a=kwargs.pop("xserie_a", None), xserie_b=kwargs.pop("xserie_b", None), cross_values=kwargs.pop("cross_values", False), cross_series=kwargs.pop("cross_series", True), offset=offset, ), ], axis=1, ) return signalsdf else: return df