def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: ADX""" # Validate Arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = 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 atr_ = atr(high=high, low=low, close=close, length=length) up = high - high.shift(drift) # high.diff(drift) dn = low.shift(drift) - low # low.diff(-drift).shift(drift) pos = ((up > dn) & (up > 0)) * up neg = ((dn > up) & (dn > 0)) * dn pos = pos.apply(zero) neg = neg.apply(zero) k = scalar / atr_ dmp = k * rma(close=pos, length=length) dmn = k * rma(close=neg, length=length) dx = scalar * (dmp - dmn).abs() / (dmp + dmn) adx = rma(close=dx, length=length) # Offset if offset != 0: dmp = dmp.shift(offset) dmn = dmn.shift(offset) adx = adx.shift(offset) # Handle fills if "fillna" in kwargs: adx.fillna(kwargs["fillna"], inplace=True) dmp.fillna(kwargs["fillna"], inplace=True) dmn.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: adx.fillna(method=kwargs["fill_method"], inplace=True) dmp.fillna(method=kwargs["fill_method"], inplace=True) dmn.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it adx.name = f"ADX_{length}" dmp.name = f"DMP_{length}" dmn.name = f"DMN_{length}" adx.category = dmp.category = dmn.category = "trend" # Prepare DataFrame to return data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn} adxdf = DataFrame(data) adxdf.name = f"ADX_{length}" adxdf.category = "trend" return adxdf
def pgo(high, low, close, length=None, offset=None, **kwargs): """Indicator: Pretty Good Oscillator (PGO)""" # Validate arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = int(length) if length and length > 0 else 14 offset = get_offset(offset) # Calculate Result pgo = close - sma(close, length) pgo /= ema(atr(high, low, close, length), length) # Offset if offset != 0: pgo = pgo.shift(offset) # Handle fills if "fillna" in kwargs: pgo.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: pgo.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it pgo.name = f"PGO_{length}" pgo.category = "momentum" return pgo
def chop(high, low, close, length=None, atr_length=None, ln=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: Choppiness Index (CHOP)""" # Validate Arguments length = int(length) if length and length > 0 else 14 atr_length = int( atr_length) if atr_length is not None and atr_length > 0 else 1 ln = bool(ln) if isinstance(ln, bool) else False scalar = float(scalar) if scalar else 100 high = verify_series(high, length) low = verify_series(low, length) close = verify_series(close, length) drift = get_drift(drift) offset = get_offset(offset) if high is None or low is None or close is None: return # Calculate Result diff = high.rolling(length).max() - low.rolling(length).min() atr_ = atr(high=high, low=low, close=close, length=atr_length) atr_sum = atr_.rolling(length).sum() chop = scalar if ln: chop *= (npLn(atr_sum) - npLn(diff)) / npLn(length) else: chop *= (npLog10(atr_sum) - npLog10(diff)) / npLog10(length) # Offset if offset != 0: chop = chop.shift(offset) # Handle fills if "fillna" in kwargs: chop.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: chop.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it chop.name = f"CHOP{'ln' if ln else ''}_{length}_{atr_length}_{scalar}" chop.category = "trend" return chop
def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs): """Indicator: Chande Kroll Stop (CKSP)""" # Validate Arguments p = int(p) if p and p > 0 else 10 x = float(x) if x and x > 0 else 1 q = int(q) if q and q > 0 else 9 _length = max(p, q, x) high = verify_series(high, _length) low = verify_series(low, _length) close = verify_series(close, _length) offset = get_offset(offset) if high is None or low is None or close is None: return # Calculate Result atr_ = atr(high=high, low=low, close=close, length=p) long_stop_ = high.rolling(p).max() - x * atr_ long_stop = long_stop_.rolling(q).max() short_stop_ = high.rolling(p).min() + x * atr_ short_stop = short_stop_.rolling(q).min() # Offset if offset != 0: long_stop = long_stop.shift(offset) short_stop = short_stop.shift(offset) # Handle fills if "fillna" in kwargs: long_stop.fillna(kwargs["fillna"], inplace=True) short_stop.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: long_stop.fillna(method=kwargs["fill_method"], inplace=True) short_stop.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it _props = f"_{p}_{x}_{q}" long_stop.name = f"CKSPl{_props}" short_stop.name = f"CKSPs{_props}" long_stop.category = short_stop.category = "trend" # Prepare DataFrame to return ckspdf = DataFrame({ long_stop.name: long_stop, short_stop.name: short_stop }) ckspdf.name = f"CKSP{_props}" ckspdf.category = long_stop.category return ckspdf
def chop( high, low, close, length=None, atr_length=None, scalar=None, drift=None, offset=None, **kwargs, ): """Indicator: Choppiness Index (CHOP)""" # Validate Arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = int(length) if length and length > 0 else 14 atr_length = int( atr_length) if atr_length is not None and atr_length > 0 else 1 scalar = float(scalar) if scalar else 100 drift = get_drift(drift) offset = get_offset(offset) # Calculate Result diff = high.rolling(length).max() - low.rolling(length).min() atr_ = atr(high=high, low=low, close=close, length=atr_length) atr_sum = atr_.rolling(length).sum() chop = scalar * (npLog10(atr_sum) - npLog10(diff)) chop /= npLog10(length) # Offset if offset != 0: chop = chop.shift(offset) # Handle fills if "fillna" in kwargs: chop.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: chop.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it chop.name = f"CHOP_{length}_{atr_length}_{scalar}" chop.category = "trend" return chop
def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kwargs): """Indicator: Supertrend""" # Validate Arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = int(length) if length and length > 0 else 7 multiplier = float(multiplier) if multiplier and multiplier > 0 else 3. offset = get_offset(offset) # Calculate Results m = close.size dir_, trend = [1] * m, [0] * m long, short = [npNaN] * m, [npNaN] * m hl2_ = hl2(high, low) matr = multiplier * atr(high, low, close, length) upperband = hl2_ + matr lowerband = hl2_ - matr for i in range(1, m): if close.iloc[i] > upperband.iloc[i - 1]: dir_[i] = 1 elif close.iloc[i] < lowerband.iloc[i - 1]: dir_[i] = -1 else: dir_[i] = dir_[i - 1] if dir_[i] > 0 and lowerband.iloc[i] < lowerband.iloc[i - 1]: lowerband.iloc[i] = lowerband.iloc[i - 1] if dir_[i] < 0 and upperband.iloc[i] > upperband.iloc[i - 1]: upperband.iloc[i] = upperband.iloc[i - 1] if dir_[i] > 0: trend[i] = long[i] = lowerband.iloc[i] else: trend[i] = short[i] = upperband.iloc[i] # Prepare DataFrame to return _props = f"_{length}_{multiplier}" df = DataFrame({ f"SUPERT{_props}": trend, f"SUPERTd{_props}": dir_, f"SUPERTl{_props}": long, f"SUPERTs{_props}": short }, index=close.index) df.name = f"SUPERT{_props}" df.category = "overlap" # Apply offset if needed if offset != 0: df = df.shift(offset) # Handle fills if "fillna" in kwargs: df.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: df.fillna(method=kwargs["fill_method"], inplace=True) return df
def pmax(high, low, close, length=None, multiplier=None, mamode=None, offset=None, **kwargs): """Indicator: PMAX""" # Validate Arguments length = int(length) if length and length > 0 else 10 mamode = mamode.lower() if mamode and isinstance(mamode, str) else "ema" multiplier = float(multiplier) if multiplier and multiplier > 0 else 3.0 high = verify_series(high, length) low = verify_series(low, length) close = verify_series(close, length) offset = get_offset(offset) if high is None or low is None or close is None: return # Calculate Results m = close.size dir_, trend = [1] * m, [0] * m long, short = [npNaN] * m, [npNaN] * m hl2_ = hl2(high, low) mavg = ma(mamode, hl2_, length=length) matr = multiplier * atr(high, low, close, length) upperband = mavg + matr lowerband = mavg - matr for i in range(1, m): if mavg.iloc[i] > upperband.iloc[i - 1]: dir_[i] = 1 elif mavg.iloc[i] < lowerband.iloc[i - 1]: dir_[i] = -1 else: dir_[i] = dir_[i - 1] if dir_[i] > 0 and lowerband.iloc[i] < lowerband.iloc[i - 1]: lowerband.iloc[i] = lowerband.iloc[i - 1] if dir_[i] < 0 and upperband.iloc[i] > upperband.iloc[i - 1]: upperband.iloc[i] = upperband.iloc[i - 1] if dir_[i] > 0: trend[i] = long[i] = lowerband.iloc[i] else: trend[i] = short[i] = upperband.iloc[i] # Prepare DataFrame to return _props = f"_{length}_{multiplier}" df = DataFrame( { f"PMAX{_props}": trend, f"PMAXd{_props}": dir_, f"PMAXSL{_props}": mavg, f"PMAXlong{_props}": long, f"PMAXshort{_props}": short }, index=close.index) df.name = f"PMAX{_props}" df.category = "overlap" # Apply offset if needed if offset != 0: df = df.shift(offset) # Handle fills if "fillna" in kwargs: df.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: df.fillna(method=kwargs["fill_method"], inplace=True) return df
def adx(data, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: ADX""" import pandas as pd from pandas import DataFrame from pandas_ta.overlap import rma from pandas_ta.volatility import atr from pandas_ta.utils import get_drift, get_offset, verify_series, zero #transform de DataFrame into sub DF high = data['High'] low = data['Low'] close = data['Close'] open = data['Open'] volume = data['Volume'] # Validate Arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = 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 atr_ = atr(high=high, low=low, close=close, length=length) up = high - high.shift(drift) # high.diff(drift) dn = low.shift(drift) - low # low.diff(-drift).shift(drift) pos = ((up > dn) & (up > 0)) * up neg = ((dn > up) & (dn > 0)) * dn pos = pos.apply(zero) neg = neg.apply(zero) k = scalar / atr_ dmp = k * rma(close=pos, length=length) dmn = k * rma(close=neg, length=length) dx = scalar * (dmp - dmn).abs() / (dmp + dmn) adx = rma(close=dx, length=length) # Offset if offset != 0: dmp = dmp.shift(offset) dmn = dmn.shift(offset) adx = adx.shift(offset) # Handle fills if "fillna" in kwargs: adx.fillna(kwargs["fillna"], inplace=True) dmp.fillna(kwargs["fillna"], inplace=True) dmn.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: adx.fillna(method=kwargs["fill_method"], inplace=True) dmp.fillna(method=kwargs["fill_method"], inplace=True) dmn.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it adx.name = f"ADX_{length}" #dmp.name = f"DMP_{length}" dmp.name = f"posDI_{length}" #dmn.name = f"DMN_{length}" dmn.name = f"negDI_{length}" adx.category = dmp.category = dmn.category = 'trend' # Prepare DataFrame to return #data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn} #data = {'Open': open, 'High': high, 'Low': low, 'Close': close, 'Volume': volume, dmp.name: dmp, dmn.name: dmn, adx.name: adx} data = pd.concat( [data, dmp, dmn, adx], axis=1 ) #le agregue esta fila para que me tome el DF inicial y le agregue el DMI y ADX #adxdf = DataFrame(data) #adxdf.name = f"ADX_{length}" #adxdf.category = 'trend' #return adxdf return data