diff --git a/README.md b/README.md index 6c6ace8..0de7dd7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Collection of Technical Analysis Functions * __Author:__ Daniel J. Umpierrez - * __Version:__ 0.0.4 + * __Version:__ 0.0.6 * __License:__ MIT ## Description diff --git a/requirements.txt b/requirements.txt index 42c9af3..2698dd0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ +pandas pandas=>23.0 numpy=>1.14.3 diff --git a/setup.py b/setup.py index 30d26b9..54f64f7 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='techa', - version='v0.0.5', + version='v0.0.6', requires=['pandas'], packages=find_packages(exclude=['contrib', 'docs', 'tests*']), package_dir={'techa': 'techa'}, diff --git a/techa/__init__.py b/techa/__init__.py index e3d2936..4941eaa 100644 --- a/techa/__init__.py +++ b/techa/__init__.py @@ -5,67 +5,81 @@ import os import sys +import cycle +import experimental +import momentum +import overlap +import pattern +import prices +import statistic +import volatility BASE_DIR = os.path.abspath(os.path.dirname(__file__)) sys.path.append(BASE_DIR) -from core import TaLib - __author__ = 'Daniel J. Umpierrez' -__version__ = '0.0.4' +__version__ = '0.0.5' + +__all__ = (*cycle.__all__, *momentum.__all__, *overlap.__all__, *volatility.__all__, *pattern.__all__, + *statistic.__all__, *experimental.__all__, *prices.__all__, 'ASI', 'SI') -__all__ = ['TaLib'] -def ASI(df, L): +def ASI(data, l): """ Accumulation Swing Index (J. Welles Wilder) source: book: New Concepts in Technical Trading Systems """ asi_list = [] - si_list = SI(df, L) + si_list = SI(data, l) i = 0 - while i < len(df['close']): + asi = .0 + while i < len(data['close']): if i < 1: asi = float('NaN') asi_list.append(asi) asi = .0 else: - asi = asi + si_list[i] + asi += si_list[i] asi_list.append(asi) i += 1 return asi_list -def SI(df, L): + +def SI(data, l): """ Swing Index (J. Welles Wilder) - source: book: New Concepts in Technical Trading Systems + From "New Concepts in Technical Trading Systems" + + :param pd.DataFrame data: + :param l: + :return: """ si_list = [] i = 0 - while i < len(df['close']): + while i < len(data['close']): if i < 1: si = float('NaN') else: - N = (df['close'][i] - df['close'][i - 1]) + (.5 * (df['close'][i] - df['open'][i])) + ( - .25 * (df['close'][i - 1] - df['open'][i - 1])) - R1 = df['high'][i] - df['close'][i - 1] - R2 = df['low'][i] - df['close'][i - 1] - R3 = df['high'][i] - df['low'][i] - if R1 > R2 and R1 > R3: - R = (df['high'][i] - df['close'][i - 1]) - (.5 * (df['low'][i] - df['close'][i - 1])) + ( - .25 * (df['close'][i - 1] - df['open'][i - 1])) - if R2 > R1 and R2 > R3: - R = (df['low'][i] - df['close'][i - 1]) - (.5 * (df['high'][i] - df['close'][i - 1])) + ( - .25 * (df['close'][i - 1] - df['open'][i - 1])) - if R3 > R1 and R3 > R2: - R = (df['high'][i] - df['low'][i]) + (.25 * (df['close'][i - 1] - df['open'][i - 1])) - K1 = df['high'][i] - df['close'][i - 1] - K2 = df['low'][i] - df['close'][i - 1] - if K1 > K2: - K = K1 + n = (data['close'][i] - data['close'][i - 1]) + (.5 * (data['close'][i] - data['open'][i])) + ( + .25 * (data['close'][i - 1] - data['open'][i - 1])) + r1 = data['high'][i] - data['close'][i - 1] + r2 = data['low'][i] - data['close'][i - 1] + r3 = data['high'][i] - data['low'][i] + if r1 > r2 and r1 > r3: + r = (data['high'][i] - data['close'][i - 1]) - (.5 * (data['low'][i] - data['close'][i - 1])) + ( + .25 * (data['close'][i - 1] - data['open'][i - 1])) + if r2 > r1 and r2 > r3: + r = (data['low'][i] - data['close'][i - 1]) - (.5 * (data['high'][i] - data['close'][i - 1])) + ( + .25 * (data['close'][i - 1] - data['open'][i - 1])) + if r3 > r1 and r3 > r2: + r = (data['high'][i] - data['low'][i]) + (.25 * (data['close'][i - 1] - data['open'][i - 1])) + k1 = data['high'][i] - data['close'][i - 1] + k2 = data['low'][i] - data['close'][i - 1] + if k1 > k2: + k = k1 else: - K = K2 - si = 50 * (N / R) * (K / L) + k = k2 + si = 50 * (n / r) * (k / l) si_list.append(si) i += 1 return si_list diff --git a/techa/core.py b/techa/core.py index 466df37..1e7f2a6 100644 --- a/techa/core.py +++ b/techa/core.py @@ -1,13 +1,30 @@ # -*- coding:utf-8 -*- -from collections import OrderedDict +import talib -from cycle import Cycle -from momentum import Momentum -from overlap import Overlap -from pattern import Pattern -from statistic import Statistic -from volatility import Volatility -from volume import Volume +import cycle +import experimental +import momentum +import overlap +import pattern +import prices +import statistic +import volatility +import volume + +# from cycle import * +# from momentum import * +# from overlap import * +# from pattern import * +# from statistic import * +# from volatility import * +# from experimental import * +# from prices import * +# from volume import * + +_function_list = [f for f in + (*cycle.__all__, *momentum.__all__, *overlap.__all__, *volatility.__all__, *pattern.__all__, + *statistic.__all__, *experimental.__all__, *prices.__all__) if f[0].isupper()] +__all__ = ['TaLib'] # noinspection SpellCheckingInspection @@ -17,23 +34,21 @@ class TaLib: """ _groups_ref = { - 'Cycle Indicators': 'Cyl', - 'Momentum Indicators': 'Mom', - 'Overlap studies': 'Ovlap', - 'Patter Recognition': 'Pattr', - 'Statistic Functions': 'Stat', - 'Volume Indicators': 'Vol', - 'Volatility Indicators': 'Volat' + 'cycle': cycle.__all__, + 'momentum': momentum.__all__, + 'overlap': overlap.__all__, + 'patter': pattern.__all__, + 'statistic': statistic.__all__, + 'volume': volatility.__all__, + 'volatility': experimental.__all__, + 'price': prices.__all__, + 'experimental': volume.__all__ } - Volat = Volatility - Olap = Overlap - Mom = Momentum - Cycl = Cycle - Vol = Volume - Pattr = Pattern - Stat = Statistic - + @classmethod + def calculate_indicator(cls, indicator, *args, **kwargs): + fn = globals().get(indicator) + return fn(*args, **kwargs) @classmethod def get_groups(cls): @@ -42,11 +57,17 @@ def get_groups(cls): :return: groups names """ - groups = OrderedDict().fromkeys(sorted([grp for grp in cls.__dict__ if grp[0].isupper()])) - for grp in groups: - groups.update({grp: [fn for fn in cls.__dict__[grp].__dict__ if fn[0].isupper()]}) - return groups + return sorted([*cls._groups_ref]) + + @classmethod + def get_talib_groups(cls): + """ + Just return groups names + + :return: groups names + """ + return sorted([*talib.get_function_groups().keys()]) @classmethod def get_functions(cls): @@ -55,34 +76,18 @@ def get_functions(cls): :return: all functions supported by this lib """ - result = list() - for grp in cls.get_groups().values(): - result.extend(grp) - return sorted(result) + return sorted(sum(cls._groups_ref.values(), [])) @classmethod - def get_function_group(cls, name, display_name=False): + def get_talib_functions(cls): """ - Get functions grouped by type + Return all functions supported by this lib - :param str name: function name - :param bool display_name: if True, full names will be show instead shorted ones - :return: functions grouped by type + :return: all functions supported by this lib """ - name = str(name).upper() - if name in cls.get_functions(): - if name in cls.Pattr.__dict__: - return cls.Pattr.__name__ if display_name is True else 'Pattr' - elif name in cls.Mom.__dict__: - return cls.Mom.__name__ if display_name is True else 'Mom' - elif name in cls.Olap.__dict__: - return cls.Olap.__name__ if display_name is True else 'Olap' - elif name in cls.Vol.__dict__: - return cls.Vol.__name__ if display_name is True else 'Vol' - elif name in cls.Cycl.__dict__: - return cls.Cycl.__name__ if display_name is True else 'Cycl' - elif name in cls.Stat.__dict__: - return cls.Stat.__name__ if display_name is True else 'Stat' - elif name in cls.Volat.__dict__: - return cls.Volat.__name__ if display_name is True else 'Volat' + return sorted([*talib.get_function_groups().values()]) + + +if __name__ == '__main__': + print(TaLib.get_functions()) diff --git a/techa/cycle.py b/techa/cycle.py index 8ba71c6..34e2b86 100644 --- a/techa/cycle.py +++ b/techa/cycle.py @@ -1,83 +1,82 @@ +# -*- coding: utf-8 -*- """ Cycle Indicators """ import pandas as pd from talib.abstract import Function +__all__ = ['HT_DCPERIOD', 'HT_DCPHASE', 'HT_SINE', 'HT_TRENDMODE', 'HT_PHASOR', 'WCLPRICE'] -class Cycle: + +def HT_DCPERIOD(data): """ - Cycle Indicators + Hilbert Transform + + Dominant Cycle Period + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results """ + fn = Function('HT_DCPERIOD') + return fn(data) - @classmethod - def HT_DCPERIOD(cls, data): - """ - Hilbert Transform - Dominant Cycle Period +def HT_DCPHASE(data): + """ + Hilbert Transform - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_DCPERIOD') - return fn(data) + Dominant Cycle Phase + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('HT_DCPHASE') + return fn(data) - @classmethod - def HT_DCPHASE(cls, data): - """ - Hilbert Transform - Dominant Cycle Phase - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_DCPHASE') - return fn(data) +def HT_PHASOR(data): + """ + Hilbert Transform + In-Phase Indicator. - @classmethod - def HT_PHASOR(cls, data): - """ - Hilbert Transform - In-Phase Indicator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('HT_PHASOR') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_PHASOR') - return fn(data) +def HT_SINE(data): + """ + Hilbert Transform - SineWave Indicator - @classmethod - def HT_SINE(cls, data): - """ - Hilbert Transform - SineWave Indicator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('HT_SINE') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_SINE') - return fn(data) +def HT_TRENDMODE(data): + """ + Hilbert Transform - @classmethod - def HT_TRENDMODE(cls, data): - """ - Hilbert Transform - Trend vs Cycle Mode + Trend vs Cycle Mode. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_TRENDMODE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('HT_TRENDMODE') + return fn(data) - @classmethod - def WCLPRICE(cls, data): - """ - Weighted Close Price +def WCLPRICE(data): + """ + Weighted Close Price - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('WCLPRICE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('WCLPRICE') + return fn(data) diff --git a/techa/experimental.py b/techa/experimental.py index 8c68af5..3772a7b 100644 --- a/techa/experimental.py +++ b/techa/experimental.py @@ -1,210 +1,280 @@ # -*- coding:utf-8 -*- +from cycle import WCLPRICE +from prices import TYPPRICE, AVGPRICE, MEDPRICE +__all__ = ['SAVGP', 'SAVGPS', 'SCO', 'SCOS', 'SMEDP', 'SMEDPS', 'SPP', 'SPPS', 'STYPP', 'STYPPS', 'SWCLP', 'SWCLPS'] -class Experimental: - - def SAVGP(cls, data): - """ - Swing Average Price - previous Average Price - """ - savgp_list = [] - avgp_list = jhta.AVGPRICE(data) - i = 0 - while i < len(data['close']): - if i < 1: - savgp = float('NaN') - else: - savgp = avgp_list[i] - avgp_list[i - 1] - savgp_list.append(savgp) - i += 1 - return savgp_list - - - def SAVGPS(cls, data): - """ - Swing Average Price - previous Average Price Summation - """ - savgps_list = [] - savgp_list = cls.SAVGP(data) - i = 0 - while i < len(data['close']): - if i < 1: - savgps = float('NaN') - savgps_list.append(savgps) - savgps = .0 - else: - savgps = savgps + savgp_list[i] - savgps_list.append(savgps) - i += 1 - return savgps_list - - - def SCO(cls, data): - """ - Swing Close - Open - """ - sco_list = [] - i = 0 - while i < len(data['close']): - sco = data['close'][i] - data['open'][i] - sco_list.append(sco) - i += 1 - return sco_list - - - def SCOS(cls, data): - """ - Swing Close - Open Summation - """ - scos_list = [] - sco_list = cls.SCO(data) - scos = .0 - i = 0 - while i < len(data['close']): - scos = scos + sco_list[i] - scos_list.append(scos) - i += 1 - return scos_list - - - def SMEDP(cls, data): - """ - Swing Median Price - previous Median Price - """ - smedp_list = [] - medp_list = jhta.MEDPRICE(data) - i = 0 - while i < len(data['close']): - if i < 1: - smedp = float('NaN') - else: - smedp = medp_list[i] - medp_list[i - 1] - smedp_list.append(smedp) - i += 1 - return smedp_list - - - def SMEDPS(cls, data): - """ - Swing Median Price - previous Median Price Summation - """ - smedps_list = [] - smedp_list = cls.SMEDP(data) - i = 0 - while i < len(data['close']): - if i < 1: - smedps = float('NaN') - smedps_list.append(smedps) - smedps = .0 - else: - smedps = smedps + smedp_list[i] - smedps_list.append(smedps) - i += 1 - return smedps_list - - - def SPP(cls, df, price='close'): - """ - Swing Price - previous Price - """ - spp_list = [] - i = 0 - while i < len(df[price]): - if i < 1: - spp = float('NaN') - else: - spp = df[price][i] - df[price][i - 1] - spp_list.append(spp) - i += 1 - return spp_list - - - def SPPS(cls, df, price='close'): - """ - Swing Price - previous Price Summation - """ - spps_list = [] - spp_list = cls.SPP(df, price) - i = 0 - while i < len(df[price]): - if i < 1: - spps = float('NaN') - spps_list.append(spps) - spps = .0 - else: - spps = spps + spp_list[i] - spps_list.append(spps) - i += 1 - return spps_list - - - def STYPP(cls, data): - """ - Swing Typical Price - previous Typical Price - """ - stypp_list = [] - typp_list = jhta.TYPPRICE(data) - i = 0 - while i < len(data['close']): - if i < 1: - stypp = float('NaN') - else: - stypp = typp_list[i] - typp_list[i - 1] - stypp_list.append(stypp) - i += 1 - return stypp_list - - - def STYPPS(cls, data): - """ - Swing Typical Price - previous Typical Price Summation - """ - stypps_list = [] - stypp_list = cls.STYPP(data) - i = 0 - while i < len(data['close']): - if i < 1: - stypps = float('NaN') - stypps_list.append(stypps) - stypps = .0 - else: - stypps = stypps + stypp_list[i] - stypps_list.append(stypps) - i += 1 - return stypps_list - - - def SWCLP(cls, data): - """ - Swing Weighted Close Price - previous Weighted Close Price - """ - swclp_list = [] - wclp_list = jhta.WCLPRICE(data) - i = 0 - while i < len(data['close']): - if i < 1: - swclp = float('NaN') - else: - swclp = wclp_list[i] - wclp_list[i - 1] - swclp_list.append(swclp) - i += 1 - return swclp_list - - - def SWCLPS(cls, data): - """ - Swing Weighted Close Price - previous Weighted Close Price Summation - """ - swclps_list = [] - swclp_list = cls.SWCLP(data) - i = 0 - while i < len(data['close']): - if i < 1: - swclps = float('NaN') - swclps_list.append(swclps) - swclps = .0 - else: - swclps = swclps + swclp_list[i] - swclps_list.append(swclps) - i += 1 - return swclps_list + +def SAVGP(data): + """ + Swing Average Price + + Previous Average Price. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + savgp_list = [] + average_price_list = AVGPRICE(data) + i = 0 + while i < len(data['close']): + if i < 1: + savgp = float('NaN') + else: + savgp = average_price_list[i] - average_price_list[i - 1] + savgp_list.append(savgp) + i += 1 + return savgp_list + + +def SAVGPS(data): + """ + Swing Average Price + + Previous Average Price Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + savgps_list = [] + savgp_list = SAVGP(data) + i = 0 + savgps = .0 + while i < len(data['close']): + if i < 1: + savgps = float('NaN') + savgps_list.append(savgps) + savgps = .0 + else: + savgps += savgp_list[i] + savgps_list.append(savgps) + i += 1 + return savgps_list + + +def SCO(data): + """ + Swing Close + + Open. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + sco_list = [] + i = 0 + while i < len(data['close']): + sco = data['close'][i] - data['open'][i] + sco_list.append(sco) + i += 1 + return sco_list + + +def SCOS(data): + """ + Swing Close + + Open Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + scos_list = [] + sco_list = SCO(data) + scos = .0 + i = 0 + while i < len(data['close']): + scos = scos + sco_list[i] + scos_list.append(scos) + i += 1 + return scos_list + + +def SMEDP(data): + """ + Swing Median Price + + Previous Median Price. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + + smedp_list = [] + median_price = MEDPRICE(data) + i = 0 + while i < len(data['close']): + if i < 1: + smedp = float('NaN') + else: + smedp = median_price[i] - median_price[i - 1] + smedp_list.append(smedp) + i += 1 + return smedp_list + + +def SMEDPS(data): + """ + Swing Median Price + + Previous Median Price Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + smedps_list = [] + smedp_list = SMEDP(data) + i = 0 + smedps = .0 + while i < len(data['close']): + if i < 1: + smedps = float('NaN') + smedps_list.append(smedps) + smedps = .0 + else: + smedps += smedp_list[i] + smedps_list.append(smedps) + i += 1 + return smedps_list + + +def SPP(data, price='close'): + """ + Swing Price + + Previous Price + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param str price: + :return pd.Series: with indicator data calculation results + """ + spp_list = [] + i = 0 + while i < len(data[price]): + if i < 1: + spp = float('NaN') + else: + spp = data[price][i] - data[price][i - 1] + spp_list.append(spp) + i += 1 + return spp_list + + +def SPPS(data, price='close'): + """ + Swing Price + + Previous Price Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + spps_list = [] + spp_list = SPP(data, price) + i = 0 + spps = .0 + while i < len(data[price]): + if i < 1: + spps = float('NaN') + spps_list.append(spps) + spps = .0 + else: + spps += spp_list[i] + spps_list.append(spps) + i += 1 + return spps_list + + +def STYPP(data): + """ + Swing Typical Price + + Previous Typical Price + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + stypp_list = [] + typical_price = TYPPRICE(data) + i = 0 + while i < len(data['close']): + if i < 1: + stypp = float('NaN') + else: + stypp = typical_price[i] - typical_price[i - 1] + stypp_list.append(stypp) + i += 1 + return stypp_list + + +def STYPPS(data): + """ + Swing Typical Price + + Previous Typical Price Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + stypps_list = [] + stypp_list = STYPP(data) + i = 0 + stypps = .0 + while i < len(data['close']): + if i < 1: + stypps = float('NaN') + stypps_list.append(stypps) + stypps = .0 + else: + stypps += stypp_list[i] + stypps_list.append(stypps) + i += 1 + return stypps_list + + +def SWCLP(data): + """ + Swing Weighted Close Price + + Previous Weighted Close Price + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + swclp_list = [] + weighted_close_price = WCLPRICE(data) + i = 0 + while i < len(data['close']): + if i < 1: + swclp = float('NaN') + else: + swclp = weighted_close_price[i] - weighted_close_price[i - 1] + swclp_list.append(swclp) + i += 1 + return swclp_list + + +def SWCLPS(data): + """ + Swing Weighted Close Price + + Previous Weighted Close Price Summation. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + swclps_list = [] + swclp_list = SWCLP(data) + i = 0 + swclps = .0 + while i < len(data['close']): + if i < 1: + swclps = float('NaN') + swclps_list.append(swclps) + swclps = .0 + else: + swclps += swclp_list[i] + swclps_list.append(swclps) + i += 1 + return swclps_list diff --git a/techa/momentum.py b/techa/momentum.py index 6917db3..986f79d 100644 --- a/techa/momentum.py +++ b/techa/momentum.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ Momentum Indicators """ @@ -5,920 +6,868 @@ from finta import TA from talib.abstract import Function -from overlap import Overlap -from volatility import Volatility +from overlap import MA +from volatility import ATR +__all__ = ['MI'] -class Momentum: + +def MI(data, period=9): """ - Momentum Indicators + Mass Index + MI uses the high-low range to identify trend reversals based on range expansions. + + In this sense, the Mass Index is a volatility indicator that does not have a directional bias. + + Instead, the Mass Index identifies range bulges that can foreshadow a reversal of the current trend. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results """ + return TA.MI(data, period=period) - @classmethod - def MI(cls, data, period=9): - """ - Mass Index - MI uses the high-low range to identify trend reversals based on range expansions. +def COPP(data): + """ + Coppock Curve - In this sense, the Mass Index is a volatility indicator that does not have a directional bias. + COPP is a momentum indicator, it signals buying opportunities when the indicator moved from negative territory + to positive territory. - Instead, the Mass Index identifies range bulges that can foreshadow a reversal of the current trend. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.COPP(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.MI(data, period=period) +def VZO(data, period=14): + """ + VZO - @classmethod - def COPP(cls, data): - """ - Coppock Curve + VZO uses price, previous price and moving averages to compute its oscillating value. - COPP is a momentum indicator, it signals buying opportunities when the indicator moved from negative territory - to positive territory. + It is a leading indicator that calculates buy and sell signals based on oversold / overbought conditions. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.COPP(data) + Oscillations between the 5% and 40% levels mark a bullish trend zone, while oscillations between -40% and 5% + mark a bearish trend zone. + Meanwhile, readings above 40% signal an overbought condition, while readings above 60% signal an extremely + overbought condition. - @classmethod - def VZO(cls, data, period=14): - """ - VZO + Alternatively, readings below -40% indicate an oversold condition, which becomes extremely oversold below -60%. - VZO uses price, previous price and moving averages to compute its oscillating value. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.VZO(data, period) - It is a leading indicator that calculates buy and sell signals based on oversold / overbought conditions. - Oscillations between the 5% and 40% levels mark a bullish trend zone, while oscillations between -40% and 5% - mark a bearish trend zone. +def KST(data, r1=10, r2=15, r3=20, r4=30): + """ + Know Sure Thing - Meanwhile, readings above 40% signal an overbought condition, while readings above 60% signal an extremely - overbought condition. + KST is a momentum oscillator based on the smoothed rate-of-change for four different time frames. - Alternatively, readings below -40% indicate an oversold condition, which becomes extremely oversold below -60%. + KST measures price momentum for four different price cycles. It can be used just like any momentum oscillator. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.VZO(data, period) + Chartists can look for divergences, overbought/oversold readings, signal line crossovers and center-line + crossovers. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int r1: period used at first ROC calculation + :param int r2: period used at second ROC calculation + :param int r3: period used at third ROC calculation + :param int r4: period used at last ROC calculation + :return pd.Series: with indicator data calculation results + """ + return TA.KST(data, r1, r2, r3, r4) - @classmethod - def KST(cls, data, r1=10, r2=15, r3=20, r4=30): - """ - Know Sure Thing - KST is a momentum oscillator based on the smoothed rate-of-change for four different time frames. +def TSI(data, long=25, short=13, signal=13): + """ + True Strength Index - KST measures price momentum for four different price cycles. It can be used just like any momentum oscillator. + TSI is a momentum oscillator based on a double smoothing of price changes. - Chartists can look for divergences, overbought/oversold readings, signal line crossovers and center-line - crossovers. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int long: long period used for indicator calculation + :param int short: short period used for indicator calculation + :param int signal: signal period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.TSI(data, long, short, signal) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int r1: period used at first ROC calculation - :param int r2: period used at second ROC calculation - :param int r3: period used at third ROC calculation - :param int r4: period used at last ROC calculation - :return pd.Series: with indicator data calculation results - """ - return TA.KST(data, r1, r2, r3, r4) +def EFI(data, period=13): + """ + Elder Force Index - @classmethod - def TSI(cls, data, long=25, short=13, signal=13): - """ - True Strength Index + EFI is an indicator that uses price and volume to assess the power behind a move or identify possible turning + points. - TSI is a momentum oscillator based on a double smoothing of price changes. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.EFI(data, period=period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int long: long period used for indicator calculation - :param int short: short period used for indicator calculation - :param int signal: signal period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.TSI(data, long, short, signal) +def IFT_RSI(data, rsi_period=14, wma_period=9): + """ + Modified Inverse Fisher Transform applied on RSI. - @classmethod - def EFI(cls, data, period=13): - """ - Elder Force Index + Suggested method to use any IFT indicator is to buy when the indicator crosses over –0.5 or crosses over +0.5 - EFI is an indicator that uses price and volume to assess the power behind a move or identify possible turning - points. + if it has not previously crossed over –0.5 and to sell short when the indicators crosses under +0.5 or crosses + under –0.5 if it has not previously crossed under +0.5. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.EFI(data, period=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int rsi_period: pandas DataFrame with open, high, low, close data + :param int wma_period: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.IFT_RSI(data, rsi_period, wma_period) - @classmethod - def IFT_RSI(cls, data, rsi_period=14, wma_period=9): - """ - Modified Inverse Fisher Transform applied on RSI. +def BASP(data, period=40): + """ + Buy and Sell Pressure - Suggested method to use any IFT indicator is to buy when the indicator crosses over –0.5 or crosses over +0.5 + BASP indicator serves to identify buying and selling pressure. - if it has not previously crossed over –0.5 and to sell short when the indicators crosses under +0.5 or crosses - under –0.5 if it has not previously crossed under +0.5. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.BASP(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int rsi_period: pandas DataFrame with open, high, low, close data - :param int wma_period: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.IFT_RSI(data, rsi_period, wma_period) +def BASPN(data, period=40): + """ + Buy and Sell Pressure Normalized - @classmethod - def BASP(cls, data, period=40): - """ - Buy and Sell Pressure + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.BASPN(data, period) - BASP indicator serves to identify buying and selling pressure. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.BASP(data, period) +def UO(data): + """ + Ultimate Oscillator + UO is a momentum oscillator designed to capture momentum across three different time frames. - @classmethod - def BASPN(cls, data, period=40): - """ - Buy and Sell Pressure Normalized + The multiple time frame objective seeks to avoid the pitfalls of other oscillators. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.BASPN(data, period) + Many momentum oscillators surge at the beginning of a strong advance and then form bearish divergence as the + advance continues. + This is because they are stuck with one time frame. The Ultimate Oscillator attempts to correct this fault by + incorporating longer time frames into the basic formula. - @classmethod - def UO(cls, data): - """ - Ultimate Oscillator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.UO(data) - UO is a momentum oscillator designed to capture momentum across three different time frames. - The multiple time frame objective seeks to avoid the pitfalls of other oscillators. +def CFI(data): + """ + Cumulative Force Index. - Many momentum oscillators surge at the beginning of a strong advance and then form bearish divergence as the - advance continues. + Adopted from Elder's Force Index (EFI). - This is because they are stuck with one time frame. The Ultimate Oscillator attempts to correct this fault by - incorporating longer time frames into the basic formula. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.CFI(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.UO(data) +def EBBP(data): + """ + Bull power and bear power by Dr. Alexander Elder - @classmethod - def CFI(cls, data): - """ - Cumulative Force Index. + EBBP show where today’s high and low lie relative to the a 13-day EMA - Adopted from Elder's Force Index (EFI). + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.EBBP(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.CFI(data) +def EMV(data, period=14): + """ + Ease of Movement - @classmethod - def EBBP(cls, data): - """ - Bull power and bear power by Dr. Alexander Elder + EMV is a volume-based oscillator that fluctuates above and below the zero line. - EBBP show where today’s high and low lie relative to the a 13-day EMA + As its name implies, it is designed to measure the "ease" of price movement. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.EBBP(data) + Prices are advancing with relative ease when the oscillator is in positive territory. + Conversely, prices are declining with relative ease when the oscillator is in negative territory. - @classmethod - def EMV(cls, data, period=14): - """ - Ease of Movement + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return:pd.Series: with indicator data calculation results + """ + return TA.EMV(data, period) - EMV is a volume-based oscillator that fluctuates above and below the zero line. - As its name implies, it is designed to measure the "ease" of price movement. +def WTO(data, channel_length=10, average_length=21): + """ + Wave Trend Oscillator - Prices are advancing with relative ease when the oscillator is in positive territory. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int channel_length: channel length value + :param int average_length: average length value + :return pd.Series: with indicator data calculation results + """ + return TA.WTO(data, channel_length, average_length) - Conversely, prices are declining with relative ease when the oscillator is in negative territory. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return:pd.Series: with indicator data calculation results - """ - return TA.EMV(data, period) +def STOCHD(data, period=3): + """ + Stochastic Oscillator %D + STOCH %D is a 3 period simple moving average of %K. - @classmethod - def WTO(cls, data, channel_length=10, average_length=21): - """ - Wave Trend Oscillator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.STOCHD(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int channel_length: channel length value - :param int average_length: average length value - :return pd.Series: with indicator data calculation results - """ - return TA.WTO(data, channel_length, average_length) +def ADX(data, period=14): + """ + ADX - @classmethod - def STOCHD(cls, data, period=3): - """ - Stochastic Oscillator %D + ADX is 100 * smoothed moving average of absolute value (DMI +/-) divided by (DMI+ + DMI-). - STOCH %D is a 3 period simple moving average of %K. + ADX does not indicate trend direction or momentum, only trend strength. + Generally, ADX readings below 20 indicate trend weakness, and readings above 40 indicate trend strength. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.STOCHD(data, period) + An extremely strong trend is indicated by readings above 50 + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + temp_df = pd.DataFrame() + temp_df['up_move'] = data['high'].diff() + temp_df['down_move'] = data['low'].diff() - @classmethod - def ADX(cls, data, period=14): - """ - ADX + positive_dm = [] + negative_dm = [] - ADX is 100 * smoothed moving average of absolute value (DMI +/-) divided by (DMI+ + DMI-). - - ADX does not indicate trend direction or momentum, only trend strength. - Generally, ADX readings below 20 indicate trend weakness, and readings above 40 indicate trend strength. - - An extremely strong trend is indicated by readings above 50 - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - temp_df = pd.DataFrame() - temp_df['up_move'] = data['high'].diff() - temp_df['down_move'] = data['low'].diff() - - positive_dm = [] - negative_dm = [] - - for row in temp_df.itertuples(): - if row.up_move > row.down_move and row.up_move > 0: - positive_dm.append(row.up_move) - else: - positive_dm.append(0) - if row.down_move > row.up_move and row.down_move > 0: - negative_dm.append(row.down_move) - else: - negative_dm.append(0) - - temp_df['positive_dm'] = positive_dm - temp_df['negative_dm'] = negative_dm - - atr = Volatility.ATR(data, period=period * 6) - - dir_plus = pd.Series(100 * (temp_df['positive_dm'] / atr).ewm(span=period, min_periods=period - 1).mean()) - - dir_minus = pd.Series(100 * (temp_df['negative_dm'] / atr).ewm(span=period, min_periods=period - 1).mean()) - return pd.concat([dir_plus, dir_minus]) - # fn = Function('ADX') - # return fn(data, period) - - - @classmethod - def ADXR(cls, data, period=14): - """ - Average Directional Movement Index Rating - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ADXR') - return fn(data, period) - - - @classmethod - def IMI(cls, data): - """ - Intraday Momentum Index - - source: http://www.fmlabs.com/reference/default.htm?url=IMI.htm - """ - imi_list = [] - upsum = .0 - downsum = .0 - i = 0 - while i < len(data['close']): - if data['close'][i] > data['open'][i]: - upsum = upsum + (data['close'][i] - data['open'][i]) - else: - downsum = downsum + (data['open'][i] - data['close'][i]) - imi = 100 * (upsum / (upsum + downsum)) - imi_list.append(imi) - i += 1 - return imi_list - - - @classmethod - def APO(cls, data, fast_period=12, slow_period=26, ma_type=0, price='close'): - """ - Absolute Price Oscillator - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fast_period: fast period used for indicator calculation - :param int slow_period: slow period used for indicator calculation - :param int ma_type: moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - - apo_list = [] - i = 0 - while i < len(data[price]): - if i + 1 < slow_period: - apo = float('NaN') - else: - start_fast = i + 1 - fast_period - end = i + 1 - sma_fast = Overlap.MA(data[price][start_fast:end], period=fast_period, ma_type=ma_type) - start_slow = i + 1 - slow_period - end = i + 1 - sma_slow = Overlap.MA(data[price][start_slow:end], period=slow_period, ma_type=ma_type) - apo = sma_slow - sma_fast - # apo *= -1 - apo_list.append(apo) - i += 1 - return pd.Series(apo_list, name='APO') - - # fn = Function('APO') - # return fn(data, fastperiod=fast_period, slowperiod=slow_period, matype=ma_type) - - - @classmethod - def AROON(cls, data, period=14): - """ - Aroon indicator - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: up and down indicators from data calculation - """ - fn = Function('AROON') - return fn(data, period) - - - @classmethod - def AROONOSC(cls, data, period=14): - """ - Aroon Oscillator + for row in temp_df.itertuples(): + if row.up_move > row.down_move and row.up_move > 0: + positive_dm.append(row.up_move) + else: + positive_dm.append(0) + if row.down_move > row.up_move and row.down_move > 0: + negative_dm.append(row.down_move) + else: + negative_dm.append(0) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('AROONOSC') - return fn(data, period) - - - @classmethod - def BOP(cls, data): - """ - Balance of Power Indicator - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('BOP') - return fn(data) - - - @classmethod - def CCI(cls, data, period=14): - """ - Commodity Index Channel + temp_df['positive_dm'] = positive_dm + temp_df['negative_dm'] = negative_dm - CCI is a versatile indicator that can be used to identify a new trend or warn of extreme conditions. - - CCI measures the current price level relative to an average price level over a given period of time. + atr = ATR(data, period=period * 6) - The CCI typically oscillates above and below a zero line. Normal oscillations will occur within the range of - +100 and −100. - - Readings above +100 imply an overbought condition, while readings below −100 imply an oversold condition. + dir_plus = pd.Series(100 * (temp_df['positive_dm'] / atr).ewm(span=period, min_periods=period - 1).mean()) - As with other overbought/oversold indicators, this means that there is a large probability that the price will - correct to more representative levels. + dir_minus = pd.Series(100 * (temp_df['negative_dm'] / atr).ewm(span=period, min_periods=period - 1).mean()) + return pd.concat([dir_plus, dir_minus]) + # fn = Function('ADX') + # return fn(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('CCI') - return fn(data, period) +def ADXR(data, period=14): + """ + Average Directional Movement Index Rating - @classmethod - def CMO(cls, data, period=14): - """ - Chaikin Momentum Oscillator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ADXR') + return fn(data, period) - CMO is an oscillator that measures the accumulation/distribution line of the moving average convergence - divergence (MACD). - The Chaikin oscillator is calculated by subtracting a 10-day exponential moving average (EMA) of the - ADL from a three-day EMA of the ADL, and highlights the momentum implied by the ADL. +def IMI(data): + """ + Inter-day Momentum Index - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('CMO') - return fn(data, period) + source: http://www.fmlabs.com/reference/default.htm?url=IMI.htm + """ + imi_list = [] + up_sum = .0 + down_sum = .0 + i = 0 + while i < len(data['close']): + if data['close'][i] > data['open'][i]: + up_sum = up_sum + (data['close'][i] - data['open'][i]) + else: + down_sum = down_sum + (data['open'][i] - data['close'][i]) + imi = 100 * (up_sum / (up_sum + down_sum)) + imi_list.append(imi) + i += 1 + return imi_list + + +def APO(data, fast_period=12, slow_period=26, ma_type=0, price='close'): + """ + Absolute Price Oscillator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fast_period: fast period used for indicator calculation + :param int slow_period: slow period used for indicator calculation + :param int ma_type: moving average type (0 simple, 1 exponential) + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + apo_list = [] + i = 0 + while i < len(data[price]): + if i + 1 < slow_period: + apo = float('NaN') + else: + start_fast = i + 1 - fast_period + end = i + 1 + sma_fast = MA(data[price][start_fast:end], period=fast_period, ma_type=ma_type) + start_slow = i + 1 - slow_period + end = i + 1 + sma_slow = MA(data[price][start_slow:end], period=slow_period, ma_type=ma_type) + apo = sma_slow - sma_fast + # apo *= -1 + apo_list.append(apo) + i += 1 + return pd.Series(apo_list, name='APO') + + +def AROON(data, period=14): + """ + Aroon indicator - @classmethod - def DX(cls, data, period=14): - """ - Directional Movement Index + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: up and down indicators from data calculation + """ + fn = Function('AROON') + return fn(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('DX') - return fn(data, period) +def AROONOSC(data, period=14): + """ + Aroon Oscillator - @classmethod - def MACD(cls, data, slow_period=10, fast_period=21, signal=9, price='close'): - """ - Moving Average Convergence Divergence + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('AROONOSC') + return fn(data, period) - The MACD Line oscillates above and below the zero line, which is also known as the center-line. - These crossovers signal that the 12-day EMA has crossed the 26-day EMA. The direction, of course, depends on - the direction of the moving average cross. +def BOP(data): + """ + Balance of Power Indicator - Positive MACD indicates that the 12-day EMA is above the 26-day EMA. Positive values increase as the shorter - EMA diverges further from the longer EMA. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('BOP') + return fn(data) - This means upside momentum is increasing. Negative MACD values indicates that the 12-day EMA is below the - 26-day EMA. - Negative values increase as the shorter EMA diverges further below the longer EMA. This means downside momentum - is increasing. +def CCI(data, period=14): + """ + Commodity Index Channel - Signal line crossovers are the most common MACD signals. The signal line is a 9-day EMA of the MACD Line. + CCI is a versatile indicator that can be used to identify a new trend or warn of extreme conditions. - As a moving average of the indicator, it trails the MACD and makes it easier to spot MACD turns. + CCI measures the current price level relative to an average price level over a given period of time. - A bullish crossover occurs when the MACD turns up and crosses above the signal line. + The CCI typically oscillates above and below a zero line. Normal oscillations will occur within the range of + +100 and −100. - A bearish crossover occurs when the MACD turns down and crosses below the signal line. + Readings above +100 imply an overbought condition, while readings below −100 imply an oversold condition. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int slow_period: slow period used for indicator calculation - :param int fast_period: fast period used for indicator calculation - :param int signal: period used for signal calculation - :return pd.Series: with indicator data calculation results - """ - ema_fast = pd.Series(data[price].ewm(ignore_na=False, - min_periods=fast_period - 1, span=fast_period).mean(), index=data.index) + As with other overbought/oversold indicators, this means that there is a large probability that the price will + correct to more representative levels. - ema_slow = pd.Series(data[price].ewm(ignore_na=False, - min_periods=slow_period - 1, span=slow_period).mean(), index=data.index) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('CCI') + return fn(data, period) - macd_series = pd.Series(ema_fast - ema_slow, index=data.index, name='macd') - macd_signal_series = macd_series.ewm(ignore_na=False, span=signal).mean() +def CMO(data, period=14): + """ + Chaikin Momentum Oscillator - macd_signal_series = pd.Series(macd_signal_series, index=data.index, name='macd_signal') - macd_df = pd.concat([macd_signal_series, macd_series], axis=1) + CMO is an oscillator that measures the accumulation/distribution line of the moving average convergence + divergence (MACD). - return pd.DataFrame(macd_df) - # fn = Function('MACD') - # return fn(data, fastperiod=fast_period, slowperiod=slow_period, signalperiod=signal) + The Chaikin oscillator is calculated by subtracting a 10-day exponential moving average (EMA) of the + ADL from a three-day EMA of the ADL, and highlights the momentum implied by the ADL. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('CMO') + return fn(data, period) - @classmethod - def MACDEXT(cls, data, fast_period=12, fast_ma_type=0, slow_period=26, slow_ma_type=0, signal_period=9, - signal_ma_type=0): - """ - Moving Average Convergence Divergence Extended - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fast_period: fast period used for indicator calculation - :param int fast_ma_type: fast moving average type (0 simple, 1 exponential) - :param int slow_period: slow period used for indicator calculation - :param int slow_ma_type: slow moving average type (0 simple, 1 exponential) - :param int signal_period: period used for signal calculation - :param int signal_ma_type: signal moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results with indicator data calculation results - """ - fn = Function('MACDEXT') - return fn(data, fastperiod=fast_period, fastmatype=fast_ma_type, - slowperiod=slow_period, - slowmatype=slow_ma_type, signalperiod=signal_period, - signalmatype=signal_ma_type) +def DX(data, period=14): + """ + Directional Movement Index + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('DX') + return fn(data, period) - @classmethod - def MACDFIX(cls, data, signal_period=9): - """ - Moving Average Convergence/Divergence Fix 12/26 - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int signal_period: period used for signal calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MACDFIX') - return fn(data, signalperiod=signal_period) +def MACD(data, slow_period=10, fast_period=21, signal=9, price='close'): + """ + Moving Average Convergence Divergence + The MACD Line oscillates above and below the zero line, which is also known as the center-line. - @classmethod - def MFI(cls, data, period=14): - """ - Money Flow Indicator + These crossovers signal that the 12-day EMA has crossed the 26-day EMA. The direction, of course, depends on + the direction of the moving average cross. - MFI is a momentum indicator that measures the inflow and outflow of money into a security over a specific - period of time. + Positive MACD indicates that the 12-day EMA is above the 26-day EMA. Positive values increase as the shorter + EMA diverges further from the longer EMA. - MFI can be understood as RSI adjusted for volume. + This means upside momentum is increasing. Negative MACD values indicates that the 12-day EMA is below the + 26-day EMA. - The money flow indicator is one of the more reliable indicators of overbought and oversold conditions, perhaps - partly because it uses the higher readings of 80 and 20 as compared to the RSI's overbought/oversold readings - of 70 and 30. + Negative values increase as the shorter EMA diverges further below the longer EMA. This means downside momentum + is increasing. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MFI') - return fn(data, period) + Signal line crossovers are the most common MACD signals. The signal line is a 9-day EMA of the MACD Line. + As a moving average of the indicator, it trails the MACD and makes it easier to spot MACD turns. - @classmethod - def MINUS_DI(cls, data, period=14): - """ - Minus Directional indicator + A bullish crossover occurs when the MACD turns up and crosses above the signal line. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MINUS_DI') - return fn(data, period) + A bearish crossover occurs when the MACD turns down and crosses below the signal line. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int slow_period: slow period used for indicator calculation + :param int fast_period: fast period used for indicator calculation + :param int signal: period used for signal calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + ema_fast = pd.Series(data[price].ewm(ignore_na=False, + min_periods=fast_period - 1, span=fast_period).mean(), index=data.index) - @classmethod - def MINUS_DM(cls, data, period=14): - """ - Minus Directional Movement indicator + ema_slow = pd.Series(data[price].ewm(ignore_na=False, + min_periods=slow_period - 1, span=slow_period).mean(), index=data.index) - DM is a valuable tool for assessing price direction and strength. + macd_series = pd.Series(ema_fast - ema_slow, index=data.index, name='macd') - This indicator was created in 1978 by J. Welles Wilder, who also created the popular relative strength index. + macd_signal_series = macd_series.ewm(ignore_na=False, span=signal).mean() - DMI tells you when to be long or short. + macd_signal_series = pd.Series(macd_signal_series, index=data.index, name='macd_signal') + macd_df = pd.concat([macd_signal_series, macd_series], axis=1) - It is especially useful for trend trading strategies because it differentiates between strong and weak trends, - allowing the trader to enter only the strongest trends. + return pd.DataFrame(macd_df) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MINUS_DM') - return fn(data, period) +def MACDEXT(data, fast_period=12, fast_ma_type=0, slow_period=26, slow_ma_type=0, signal_period=9, + signal_ma_type=0): + """ + Moving Average Convergence Divergence Extended + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fast_period: fast period used for indicator calculation + :param int fast_ma_type: fast moving average type (0 simple, 1 exponential) + :param int slow_period: slow period used for indicator calculation + :param int slow_ma_type: slow moving average type (0 simple, 1 exponential) + :param int signal_period: period used for signal calculation + :param int signal_ma_type: signal moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results with indicator data calculation results + """ + fn = Function('MACDEXT') + return fn(data, fastperiod=fast_period, fastmatype=fast_ma_type, + slowperiod=slow_period, + slowmatype=slow_ma_type, signalperiod=signal_period, + signalmatype=signal_ma_type) - @classmethod - def MOM(cls, data, period=9): - """ - Momentum Indicator - MOM is measured by continually taking price differences for a fixed time interval. +def MACDFIX(data, signal_period=9): + """ + Moving Average Convergence/Divergence Fix 12/26 - To construct a 10-day momentum line, simply subtract the closing price 10 days ago from the last closing price. - - This positive or negative value is then plotted around a zero line. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int signal_period: period used for signal calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MACDFIX') + return fn(data, signalperiod=signal_period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MOM') - return fn(data, period) +def MFI(data, period=14): + """ + Money Flow Indicator - @classmethod - def PLUS_DI(cls, data, period=14): - """ - Plus Directional Index indicator + MFI is a momentum indicator that measures the inflow and outflow of money into a security over a specific + period of time. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('PLUS_DI') - return fn(data, period) + MFI can be understood as RSI adjusted for volume. + The money flow indicator is one of the more reliable indicators of overbought and oversold conditions, perhaps + partly because it uses the higher readings of 80 and 20 as compared to the RSI's overbought/oversold readings + of 70 and 30. - @classmethod - def PLUS_DM(cls, data, period=14): - """ - Plus Directional Movement indicator - DM is a valuable tool for assessing price direction and strength. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MFI') + return fn(data, period) - This indicator was created in 1978 by J. Welles Wilder, who also created the popular relative strength index. - DMI tells you when to be long or short. +def MINUS_DI(data, period=14): + """ + Minus Directional indicator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MINUS_DI') + return fn(data, period) + + +def MINUS_DM(data, period=14): + """ + Minus Directional Movement indicator + + DM is a valuable tool for assessing price direction and strength. - It is especially useful for trend trading strategies because it differentiates between strong and weak trends, - allowing the trader to enter only the strongest trends. + This indicator was created in 1978 by J. Welles Wilder, who also created the popular relative strength index. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('PLUS_DM') - return fn(data, period) + DMI tells you when to be long or short. + It is especially useful for trend trading strategies because it differentiates between strong and weak trends, + allowing the trader to enter only the strongest trends. - @classmethod - def PPO(cls, data, fast_period=12, slow_period=26, ma_type=0): - """ - Percentage Price Oscillator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MINUS_DM') + return fn(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fast_period: fast period used for indicator calculation - :param int slow_period: slow period used for indicator calculation - :param int ma_type: moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('PPO') - return fn(data, fastperiod=fast_period, slowperiod=slow_period, matype=ma_type) +def MOM(data, period=9): + """ + Momentum Indicator + + MOM is measured by continually taking price differences for a fixed time interval. - @classmethod - def ROC(cls, data, period=10): - """ - Rate of Change + To construct a 10-day momentum line, simply subtract the closing price 10 days ago from the last closing price. - ROC is a pure momentum oscillator that measures the percent change in price from one period to the next. + This positive or negative value is then plotted around a zero line. - The ROC calculation compares the current price with the price “n” periods ago. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MOM') + return fn(data, period) + + +def PLUS_DI(data, period=14): + """ + Plus Directional Index indicator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('PLUS_DI') + return fn(data, period) + + +def PLUS_DM(data, period=14): + """ + Plus Directional Movement indicator + DM is a valuable tool for assessing price direction and strength. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ROC') - return fn(data, period) + This indicator was created in 1978 by J. Welles Wilder, who also created the popular relative strength index. + DMI tells you when to be long or short. - @classmethod - def ROCP(cls, data, period=10): - """ - Rate of Change - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ROCP') - return fn(data, period) - - - @classmethod - def ROCR(cls, data, period=10): - """ - Rate of Change - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ROCR') - return fn(data, period) - - - @classmethod - def ROCR100(cls, data, period=10): - """ - Rate of Change as 100 percentage - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ROCR100') - return fn(data, period) - - - @classmethod - def RSI(cls, data, period=14, price='close'): - """ - Relative Strength Index - - RSI is a momentum oscillator that measures the speed and change of price movements. - - RSI oscillates between zero and 100. Traditionally, and according to Wilder, RSI is considered overbought when - above 70 and oversold when below 30. - - Signals can also be generated by looking for divergences, failure swings and center-line crossovers. - - RSI can also be used to identify the general trend. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - rsi_series = pd.DataFrame(index=data.index) - gain = [0] - loss = [0] - - for row, shifted_row in zip(data[price], data[price].shift(-1)): - if row - shifted_row > 0: - gain.append(row - shifted_row) - loss.append(0) - elif row - shifted_row < 0: - gain.append(0) - loss.append(abs(row - shifted_row)) - elif row - shifted_row == 0: - gain.append(0) - loss.append(0) - - rsi_series['gain'] = gain - rsi_series['loss'] = loss - - avg_gain = rsi_series['gain'].rolling(window=period).mean() - avg_loss = rsi_series['loss'].rolling(window=period).mean() - relative_strength = avg_gain / avg_loss - rsi_ = 100 - (100 / (1 + relative_strength)) - return pd.Series(rsi_, index=data.index, name='RSI') - # fn = Function('RSI') - # return fn(data, period) - - - @classmethod - def STOCH(cls, data, fastk_period=5, slowk_period=3, slowk_ma_type=0, slowd_period=3, slowd_ma_type=0): - """ - Stochastic Oscillator - - The Stochastic Oscillator is a momentum indicator comparing the closing price of a security to the range of it's - prices over a certain period of time. - - The sensitivity of the oscillator to market movements is reducible by adjusting that time period or by taking a - moving average of the result. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fastk_period: period used for K fast indicator calculation - :param int slowk_period: period used for K slow indicator calculation - :param int slowk_ma_type: slow K moving average type (0 simple, 1 exponential) - :param int slowd_period: period used for D slow indicator calculation - :param int slowd_ma_type: slow D moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('STOCH') - return fn(data, fastk_period=fastk_period, slowk_period=slowk_period, - slowk_matype=slowk_ma_type, slowd_matype=slowd_ma_type, - slowd_period=slowd_period) - - - @classmethod - def STOCHF(cls, data, fastk_period=5, fastd_period=3, fastd_ma_type=0): - """ - Stochastic %F - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fastk_period: period used for K fast indicator calculation - :param int fastd_period: period used for D fast indicator calculation - :param int fastd_ma_type: fast D moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('STOCHF') - return fn(data, fastk_period=fastk_period, fastd_period=fastd_period, - fastd_ma_type=fastd_ma_type) - - - @classmethod - def STOCHRSI(cls, data, period=14, fastk_period=5, fastd_period=3, fastd_ma_type=0): - """ - Stochastic RSI - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: RSI period - :param int fastk_period: period used for K fast indicator calculation - :param int fastd_period: period used for D fast indicator calculation - :param int fastd_ma_type: fast D moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('STOCHRSI') - return fn(data, period, fastk_period=fastk_period, - fastd_period=fastd_period, - fastd_ma_type=fastd_ma_type) - - - @classmethod - def TRIX(cls, data, period=30): - """ - Triple Exponential Moving Average Oscillator - - The TRIX is a momentum indicator that oscillates around zero. - - It displays the percentage rate of change between two triple smoothed exponential moving averages. - - To calculate TRIX we calculate triple smoothed EMA3 of n periods and then subtracts previous period EMA3 value - from last EMA3 value and divide the result with yesterdays EMA3 value. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('TRIX') - return fn(data, period) - - - @classmethod - def ULTOSC(cls, data, period1=7, period2=14, period3=28): - """ - Ultimate Oscillator - - UO or ULTOSC is a momentum oscillator designed to capture momentum across three different time frames. - - The multiple time frame objective seeks to avoid the pitfalls of other oscillators. - - Many momentum oscillators surge at the beginning of a strong advance and then form bearish divergence as the - advance continues. - - This is because they are stuck with one time frame. The Ultimate Oscillator attempts to correct this fault by - incorporating longer time frames into the basic formula. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period1: first period used for indicator calculation period used for indicator calculation - :param int period2: second period used for indicator calculation period used for indicator calculation - :param int period3: third period used for indicator calculation period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ULTOSC') - return fn(data, timeperiod1=period1, timeperiod2=period2, timeperiod3=period3) - - - @classmethod - def WILLR(cls, data, period=14): - """ - Williams %R - - Williams %R, or just %R, is a technical analysis oscillator showing the current closing price in relation to - the high and low of the past N days (for a given N). - - It was developed by a publisher and promoter of trading materials, Larry Williams. - - It's purpose is to tell whether a stock or commodity market is trading near the high or the low, or somewhere in - between, of its recent trading range. - - The oscillator is on a negative scale, from −100 (lowest) up to 0 (highest). - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - willr_list = [] - i = 0 - close, high, low = data['close'], data['high'], data['low'] - while i < len(close): - if i + 1 < period: - willr = float('NaN') - else: - start = i + 1 - period - end = i + 1 - willr = (max(high[start:end]) - close[i]) / (max(high[start:end]) - min(low[start:end])) * 100 - # willr *= -1 - willr_list.append(willr) - i += 1 - return willr_list - # fn = Function('WILLR') - # return fn(data, period) + It is especially useful for trend trading strategies because it differentiates between strong and weak trends, + allowing the trader to enter only the strongest trends. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('PLUS_DM') + return fn(data, period) + + +def PPO(data, fast_period=12, slow_period=26, ma_type=0): + """ + Percentage Price Oscillator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fast_period: fast period used for indicator calculation + :param int slow_period: slow period used for indicator calculation + :param int ma_type: moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('PPO') + return fn(data, fastperiod=fast_period, slowperiod=slow_period, matype=ma_type) + + +def ROC(data, period=10): + """ + Rate of Change + + ROC is a pure momentum oscillator that measures the percent change in price from one period to the next. + + The ROC calculation compares the current price with the price “n” periods ago. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ROC') + return fn(data, period) + + +def ROCP(data, period=10): + """ + Rate of Change + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ROCP') + return fn(data, period) + + +def ROCR(data, period=10): + """ + Rate of Change + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ROCR') + return fn(data, period) + + +def ROCR100(data, period=10): + """ + Rate of Change as 100 percentage + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ROCR100') + return fn(data, period) + + +def RSI(data, period=14, price='close'): + """ + Relative Strength Index + + RSI is a momentum oscillator that measures the speed and change of price movements. + + RSI oscillates between zero and 100. Traditionally, and according to Wilder, RSI is considered overbought when + above 70 and oversold when below 30. + + Signals can also be generated by looking for divergences, failure swings and center-line crossovers. + + RSI can also be used to identify the general trend. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + rsi_series = pd.DataFrame(index=data.index) + gain = [0] + loss = [0] + + for row, shifted_row in zip(data[price], data[price].shift(-1)): + if row - shifted_row > 0: + gain.append(row - shifted_row) + loss.append(0) + elif row - shifted_row < 0: + gain.append(0) + loss.append(abs(row - shifted_row)) + elif row - shifted_row == 0: + gain.append(0) + loss.append(0) + + rsi_series['gain'] = gain + rsi_series['loss'] = loss + + avg_gain = rsi_series['gain'].rolling(window=period).mean() + avg_loss = rsi_series['loss'].rolling(window=period).mean() + relative_strength = avg_gain / avg_loss + rsi_ = 100 - (100 / (1 + relative_strength)) + return pd.Series(rsi_, index=data.index, name='RSI') + # fn = Function('RSI') + # return fn(data, period) + + +def STOCH(data, fastk_period=5, slowk_period=3, slowk_ma_type=0, slowd_period=3, slowd_ma_type=0): + """ + Stochastic Oscillator + + The Stochastic Oscillator is a momentum indicator comparing the closing price of a security to the range of it's + prices over a certain period of time. + + The sensitivity of the oscillator to market movements is reducible by adjusting that time period or by taking a + moving average of the result. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fastk_period: period used for K fast indicator calculation + :param int slowk_period: period used for K slow indicator calculation + :param int slowk_ma_type: slow K moving average type (0 simple, 1 exponential) + :param int slowd_period: period used for D slow indicator calculation + :param int slowd_ma_type: slow D moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('STOCH') + return fn(data, fastk_period=fastk_period, slowk_period=slowk_period, + slowk_matype=slowk_ma_type, slowd_matype=slowd_ma_type, + slowd_period=slowd_period) + + +def STOCHF(data, fastk_period=5, fastd_period=3, fastd_ma_type=0): + """ + Stochastic %F + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fastk_period: period used for K fast indicator calculation + :param int fastd_period: period used for D fast indicator calculation + :param int fastd_ma_type: fast D moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('STOCHF') + return fn(data, fastk_period=fastk_period, fastd_period=fastd_period, + fastd_ma_type=fastd_ma_type) + + +def STOCHRSI(data, period=14, fastk_period=5, fastd_period=3, fastd_ma_type=0): + """ + Stochastic RSI + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: RSI period + :param int fastk_period: period used for K fast indicator calculation + :param int fastd_period: period used for D fast indicator calculation + :param int fastd_ma_type: fast D moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('STOCHRSI') + return fn(data, period, fastk_period=fastk_period, + fastd_period=fastd_period, + fastd_ma_type=fastd_ma_type) + + +def TRIX(data, period=30): + """ + Triple Exponential Moving Average Oscillator + + The TRIX is a momentum indicator that oscillates around zero. + + It displays the percentage rate of change between two triple smoothed exponential moving averages. + + To calculate TRIX we calculate triple smoothed EMA3 of n periods and then subtracts previous period EMA3 value + from last EMA3 value and divide the result with yesterdays EMA3 value. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('TRIX') + return fn(data, period) + + +def ULTOSC(data, period1=7, period2=14, period3=28): + """ + Ultimate Oscillator + + UO or ULTOSC is a momentum oscillator designed to capture momentum across three different time frames. + + The multiple time frame objective seeks to avoid the pitfalls of other oscillators. + + Many momentum oscillators surge at the beginning of a strong advance and then form bearish divergence as the + advance continues. + + This is because they are stuck with one time frame. The Ultimate Oscillator attempts to correct this fault by + incorporating longer time frames into the basic formula. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period1: first period used for indicator calculation period used for indicator calculation + :param int period2: second period used for indicator calculation period used for indicator calculation + :param int period3: third period used for indicator calculation period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ULTOSC') + return fn(data, timeperiod1=period1, timeperiod2=period2, timeperiod3=period3) + + +def WILLR(data, period=14): + """ + Williams %R + + Williams %R, or just %R, is a technical analysis oscillator showing the current closing price in relation to + the high and low of the past N days (for a given N). + + It was developed by a publisher and promoter of trading materials, Larry Williams. + + It's purpose is to tell whether a stock or commodity market is trading near the high or the low, or somewhere in + between, of its recent trading range. + + The oscillator is on a negative scale, from −100 (lowest) up to 0 (highest). + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + willr_list = [] + i = 0 + close, high, low = data['close'], data['high'], data['low'] + while i < len(close): + if i + 1 < period: + willr = float('NaN') + else: + start = i + 1 - period + end = i + 1 + willr = (max(high[start:end]) - close[i]) / (max(high[start:end]) - min(low[start:end])) * 100 + # willr *= -1 + willr_list.append(willr) + i += 1 + return willr_list + # fn = Function('WILLR') + # return fn(data, period) diff --git a/techa/overlap.py b/techa/overlap.py index 7a87ba8..7d23ae0 100644 --- a/techa/overlap.py +++ b/techa/overlap.py @@ -4,820 +4,790 @@ import pandas as pd from finta import TA -from talib.abstract import * +from talib.abstract import Function +__all__ = ['TRIMA', 'TRIX', 'KC', 'MA', 'MIDPRICE', 'HT_TRENDLINE', 'CHANDELIER', 'BBANDS', 'MIDPOINT', 'DO', 'DEMA', + 'EMA', 'ZLEMA', 'APZ', 'SAR', 'SAREXT', 'SMA', 'SMMA', 'FISH', 'HMA', 'TEMA', 'VAMA', 'VORTEX', 'ICHIMOKU', + 'ER', 'KAMA', 'VWAP', 'MAVP', 'MAMA', 'T3', 'WMA'] -class Overlap: + +def TRIX(data, period=15, price='close'): """ - Overlap Studies + Triple Exponential Moving Average Oscillator + + TRIX is a momentum indicator that oscillates around zero. + + It displays the percentage rate of change between two triple smoothed exponential moving averages. + + To calculate TRIX we calculate triple smoothed EMA3 of n periods and then subtract previous period EMA3 value + + from last EMA3 value and divide the result with yesterdays EMA3 value. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results """ + exponential_average_one = EMA(data, period, price=price) + exponential_average_two = exponential_average_one.ewm(ignore_na=False, min_periods=period - 1, span=period).mean() + exponential_average_three = exponential_average_two.ewm(ignore_na=False, min_periods=period - 1, span=period).mean() + return exponential_average_three.pct_change(periods=1) - @classmethod - def TRIX(cls, data, period=15, price='close'): - """ - Triple Exponential Moving Average Oscillator - TRIX is a momentum indicator that oscillates around zero. +def KC(data, period=20): + """ + Keltner Channels - It displays the percentage rate of change between two triple smoothed exponential moving averages. + KC are volatility-based envelopes set above and below an exponential moving average. - To calculate TRIX we calculate triple smoothed EMA3 of n periods and then subtract previous period EMA3 value + This indicator is similar to Bollinger Bands, which use the standard deviation to set the bands. - from last EMA3 value and divide the result with yesterdays EMA3 value. + Instead of using the standard deviation, Keltner Channels use the Average True Range (ATR) to set channel + distance. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - emwa_one = cls.EMA(data, period, price=price) + The channels are typically set two Average True Range values above and below the 20-day EMA. - emwa_two = emwa_one.ewm(ignore_na=False, min_periods=period - 1, span=period).mean() + The exponential moving average dictates direction and the Average True Range sets channel width. - emwa_three = emwa_two.ewm(ignore_na=False, min_periods=period - 1, span=period).mean() + Keltner Channels are a trend following indicator used to identify reversals with channel breakouts and channel + direction. - return emwa_three.pct_change(periods=1) - # return TA.TRIX(data, period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.KC(data, period) - @classmethod - def KC(cls, data, period=20): - """ - Keltner Channels +def DO(data, period=20): + """ + Donchian Channel - KC are volatility-based envelopes set above and below an exponential moving average. + DC is a moving average indicator developed by Richard Donchian. - This indicator is similar to Bollinger Bands, which use the standard deviation to set the bands. + It plots the highest high and lowest low over the last period time intervals. - Instead of using the standard deviation, Keltner Channels use the Average True Range (ATR) to set channel - distance. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.DO(data, period) - The channels are typically set two Average True Range values above and below the 20-day EMA. - The exponential moving average dictates direction and the Average True Range sets channel width. +def ICHIMOKU(data): + """ + Ichimoku indicator - Keltner Channels are a trend following indicator used to identify reversals with channel breakouts and channel - direction. + The Ichimoku Cloud, also known as Ichimoku Kinko Hyo, is a versatile indicator that defines support and + resistance, identifies trend direction, gauges momentum and provides trading signals. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.KC(data, period) + Ichimoku Kinko Hyo translates into “one look equilibrium chart”. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.ICHIMOKU(data) - @classmethod - def DO(cls, data, period=20): - """ - Donchian Channel - DC is a moving average indicator developed by Richard Donchian. +def CHANDELIER(data, period_1=14, period_2=22, k=3): + """ + Chandelier Exit - It plots the highest high and lowest low over the last period time intervals. + Chandelier Exit sets a trailing stop-loss based on the Average True Range (ATR). - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.DO(data, period) + The indicator is designed to keep traders in a trend and prevent an early exit as long as the trend extends. + Typically, the Chandelier Exit will be above prices during a downtrend and below prices during an uptrend. - @classmethod - def ICHIMOKU(cls, data): - """ - Ichimoku indicator + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period_1: first period used for indicator calculation + :param int period_2: second period used for indicator calculation + :param k: + :return pd.Series: with indicator data calculation results + """ + return TA.CHANDELIER(ohlc=data, period_1=period_1, period_2=period_2, k=k) - The Ichimoku Cloud, also known as Ichimoku Kinko Hyo, is a versatile indicator that defines support and - resistance, identifies trend direction, gauges momentum and provides trading signals. - Ichimoku Kinko Hyo translates into “one look equilibrium chart”. +def ER(data, period=10, price='close'): + """ + Kaufman Efficiency Oscillator - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.ICHIMOKU(data) + ER indicator is an oscillator indicator that oscillates between +100 and -100, where zero is the center point. + +100 is upward FOREX trending market and -100 is downwards trending markets. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + change = data[price].diff(periods=period).abs() + vol = data[price].diff().abs().rolling(window=period).sum() + return pd.Series(change / vol) - @classmethod - def CHANDELIER(cls, data, period_1=14, period_2=22, k=3): - """ - Chandelier Exit + # return TA.ER(data, period) - Chandelier Exit sets a trailing stop-loss based on the Average True Range (ATR). - The indicator is designed to keep traders in a trend and prevent an early exit as long as the trend extends. +def VAMA(data, period=8, column='close'): + """ + Volume Adjusted Moving Average - Typically, the Chandelier Exit will be above prices during a downtrend and below prices during an uptrend. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str column: column used for indicator calculation (default = "close") + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + """ + return TA.VAMA(data, period, column) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period_1: first period used for indicator calculation - :param int period_2: second period used for indicator calculation - :param k: - :return pd.Series: with indicator data calculation results - """ - return TA.CHANDELIER(ohlc=data, period_1=period_1, period_2=period_2, k=k) +def ZLEMA(data, period=26, price='close'): + """ + Zero Lag Moving Average - @classmethod - def ER(cls, data, period=10, price='close'): - """ - Kaufman Efficiency Oscillator + ZLEMA is an abbreviation of Zero Lag Exponential Moving Average. It was developed by John Ehlers and Rick Way. - ER indicator is an oscillator indicator that oscillates between +100 and -100, where zero is the center point. - +100 is upward FOREX trending market and -100 is downwards trending markets. + ZLEMA is a kind of Exponential moving average but its main idea is to eliminate the lag arising from the very + nature of the moving averages and other trend following indicators. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - change = data[price].diff(periods=period).abs() - vol = data[price].diff().abs().rolling(window=period).sum() - return pd.Series(change / vol) + As it follows price closer, it also provides better price averaging and responds better to price swings. - # return TA.ER(data, period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + lag = (period - 1) / 2 + return pd.Series(data[price] + (data[price].diff(lag)), name='zero_lag_ema') + # return TA.ZLEMA(data, period) - @classmethod - def VAMA(cls, data, period=8, column='close'): - """ - Volume Adjusted Moving Average - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param str column: column used for indicator calculation (default = "close") - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - """ - return TA.VAMA(data, period, column) +def HMA(data, period=16): + """ + Hell's Moving Average + HMA indicator is a common abbreviation of Hull Moving Average. - @classmethod - def ZLEMA(cls, data, period=26, price='close'): - """ - Zero Lag Moving Average + The average was developed by Allan Hull and is used mainly to identify the current market trend. - ZLEMA is an abbreviation of Zero Lag Exponential Moving Average. It was developed by John Ehlers and Rick Way. + Unlike SMA (simple moving average) the curve of Hull moving average is considerably smoother. - ZLEMA is a kind of Exponential moving average but its main idea is to eliminate the lag arising from the very - nature of the moving averages and other trend following indicators. + Moreover, because its aim is to minimize the lag between HMA and price it does follow the price activity much + closer. - As it follows price closer, it also provides better price averaging and responds better to price swings. + It is used especially for middle-term and long-term trading. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - lag = (period - 1) / 2 - return pd.Series(data[price] + (data[price].diff(lag)), name='zero_lag_ema') + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.HMA(data, period) + + +def VORTEX(data, period=42): + """ + Vortex Indicator + + The Vortex indicator plots two oscillating lines, one to identify positive trend movement and the other + to identify negative price movement. + + Indicator construction revolves around the highs and lows of the last two days or periods. + + The distance from the current high to the prior low designates positive trend movement while the + distance between the current low and the prior high designates negative trend movement. + + Strongly positive or negative trend movements will show a longer length between the two numbers while + weaker positive or negative trend movement will show a shorter length. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.VORTEX(data, period) - # return TA.ZLEMA(data, period) +def SMMA(data, period=14, price='close'): + """ + Smoothed Simple Moving Average - @classmethod - def HMA(cls, data, period=16): - """ - Hell's Moving Average + SMMA gives recent prices an equal weighting to historic prices. - HMA indicator is a common abbreviation of Hull Moving Average. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + ma = data[price].ewm(alpha=1 / period).mean() + return pd.Series(ma, index=data.index, name='smoothed_ma') - The average was developed by Allan Hull and is used mainly to identify the current market trend. - Unlike SMA (simple moving average) the curve of Hull moving average is considerably smoother. +def VWAP(data): + """ + Weighted Moving Average - Moreover, because its aim is to minimize the lag between HMA and price it does follow the price activity much - closer. + WMAP helps to smooth the price curve for better trend identification. - It is used especially for middle-term and long-term trading. + It places even greater importance on recent data than the EMA does. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.HMA(data, period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + return TA.VWAP(data) - @classmethod - def VORTEX(cls, data, period=42): - """ - Vortex Indicator +def FISH(data, period=10): + """ + Fisher's Transform - The Vortex indicator plots two oscillating lines, one to identify positive trend movement and the other - to identify negative price movement. + FISH was presented by John Ehler's. It assumes that price distributions behave like square waves. - Indicator construction revolves around the highs and lows of the last two days or periods. + The Fisher Transform uses the mid-point or median price in a series of calculations to produce an oscillator. - The distance from the current high to the prior low designates positive trend movement while the - distance between the current low and the prior high designates negative trend movement. + A signal line which is a previous value of itself is also calculated. - Strongly positive or negative trend movements will show a longer length between the two numbers while - weaker positive or negative trend movement will show a shorter length. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + return TA.FISH(data, period) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.VORTEX(data, period) +def APZ(data, period=21, dev_factor=2, ma_type=None): + """ + Adaptive Price Zone - @classmethod - def SMMA(cls, data, period=14, price='close'): - """ - Smoothed Simple Moving Average + APZ is as a volatility based indicator developed by Lee Leibfarth that appears as a set of bands placed over a + price chart. - SMMA gives recent prices an equal weighting to historic prices. + Especially useful in non-trending, choppy markets, the APZ was created to help traders find potential turning + points in the markets. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param str price: column used for indicator calculation (default = "close") - :return pd.Series: with indicator data calculation results - """ - ma = data[price].ewm(alpha=1 / period).mean() - return pd.Series(ma, index=data.index, name='smoothed_ma') + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param float dev_factor: standard derivation factor + :param int ma_type: moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ - # return TA.SMMA(data, period, column) + return TA.APZ(data, period, dev_factor, ma_type) - @classmethod - def VWAP(cls, data): - """ - Weighted Moving Average +# noinspection SpellCheckingInspection - WMAP helps to smooth the price curve for better trend identification. +def BBANDS(data, period=5, nbdevup=2, nbdevdn=2, ma_type=0, price='close'): + """ + Bollinger Bands - It places even greater importance on recent data than the EMA does. + Developed by John Bollinger, Bollinger Bands are volatility bands placed above and below a moving average. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - return TA.VWAP(data) + Volatility is based on the standard deviation, which changes as volatility increases and decreases. + The bands automatically widen when volatility increases and narrow when volatility decreases. + This method allows input of some other form of moving average like EMA or KAMA around which BBAND will be + formed. - @classmethod - def FISH(cls, data, period=10): - """ - Fisher's Transform + Pass desired moving average as argument. For example BBANDS(MA=TA.KAMA(20)). - FISH was presented by John Ehler's. It assumes that price distributions behave like square waves. + This method returns other variations and derivatives of BBANDS as well. - The Fisher Transform uses the mid-point or median price in a series of calculations to produce an oscillator. + Bandwidth tells how wide the Bollinger Bands are on a normalized basis. - A signal line which is a previous value of itself is also calculated. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param float, int nbdevup: standard derivation to upper band + :param float, int nbdevdn: standard derivation to lower band + :param int ma_type: 0 for SMA or 1 for EMA + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + std_dev = data[price].std() + if ma_type == 1: + middle_band = EMA(data, period=period, price=price) + else: + middle_band = SMA(data, period=period, price=price) + upper_bband = pd.Series(middle_band + (nbdevup * std_dev), name='upper_bband') + lower_bband = pd.Series(middle_band - (nbdevdn * std_dev), name='lower_bband') - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return TA.FISH(data, period) + percent_b = (data[price] - lower_bband) / (upper_bband - lower_bband) + b_bandwidth = pd.Series((upper_bband - lower_bband) / middle_band) - @classmethod - def APZ(cls, data, period=21, dev_factor=2, ma_type=None): - """ - Adaptive Price Zone + return pd.concat([upper_bband, middle_band, lower_bband, b_bandwidth, percent_b], axis=1) - APZ is as a volatility based indicator developed by Lee Leibfarth that appears as a set of bands placed over a - price chart. - Especially useful in non-trending, choppy markets, the APZ was created to help traders find potential turning - points in the markets. +def DEMA(data, period): + """ + Double Exponential Moving Average - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param float dev_factor: standard derivation factor - :param int ma_type: moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ + DEMA indicator attempts to remove the inherent lag associated to Moving Averages by placing more weight on + recent values. - return TA.APZ(data, period, dev_factor, ma_type) + The name suggests this is achieved by applying a double exponential smoothing which is not the case. + The name double comes from the fact that the value of an EMA (Exponential Moving Average) is doubled. - # noinspection SpellCheckingInspection - @classmethod - def BBANDS(cls, data, period=5, nbdevup=2, nbdevdn=2, ma_type=0, price='close'): - """ - Bollinger Bands + To keep it in line with the actual data and to remove the lag the value "EMA of EMA" is subtracted from the + previously doubled EMA. - Developed by John Bollinger, Bollinger Bands are volatility bands placed above and below a moving average. + Because EMA(EMA) is used in the calculation, DEMA needs 2 * period -1 samples to start producing values in + contrast to the period samples needed by a regular EMA - Volatility is based on the standard deviation, which changes as volatility increases and decreases. - The bands automatically widen when volatility increases and narrow when volatility decreases. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('DEMA') + return fn(data, timeperiod=period) - This method allows input of some other form of moving average like EMA or KAMA around which BBAND will be - formed. - Pass desired moving average as argument. For example BBANDS(MA=TA.KAMA(20)). +def EMA(data, period=30, price='close'): + """ + Exponential Moving Average - This method returns other variations and derivatives of BBANDS as well. + Like all moving average indicators, they are much better suited for trending markets. - Bandwidth tells how wide the Bollinger Bands are on a normalized basis. + When the market is in a strong and sustained uptrend, the EMA indicator line will also show an uptrend and + vice-versa for a down trend. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param float, int nbdevup: standard derivation to upper band - :param float, int nbdevdn: standard derivation to lower band - :param int ma_type: 0 for SMA or 1 for EMA - :return pd.Series: with indicator data calculation results - """ - std_dev = data[price].std() - middle_band = cls.SMA(data, period=period, price='close') - upper_bband = pd.Series(middle_band + (2 * std_dev), name='upper_bband') - lower_bband = pd.Series(middle_band - (2 * std_dev), name='lower_bband') + EMAs are commonly used in conjunction with other indicators to confirm significant market moves and to gauge + their validity. - percent_b = (data[price] - lower_bband) / (upper_bband - lower_bband) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + return data[price].ewm(ignore_na=False, min_periods=period - 1, span=period).mean() - b_bandwidth = pd.Series((upper_bband - lower_bband) / middle_band) - return pd.concat([upper_bband, middle_band, lower_bband, b_bandwidth, percent_b], axis=1) - # fn = Function('BBANDS') - # return fn(data, timeperiod=period, nbdevup=nbdevup, nbdevdn=nbdevdn, matype=ma_type) +def HT_TRENDLINE(data, price='close'): + """ + Hilbert Transform + Instantaneous Trend-line - @classmethod - def DEMA(cls, data, period): - """ - Double Exponential Moving Average + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + fn = Function('HT_TRENDLINE') + return fn(data, price) - DEMA indicator attempts to remove the inherent lag associated to Moving Averages by placing more weight on - recent values. - The name suggests this is achieved by applying a double exponential smoothing which is not the case. +def KAMA(data, period=20, er_period=10, fast=2, slow=30, price='close'): + """ + Kaufman's Adaptive Moving Average - The name double comes from the fact that the value of an EMA (Exponential Moving Average) is doubled. + KAMA is a moving average designed to account for market noise or volatility. - To keep it in line with the actual data and to remove the lag the value "EMA of EMA" is subtracted from the - previously doubled EMA. + It's main advantage is that it takes into consideration not just the direction, but the market volatility as + well. - Because EMA(EMA) is used in the calculation, DEMA needs 2 * period -1 samples to start producing values in - contrast to the period samples needed by a regular EMA + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param int er_period: period used for indicator calculation + :param int fast: fast period used for indicator calculation + :param int slow: slow period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + er = ER(data, er_period) + fast_alpha = 2 / (fast + 1) + slow_alpha = 2 / (slow + 1) + + # smoothing constant + # noinspection PyTypeChecker + sc = pd.Series((er * (fast_alpha - slow_alpha) + slow_alpha) ** 2) + sma_ = SMA(data, period, price) + + kama_ = [] + + for smooth, ma, price in zip(sc, sma_.shift(-1), data[price]): + try: + kama_.append(kama_[-1] + smooth * (price - kama_[-1])) + except (IndexError, TypeError): + if pd.notnull(ma): + kama_.append(ma + smooth * (price - ma)) + else: + kama_.append(None) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('DEMA') - return fn(data, timeperiod=period) + return pd.Series(kama_, index=sma_.index, name='KAMA') - @classmethod - def EMA(cls, data, period=30, price='close'): - """ - Exponential Moving Average +def MA(data, period=25, ma_type=0): + """ + Moving Average - Like all moving average indicators, they are much better suited for trending markets. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param int ma_type: moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('MA') + return fn(data, timeperiod=period, matype=ma_type) - When the market is in a strong and sustained uptrend, the EMA indicator line will also show an uptrend and - vice-versa for a down trend. - EMAs are commonly used in conjunction with other indicators to confirm significant market moves and to gauge - their validity. +def MAMA(data, fast_limit=0.5, slow_limit=0.05): + """ + MESA Adaptive Moving Average - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - return data[price].ewm(ignore_na=False, min_periods=period - 1, span=period).mean() - # fn = Function('EMA') - # return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param float fast_limit: fast limit period used for indicator calculation + :param float slow_limit: slow limit period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MAMA') + return fn(data, fastlimit=fast_limit, slowlimit=slow_limit) - @classmethod - def HT_TRENDLINE(cls, data, column='close'): - """ - Hilbert Transform - Instantaneous Trend-line +def MAVP(data, min_period=2, max_period=30, ma_type=0): + """ + Volume Adjusted Moving Average - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param str column: column used for indicator calculation (default = "close") - :return pd.Series: with indicator data calculation results - """ - fn = Function('HT_TRENDLINE') - return fn(data, column) + Moving average with variable period. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int min_period: min period used for indicator calculation + :param int max_period: max period used for indicator calculation + :param int ma_type: moving average type (0 simple, 1 exponential) + :return pd.Series: with indicator data calculation results + """ + fn = Function('MAVP') + return fn(data, minperiod=min_period, maxperiod=max_period, matype=ma_type) - @classmethod - def KAMA(cls, data, period=20, er_period=10, fast=2, slow=30, price='close'): - """ - Kaufman's Adaptive Moving Average - KAMA is a moving average designed to account for market noise or volatility. +def MIDPOINT(data, period=14): + """ + Mid Point - It's main advantage is that it takes into consideration not just the direction, but the market volatility as - well. + MidPoint over period. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int er_period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - er = cls.ER(data, er_period) - fast_alpha = 2 / (fast + 1) - slow_alpha = 2 / (slow + 1) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MIDPOINT') + return fn(data, timeperiod=period) - # smoothing constant - # noinspection PyTypeChecker - sc = pd.Series((er * (fast_alpha - slow_alpha) + slow_alpha) ** 2) - sma_ = cls.SMA(data, period, price) - kama_ = [] +def MIDPRICE(data, period=14): + """ + Mid Price - for smooth, ma, price in zip(sc, sma_.shift(-1), data[price]): - try: - kama_.append(kama_[-1] + smooth * (price - kama_[-1])) - except (IndexError, TypeError): - if pd.notnull(ma): - kama_.append(ma + smooth * (price - ma)) - else: - kama_.append(None) + Midpoint Price over period - return pd.Series(kama_, index=sma_.index, name='KAMA') - # fn = Function('KAMA') - # return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('MIDPRICE') + return fn(data, timeperiod=period) - @classmethod - def MA(cls, data, period=25, ma_type=0): - """ - Moving Average +def SAR(data, accel=0.02, max_accel=0.2): + """ + SAR stands for “stop and reverse,” which is the actual indicator used in the system. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param int ma_type: moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('MA') - return fn(data, timeperiod=period, matype=ma_type) + SAR trails price as the trend extends over time. + The indicator is below prices when prices are rising and above prices when prices are falling. - @classmethod - def MAMA(cls, data, fast_limit=0.5, slow_limit=0.05): - """ - MESA Adaptive Moving Average + In this regard, the indicator stops and reverses when the price trend reverses and breaks above or below the + indicator. + Developed by John Bollinger, Bollinger Bands® are volatility bands placed above and below a moving average. + Volatility is based on the standard deviation, which changes as volatility increases and decreases. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param float fast_limit: fast limit period used for indicator calculation - :param float slow_limit: slow limit period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MAMA') - return fn(data, fastlimit=fast_limit, slowlimit=slow_limit) + The bands automatically widen when volatility increases and narrow when volatility decreases. + This method allows input of some other form of moving average like EMA or KAMA around which BBAND will be + formed. - @classmethod - def MAVP(cls, data, min_period=2, max_period=30, ma_type=0): - """ - Volume Adjusted Moving Average + Pass desired moving average as argument. For example BBANDS(MA=TA.KAMA(20)). - Moving average with variable period. + This method returns other variations and derivatives of BBANDS as well. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int min_period: min period used for indicator calculation - :param int max_period: max period used for indicator calculation - :param int ma_type: moving average type (0 simple, 1 exponential) - :return pd.Series: with indicator data calculation results - """ - fn = Function('MAVP') - return fn(data, minperiod=min_period, maxperiod=max_period, matype=ma_type) + Bandwidth tells how wide the Bollinger Bands are on a normalized basis. + %b (pronounced "percent b") is derived from the formula for Stochastics and shows where price is in relation to + the bands. - @classmethod - def MIDPOINT(cls, data, period=14): - """ - Mid Point + %b equals 1 at the upper band and 0 at the lower band. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param float accel: acceleration factor + :param float max_accel: max acceleration factor + :return pd.Series: with indicator data calculation results with indicator data calculation results + """ + # sar_list = [] + # i = 0 + # + # while i < len(data['close']): + # if i < 1: + # sar = float('NaN') + # sar_list.append(sar) + # is_long = True + # sar = data['low'][i] + # ep = data['high'][i] + # af = accel + # else: + # if is_long: + # if data['low'][i] <= sar: + # is_long = False + # sar = ep + # if sar < data['high'][i - 1]: + # sar = data['high'][i - 1] + # if sar < data['high'][i]: + # sar = data['high'][i] + # sar_list.append(sar) + # af = accel + # ep = data['low'][i] + # sar = sar + af * (ep - sar) + # # sar = round(sar) + # if sar < data['high'][i - 1]: + # sar = data['high'][i - 1] + # if sar < data['high'][i]: + # sar = data['high'][i] + # else: + # sar_list.append(sar) + # if data['high'][i] > ep: + # ep = data['high'][i] + # af += accel + # if af > max_accel: + # af = max_accel + # sar = sar + af * (ep - sar) + # # sar = round(sar) + # if sar > data['low'][i - 1]: + # sar = data['low'][i - 1] + # if sar > data['low'][i]: + # sar = data['low'][i] + # else: + # if data['high'][i] >= sar: + # is_long = True + # sar = ep + # if sar > data['low'][i - 1]: + # sar = data['low'][i - 1] + # if sar > data['low'][i]: + # sar = data['low'][i] + # sar_list.append(sar) + # af = accel + # ep = data['high'][i] + # sar = sar + af * (ep - sar) + # # sar = round(sar) + # if sar > data['low'][i - 1]: + # sar = data['low'][i - 1] + # if sar > data['low'][i]: + # sar = data['low'][i] + # else: + # sar_list.append(sar) + # if data['low'][i] < ep: + # ep = data['low'][i] + # af += accel + # if af > max_accel: + # af = max_accel + # sar = sar + af * (ep - sar) + # # sar = round(sar) + # if sar < data['high'][i - 1]: + # sar = data['high'][i - 1] + # if sar < data['high'][i]: + # sar = data['high'][i] + # i += 1 + # return pd.Series(sar_list, 'SAR') + fn = Function('SAR') + return fn(data, acceleration=accel, maximum=max_accel) + + +def SAREXT(data, start=0, offset_on_reverse=0, accel_init_long=0.02, accel_long=0.02, + accel_max_long=0.2, accel_init_short=0.02, accel_short=0.02, accel_max_short=0.2): + """ + Parabolic SAR - Extended + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param start: start value + :param int offset_on_reverse: offset on reverse + :param float accel_init_long: initial long acceleration factor + :param float accel_long: long acceleration factor + :param float accel_max_long: max long acceleration factor + :param float accel_init_short: initial short acceleration factor + :param float accel_short: short acceleration factor + :param float accel_max_short: max short acceleration factor + :return pd.Series: with indicator data calculation results with indicator data calculation results + """ + fn = Function('SAREXT') + return fn(data, startvalue=start, offsetonreverse=offset_on_reverse, accelerationinitlong=accel_init_long, + accelerationlong=accel_long, accelerationmaxlong=accel_max_long, + accelerationinitshort=accel_init_short, accelerationshort=accel_short, + accelerationmaxshort=accel_max_short) - MidPoint over period. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MIDPOINT') - return fn(data, timeperiod=period) +def SMA(data, period=25, price='close'): + """ + Simple Moving Average + The simple moving average (SMA) is the most basic of the moving averages used for trading. - @classmethod - def MIDPRICE(cls, data, period=14): - """ - Mid Price + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + sma = data[price].rolling(center=False, window=period, min_periods=period - 1).mean() + return pd.Series(sma, name='sma', index=data.index) - Midpoint Price over period - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('MIDPRICE') - return fn(data, timeperiod=period) +def T3(data, period=5, v_factor=0.7): + """ + Triple Exponential Moving Average (T3) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param float v_factor: v factor + :return pd.Series: with indicator data calculation results + """ + fn = Function('T3') + return fn(data, timeperiod=period, vfactor=v_factor) - @classmethod - def SAR(cls, data, accel=0.02, max_accel=0.2): - """ - SAR stands for “stop and reverse,” which is the actual indicator used in the system. - SAR trails price as the trend extends over time. +def TEMA(data, period=30): + """ + Triple exponential moving average - The indicator is below prices when prices are rising and above prices when prices are falling. + Attempts to remove the inherent lag associated to Moving Averages by placing more weight on recent values. - In this regard, the indicator stops and reverses when the price trend reverses and breaks above or below the - indicator. + The name suggests this is achieved by applying a triple exponential smoothing which is not the case. - Developed by John Bollinger, Bollinger Bands® are volatility bands placed above and below a moving average. + The name triple comes from the fact that the value of an EMA (Exponential Moving Average) is triple. - Volatility is based on the standard deviation, which changes as volatility increases and decreases. + To keep it in line with the actual data and to remove the lag the value "EMA of EMA" is subtracted 3 times + from the previously tripled EMA. - The bands automatically widen when volatility increases and narrow when volatility decreases. + Finally "EMA of EMA of EMA" is added. - This method allows input of some other form of moving average like EMA or KAMA around which BBAND will be - formed. + Because EMA(EMA(EMA)) is used in the calculation, TEMA needs 3 * period - 2 samples to start producing values + in contrast to the period samples needed by a regular EMA. - Pass desired moving average as argument. For example BBANDS(MA=TA.KAMA(20)). + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('TEMA') + return fn(data, timeperiod=period) - This method returns other variations and derivatives of BBANDS as well. - Bandwidth tells how wide the Bollinger Bands are on a normalized basis. +def TRIMA(data, period=30, price='close'): + """ + Triangular Moving Average (TRIMA or TMA) - %b (pronounced "percent b") is derived from the formula for Stochastics and shows where price is in relation to - the bands. + Represents an average of prices, but places weight on the middle prices of the time period. - %b equals 1 at the upper band and 0 at the lower band. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param float accel: acceleration factor - :param float max_accel: max acceleration factor - :return pd.Series: with indicator data calculation results with indicator data calculation results - """ - sar_list = [] - i = 0 + The calculations double-smooth the data using a window width that is one-half the length of the series. - while i < len(data['close']): - if i < 1: - sar = float('NaN') - sar_list.append(sar) - is_long = True - sar = data['low'][i] - ep = data['high'][i] - af = accel - else: - if is_long: - if data['low'][i] <= sar: - is_long = False - sar = ep - if sar < data['high'][i - 1]: - sar = data['high'][i - 1] - if sar < data['high'][i]: - sar = data['high'][i] - sar_list.append(sar) - af = accel - ep = data['low'][i] - sar = sar + af * (ep - sar) - # sar = round(sar) - if sar < data['high'][i - 1]: - sar = data['high'][i - 1] - if sar < data['high'][i]: - sar = data['high'][i] - else: - sar_list.append(sar) - if data['high'][i] > ep: - ep = data['high'][i] - af += accel - if af > max_accel: - af = max_accel - sar = sar + af * (ep - sar) - # sar = round(sar) - if sar > data['low'][i - 1]: - sar = data['low'][i - 1] - if sar > data['low'][i]: - sar = data['low'][i] - else: - if data['high'][i] >= sar: - is_long = True - sar = ep - if sar > data['low'][i - 1]: - sar = data['low'][i - 1] - if sar > data['low'][i]: - sar = data['low'][i] - sar_list.append(sar) - af = accel - ep = data['high'][i] - sar = sar + af * (ep - sar) - # sar = round(sar) - if sar > data['low'][i - 1]: - sar = data['low'][i - 1] - if sar > data['low'][i]: - sar = data['low'][i] - else: - sar_list.append(sar) - if data['low'][i] < ep: - ep = data['low'][i] - af += accel - if af > max_accel: - af = max_accel - sar = sar + af * (ep - sar) - # sar = round(sar) - if sar < data['high'][i - 1]: - sar = data['high'][i - 1] - if sar < data['high'][i]: - sar = data['high'][i] - i += 1 - return pd.Series(sar_list, 'SAR') - # return fn(data, acceleration=accel, maximum=max_accel) - - - @classmethod - def SAREXT(cls, data, start=0, offset_on_reverse=0, accel_init_long=0.02, accel_long=0.02, - accel_max_long=0.2, accel_init_short=0.02, accel_short=0.02, accel_max_short=0.2): - """ - Parabolic SAR - Extended - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param start: start value - :param int offset_on_reverse: offset on reverse - :param float accel_init_long: initial long acceleration factor - :param float accel_long: long acceleration factor - :param float accel_max_long: max long acceleration factor - :param float accel_init_short: initial short acceleration factor - :param float accel_short: short acceleration factor - :param float accel_max_short: max short acceleration factor - :return pd.Series: with indicator data calculation results with indicator data calculation results - """ - fn = Function('SAREXT') - return fn(data, startvalue=start, offsetonreverse=offset_on_reverse, accelerationinitlong=accel_init_long, - accelerationlong=accel_long, accelerationmaxlong=accel_max_long, - accelerationinitshort=accel_init_short, accelerationshort=accel_short, - accelerationmaxshort=accel_max_short) - - - @classmethod - def SMA(cls, data, period=25, price='close'): - """ - Simple Moving Average - - The simple moving average (SMA) is the most basic of the moving averages used for trading. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - sma = data[price].rolling(center=False, - window=period, - min_periods=period - 1).mean() - return pd.Series(sma, name='sma', index=data.index) - - - @classmethod - def T3(cls, data, period=5, v_factor=0.7): - """ - Triple Exponential Moving Average (T3) - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param float v_factor: v factor - :return pd.Series: with indicator data calculation results - """ - fn = Function('T3') - return fn(data, timeperiod=period, vfactor=v_factor) - - - @classmethod - def TEMA(cls, data, period=30): - """ - Triple exponential moving average - - Attempts to remove the inherent lag associated to Moving Averages by placing more weight on recent values. - - The name suggests this is achieved by applying a triple exponential smoothing which is not the case. - - The name triple comes from the fact that the value of an EMA (Exponential Moving Average) is triple. - - To keep it in line with the actual data and to remove the lag the value "EMA of EMA" is subtracted 3 times - from the previously tripled EMA. - - Finally "EMA of EMA of EMA" is added. - - Because EMA(EMA(EMA)) is used in the calculation, TEMA needs 3 * period - 2 samples to start producing values - in contrast to the period samples needed by a regular EMA. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('TEMA') - return fn(data, timeperiod=period) - - - @classmethod - def TRIMA(cls, data, period=30, price='close'): - """ - Triangular Moving Average (TRIMA or TMA) - - Represents an average of prices, but places weight on the middle prices of the time period. - - The calculations double-smooth the data using a window width that is one-half the length of the series. - - The TRIMA is simply the SMA of the SMA. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - tma_list = [] - sma_list = [] - i = 0 - while i < len(data[price]): - if n % 2 == 0: - n_sma = period / 2 + 1 - start = i + 1 - n_sma - end = i + 1 - sma = sum(data[price][start:end]) / n_sma - sma_list.append(sma) - n_tma = n / 2 - start = i + 1 - n_tma - end = i + 1 - else: - n_sma = (n + 1) / 2 - start = i + 1 - n_sma - end = i + 1 - sma = sum(data[price][start:end]) / n_sma - sma_list.append(sma) - n_tma = (period + 1) / 2 - start = i + 1 - n_tma - end = i + 1 - if i + 1 < period: - tma = float('NaN') - else: - tma = sum(sma_list[start:end]) / n_tma - tma_list.append(tma) - i += 1 - return pd.Series(tma_list, 'TRIMA_{:d}'.format(period)) + The TRIMA is simply the SMA of the SMA. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + tma_list = [] + sma_list = [] + i = 0 + while i < len(data[price]): + if period % 2 == 0: + n_sma = period / 2 + 1 + start = i + 1 - n_sma + end = i + 1 + sma = sum(data[price][start:end]) / n_sma + sma_list.append(sma) + n_tma = period / 2 + start = i + 1 - n_tma + end = i + 1 + else: + n_sma = (period + 1) / 2 + start = i + 1 - n_sma + end = i + 1 + sma = sum(data[price][start:end]) / n_sma + sma_list.append(sma) + n_tma = (period + 1) / 2 + start = i + 1 - n_tma + end = i + 1 + if i + 1 < period: + tma = float('NaN') + else: + tma = sum(sma_list[start:end]) / n_tma + tma_list.append(tma) + i += 1 + return pd.Series(tma_list, 'TRIMA_{:d}'.format(period)) + + +def WMA(data, period=30, price='close'): + """ + Weighted Moving Average - @classmethod - def WMA(cls, data, period=30, price='close'): - """ - Weighted Moving Average + It helps to smooth the price curve for better trend identification. - It helps to smooth the price curve for better trend identification. + HMA indicator is a common abbreviation of Hull Moving Average. - HMA indicator is a common abbreviation of Hull Moving Average. + The average was developed by Allan Hull and is used mainly to identify the current market trend. - The average was developed by Allan Hull and is used mainly to identify the current market trend. + Unlike SMA (simple moving average) the curve of Hull moving average is considerably smoother. - Unlike SMA (simple moving average) the curve of Hull moving average is considerably smoother. + Moreover, because its aim is to minimize the lag between HMA and price it does follow the price activity much + closer. - Moreover, because its aim is to minimize the lag between HMA and price it does follow the price activity much - closer. + It is used especially for middle-term and long-term trading. - It is used especially for middle-term and long-term trading. + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param str price: column used for indicator calculation (default = "close") + :return pd.Series: with indicator data calculation results + """ + wma_ = [] - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - wma_ = [] + for chunk in _chunks(data, period, price): + try: + wma_.append(_chunked_wma(chunk, period)) + except AttributeError: + wma_.append(None) - for chunk in cls._chunks(data, period, price): - try: - wma_.append(cls._chunked_wma(chunk, period)) - except AttributeError: - wma_.append(None) + wma_.reverse() + return pd.Series(wma_, index=data.index, name='wma') - wma_.reverse() - return pd.Series(wma_, index=data.index, name='wma') - # fn = Function('WMA') - # return fn(data, timeperiod=period) +def _chunks(data, period, price='close'): + """ + Create "n" chunks based on the number of periods. + :param pd.DataFrame data: + :param int period: + :param str price: column used for indicator calculation (default = "close") + :return: + """ + df_rev = data[price].iloc[::-1] - @classmethod - def _chunks(cls, df, - period, - col='close'): - """ - Create `n` chunks based on the number of periods. - :param df: - :param period: - :param col: - :return: - """ - df_rev = df[col].iloc[::-1] + for i in enumerate(df_rev): + chunk = df_rev.iloc[i[0]:i[0] + period] + if len(chunk) != period: + yield None + else: + yield chunk - for i in enumerate(df_rev): - chunk = df_rev.iloc[i[0]:i[0] + period] - if len(chunk) != period: - yield None - else: - yield chunk +def _chunked_wma(chunk, period): + """ - @classmethod - def _chunked_wma(cls, chunk, period): - denominator = (period * (period + 1)) / 2 + :param pd.DataFrame chunk: + :param int period: + :return float: + """ + denominator = (period * (period + 1)) / 2 - ma = [] + ma = [] - for price, i in zip(chunk.iloc[::-1].items(), - range(period + 1)[1:]): - ma.append(price[1] * (i / denominator)) + for price, i in zip(chunk.iloc[::-1].items(), + range(period + 1)[1:]): + ma.append(price[1] * (i / denominator)) - return sum(ma) + return sum(ma) diff --git a/techa/pattern.py b/techa/pattern.py index 4a7c397..2761b14 100644 --- a/techa/pattern.py +++ b/techa/pattern.py @@ -3,740 +3,709 @@ """ from talib.abstract import Function +__all__ = ['ABANDONED_BABY', 'ADVANCE_BLOCK', 'BELT_HOLD', 'BREAKAWAY', 'CLOSING_MARUBOZU', 'CONCEAL_BABY_SWALL', + 'COUNTER_ATTACK', 'DARK_CLOUD_COVER', 'DOJI', 'DOJI_STAR', 'DRAGON_FLY_DOJI', 'ENGULFING', + 'EVENING_DOJI_STAR', 'EVENING_STAR', 'Function', 'GAP_SIDE_SIDE_WHITE', 'GRAVESTONE_DOJI', 'HAMMER', + 'HANGING_MAN', 'HARAMI', 'HARAMI_CROSS', 'HIGH_WAVE', 'HIKKAKE', 'HIKKAKE_MOD', 'HOMING_PIGEON', + 'IDENTICAL_THREE_CROWS', 'INVERTED_HAMMER', 'IN_NECK', 'KICKING', 'KICKING_BY_LENGTH', 'LADDER_BOTTOM', + 'LONG_LEGGED_DOJI', 'LONG_LINE', 'MARUBOZU', 'MATCHING_LOW', 'MAT_HOLD', 'MORNING_DOJI_STAR', 'MORNING_STAR', + 'ON_NECK', 'PIERCING', 'RICK_SHAW_MAN', 'RISE_FALL_THREE_METHODS', 'SEPARATING_LINES', 'SHOOTING_STAR', + 'SHORT_LINE', 'SPINNING_TOP', 'STALLED_PATTERN', 'STICK_SANDWICH', 'TAKURI', 'TASUKI_GAP', + 'THREE_BLACK_CROWS', 'THREE_INSIDE', 'THREE_LINE_STRIKE', 'THREE_OUTSIDE', 'THREE_STARSINSOUTH', + 'THREE_WHITE_SOLDIERS', 'THRUSTING', 'TRISTAR', 'TWO_CROWS', 'UNIQUE_THREE_RIVER', 'UPSIDE_GAP_TWO_CROWS', + 'X_SIDE_GAP_THREE_METHODS', 'detect_pattern', 'get_pattern_list'] + + +def detect_pattern(pattern, data): + """ + Detect a candlestick pattern using a DataFrame. + + :param str pattern: name of pattern to be detected + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: for each DataFrame entry a 100, 0 or -100 will be returned + """ + fn = getattr(__import__(__name__), pattern) + return fn(data) + -class Pattern: +def get_pattern_list(): """ - Pattern Recognition + Get all supported patters names as list + :return list: patters names list """ + return [p for p in __all__ if p[0].isupper()] - @classmethod - def CDL2CROWS(cls, data): - """ - Two Crows +def TWO_CROWS(data): + """ + Two Crows - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL2CROWS') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL2CROWS') + return fn(data) - @classmethod - def CDL3BLACKCROWS(cls, data): - """ - Three Black Crows +def THREE_BLACK_CROWS(data): + """ + Three Black Crows - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3BLACKCROWS') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3BLACKCROWS') + return fn(data) - @classmethod - def CDL3INSIDE(cls, data): - """ - Three Inside Up/Down +def THREE_INSIDE(data): + """ + Three Inside Up/Down - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3INSIDE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3INSIDE') + return fn(data) - @classmethod - def CDL3LINESTRIKE(cls, data): - """ - Three-Line Strike +def THREE_LINE_STRIKE(data): + """ + Three-Line Strike - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3LINESTRIKE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3LINESTRIKE') + return fn(data) - @classmethod - def CDL3OUTSIDE(cls, data): - """ - Three Outside Up/Down +def THREE_OUTSIDE(data): + """ + Three Outside Up/Down - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3OUTSIDE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3OUTSIDE') + return fn(data) - @classmethod - def CDL3STARSINSOUTH(cls, data): - """ - Three Stars In The South - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3STARSINSOUTH') - return fn(data) +def THREE_STARSINSOUTH(data): + """ + Three Stars In The South + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3STARSINSOUTH') + return fn(data) - @classmethod - def CDL3WHITESOLDIERS(cls, data): - """ - Three Advancing White Soldiers +def THREE_WHITE_SOLDIERS(data): + """ + Three Advancing White Soldiers - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDL3WHITESOLDIERS') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDL3WHITESOLDIERS') + return fn(data) - @classmethod - def CDLABANDONEDBABY(cls, data): - """ - Abandoned Baby - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLABANDONEDBABY') - return fn(data) +def ABANDONED_BABY(data): + """ + Abandoned Baby + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLABANDONEDBABY') + return fn(data) - @classmethod - def CDLADVANCEBLOCK(cls, data): - """ - Advance Block - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLADVANCEBLOCK') - return fn(data) - - - @classmethod - def CDLBELTHOLD(cls, data): - """ - Belt-hold - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLBELTHOLD') - return fn(data) - - - @classmethod - def CDLBREAKAWAY(cls, data): - """ - Breakaway - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLBREAKAWAY') - return fn(data) - - - @classmethod - def CDLCLOSINGMARUBOZU(cls, data): - """ - Closing Marubozu - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLCLOSINGMARUBOZU') - return fn(data) - - - @classmethod - def CDLCONCEALBABYSWALL(cls, data): - """ - Concealing Baby Swallow - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLCONCEALBABYSWALL') - return fn(data) - - - @classmethod - def CDLCOUNTERATTACK(cls, data): - """ - Counterattack - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLCOUNTERATTACK') - return fn(data) - - - @classmethod - def CDLDARKCLOUDCOVER(cls, data): - """ - Dark Cloud Cover - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLDARKCLOUDCOVER') - return fn(data) - - - @classmethod - def CDLDOJI(cls, data): - """ - Doji - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLDOJI') - return fn(data) +def ADVANCE_BLOCK(data): + """ + Advance Block + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLADVANCEBLOCK') + return fn(data) - @classmethod - def CDLDOJISTAR(cls, data): - """ - Doji Star - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLDOJISTAR') - return fn(data) +def BELT_HOLD(data): + """ + Belt-hold - @classmethod - def CDLDRAGONFLYDOJI(cls, data): - """ - Dragon Fly Doji - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLDRAGONFLYDOJI') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLBELTHOLD') + return fn(data) - @classmethod - def CDLENGULFING(cls, data): - """ - Engulfing Pattern - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLENGULFING') - return fn(data) +def BREAKAWAY(data): + """ + Breakaway + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLBREAKAWAY') + return fn(data) - @classmethod - def CDLEVENINGDOJISTAR(cls, data): - """ - Evening Doji Star - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLEVENINGDOJISTRAR') - return fn(data) +def CLOSING_MARUBOZU(data): + """ + Closing Marubozu - @classmethod - def CDLEVENINGSTAR(cls, data): - """ - Evening Star - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLEVENINGSTAR') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLCLOSINGMARUBOZU') + return fn(data) - @classmethod - def CDLGAPSIDESIDEWHITE(cls, data): - """ - Gap Side +def CONCEAL_BABY_SWALL(data): + """ + Concealing Baby Swallow - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLGAPSIDESIDEWHITEITE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLCONCEALBABYSWALL') + return fn(data) - @classmethod - def CDLGRAVESTONEDOJI(cls, data): - """ - Gravestone Doji +def COUNTER_ATTACK(data): + """ + Counterattack - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLGRAVESTONEDOJII') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLCOUNTERATTACK') + return fn(data) - @classmethod - def CDLHAMMER(cls, data): - """ - Hammer +def DARK_CLOUD_COVER(data): + """ + Dark Cloud Cover - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHAMMER') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLDARKCLOUDCOVER') + return fn(data) - @classmethod - def CDLHANGINGMAN(cls, data): - """ - Hanging Man +def DOJI(data): + """ + Doji - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHANGINGMAN') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLDOJI') + return fn(data) - @classmethod - def CDLHARAMI(cls, data): - """ - Harami Patter +def DOJI_STAR(data): + """ + Doji Star - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHARAMI') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLDOJISTAR') + return fn(data) - @classmethod - def CDLHARAMICROSS(cls, data): - """ - Harami Cross Patter +def DRAGON_FLY_DOJI(data): + """ + Dragon Fly Doji - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHARAMICROSS') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLDRAGONFLYDOJI') + return fn(data) - @classmethod - def CDLHIGHWAVE(cls, data): - """ - High Wave Candle +def ENGULFING(data): + """ + Engulfing Pattern - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHIGHWAVE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLENGULFING') + return fn(data) - @classmethod - def CDLHIKKAKE(cls, data): - """ - Hikkake Pattern +def EVENING_DOJI_STAR(data): + """ + Evening Doji Star - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHIKKAKE') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLEVENINGDOJISTRAR') + return fn(data) - @classmethod - def CDLHIKKAKEMOD(cls, data): - """ - Modified Hikkake Pattern +def EVENING_STAR(data): + """ + Evening Star - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLEVENINGSTAR') + return fn(data) - fn = Function('CDLHIKKAKEMOD') - return fn(data) +def GAP_SIDE_SIDE_WHITE(data): + """ + Gap Side - @classmethod - def CDLHOMINGPIGEON(cls, data): - """ - Homing Pigeon + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLGAPSIDESIDEWHITEITE') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLHOMINGPIGEON') - return fn(data) +def GRAVESTONE_DOJI(data): + """ + Gravestone Doji - @classmethod - def CDLIDENTICAL3CROWS(cls, data): - """ - Identical 3 Crows + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLGRAVESTONEDOJII') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLIDENTICAL3CROWS') - return fn(data) +def HAMMER(data): + """ + Hammer - @classmethod - def CDLINNECK(cls, data): - """ - In-Neck Pattern + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHAMMER') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLINNECK') - return fn(data) +def HANGING_MAN(data): + """ + Hanging Man - @classmethod - def CDLINVERTEDHAMMER(cls, data): - """ - Inverted Hammer + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHANGINGMAN') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLINVERTEDHAMMER') - return fn(data) +def HARAMI(data): + """ + Harami Patter - @classmethod - def CDLKICKING(cls, data): - """ - Kicking + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHARAMI') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLKICKING') - return fn(data) +def HARAMI_CROSS(data): + """ + Harami Cross Patter - @classmethod - def CDLKICKINGBYLENGTH(cls, data): - """ - Kicking - bull/bear determined by the longer marubozu + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHARAMICROSS') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLKICKINGBYLENGTH') - return fn(data) +def HIGH_WAVE(data): + """ + High Wave Candle - @classmethod - def CDLLADDERBOTTOM(cls, data): - """ - Ladder Bottom + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHIGHWAVE') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLLADDERBOTTOM') - return fn(data) +def HIKKAKE(data): + """ + Hikkake Pattern - @classmethod - def CDLLONGLEGGEDDOJI(cls, data): - """ - Long Legged Doji + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHIKKAKE') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLLONGLEGGEDDOJI') - return fn(data) +def HIKKAKE_MOD(data): + """ + Modified Hikkake Pattern - @classmethod - def CDLLONGLINE(cls, data): - """ - Long Line Candle + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLLONGLINE') - return fn(data) + fn = Function('CDLHIKKAKEMOD') + return fn(data) - @classmethod - def CDLMARUBOZU(cls, data): - """ - Marubozu +def HOMING_PIGEON(data): + """ + Homing Pigeon - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLMARUBOZU') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLHOMINGPIGEON') + return fn(data) - @classmethod - def CDLMATCHINGLOW(cls, data): - """ - Matching Low +def IDENTICAL_THREE_CROWS(data): + """ + Identical 3 Crows - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLMATCHINGLOW') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLIDENTICAL3CROWS') + return fn(data) - @classmethod - def CDLMATHOLD(cls, data): - """ - Mat Hold +def IN_NECK(data): + """ + In-Neck Pattern - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLMATHOLD') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLINNECK') + return fn(data) - @classmethod - def CDLMORNINGDOJISTAR(cls, data): - """ - Morning Doji Star +def INVERTED_HAMMER(data): + """ + Inverted Hammer - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLMORNINGDOJISTAR') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLINVERTEDHAMMER') + return fn(data) - @classmethod - def CDLMORNINGSTAR(cls, data): - """ - Morning Star +def KICKING(data): + """ + Kicking - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLMORNINGSTAR') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLKICKING') + return fn(data) - @classmethod - def CDLONNECK(cls, data): - """ - On-Neck Pattern +def KICKING_BY_LENGTH(data): + """ + Kicking - bull/bear determined by the longer marubozu + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLKICKINGBYLENGTH') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLONNECK') - return fn(data) +def LADDER_BOTTOM(data): + """ + Ladder Bottom - @classmethod - def CDLPIERCING(cls, data): - """ - Piercing Pattern + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLLADDERBOTTOM') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLPIERCING') - return fn(data) +def LONG_LEGGED_DOJI(data): + """ + Long Legged Doji - @classmethod - def CDLRICKSHAWMAN(cls, data): - """ - Rickshaw Man + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLLONGLEGGEDDOJI') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLRICKSHAWMAN') - return fn(data) +def LONG_LINE(data): + """ + Long Line Candle - @classmethod - def CDLRISEFALL3METHODS(cls, data): - """ - Rising/Falling Three Methods + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLLONGLINE') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLRISEFALL3METHODS') - return fn(data) +def MARUBOZU(data): + """ + Marubozu - @classmethod - def CDLSEPARATINGLINES(cls, data): - """ - Separating Lines + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLMARUBOZU') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSEPARATINGLINES') - return fn(data) +def MATCHING_LOW(data): + """ + Matching Low - @classmethod - def CDLSHOOTINGSTAR(cls, data): - """ - Shooting Star + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLMATCHINGLOW') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSHOOTINGSTAR') - return fn(data) +def MAT_HOLD(data): + """ + Mat Hold - @classmethod - def CDLSHORTLINE(cls, data): - """ - Short Line Candle + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLMATHOLD') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSHORTLINE') - return fn(data) +def MORNING_DOJI_STAR(data): + """ + Morning Doji Star - @classmethod - def CDLSPINNINGTOP(cls, data): - """ - Spinning Top + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLMORNINGDOJISTAR') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSPINNINGTOP') - return fn(data) +def MORNING_STAR(data): + """ + Morning Star + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLMORNINGSTAR') + return fn(data) - @classmethod - def CDLSTALLEDPATTERN(cls, data): - """ - Stalled Pattern - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSTALLEDPATTERN') - return fn(data) +def ON_NECK(data): + """ + On-Neck Pattern - @classmethod - def CDLSTICKSANDWICH(cls, data): - """ - Stick Sandwich + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLONNECK') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLSTICKSANDWICH') - return fn(data) +def PIERCING(data): + """ + Piercing Pattern - @classmethod - def CDLTAKURI(cls, data): - """ - Takuri (Dragonfly Doji with very long lower shadow) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLPIERCING') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLTAKURI') - return fn(data) +def RICK_SHAW_MAN(data): + """ + Rickshaw Man - @classmethod - def CDLTASUKIGAP(cls, data): - """ - Tasuki Gap + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLRICKSHAWMAN') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLTASUKIGAP') - return fn(data) +def RISE_FALL_THREE_METHODS(data): + """ + Rising/Falling Three Methods - @classmethod - def CDLTHRUSTING(cls, data): - """ - Thrusting Pattern - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLTHRUSTING') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLRISEFALL3METHODS') + return fn(data) + + +def SEPARATING_LINES(data): + """ + Separating Lines + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSEPARATINGLINES') + return fn(data) - @classmethod - def CDLTRISTAR(cls, data): - """ - Tristar Pattern +def SHOOTING_STAR(data): + """ + Shooting Star - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLTRISTAR') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSHOOTINGSTAR') + return fn(data) - @classmethod - def CDLUNIQUE3RIVER(cls, data): - """ - Unique 3 River +def SHORT_LINE(data): + """ + Short Line Candle - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLUNIQUE3RIVER') - return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSHORTLINE') + return fn(data) - @classmethod - def CDLUPSIDEGAP2CROWS(cls, data): - """ +def SPINNING_TOP(data): + """ + Spinning Top + + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSPINNINGTOP') + return fn(data) + + +def STALLED_PATTERN(data): + """ + Stalled Pattern + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSTALLEDPATTERN') + return fn(data) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLUPSIDEGAP2CROWS') - return fn(data) - +def STICK_SANDWICH(data): + """ + Stick Sandwich + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLSTICKSANDWICH') + return fn(data) + + +def TAKURI(data): + """ + Takuri (Dragonfly Doji with very long lower shadow) + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLTAKURI') + return fn(data) + + +def TASUKI_GAP(data): + """ + Tasuki Gap + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLTASUKIGAP') + return fn(data) + + +def THRUSTING(data): + """ + Thrusting Pattern + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLTHRUSTING') + return fn(data) + + +def TRISTAR(data): + """ + Tristar Pattern + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLTRISTAR') + return fn(data) + + +def UNIQUE_THREE_RIVER(data): + """ + Unique 3 River + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLUNIQUE3RIVER') + return fn(data) + + +def UPSIDE_GAP_TWO_CROWS(data): + """ + + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLUPSIDEGAP2CROWS') + return fn(data) + + +def X_SIDE_GAP_THREE_METHODS(data): + """ + Upside/Downside Gap Three Methods + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + fn = Function('CDLXSIDEGAP3METHODS') + return fn(data) - @classmethod - def CDLXSIDEGAP3METHODS(cls, data): - """ - Upside/Downside Gap Three Methods - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - fn = Function('CDLXSIDEGAP3METHODS') - return fn(data) +if __name__ == '__main__': + print(dir(__import__(__name__))) diff --git a/techa/prices.py b/techa/prices.py index 74eb3e8..2459164 100644 --- a/techa/prices.py +++ b/techa/prices.py @@ -1,62 +1,79 @@ # -*- coding:utf-8 -*- +""" +Price transform functions -class Transform: - - @classmethod - def AVGPRICE(cls, data): - """ - Average Price - source: http://www.fmlabs.com/reference/default.htm?url=AvgPrices.htm - """ - avgprice_list = [] - i = 0 - while i < len(data['close']): - avgprice = (data['open'][i] + data['high'][i] + data['low'][i] + data['close'][i]) / 4 - avgprice_list.append(avgprice) - i += 1 - return avgprice_list - - - @classmethod - def MEDPRICE(cls, data): - """ - Median Price - source: http://www.fmlabs.com/reference/default.htm?url=MedianPrices.htm - """ - medprice_list = [] - i = 0 - while i < len(data['close']): - medprice = (data['high'][i] + data['low'][i]) / 2 - medprice_list.append(medprice) - i += 1 - return medprice_list - - - @classmethod - def TYPPRICE(cls, data): - """ - Typical Price - source: http://www.fmlabs.com/reference/default.htm?url=TypicalPrices.htm - """ - typprice_list = [] - i = 0 - while i < len(data['close']): - typprice = (data['high'][i] + data['low'][i] + data['close'][i]) / 3 - typprice_list.append(typprice) - i += 1 - return typprice_list - - - @classmethod - def WCLPRICE(cls, data): - """ - Weighted Close Price - source: http://www.fmlabs.com/reference/default.htm?url=WeightedCloses.htm - """ - wclprice_list = [] - i = 0 - while i < len(data['close']): - wclprice = (data['high'][i] + data['low'][i] + (data['close'][i] * 2)) / 4 - wclprice_list.append(wclprice) - i += 1 - return wclprice_list +References: + http://www.fmlabs.com/reference + http://www.fmlabs.com/reference/default.htm?url=TypicalPrices.htm + http://www.fmlabs.com/reference/default.htm?url=AvgPrices.htm + http://www.fmlabs.com/reference/default.htm?url=MedianPrices.htm + http://www.fmlabs.com/reference/default.htm?url=WeightedCloses.htm + +""" +import pandas as pd + +__all__ = ['AVGPRICE', 'WCLPRICE', 'TYPPRICE', 'MEDPRICE'] + + +def AVGPRICE(data): + """ + Average Price. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + avgprice_list = [] + i = 0 + while i < len(data['close']): + avgprice = (data['open'][i] + data['high'][i] + data['low'][i] + data['close'][i]) / 4 + avgprice_list.append(avgprice) + i += 1 + return pd.Series(avgprice_list, name='AVGPRICE') + + +def MEDPRICE(data): + """ + Median Price + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + medprice_list = [] + i = 0 + while i < len(data['close']): + medprice = (data['high'][i] + data['low'][i]) / 2 + medprice_list.append(medprice) + i += 1 + return pd.Series(medprice_list, name='MIDPRICE') + + +def TYPPRICE(data): + """ + Typical Price + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + typprice_list = [] + i = 0 + while i < len(data['close']): + typprice = (data['high'][i] + data['low'][i] + data['close'][i]) / 3 + typprice_list.append(typprice) + i += 1 + return pd.Series(typprice_list, name='TYPPRICE') + + +def WCLPRICE(data): + """ + Weighted Close Price. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + wclprice_list = [] + i = 0 + while i < len(data['close']): + wclprice = (data['high'][i] + data['low'][i] + (data['close'][i] * 2)) / 4 + wclprice_list.append(wclprice) + i += 1 + return pd.Series(wclprice_list, name='WCLPRICE') diff --git a/techa/statistic.py b/techa/statistic.py index c27a7df..f3c0c80 100644 --- a/techa/statistic.py +++ b/techa/statistic.py @@ -1,131 +1,118 @@ +# -*- coding:utf-8 -*- """ Statistic Functions """ import pandas as pd -from talib.abstract import * +from talib.abstract import Function +__all__ = ['BETA', 'CORREL', 'LINEARREG', 'LINEARREG_ANGLE', 'LINEARREG_INTERCEPT', 'LINEARREG_SLOPE'] -class Statistic: + +def BETA(data, period=5): """ - Statistic Functions + Beta function + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results """ + fn = Function('BETA') + return fn(data, timeperiod=period) - @classmethod - def BETA(cls, data, period=5): - """ - Beta function +def CORREL(data, period=30): + """ + Pearson's Correlation Coefficient (r) - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('BETA') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('CORREL') + return fn(data, timeperiod=period) - @classmethod - def CORREL(cls, data, period=30): - """ - Pearson's Correlation Coefficient (r) +def LINEARREG(data, period=14): + """ + Linear Regression - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('CORREL') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('LINEARREG') + return fn(data, timeperiod=period) - @classmethod - def LINEARREG(cls, data, period=14): - """ - Linear Regression +def LINEARREG_ANGLE(data, period=14): + """ + Linear Regression Angle - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('LINEARREG') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('LINEARREG_ANGLE') + return fn(data, timeperiod=period) - @classmethod - def LINEARREG_ANGLE(cls, data, period=14): - """ - Linear Regression Angle +def LINEARREG_INTERCEPT(data, period=14): + """ + Linear Regression Intercept - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('LINEARREG_ANGLE') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('LINEARREG_INTERCEPT') + return fn(data, timeperiod=period) - @classmethod - def LINEARREG_INTERCEPT(cls, data, period=14): - """ - Linear Regression Intercept +def LINEARREG_SLOPE(data, period=14): + """ + Linear Regression Slope - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('LINEARREG_INTERCEPT') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('LINEARREG_SLOPE') + return fn(data, timeperiod=period) - @classmethod - def LINEARREG_SLOPE(cls, data, period=14): - """ - Linear Regression Slope +def STDDEV(data, period=5, nbdev=1): + """ + Standard Derivation - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('LINEARREG_SLOPE') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param float, int nbdev: deviation + :return pd.Series: with indicator data calculation results + """ + fn = Function('STDDEV') + return fn(data, timeperiod=period, nbdev=nbdev) - @classmethod - def STDDEV(cls, data, period=5, nbdev=1): - """ - Standard Derivation +def TSF(data, period=14): + """ + Time Series Forecast - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param float, int nbdev: deviation - :return pd.Series: with indicator data calculation results - """ - fn = Function('STDDEV') - return fn(data, timeperiod=period, nbdev=nbdev) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('TSF') + return fn(data, timeperiod=period) - @classmethod - def TSF(cls, data, period=14): - """ - Time Series Forecast - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('TSF') - return fn(data, timeperiod=period) - - - @classmethod - def VAR(cls, data, period=5, nbdev=1): - """ - Variance - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int period: period used for indicator calculation - :param float, int nbdev: deviation - :return pd.Series: with indicator data calculation results - """ - fn = Function('VAR') - return fn(data, timeperiod=period, nbdev=nbdev) +def VAR(data, period=5, nbdev=1): + """ + Variance + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :param float, int nbdev: deviation + :return pd.Series: with indicator data calculation results + """ + fn = Function('VAR') + return fn(data, timeperiod=period, nbdev=nbdev) diff --git a/techa/volatility.py b/techa/volatility.py index 0d5eecc..532bfbc 100644 --- a/techa/volatility.py +++ b/techa/volatility.py @@ -1,85 +1,75 @@ +# -*- coding: utf-8 -*- """ Volatility Indicators """ import pandas as pd from talib.abstract import * - -class Volatility: - """ - Volatility Indicators - """ +__all__ = ['ATR', 'NATR', 'TRANGE'] - @classmethod - def ATR(cls, data, period=14): - """ - Average True Range +def ATR(data, period=14): + """ + Average True Range - ATR is moving average of True Range. + ATR is moving average of True Range. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data( - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - tr_list = cls.TRANGE(data) - atr_list = [] - i = 0 - while i < len(data['close']): - if i + 1 < period: - atr = float('NaN') - else: - atr = ((tr_list[i - 1] * (period - 1)) + tr_list[i]) / period - atr_list.append(atr) - i += 1 - return pd.Series(atr_list, name='ATR') - # fn = Function('ATR') - # return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + tr_list = TRANGE(data) + atr_list = [] + i = 0 + while i < len(data['close']): + if i + 1 < period: + atr = float('NaN') + else: + atr = ((tr_list[i - 1] * (period - 1)) + tr_list[i]) / period + atr_list.append(atr) + i += 1 + return pd.Series(atr_list, name='ATR') - @classmethod - def NATR(cls, data, period=14): - """ - Normalized Average True Range +def NATR(data, period=14): + """ + Normalized Average True Range - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data( - :param int period: period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('NATR') - return fn(data, timeperiod=period) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int period: period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('NATR') + return fn(data, timeperiod=period) - @classmethod - def TRANGE(cls, data): - """ - True Range - TR or TRANGE is the maximum of three price ranges. +def TRANGE(data): + """ + True Range + TR or TRANGE is the maximum of three price ranges. - Most recent period's high minus the most recent period's low. + Most recent period's high minus the most recent period's low. - Absolute value of the most recent period's high minus the previous close. + Absolute value of the most recent period's high minus the previous close. - Absolute value of the most recent period's low minus the previous close. + Absolute value of the most recent period's low minus the previous close. - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data( - :return pd.Series: with indicator data calculation results - """ - tr_list = [] - i = 0 - while i < len(data['close']): - if i < 1: - tr = float('NaN') - else: - true_high = data['high'][i] - if data['close'][i - 1] > data['high'][i]: - true_high = data['close'][i - 1] - true_low = data['low'][i] - if data['close'][i - 1] < data['low'][i]: - true_low = data['close'][i - 1] - tr = true_high - true_low - tr_list.append(tr) - i += 1 - return pd.Series(tr_list, name='TRANGE') - # fn = Function('TRANGE') - # return fn(data) + :param pd.DataFrame data: pandas DataFrame with open, high, low, close, data + :return pd.Series: with indicator data calculation results. + """ + tr_list = [] + i = 0 + while i < len(data['close']): + if i < 1: + tr = float('NaN') + else: + true_high = data['high'][i] + if data['close'][i - 1] > data['high'][i]: + true_high = data['close'][i - 1] + true_low = data['low'][i] + if data['close'][i - 1] < data['low'][i]: + true_low = data['close'][i - 1] + tr = true_high - true_low + tr_list.append(tr) + i += 1 + return pd.Series(tr_list, name='TRANGE') diff --git a/techa/volume.py b/techa/volume.py index 9759ebd..3584835 100644 --- a/techa/volume.py +++ b/techa/volume.py @@ -5,91 +5,90 @@ from finta import TA from talib.abstract import Function +__all__ = ['AD', 'WOBV', 'ADOSC', 'OBV'] -class Volume: + +# +# class Volume: +# """ +# Volume Indicators +# """ + + +def AD(data): + """ + Accumulation Distribution Line Indicator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + ad_list = [] + i = 0 + while i < len(data['close']): + ad = 0 + if i > 0: + clv = ((data['close'][i] - data['low'][i]) - (data['high'][i] - data['close'][i])) / ( + data['high'][i] - data['low'][i]) + ad = ad_list[i - 1] + clv * data['volume'][i] + ad_list.append(ad) + i += 1 + return pd.Series(ad_list, name='AD') + + +def WOBV(data): + """ + Weighted On Balance Volume + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + + return TA.WOBV(data) + + +def ADOSC(data, fast_period=3, slow_period=10): """ - Volume Indicators + Accumulation/Distribution Oscillator + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :param int fast_period: fast period used for indicator calculation + :param int slow_period: slow period used for indicator calculation + :return pd.Series: with indicator data calculation results + """ + fn = Function('ADOSC') + return fn(data, fastperiod=fast_period, slowperiod=slow_period) + + +def OBV(data): """ + On Balance Volume + + OBV measures buying and selling pressure as a cumulative indicator that adds volume on up days and subtracts + volume on down days. + + OBV was developed by Joe Granville and introduced in his 1963 book, Granville's New Key to Stock Market Profits. + It was one of the first indicators to measure positive and negative volume flow. - @classmethod - def AD(cls, data): - """ - Accumulation Distribution Line Indicator - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - ad_list = [] - i = 0 - while i < len(data['close']): - ad = 0 - if i > 0: - clv = ((data['close'][i] - data['low'][i]) - (data['high'][i] - data['close'][i])) / ( - data['high'][i] - data['low'][i]) - ad = ad_list[i - 1] + clv * data['volume'][i] - ad_list.append(ad) - i += 1 - return pd.Series(ad_list, name='AD') - - - @classmethod - def WOBV(cls, data): - """ - Weighted On Balance Volume - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - - return TA.WOBV(data) - - - @classmethod - def ADOSC(cls, data, fast_period=3, slow_period=10): - """ - Accumulation/Distribution Oscillator - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :param int fast_period: fast period used for indicator calculation - :param int slow_period: slow period used for indicator calculation - :return pd.Series: with indicator data calculation results - """ - fn = Function('ADOSC') - return fn(data, fastperiod=fast_period, slowperiod=slow_period) - - - @classmethod - def OBV(cls, data): - """ - On Balance Volume - - OBV measures buying and selling pressure as a cumulative indicator that adds volume on up days and subtracts - volume on down days. - - OBV was developed by Joe Granville and introduced in his 1963 book, Granville's New Key to Stock Market Profits. - - It was one of the first indicators to measure positive and negative volume flow. - - Chartists can look for divergences between OBV and price to predict price movements or use OBV to confirm price - trends. - - :param pd.DataFrame data: pandas DataFrame with open, high, low, close data - :return pd.Series: with indicator data calculation results - """ - obv_list = [] - i = 0 - while i < len(data['close']): - obv = 0 - if i > 0: - if data['close'][i] > data['close'][i - 1]: - obv = obv_list[i - 1] + data['volume'][i] - elif data['close'][i] < data['close'][i - 1]: - obv = obv_list[i - 1] - data['volume'][i] - else: - obv = obv_list[i - 1] - obv_list.append(obv) - i += 1 - return pd.Series(obv_list, name='OBV') - # fn = Function('OBV') - # return fn(data) + Chartists can look for divergences between OBV and price to predict price movements or use OBV to confirm price + trends. + + :param pd.DataFrame data: pandas DataFrame with open, high, low, close data + :return pd.Series: with indicator data calculation results + """ + obv_list = [] + i = 0 + while i < len(data['close']): + obv = 0 + if i > 0: + if data['close'][i] > data['close'][i - 1]: + obv = obv_list[i - 1] + data['volume'][i] + elif data['close'][i] < data['close'][i - 1]: + obv = obv_list[i - 1] - data['volume'][i] + else: + obv = obv_list[i - 1] + obv_list.append(obv) + i += 1 + return pd.Series(obv_list, name='OBV') + # fn = Function('OBV') + # return fn(data)