# -*- coding: utf-8 -*- import time import pandas as pd from pandas.core.base import PandasObject from .utils import * class BasePandasObject(PandasObject): """Simple PandasObject Extension Ensures the DataFrame is not empty and has columns. Args: df (pd.DataFrame): Extends Pandas DataFrame """ def __init__(self, df, **kwargs): if df.empty: return if len(df.columns) > 0: self._df = df else: raise AttributeError(f" [X] No columns!") def __call__(self, kind, *args, **kwargs): raise NotImplementedError() @pd.api.extensions.register_dataframe_accessor('ta') class AnalysisIndicators(BasePandasObject): """AnalysisIndicators is class that extends the Pandas DataFrame via Pandas @pd.api.extensions.register_dataframe_accessor('name') decorator. This Pandas Extension is named 'ta' for Technical Analysis that allows us to apply technical indicators with an one extension. Even though 'ta' is now a Pandas DataFrame Extension, you can still call the Indicators individually. However many of the Indicators have been updated and new ones added, so make sure to check help. By default the 'ta' extensions uses lower case column names: open, high, low, close, and volume. You can override the defaults but providing the it's replacement name when calling the indicator. For example, to call the indicator hl2(). With 'default' columns: open, high, low, close, and volume. >>> df.ta.hl2() >>> df.ta(kind='hl2') With DataFrame columns: Open, High, Low, Close, and Volume. >>> df.ta.hl2(high='High', low='Low') >>> df.ta(kind='hl2', high='High', low='Low') Args: kind (str, optional): Default: None. Name of the indicator. Converts kind to lowercase before calling. timed (bool, optional): Default: False. Curious about the execution speed? Well it's not ground breaking, but you can enable with True. kwargs: Extension specific modifiers. append (bool, optional): Default: False. When True, it appends to result column(s) of the indicator onto the DataFrame. Returns: Most Indicators will return a Pandas Series. Others like MACD, BBANDS, KC, et al will return a Pandas DataFrame. Ichimoku on the other hand will return two DataFrames, the Ichimoku DataFrame for the known period and a Span DataFrame for the future of the Span values. Let's get started! 1. Loading the 'ta' module: >>> import pandas as pd >>> import ta as ta 2. Load some data: >>> df = pd.read_csv('AAPL.csv', index_col='date', parse_dates=True) 3. Help! 3a. General Help: >>> help(df.ta) >>> df.ta() 3a. Indicator Help: >>> help(ta.apo) 3b. Indicator Extension Help: >>> help(df.ta.apo) 4. Ways of calling an indicator. 4a. Calling just the MACD indicator without 'ta' DataFrame extension. >>> ta.apo(df['close']) 4b. Calling just the MACD indicator with 'ta' DataFrame extension. >>> df.ta.apo() 4c. Calling using kind. >>> df.ta(kind='apo') 5. Working with kwargs 5a. Append the result to the working df. >>> df.ta.apo(append=True) 5b. Timing an indicator. >>> apo = df.ta(kind='apo', timed=True) >>> print(apo.timed) """ def __call__(self, kind=None, alias=None, timed=False, **kwargs): try: if isinstance(kind, str): kind = kind.lower() fn = getattr(self, kind) if timed: stime = time.time() # Run the indicator indicator = fn(**kwargs) if timed: time_diff = time.time() - stime ms = time_diff * 1000 indicator.timed = f"{ms:2.3f} ms ({time_diff:2.3f} s)" # print(f"execution time: {indicator.timed}") # Add an alias if passed if alias: indicator.alias = f"{alias}" return indicator else: self.help() except: self.help() def _append(self, result=None, **kwargs): """Appends a Pandas Series or DataFrame columns to self._df.""" if 'append' in kwargs and kwargs['append']: df = self._df if df is None or result is None: return else: if isinstance(result, pd.DataFrame): for i, column in enumerate(result.columns): df[column] = result.iloc[:,i] else: df[result.name] = result def _get_column(self, series, default): """Attempts to get the correct series or 'column' and return it.""" df = self._df if df is None: return # Explicit passing a pd.Series to override default. if isinstance(series, pd.Series): return series # Apply default if no series nor a default. elif series is None or default is None: return df[default] # Ok. So it's a str. elif isinstance(series, str): # Return the df column since it's in there. if series in df.columns: return df[series] else: # Attempt to match the 'series' because it was likely misspelled. matches = df.columns.str.match(series, case=False) match = [i for i, x in enumerate(matches) if x] # If found, awesome. Return it or return the 'series'. cols = ', '.join(list(df.columns)) NOT_FOUND = f" [X] Ooops!!!: It's {series not in df.columns}, the series '{series}' not in {cols}" return df.iloc[:,match[0]] if len(match) else print(NOT_FOUND) def constants(self, apply, lower_bound=-100, upper_bound=100, every=1): """Constants Useful for indicator levels or if you need some constant value. Add constant '1' to the DataFrame >>> df.ta.constants(True, 1, 1, 1) Remove constant '1' to the DataFrame >>> df.ta.constants(False, 1, 1, 1) Adding constants that range of constants from -4 to 4 inclusive >>> df.ta.constants(True, -4, 4, 1) Removing constants that range of constants from -4 to 4 inclusive >>> df.ta.constants(False, -4, 4, 1) Args: apply (bool): Default: None. If True, appends the range of constants to the working DataFrame. If False, it removes the constant range from the working DataFrame. lower_bound (int): Default: -100. Lowest integer for the constant range. upper_bound (int): Default: 100. Largest integer for the constant range. every (int): Default: 10. How often to include a new constant. Returns: Returns nothing to the user. Either adds or removes constant ranges from the working DataFrame. """ levels = [x for x in range(lower_bound, upper_bound + 1) if x % every == 0] if apply: for x in levels: self._df[f'{x}'] = x else: for x in levels: del self._df[f'{x}'] def indicators(self, **kwargs): """Indicator list""" header = f"pandas.ta - Technical Analysis Indicators" helper_methods = ['indicators', 'constants'] # Public non-indicator methods exclude_methods = kwargs.pop('exclude', None) as_list = kwargs.pop('as_list', False) ta_indicators = list((x for x in dir(pd.DataFrame().ta) if not x.startswith('_') and not x.endswith('_'))) for x in helper_methods: ta_indicators.remove(x) if isinstance(exclude_methods, list) and exclude_methods in ta_indicators and len(exclude_methods) > 0: for x in exclude_methods: ta_indicators.remove(x) if as_list: return ta_indicators total_indicators = len(ta_indicators) s = f"{header}\nTotal Indicators: {total_indicators}\n" if total_indicators > 0: abbr_list = ', '.join(ta_indicators) print(f"{s}Abbreviations:\n {abbr_list}") else: print(s) # Momentum Indicators def ao(self, high=None, low=None, fast=None, slow=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') from .momentum.ao import ao result = ao(high=high, low=low, fast=fast, slow=slow, offset=offset, **kwargs) self._append(result, **kwargs) return result def apo(self, close=None, fast=None, slow=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.apo import apo result = apo(close=close, fast=fast, slow=slow, offset=offset, **kwargs) self._append(result, **kwargs) return result def bop(self, open_=None, high=None, low=None, close=None, percentage=False, offset=None, **kwargs): open_ = self._get_column(open_, 'open') high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .momentum.bop import bop result = bop(open_=open_, high=high, low=low, close=close, percentage=percentage, offset=offset, **kwargs) self._append(result, **kwargs) return result def cci(self, high=None, low=None, close=None, length=None, c=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .momentum.cci import cci result = cci(high=high, low=low, close=close, length=length, c=c, offset=offset, **kwargs) self._append(result, **kwargs) return result def cg(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.cg import cg result = cg(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def cmo(self, close=None, length=None, drift=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.cmo import cmo result = cmo(close=close, length=length, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def coppock(self, close=None, length=None, fast=None, slow=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.coppock import coppock result = coppock(close=close, length=length, fast=fast, slow=slow, offset=offset, **kwargs) self._append(result, **kwargs) return result def fisher(self, high=None, low=None, length=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') from .momentum.fisher import fisher result = fisher(high=high, low=low, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def kst(self, close=None, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None, sma3=None, sma4=None, signal=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.kst import kst result = kst(close=close, roc1=roc1, roc2=roc2, roc3=roc3, roc4=roc4, sma1=sma1, sma2=sma2, sma3=sma3, sma4=sma4, signal=signal, offset=offset, **kwargs) self._append(result, **kwargs) return result def macd(self, close=None, fast=None, slow=None, signal=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.macd import macd result = macd(close=close, fast=fast, slow=slow, signal=signal, offset=offset, **kwargs) self._append(result, **kwargs) return result def mom(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.mom import mom result = mom(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def ppo(self, close=None, fast=None, slow=None, percentage=True, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.ppo import ppo result = ppo(close=close, fast=fast, slow=slow, percentage=percentage, offset=offset, **kwargs) self._append(result, **kwargs) return result def roc(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.roc import roc result = roc(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def rsi(self, close=None, length=None, drift=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.rsi import rsi result = rsi(close=close, length=length, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def slope(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.slope import slope result = slope(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def stoch(self, high=None, low=None, close=None, fast_k=None, slow_k=None, slow_d=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .momentum.stoch import stoch result = stoch(high=high, low=low, close=close, fast_k=fast_k, slow_k=slow_k, slow_d=slow_d, offset=offset, **kwargs) self._append(result, **kwargs) return result def trix(self, close=None, length=None, drift=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.trix import trix result = trix(close=close, length=length, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def tsi(self, close=None, fast=None, slow=None, drift=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.tsi import tsi result = tsi(close=close, fast=fast, slow=slow, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def uo(self, high=None, low=None, close=None, fast=None, medium=None, slow=None, fast_w=None, medium_w=None, slow_w=None, drift=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .momentum.uo import uo result = uo(high=high, low=low, close=close, fast=fast, medium=medium, slow=slow, fast_w=fast_w, medium_w=medium_w, slow_w=slow_w, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def willr(self, high=None, low=None, close=None, length=None, percentage=True, offset=None,**kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .momentum.willr import willr result = willr(high=high, low=low, close=close, length=length, percentage=percentage, offset=offset, **kwargs) self._append(result, **kwargs) return result # Overlap Indicators def dema(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.dema import dema result = dema(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def ema(self, close=None, length=None, offset=None, adjust=None, **kwargs): close = self._get_column(close, 'close') from .overlap.ema import ema result = ema(close=close, length=length, offset=offset, adjust=adjust, **kwargs) self._append(result, **kwargs) return result def fwma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.fwma import fwma result = fwma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def hl2(self, high=None, low=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') from .overlap.hl2 import hl2 result = hl2(high=high, low=low, offset=offset, **kwargs) self._append(result, **kwargs) return result def hlc3(self, high=None, low=None, close=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .overlap.hlc3 import hlc3 result = hlc3(high=high, low=low, close=close, offset=offset, **kwargs) self._append(result, **kwargs) return result def hma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.hma import hma result = hma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def ichimoku(self, high=None, low=None, close=None, tenkan=None, kijun=None, senkou=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .overlap.ichimoku import ichimoku result, span = ichimoku(high=high, low=low, close=close, tenkan=tenkan, kijun=kijun, senkou=senkou, offset=offset, **kwargs) self._append(result, **kwargs) return result, span def linreg(self, close=None, length=None, offset=None, adjust=None, **kwargs): close = self._get_column(close, 'close') from .overlap.linreg import linreg result = linreg(close=close, length=length, offset=offset, adjust=adjust, **kwargs) self._append(result, **kwargs) return result def midpoint(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.midpoint import midpoint result = midpoint(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def midprice(self, high=None, low=None, length=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') from .overlap.midprice import midprice result = midprice(high=high, low=low, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def ohlc4(self, open_=None, high=None, low=None, close=None, offset=None, **kwargs): open_ = self._get_column(open_, 'open') high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .overlap.ohlc4 import ohlc4 result = ohlc4(open_=open_, high=high, low=low, close=close, offset=offset, **kwargs) self._append(result, **kwargs) return result def pwma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.pwma import pwma result = pwma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def rma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.rma import rma result = rma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def sma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.sma import sma result = sma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def swma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.swma import swma result = swma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def t3(self, close=None, length=None, a=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.t3 import t3 result = t3(close=close, length=length, a=a, offset=offset, **kwargs) self._append(result, **kwargs) return result def tema(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.tema import tema result = tema(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def trima(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.trima import trima result = trima(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def vwap(self, high=None, low=None, close=None, volume=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from .overlap.vwap import vwap result = vwap(high=high, low=low, close=close, volume=volume, offset=offset, **kwargs) self._append(result, **kwargs) return result def vwma(self, close=None, volume=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from .overlap.vwma import vwma result = vwma(close=close, volume=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def wma(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .overlap.wma import wma result = wma(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def zlma(self, close=None, length=None, offset=None, mamode=None, **kwargs): close = self._get_column(close, 'close') from .overlap.zlma import zlma result = zlma(close=close, length=length, offset=offset, mamode=mamode, **kwargs) self._append(result, **kwargs) return result # Performance Indicators def log_return(self, close=None, length=None, cumulative=False, percent=False, offset=None, **kwargs): close = self._get_column(close, 'close') from pandas_ta.performance.log_return import log_return result = log_return(close=close, length=length, cumulative=cumulative, percent=percent, offset=offset, **kwargs) self._append(result, **kwargs) return result def percent_return(self, close=None, length=None, cumulative=False, percent=False, offset=None, **kwargs): close = self._get_column(close, 'close') from pandas_ta.performance.percent_return import percent_return result = percent_return(close=close, length=length, cumulative=cumulative, percent=percent, offset=offset, **kwargs) self._append(result, **kwargs) return result def trend_return(self, close=None, trend=None, log=None, cumulative=None, offset=None, trend_reset=None, **kwargs): close = self._get_column(close, 'close') trend = self._get_column(trend, f"{trend}") from pandas_ta.performance.trend_return import trend_return result = trend_return(close=close, trend=trend, log=log, cumulative=cumulative, offset=offset, trend_reset=trend_reset, **kwargs) self._append(result, **kwargs) return result # Statistics Indicators def kurtosis(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.kurtosis import kurtosis result = kurtosis(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def mad(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.mad import mad result = mad(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def median(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.median import median result = median(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def quantile(self, close=None, length=None, q=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.quantile import quantile result = quantile(close=close, length=length, q=q, offset=offset, **kwargs) self._append(result, **kwargs) return result def skew(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.skew import skew result = skew(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def stdev(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.stdev import stdev result = stdev(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def variance(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.variance import variance result = variance(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def zscore(self, close=None, length=None, std=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .statistics.zscore import zscore result = zscore(close=close, length=length, std=std, offset=offset, **kwargs) self._append(result, **kwargs) return result # Trend Indicators def adx(self, high=None, low=None, close=None, drift=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .trend.adx import adx result = adx(high=high, low=low, close=close, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def amat(self, close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.amat import amat result = amat(close=close, fast=fast, slow=slow, mamode=mamode, lookback=lookback, offset=offset, **kwargs) self._append(result, **kwargs) return result def aroon(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.aroon import aroon result = aroon(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def decreasing(self, close=None, length=None, asint=True, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.decreasing import decreasing result = decreasing(close=close, length=length, asint=asint, offset=offset, **kwargs) self._append(result, **kwargs) return result def dpo(self, close=None, length=None, centered=True, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.dpo import dpo result = dpo(close=close, length=length, centered=centered, offset=offset, **kwargs) self._append(result, **kwargs) return result def increasing(self, close=None, length=None, asint=True, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.increasing import increasing result = increasing(close=close, length=length, asint=asint, offset=offset, **kwargs) self._append(result, **kwargs) return result def linear_decay(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .trend.linear_decay import linear_decay result = linear_decay(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def long_run(self, fast=None, slow=None, length=None, offset=None, **kwargs): if fast is None and slow is None: return self._df else: fast = self._get_column(fast, f"{fast}") slow = self._get_column(slow, f"{slow}") from .trend.long_run import long_run result = long_run(fast=fast, slow=slow, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def qstick(self, open_=None, close=None, length=None, offset=None, **kwargs): open_ = self._get_column(open_, 'open') close = self._get_column(close, 'close') from .trend.qstick import qstick result = qstick(open_=open_, close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def short_run(self, fast=None, slow=None, length=None, offset=None, **kwargs): if fast is None and slow is None: return self._df else: fast = self._get_column(fast, f"{fast}") slow = self._get_column(slow, f"{slow}") from .trend.short_run import short_run result = short_run(fast=fast, slow=slow, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def vortex(self, high=None, low=None, close=None, drift=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from .trend.vortex import vortex result = vortex(high=high, low=low, close=close, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result # Utility Indicators def cross(self, a=None, b=None, above=True, asint=True, offset=None, **kwargs): if a is None and b is None: return self._df else: a = self._get_column(a, f"{a}") b = self._get_column(b, f"{b}") result = cross(series_a=a, series_b=b, above=above, asint=asint, offset=offset, **kwargs) self._append(result, **kwargs) return result # Volatility Indicators def accbands(self, high=None, low=None, close=None, length=None, c=None, mamode=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from pandas_ta.volatility.accbands import accbands result = accbands(high=high, low=low, close=close, length=length, c=c, mamode=mamode, offset=offset, **kwargs) self._append(result, **kwargs) return result def atr(self, high=None, low=None, close=None, length=None, mamode=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from pandas_ta.volatility.atr import atr result = atr(high=high, low=low, close=close, length=length, mamode=mamode, offset=offset, **kwargs) self._append(result, **kwargs) return result def bbands(self, close=None, length=None, stdev=None, mamode=None, offset=None, **kwargs): close = self._get_column(close, 'close') from pandas_ta.volatility.bbands import bbands result = bbands(close=close, length=length, stdev=stdev, mamode=mamode, offset=offset, **kwargs) self._append(result, **kwargs) return result def donchian(self, close=None, length=None, offset=None, **kwargs): close = self._get_column(close, 'close') from pandas_ta.volatility.donchian import donchian result = donchian(close=close, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def kc(self, high=None, low=None, close=None, length=None, scalar=None, mamode=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from pandas_ta.volatility.kc import kc result = kc(high=high, low=low, close=close, length=length, scalar=scalar, mamode=mamode, offset=offset, **kwargs) self._append(result, **kwargs) return result def massi(self, high=None, low=None, fast=None, slow=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') from pandas_ta.volatility.massi import massi result = massi(high=high, low=low, fast=fast, slow=slow, offset=offset, **kwargs) self._append(result, **kwargs) return result def natr(self, high=None, low=None, close=None, length=None, mamode=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from pandas_ta.volatility.natr import natr result = natr(high=high, low=low, close=close, length=length, mamode=mamode, offset=offset, **kwargs) self._append(result, **kwargs) return result def true_range(self, high=None, low=None, close=None, drift=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') from pandas_ta.volatility.true_range import true_range result = true_range(high=high, low=low, close=close, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result # Volume Indicators def ad(self, high=None, low=None, close=None, volume=None, open_=None, signed=True, offset=None, **kwargs): if open_ is not None: open_ = self._get_column(open_, 'open') high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.ad import ad result = ad(high=high, low=low, close=close, volume=volume, open_=open_, signed=signed, offset=offset, **kwargs) self._append(result, **kwargs) return result def adosc(self, high=None, low=None, close=None, volume=None, open_=None, fast=None, slow=None, signed=True, offset=None, **kwargs): if open_ is not None: open_ = self._get_column(open_, 'open') high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.adosc import adosc result = adosc(high=high, low=low, close=close, volume=volume, open_=open_, fast=fast, slow=slow, signed=signed, offset=offset, **kwargs) self._append(result, **kwargs) return result def aobv(self, close=None, volume=None, fast=None, slow=None, mamode=None, max_lookback=None, min_lookback=None, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.aobv import aobv result = aobv(close=close, volume=volume, fast=fast, slow=slow, mamode=mamode, max_lookback=max_lookback, min_lookback=min_lookback, offset=offset, **kwargs) self._append(result, **kwargs) return result def cmf(self, high=None, low=None, close=None, volume=None, open_=None, length=None, offset=None, **kwargs): if open_ is not None: open_ = self._get_column(open_, 'open') high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.cmf import cmf result = cmf(high=high, low=low, close=close, volume=volume, open_=open_, length=length, offset=offset, **kwargs) self._append(result, **kwargs) return result def efi(self, close=None, volume=None, length=None, mamode=None, offset=None, drift=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.efi import efi result = efi(close=close, volume=volume, length=length, offset=offset, mamode=mamode, drift=drift, **kwargs) self._append(result, **kwargs) return result def eom(self, high=None, low=None, close=None, volume=None, length=None, divisor=None, offset=None, drift=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.eom import eom result = eom(high=high, low=low, close=close, volume=volume, length=length, divisor=divisor, offset=offset, drift=drift, **kwargs) self._append(result, **kwargs) return result def mfi(self, high=None, low=None, close=None, volume=None, length=None, drift=None, offset=None, **kwargs): high = self._get_column(high, 'high') low = self._get_column(low, 'low') close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.mfi import mfi result = mfi(high=high, low=low, close=close, volume=volume, length=length, drift=drift, offset=offset, **kwargs) self._append(result, **kwargs) return result def nvi(self, close=None, volume=None, length=None, initial=None, signed=True, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.nvi import nvi result = nvi(close=close, volume=volume, length=length, initial=initial, signed=signed, offset=offset, **kwargs) self._append(result, **kwargs) return result def obv(self, close=None, volume=None, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.obv import obv result = obv(close=close, volume=volume, offset=offset, **kwargs) self._append(result, **kwargs) return result def pvi(self, close=None, volume=None, length=None, initial=None, signed=True, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.pvi import pvi result = pvi(close=close, volume=volume, length=length, initial=initial, signed=signed, offset=offset, **kwargs) self._append(result, **kwargs) return result def pvol(self, close=None, volume=None, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.pvol import pvol result = pvol(close=close, volume=volume, offset=offset, **kwargs) self._append(result, **kwargs) return result def pvt(self, close=None, volume=None, offset=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.pvt import pvt result = pvt(close=close, volume=volume, offset=offset, **kwargs) self._append(result, **kwargs) return result def vp(self, close=None, volume=None, width=None, percent=None, **kwargs): close = self._get_column(close, 'close') volume = self._get_column(volume, 'volume') from pandas_ta.volume.vp import vp return vp(close=close, volume=volume, width=width, percent=percent, **kwargs)