def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs): """Indicator: Archer Moving Averages Trends (AMAT)""" # Validate Arguments close = verify_series(close) fast = int(fast) if fast and fast > 0 else 8 slow = int(slow) if slow and slow > 0 else 21 lookback = int(lookback) if lookback and lookback > 0 else 2 mamode = mamode.lower() if mamode else "ema" offset = get_offset(offset) # Calculate Result if mamode == "hma": fast_ma = hma(close=close, length=fast, **kwargs) slow_ma = hma(close=close, length=slow, **kwargs) elif mamode == "linreg": fast_ma = linreg(close=close, length=fast, **kwargs) slow_ma = linreg(close=close, length=slow, **kwargs) elif mamode == "rma": fast_ma = rma(close=close, length=fast, **kwargs) slow_ma = rma(close=close, length=slow, **kwargs) elif mamode == "sma": fast_ma = sma(close=close, length=fast, **kwargs) slow_ma = sma(close=close, length=slow, **kwargs) elif mamode == "wma": fast_ma = wma(close=close, length=fast, **kwargs) slow_ma = wma(close=close, length=slow, **kwargs) else: # "ema" fast_ma = ema(close=close, length=fast, **kwargs) slow_ma = ema(close=close, length=slow, **kwargs) mas_long = long_run(fast_ma, slow_ma, length=lookback) mas_short = short_run(fast_ma, slow_ma, length=lookback) # Offset if offset != 0: mas_long = mas_long.shift(offset) mas_short = mas_short.shift(offset) # # Handle fills if "fillna" in kwargs: mas_long.fillna(kwargs["fillna"], inplace=True) mas_short.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: mas_long.fillna(method=kwargs["fill_method"], inplace=True) mas_short.fillna(method=kwargs["fill_method"], inplace=True) # Prepare DataFrame to return amatdf = DataFrame({ f"AMAT_{mas_long.name}": mas_long, f"AMAT_{mas_short.name}": mas_short }) # Name and Categorize it amatdf.name = f"AMAT_{mamode.upper()}_{fast}_{slow}_{lookback}" amatdf.category = "trend" return amatdf
def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs): """Indicator: Coppock Curve (COPC)""" # Validate Arguments length = int(length) if length and length > 0 else 10 fast = int(fast) if fast and fast > 0 else 11 slow = int(slow) if slow and slow > 0 else 14 close = verify_series(close, max(length, fast, slow)) offset = get_offset(offset) if close is None: return # Calculate Result total_roc = roc(close, fast) + roc(close, slow) coppock = wma(total_roc, length) # Offset if offset != 0: coppock = coppock.shift(offset) # Handle fills if "fillna" in kwargs: coppock.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: coppock.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it coppock.name = f"COPC_{fast}_{slow}_{length}" coppock.category = "momentum" return coppock
def atr(high, low, close, length=None, mamode=None, drift=None, offset=None, **kwargs): """Indicator: Average True Range (ATR)""" # Validate arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) length = int(length) if length and length > 0 else 14 mamode = mamode = mamode.lower() if mamode else "rma" drift = get_drift(drift) offset = get_offset(offset) # Calculate Result _mode = "" tr = true_range(high=high, low=low, close=close, drift=drift) if mamode == "ema": atr, _mode = ema(tr, length=length), "ema" elif mamode == "sma": atr, _mode = sma(tr, length=length), "sma" elif mamode == "wma": atr, _mode = wma(tr, length=length), "wma" else: # "rma" atr = rma(tr, length=length) percentage = kwargs.pop("percent", False) if percentage: atr *= 100 / close # Offset if offset != 0: atr = atr.shift(offset) # Handle fills if "fillna" in kwargs: atr.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: atr.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it atr.name = f"ATR{_mode}_{length}{'p' if percentage else ''}" atr.category = "volatility" return atr
def bias(close, length=None, mamode=None, offset=None, **kwargs): """Indicator: Bias (BIAS)""" # Validate Arguments close = verify_series(close) length = int(length) if length and length > 0 else 26 mamode = mamode.lower() if mamode else None offset = get_offset(offset) # Calculate Result if mamode == "ema": ma = ema(close, length=length, **kwargs) elif mamode == "hma": ma = hma(close, length=length, **kwargs) elif mamode == "rma": ma = rma(close, length=length, **kwargs) elif mamode == "wma": ma = wma(close, length=length, **kwargs) else: # "sma" ma = sma(close, length=length, **kwargs) bias = (close / ma) - 1 # Offset if offset != 0: bias = bias.shift(offset) # Handle fills if "fillna" in kwargs: bias.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: bias.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it bias.name = f"BIAS_{ma.name}" bias.category = "momentum" return bias
def aobv(close, volume, fast=None, slow=None, mamode=None, max_lookback=None, min_lookback=None, offset=None, **kwargs): """Indicator: Archer On Balance Volume (AOBV)""" # Validate arguments close = verify_series(close) volume = verify_series(volume) offset = get_offset(offset) fast = int(fast) if fast and fast > 0 else 4 slow = int(slow) if slow and slow > 0 else 12 max_lookback = int( max_lookback) if max_lookback and max_lookback > 0 else 2 min_lookback = int( min_lookback) if min_lookback and min_lookback > 0 else 2 if slow < fast: fast, slow = slow, fast mamode = mamode.upper() if mamode else None run_length = kwargs.pop("run_length", 2) # Calculate Result obv_ = obv(close=close, volume=volume, **kwargs) if mamode is None or mamode == "EMA": mamode = "EMA" maf = ema(close=obv_, length=fast, **kwargs) mas = ema(close=obv_, length=slow, **kwargs) elif mamode == "HMA": maf = hma(close=obv_, length=fast, **kwargs) mas = hma(close=obv_, length=slow, **kwargs) elif mamode == "LINREG": maf = linreg(close=obv_, length=fast, **kwargs) mas = linreg(close=obv_, length=slow, **kwargs) elif mamode == "SMA": maf = sma(close=obv_, length=fast, **kwargs) mas = sma(close=obv_, length=slow, **kwargs) elif mamode == "WMA": maf = wma(close=obv_, length=fast, **kwargs) mas = wma(close=obv_, length=slow, **kwargs) # When MAs are long and short obv_long = long_run(maf, mas, length=run_length) obv_short = short_run(maf, mas, length=run_length) # Offset if offset != 0: obv_ = obv_.shift(offset) maf = maf.shift(offset) mas = mas.shift(offset) obv_long = obv_long.shift(offset) obv_short = obv_short.shift(offset) # # Handle fills if "fillna" in kwargs: obv_.fillna(kwargs["fillna"], inplace=True) maf.fillna(kwargs["fillna"], inplace=True) mas.fillna(kwargs["fillna"], inplace=True) obv_long.fillna(kwargs["fillna"], inplace=True) obv_short.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: obv_.fillna(method=kwargs["fill_method"], inplace=True) maf.fillna(method=kwargs["fill_method"], inplace=True) mas.fillna(method=kwargs["fill_method"], inplace=True) obv_long.fillna(method=kwargs["fill_method"], inplace=True) obv_short.fillna(method=kwargs["fill_method"], inplace=True) # Prepare DataFrame to return data = { obv_.name: obv_, f"OBV_min_{min_lookback}": obv_.rolling(min_lookback).min(), f"OBV_max_{max_lookback}": obv_.rolling(max_lookback).max(), f"OBV_{maf.name}": maf, f"OBV_{mas.name}": mas, f"AOBV_LR_{run_length}": obv_long, f"AOBV_SR_{run_length}": obv_short, } aobvdf = DataFrame(data) # Name and Categorize it aobvdf.name = ( f"AOBV_{mamode}_{fast}_{slow}_{min_lookback}_{max_lookback}_{run_length}" ) aobvdf.category = "volume" return aobvdf
def RiskRange(Price_Data, window=10, length=63, volume_weighted=True, vol_window=10, mindiff=100000000.0, maxdiff=-100000000.0): """ Function to Calculate Risk Ranges """ Windowminus1 = window - 1 Close = (Price_Data[['Close']]).dropna() High = (Price_Data[['High']]).dropna() Low = (Price_Data[['Low']]).dropna() Volume = (Price_Data[['Volume']]).dropna() Slope = (Close.apply(func=lambda x: x - (x.shift(Windowminus1))) / (Windowminus1)).dropna() for i in range(0, Windowminus1): Min = np.minimum( mindiff, Close.apply(func=lambda x: x.shift(Windowminus1 - i) - (x.shift(Windowminus1) + (Slope['Close'] * i)), axis=0)) for i in range(0, Windowminus1): Max = np.maximum( maxdiff, Close.apply(func=lambda x: x.shift(Windowminus1 - i) - (x.shift(Windowminus1) + (Slope['Close'] * i)), axis=0)) BridgeBottom = (Close + Min).dropna() BridgeTop = (Close + Max).dropna() ATR = average_true_range(High['High'], Low['Low'], Close['Close'], window=window).dropna() Hurst = ((np.log( pd.DataFrame.rolling(High['High'], window=window).max() - pd.DataFrame.rolling(Low['Low'], window=window).min()) - np.log(ATR)) / (np.log(window))) Hurst_New = pd.DataFrame(Hurst.values, index=Hurst.index).rename(columns={0: 'Hurst'}) SD = (Close['Close']).rolling(vol_window).std() if volume_weighted == True: WMA = vwma(Close['Close'], Volume['Volume'], length=vol_window) elif volume_weighted == False: WMA = wma(Close['Close'], length=vol_window) BBBottom = (WMA - (SD * 2)).dropna() BBTop = (WMA + (SD * 2)).dropna() Final_Bottom = BBBottom + ((BridgeBottom['Close'] - BBBottom) * np.abs((Hurst_New['Hurst'] * 2) - 1)) Final_Top = BBTop + ( (BridgeTop['Close'] - BBTop) * np.abs((Hurst_New['Hurst'] * 2) - 1)) Final_Mid = Final_Bottom + ((Final_Top - Final_Bottom) / 2) Trend = ((pd.DataFrame.rolling(Low['Low'], window=length).min()) + ((pd.DataFrame.rolling(High['High'], window=length).max() - pd.DataFrame.rolling(Low['Low'], window=length).min()) / 2)) Output = pd.DataFrame(Final_Bottom).rename(columns={0: 'Bottom RR'}) Output['Top RR'] = Final_Top Output['Mid RR'] = Final_Mid Output['Trend'] = Trend Output['Price'] = Close Output = Output.dropna() return Output
def qqe(close, length=None, smooth=None, factor=None, mamode=None, drift=None, offset=None, **kwargs): """Indicator: Quantitative Qualitative Estimation (QQE)""" # Validate arguments close = verify_series(close) length = int(length) if length and length > 0 else 14 smooth = int(smooth) if smooth and smooth > 0 else 5 factor = float(factor) if factor else 4.236 mamode = mamode.lower() if mamode else "ema" drift = get_drift(drift) offset = get_offset(offset) # Calculate Result rsi_ = rsi(close, length) if mamode == "hma": rsi_ma, _mode = hma(rsi_, length=smooth), "h" elif mamode == "rma": rsi_ma, _mode = rma(rsi_, length=smooth), "r" elif mamode == "sma": rsi_ma, _mode = sma(rsi_, length=smooth), "s" elif mamode == "wma": rsi_ma, _mode = wma(rsi_, length=smooth), "w" else: # "ema" rsi_ma, _mode = ema(rsi_, length=smooth), "" # RSI MA True Range rsi_ma_tr = rsi_ma.diff(drift).abs() # Double Smooth the RSI MA True Range using Wilder's Length with a default # width of 4.236. wilders_length = 2 * length - 1 smoothed_rsi_tr_ma = ema(rsi_ma_tr, length=wilders_length) dar = factor * ema(smoothed_rsi_tr_ma, length=wilders_length) # Create the Upper and Lower Bands around RSI MA. upperband = rsi_ma + dar lowerband = rsi_ma - dar m = close.size long = Series(0, index=close.index) short = Series(0, index=close.index) trend = Series(1, index=close.index) qqe = Series(rsi_ma.iloc[0], index=close.index) qqe_long = Series(npNaN, index=close.index) qqe_short = Series(npNaN, index=close.index) for i in range(1, m): c_rsi, p_rsi = rsi_ma.iloc[i], rsi_ma.iloc[i - 1] c_long, p_long = long.iloc[i - 1], long.iloc[i - 2] c_short, p_short = short.iloc[i - 1], short.iloc[i - 2] # Long Line if p_rsi > c_long and c_rsi > c_long: long.iloc[i] = npMaximum(c_long, lowerband.iloc[i]) else: long.iloc[i] = lowerband.iloc[i] # Short Line if p_rsi < c_short and c_rsi < c_short: short.iloc[i] = npMinimum(c_short, upperband.iloc[i]) else: short.iloc[i] = upperband.iloc[i] # Trend & QQE Calculation # Long: Current RSI_MA value Crosses the Prior Short Line Value # Short: Current RSI_MA Crosses the Prior Long Line Value if (c_rsi > c_short and p_rsi < p_short) or (c_rsi <= c_short and p_rsi >= p_short): trend.iloc[i] = 1 qqe.iloc[i] = qqe_long.iloc[i] = long.iloc[i] elif (c_rsi > c_long and p_rsi < p_long) or (c_rsi <= c_long and p_rsi >= p_long): trend.iloc[i] = -1 qqe.iloc[i] = qqe_short.iloc[i] = short.iloc[i] else: trend.iloc[i] = trend.iloc[i - 1] if trend.iloc[i] == 1: qqe.iloc[i] = qqe_long.iloc[i] = long.iloc[i] else: qqe.iloc[i] = qqe_short.iloc[i] = short.iloc[i] # Offset if offset != 0: rsi_ma = rsi_ma.shift(offset) qqe = qqe.shift(offset) long = long.shift(offset) short = short.shift(offset) # Handle fills if "fillna" in kwargs: rsi_ma.fillna(kwargs["fillna"], inplace=True) qqe.fillna(kwargs["fillna"], inplace=True) long.fillna(kwargs["fillna"], inplace=True) short.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: rsi_ma.fillna(method=kwargs["fill_method"], inplace=True) qqe.fillna(method=kwargs["fill_method"], inplace=True) long.fillna(method=kwargs["fill_method"], inplace=True) short.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it _props = f"{_mode}_{length}_{smooth}_{factor}" qqe.name = f"QQE{_props}" rsi_ma.name = f"QQE{_props}_RSI{_mode.upper()}MA" long.name = f"QQEl{_props}" short.name = f"QQEs{_props}" qqe.category = rsi_ma.category = "momentum" long.category = short.category = qqe.category # Prepare DataFrame to return data = { qqe.name: qqe, rsi_ma.name: rsi_ma, # long.name: long, short.name: short long.name: qqe_long, short.name: qqe_short } df = DataFrame(data) df.name = f"QQE{_props}" df.category = qqe.category return df