formatting fixes, PEP8 etc

This commit is contained in:
James Sawyer
2020-10-01 16:18:01 +01:00
parent 60b6cc42f6
commit 99973f3611
153 changed files with 3599 additions and 1740 deletions
+33 -37
View File
@@ -16,18 +16,16 @@
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'pandas_ta'
copyright = '2019, Kevin Johnson'
author = 'Kevin Johnson'
project = "pandas_ta"
copyright = "2019, Kevin Johnson"
author = "Kevin Johnson"
# The short X.Y version
version = '0.0.1'
version = "0.0.1"
# The full version, including alpha/beta/rc tags
release = 'alpha'
release = "alpha"
# -- General configuration ---------------------------------------------------
@@ -39,22 +37,22 @@ release = 'alpha'
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.todo',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
"sphinx.ext.todo",
"sphinx.ext.mathjax",
"sphinx.ext.viewcode",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -66,18 +64,17 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -88,7 +85,7 @@ html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -100,12 +97,10 @@ html_static_path = ['_static']
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'pandas_tadoc'
htmlhelp_basename = "pandas_tadoc"
# -- Options for LaTeX output ------------------------------------------------
@@ -113,15 +108,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -131,20 +123,20 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'pandas_ta.tex', 'pandas\\_ta Documentation',
'Kevin Johnson', 'manual'),
(
master_doc,
"pandas_ta.tex",
"pandas\\_ta Documentation",
"Kevin Johnson",
"manual",
),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pandas_ta', 'pandas_ta Documentation',
[author], 1)
]
man_pages = [(master_doc, "pandas_ta", "pandas_ta Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
@@ -152,12 +144,17 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'pandas_ta', 'pandas_ta Documentation',
author, 'pandas_ta', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"pandas_ta",
"pandas_ta Documentation",
author,
"pandas_ta",
"One line description of project.",
"Miscellaneous",
),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
@@ -173,8 +170,7 @@ epub_title = project
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
+34 -18
View File
@@ -4,12 +4,13 @@ import datetime as dt
from pathlib import Path
from random import random
import pandas as pd # pip install pandas
import pandas as pd # pip install pandas
import yfinance as yf
# yf.pdr_override() # <== that's all it takes :-)
import alphaVantageAPI as AV # pip install alphaVantage-api
import pandas_ta as ta # pip install pandas_ta
import alphaVantageAPI as AV # pip install alphaVantage-api
import pandas_ta as ta # pip install pandas_ta
def colors(colors: str = None, default: str = "GrRd"):
@@ -17,17 +18,14 @@ def colors(colors: str = None, default: str = "GrRd"):
# Pairs
"GrRd": ["green", "red"],
"RdGr": ["red", "green"],
"BkGy": ["black", "gray"],
"BkSv": ["black", "silver"],
"BkPr": ["black", "purple"],
"BkBl": ["black", "blue"],
"GyBk": ["gray", "black"],
"GySv": ["gray", "silver"],
"GyPr": ["gray", "purple"],
"GyBl": ["gray", "blue"],
"SvGy": ["silver", "gray"],
"FcLi": ["fuchsia", "lime"],
# Triples
@@ -69,6 +67,7 @@ class Watchlist(object):
## Required Arguments:
- tickers: A list of strings containing tickers. Example: ["SPY", "AAPL"]
"""
def __init__(
self,
tickers: list,
@@ -76,14 +75,15 @@ class Watchlist(object):
name: str = None,
strategy: ta.Strategy = None,
ds: object = None,
**kwargs
**kwargs,
):
self.verbose = kwargs.pop("verbose", False)
self.debug = kwargs.pop("debug", False)
self.tickers = tickers
self.tf = tf
self.name = name if isinstance(name, str) else f"Watch: {', '.join(tickers)}"
self.name = name if isinstance(name,
str) else f"Watch: {', '.join(tickers)}"
self.data = None
self.kwargs = kwargs
self.strategy = strategy
@@ -96,12 +96,23 @@ class Watchlist(object):
elif isinstance(ds, str) and ds.lower() == "yahoo":
self.ds = yf
else:
AVkwargs = {"api_key": "YOUR API KEY", "clean": True, "export": True, "export_path": ".", "output_size": "full", "premium": False}
AVkwargs = {
"api_key": "YOUR API KEY",
"clean": True,
"export": True,
"export_path": ".",
"output_size": "full",
"premium": False,
}
self.av_kwargs = self.kwargs.pop("av_kwargs", AVkwargs)
self.file_path = self.av_kwargs["export_path"]
self.ds = AV.AlphaVantage(**self.av_kwargs)
def _drop_columns(self, df: pd.DataFrame, cols: list = ["Unnamed: 0", "date", "split_coefficient", "dividend"]):
def _drop_columns(
self,
df: pd.DataFrame,
cols: list = ["Unnamed: 0", "date", "split_coefficient", "dividend"],
):
"""Helper methods to drop columns silently."""
df_columns = list(df.columns)
if any(_ in df_columns for _ in cols):
@@ -113,8 +124,11 @@ class Watchlist(object):
def _load_all(self, **kwargs) -> dict:
"""Updates the Watchlist's data property with a dictionary of DataFrames
keyed by ticker."""
if self.tickers is not None and isinstance(self.tickers, list) and len(self.tickers):
self.data = {ticker: self.load(ticker, **kwargs) for ticker in self.tickers}
if (self.tickers is not None and isinstance(self.tickers, list) and
len(self.tickers)):
self.data = {
ticker: self.load(ticker, **kwargs) for ticker in self.tickers
}
return self.data
def load(
@@ -123,7 +137,7 @@ class Watchlist(object):
tf: str = None,
index: str = "date",
drop: list = ["dividend", "split_coefficient"],
**kwargs
**kwargs,
) -> pd.DataFrame:
"""Loads or Downloads (if a local csv does not exist) the data from the
Data Source. When successful, it returns a Data Frame for the requested
@@ -163,10 +177,11 @@ class Watchlist(object):
df = self._drop_columns(df)
if kwargs.pop("analyze", True):
if self.debug: print(f"[+] TA[{len(self.strategy.ta)}]: {self.strategy.name}")
if self.debug:
print(f"[+] TA[{len(self.strategy.ta)}]: {self.strategy.name}")
df.ta.strategy(self.strategy, **kwargs)
df.ticker = ticker # Attach ticker to the DataFrame
df.ticker = ticker # Attach ticker to the DataFrame
return df
@property
@@ -178,7 +193,8 @@ class Watchlist(object):
def data(self, value: dict) -> None:
# Later check dict has string keys and DataFrame values
if value is not None and isinstance(value, dict):
if self.verbose: print(f"[+] New data")
if self.verbose:
print(f"[+] New data")
self._data = value
else:
self._data = None
@@ -205,7 +221,7 @@ class Watchlist(object):
if value is not None and isinstance(value, ta.Strategy):
self._strategy = value
else:
self._strategy = ta.CommonStrategy
self._strategy = ta.CommonStrategy
@property
def tf(self) -> str:
@@ -262,4 +278,4 @@ class Watchlist(object):
if self.data is not None:
s += f", data[{len(self.data.keys())}])"
return s
return s + ")"
return s + ")"
+141 -23
View File
@@ -19,6 +19,7 @@ else:
__version__ = _dist.version
from importlib.util import find_spec
Imports = {
"scipy": find_spec("scipy") is not None,
"sklearn": find_spec("sklearn") is not None,
@@ -26,7 +27,7 @@ Imports = {
"mplfinance": find_spec("mplfinance") is not None,
"alphaVantage-api ": find_spec("alphaVantageAPI") is not None,
"yfinance": find_spec("yfinance") is not None,
"talib": find_spec("talib") is not None
"talib": find_spec("talib") is not None,
}
# Not ideal and not dynamic but it works.
@@ -34,43 +35,160 @@ Imports = {
Category = {
# Candles
"candles": ["cdl_doji", "cdl_inside", "ha"],
# Momentum
"momentum": ["ao", "apo", "bias", "bop", "brar", "cci", "cfo", "cg", "cmo", "coppock", "er", "eri", "fisher", "inertia", "kdj", "kst", "macd", "mom", "pgo", "ppo", "psl", "pvo", "roc", "rsi", "rvgi", "slope", "smi", "squeeze", "stoch", "stochrsi", "trix", "tsi", "uo", "willr"],
"momentum": [
"ao",
"apo",
"bias",
"bop",
"brar",
"cci",
"cfo",
"cg",
"cmo",
"coppock",
"er",
"eri",
"fisher",
"inertia",
"kdj",
"kst",
"macd",
"mom",
"pgo",
"ppo",
"psl",
"pvo",
"roc",
"rsi",
"rvgi",
"slope",
"smi",
"squeeze",
"stoch",
"stochrsi",
"trix",
"tsi",
"uo",
"willr",
],
# Overlap
"overlap": ["dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku", "kama", "linreg", "midpoint", "midprice", "ohlc4", "pwma", "rma", "sinwma", "sma", "supertrend", "swma", "t3", "tema", "trima", "vwap", "vwma", "wcp", "wma", "zlma"],
"overlap": [
"dema",
"ema",
"fwma",
"hilo",
"hl2",
"hlc3",
"hma",
"ichimoku",
"kama",
"linreg",
"midpoint",
"midprice",
"ohlc4",
"pwma",
"rma",
"sinwma",
"sma",
"supertrend",
"swma",
"t3",
"tema",
"trima",
"vwap",
"vwma",
"wcp",
"wma",
"zlma",
],
# Performance
"performance": ["log_return", "percent_return", "trend_return"],
# Statistics
"statistics": ["entropy", "kurtosis", "mad", "median", "quantile", "skew", "stdev", "variance", "zscore"],
"statistics": [
"entropy",
"kurtosis",
"mad",
"median",
"quantile",
"skew",
"stdev",
"variance",
"zscore",
],
# Trend
"trend": ["adx", "amat", "aroon", "chop", "cksp", "decay", "decreasing", "dpo", "increasing", "long_run", "psar", "qstick", "short_run", "ttm_trend", "vortex"],
"trend": [
"adx",
"amat",
"aroon",
"chop",
"cksp",
"decay",
"decreasing",
"dpo",
"increasing",
"long_run",
"psar",
"qstick",
"short_run",
"ttm_trend",
"vortex",
],
# Volatility
"volatility": ["aberration", "accbands", "atr", "bbands", "donchian", "kc", "massi", "natr", "pdist", "rvi", "true_range", "ui"],
"volatility": [
"aberration",
"accbands",
"atr",
"bbands",
"donchian",
"kc",
"massi",
"natr",
"pdist",
"rvi",
"true_range",
"ui",
],
# Volume, "vp" or "Volume Profile" is unique
"volume": ["ad", "adosc", "aobv", "cmf", "efi", "eom", "mfi", "nvi", "obv", "pvi", "pvol", "pvt"],
"volume": [
"ad",
"adosc",
"aobv",
"cmf",
"efi",
"eom",
"mfi",
"nvi",
"obv",
"pvi",
"pvol",
"pvt",
],
}
# https://www.worldtimezone.com/markets24.php
EXCHANGE_TZ = {
"NZSX": 12, "ASX": 11,
"TSE": 9, "HKE": 8, "SSE": 8, "SGX": 8,
"NSE": 5.5, "DIFX": 4, "RTS": 3,
"JSE": 2, "FWB": 1, "LSE": 1,
"BMF": -2, "NYSE": -4, "TSX": -4
"NZSX": 12,
"ASX": 11,
"TSE": 9,
"HKE": 8,
"SSE": 8,
"SGX": 8,
"NSE": 5.5,
"DIFX": 4,
"RTS": 3,
"JSE": 2,
"FWB": 1,
"LSE": 1,
"BMF": -2,
"NYSE": -4,
"TSX": -4,
}
RATE = {
"TRADING_DAYS_PER_YEAR": 252, # Keep even
"TRADING_DAYS_PER_YEAR": 252, # Keep even
"TRADING_HOURS_PER_DAY": 6.5,
"MINUTES_PER_HOUR": 60
"MINUTES_PER_HOUR": 60,
}
from pandas_ta.core import *
from pandas_ta.core import *
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
from .ha import ha
from .cdl_doji import cdl_doji
from .cdl_inside import cdl_inside
from .cdl_inside import cdl_inside
+14 -3
View File
@@ -3,7 +3,19 @@ from pandas_ta.overlap import sma
from pandas_ta.utils import get_offset, high_low_range, is_percent
from pandas_ta.utils import non_zero_range, real_body, verify_series
def cdl_doji(open_, high, low, close, length=None, factor=None, scalar=None, asint=True, offset=None, **kwargs):
def cdl_doji(
open_,
high,
low,
close,
length=None,
factor=None,
scalar=None,
asint=True,
offset=None,
**kwargs,
):
"""Candle Type: Doji"""
# Validate Arguments
open_ = verify_series(open_)
@@ -44,8 +56,7 @@ def cdl_doji(open_, high, low, close, length=None, factor=None, scalar=None, asi
return doji
cdl_doji.__doc__ = \
"""Candle Type: Doji
cdl_doji.__doc__ = """Candle Type: Doji
A candle body is Doji, when it's shorter than 10% of the
average of the 10 previous candles' high-low range.
+26 -27
View File
@@ -3,42 +3,41 @@ from pandas import DataFrame, set_option
from pandas_ta.utils import candle_color, get_drift, get_offset
from pandas_ta.utils import non_zero_range, real_body, verify_series
def cdl_inside(open_, high, low, close, asbool=False, offset=None, **kwargs):
"""Candle Type: Inside Bar"""
# Validate arguments
open_ = verify_series(open_)
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
offset = get_offset(offset)
"""Candle Type: Inside Bar"""
# Validate arguments
open_ = verify_series(open_)
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
offset = get_offset(offset)
# Calculate Result
inside = (high.diff() < 0) & (low.diff() > 0)
# Calculate Result
inside = (high.diff() < 0) & (low.diff() > 0)
if not asbool:
inside *= candle_color(open_, close)
if not asbool:
inside *= candle_color(open_, close)
# Offset
if offset != 0:
inside = inside.shift(offset)
# Offset
if offset != 0:
inside = inside.shift(offset)
# Handle fills
if "fillna" in kwargs:
inside.fillna(kwargs["fillna"], inplace=True)
# Handle fills
if "fillna" in kwargs:
inside.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
inside.fillna(method=kwargs["fill_method"], inplace=True)
if "fill_method" in kwargs:
inside.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
inside.name = f"CDL_INSIDE"
inside.category = "candles"
return inside
# Name and Categorize it
inside.name = f"CDL_INSIDE"
inside.category = "candles"
return inside
cdl_inside.__doc__ = \
"""Candle Type: Inside Bar
cdl_inside.__doc__ = """Candle Type: Inside Bar
An Inside Bar is a bar that is engulfed by the prior highs and lows of it's
previous bar. In other words, the current bar is smaller than it's previous bar.
+3 -4
View File
@@ -19,7 +19,7 @@ def ha(open_, high, low, close, offset=None, **kwargs):
"HA_open": 0.5 * (open_.iloc[0] + close.iloc[0]),
"HA_high": high,
"HA_low": low,
"HA_close": 0.25 * (open_ + high + low + close)
"HA_close": 0.25 * (open_ + high + low + close),
})
for i in range(1, m):
@@ -45,8 +45,7 @@ def ha(open_, high, low, close, offset=None, **kwargs):
return df
ha.__doc__ = \
"""Heikin Ashi Candles (HA)
ha.__doc__ = """Heikin Ashi Candles (HA)
The Heikin-Ashi technique averages price data to create a Japanese
candlestick chart that filters out market noise. Heikin-Ashi charts,
@@ -55,7 +54,7 @@ with standard candlestick charts but differ based on the values used
to create each candle. Instead of using the open, high, low, and close
like standard candlestick charts, the Heikin-Ashi technique uses a
modified formula based on two-period averages. This gives the chart a
smoother appearance, making it easier to spots trends and reversals,
smoother appearance, making it easier to spots trends and reversals,
but also obscures gaps and some price data.
Sources:
+1309 -401
View File
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def ao(high, low, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Awesome Oscillator (AO)"""
# Validate Arguments
@@ -10,7 +11,8 @@ def ao(high, low, fast=None, slow=None, offset=None, **kwargs):
slow = int(slow) if slow and slow > 0 else 34
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else fast)
offset = get_offset(offset)
# Calculate Result
@@ -24,21 +26,19 @@ def ao(high, low, fast=None, slow=None, offset=None, **kwargs):
ao = ao.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ao.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ao.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
ao.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
ao.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
ao.name = f"AO_{fast}_{slow}"
ao.category = 'momentum'
ao.category = "momentum"
return ao
ao.__doc__ = \
"""Awesome Oscillator (AO)
ao.__doc__ = """Awesome Oscillator (AO)
The Awesome Oscillator is an indicator used to measure a security's momentum.
AO is generally used to affirm trends or to anticipate possible reversals.
@@ -67,4 +67,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+9 -9
View File
@@ -2,6 +2,7 @@
from pandas_ta.overlap import sma
from pandas_ta.utils import get_offset, verify_series
def apo(close, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Absolute Price Oscillator (APO)"""
# Validate Arguments
@@ -10,7 +11,8 @@ def apo(close, fast=None, slow=None, offset=None, **kwargs):
slow = int(slow) if slow and slow > 0 else 26
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else fast)
offset = get_offset(offset)
# Calculate Result
@@ -23,21 +25,19 @@ def apo(close, fast=None, slow=None, offset=None, **kwargs):
apo = apo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
apo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
apo.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
apo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
apo.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
apo.name = f"APO_{fast}_{slow}"
apo.category = 'momentum'
apo.category = "momentum"
return apo
apo.__doc__ = \
"""Absolute Price Oscillator (APO)
apo.__doc__ = """Absolute Price Oscillator (APO)
The Absolute Price Oscillator is an indicator used to measure a security's
momentum. It is simply the difference of two Exponential Moving Averages
+14 -15
View File
@@ -6,6 +6,7 @@ from ..overlap.rma import rma
from ..overlap.wma import wma
from ..utils import get_offset, verify_series, zero
def bias(close, length=None, mamode=None, offset=None, **kwargs):
"""Indicator: Bias (BIAS)"""
# Validate Arguments
@@ -15,15 +16,15 @@ def bias(close, length=None, mamode=None, offset=None, **kwargs):
offset = get_offset(offset)
# Calculate Result
if mamode is None or mamode == 'sma':
if mamode is None or mamode == "sma":
ma = sma(close, length=length, **kwargs)
if mamode == 'ema':
if mamode == "ema":
ma = ema(close, length=length, **kwargs)
if mamode == 'hma':
if mamode == "hma":
ma = hma(close, length=length, **kwargs)
if mamode == 'rma':
if mamode == "rma":
ma = rma(close, length=length, **kwargs)
if mamode == 'wma':
if mamode == "wma":
ma = wma(close, length=length, **kwargs)
bias = (close / ma) - 1
@@ -33,21 +34,19 @@ def bias(close, length=None, mamode=None, offset=None, **kwargs):
bias = bias.shift(offset)
# Handle fills
if 'fillna' in kwargs:
bias.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
bias.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
bias.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
bias.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
bias.name = f"BIAS_{ma.name}"
bias.category = 'momentum'
bias.category = "momentum"
return bias
bias.__doc__ = \
"""Bias (BIAS)
bias.__doc__ = """Bias (BIAS)
Rate of change between the source and a moving average.
@@ -58,7 +57,7 @@ Sources:
Calculation:
Default Inputs:
length=26, MA='sma'
BIAS = (close - MA(close, length)) / MA(close, length)
= (close / MA(close, length)) - 1
@@ -75,4 +74,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, non_zero_range, verify_series
def bop(open_, high, low, close, scalar=None, offset=None, **kwargs):
"""Indicator: Balance of Power (BOP)"""
# Validate Arguments
@@ -33,9 +34,7 @@ def bop(open_, high, low, close, scalar=None, offset=None, **kwargs):
return bop
bop.__doc__ = \
"""Balance of Power (BOP)
bop.__doc__ = """Balance of Power (BOP)
Balance of Power measure the market strength of buyers against sellers.
@@ -59,4 +58,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+22 -15
View File
@@ -2,7 +2,16 @@
from pandas import DataFrame
from ..utils import get_drift, get_offset, non_zero_range, verify_series
def brar(open_, high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs):
def brar(open_,
high,
low,
close,
length=None,
scalar=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: BRAR (BRAR)"""
# Validate Arguments
open_ = verify_series(open_)
@@ -20,8 +29,8 @@ def brar(open_, high, low, close, length=None, scalar=None, drift=None, offset=N
hcy = non_zero_range(high, close.shift(drift))
cyl = non_zero_range(close.shift(drift), low)
hcy[hcy < 0] = 0 # Zero negative values
cyl[cyl < 0] = 0 # ""
hcy[hcy < 0] = 0 # Zero negative values
cyl[cyl < 0] = 0 # ""
ar = scalar * high_open_range.rolling(length).sum()
ar /= open_low_range.rolling(length).sum()
@@ -35,30 +44,28 @@ def brar(open_, high, low, close, length=None, scalar=None, drift=None, offset=N
br = ar.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ar.fillna(kwargs['fillna'], inplace=True)
br.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ar.fillna(method=kwargs['fill_method'], inplace=True)
br.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
ar.fillna(kwargs["fillna"], inplace=True)
br.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
ar.fillna(method=kwargs["fill_method"], inplace=True)
br.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_props = f"_{length}"
ar.name = f"AR{_props}"
br.name = f"BR{_props}"
ar.category = br.category = 'momentum'
ar.category = br.category = "momentum"
# Prepare DataFrame to return
brardf = DataFrame({ar.name: ar, br.name: br})
brardf.name = f"BRAR{_props}"
brardf.category = 'momentum'
brardf.category = "momentum"
return brardf
brar.__doc__ = \
"""BRAR (BRAR)
brar.__doc__ = """BRAR (BRAR)
BR and AR
@@ -96,4 +103,4 @@ Kwargs:
Returns:
pd.DataFrame: ar, br columns.
"""
"""
+8 -9
View File
@@ -4,6 +4,7 @@ from ..overlap.sma import sma
from ..statistics.mad import mad
from ..utils import get_offset, verify_series
def cci(high, low, close, length=None, c=None, offset=None, **kwargs):
"""Indicator: Commodity Channel Index (CCI)"""
# Validate Arguments
@@ -27,21 +28,19 @@ def cci(high, low, close, length=None, c=None, offset=None, **kwargs):
cci = cci.shift(offset)
# Handle fills
if 'fillna' in kwargs:
cci.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
cci.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
cci.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
cci.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
cci.name = f"CCI_{length}_{c}"
cci.category = 'momentum'
cci.category = "momentum"
return cci
cci.__doc__ = \
"""Commodity Channel Index (CCI)
cci.__doc__ = """Commodity Channel Index (CCI)
Commodity Channel Index is a momentum oscillator used to primarily identify
overbought and oversold levels relative to a mean.
@@ -73,4 +72,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -4
View File
@@ -2,6 +2,7 @@
from pandas_ta.overlap import linreg
from pandas_ta.utils import get_drift, get_offset, verify_series
def cfo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
"""Indicator: Chande Forcast Oscillator (CFO)"""
# Validate Arguments
@@ -11,8 +12,8 @@ def cfo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
drift = get_drift(drift)
offset = get_offset(offset)
#Finding linear regression of Series
cfo = scalar * (close - linreg(close, length=length, tsf=True))
# Finding linear regression of Series
cfo = scalar * (close - linreg(close, length=length, tsf=True))
cfo /= close
# Offset
@@ -31,8 +32,8 @@ def cfo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
return cfo
cfo.__doc__ = \
"""Chande Forcast Oscillator (CFO)
cfo.__doc__ = """Chande Forcast Oscillator (CFO)
The Forecast Oscillator calculates the percentage difference between the actual
price and the Time Series Forecast (the endpoint of a linear regression line).
+7 -8
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series, weights
def cg(close, length=None, offset=None, **kwargs):
"""Indicator: Center of Gravity (CG)"""
# Validate Arguments
@@ -18,21 +19,19 @@ def cg(close, length=None, offset=None, **kwargs):
cg = cg.shift(offset)
# Handle fills
if 'fillna' in kwargs:
cg.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
cg.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
cg.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
cg.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
cg.name = f"CG_{length}"
cg.category = 'momentum'
cg.category = "momentum"
return cg
cg.__doc__ = \
"""Center of Gravity (CG)
cg.__doc__ = """Center of Gravity (CG)
The Center of Gravity Indicator by John Ehlers attempts to identify turning
points while exhibiting zero lag and smoothing.
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_drift, get_offset, verify_series
def cmo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
"""Indicator: Chande Momentum Oscillator (CMO)"""
# Validate Arguments
@@ -45,9 +46,7 @@ def cmo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
return cmo
cmo.__doc__ = \
"""Chande Momentum Oscillator (CMO)
cmo.__doc__ = """Chande Momentum Oscillator (CMO)
Attempts to capture the momentum of an asset with overbought at 50 and
oversold at -50.
@@ -75,4 +74,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -10
View File
@@ -4,6 +4,7 @@ from ..overlap.rma import rma
from ..overlap.wma import wma
from ..utils import get_offset, verify_series
def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Coppock Curve (COPC)"""
# Validate Arguments
@@ -11,7 +12,8 @@ def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs):
length = int(length) if length and length > 0 else 10
fast = int(fast) if fast and fast > 0 else 11
slow = int(slow) if slow and slow > 0 else 14
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -23,21 +25,19 @@ def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs):
coppock = coppock.shift(offset)
# Handle fills
if 'fillna' in kwargs:
coppock.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
coppock.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
coppock.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
coppock.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
coppock.name = f"COPC_{fast}_{slow}_{length}"
coppock.category = 'momentum'
coppock.category = "momentum"
return coppock
coppock.__doc__ = \
"""Coppock Curve (COPC)
coppock.__doc__ = """Coppock Curve (COPC)
Coppock Curve (originally called the "Trendex Model") is a momentum indicator
is designed for use on a monthly time scale. Although designed for monthly
@@ -71,4 +71,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+17 -20
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame, concat
from pandas_ta.overlap import rma
from pandas_ta.utils import get_drift, get_offset, verify_series, signals
def er(close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Efficiency Ratio (ER)"""
# Validate arguments
@@ -23,35 +24,33 @@ def er(close, length=None, drift=None, offset=None, **kwargs):
er = er.shift(offset)
# Handle fills
if 'fillna' in kwargs:
er.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
er.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
er.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
er.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
er.name = f"ER_{length}"
er.category = "momentum"
signal_indicators = kwargs.pop('signal_indicators', False)
signal_indicators = kwargs.pop("signal_indicators", False)
if signal_indicators:
signalsdf = concat(
[
DataFrame(
{er.name: er}
),
DataFrame({er.name: er}),
signals(
indicator=er,
xa=kwargs.pop('xa', 80),
xb=kwargs.pop('xb', 20),
xserie=kwargs.pop('xserie', None),
xserie_a=kwargs.pop('xserie_a', None),
xserie_b=kwargs.pop('xserie_b', None),
cross_values=kwargs.pop('cross_values', False),
cross_series=kwargs.pop('cross_series', True),
xa=kwargs.pop("xa", 80),
xb=kwargs.pop("xb", 20),
xserie=kwargs.pop("xserie", None),
xserie_a=kwargs.pop("xserie_a", None),
xserie_b=kwargs.pop("xserie_b", None),
cross_values=kwargs.pop("cross_values", False),
cross_series=kwargs.pop("cross_series", True),
offset=offset,
),
],
axis=1
axis=1,
)
return signalsdf
@@ -59,9 +58,7 @@ def er(close, length=None, drift=None, offset=None, **kwargs):
return er
er.__doc__ = \
"""Efficiency Ratio (ER)
er.__doc__ = """Efficiency Ratio (ER)
The Efficiency Ratio was invented by Perry J. Kaufman and presented in his book "New Trading Systems and Methods". It is designed to account for market noise or volatility.
@@ -91,4 +88,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -11
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame
from pandas_ta.overlap import ema
from pandas_ta.utils import get_offset, verify_series
def eri(high, low, close, length=None, offset=None, **kwargs):
"""Indicator: Elder Ray Index (ERI)"""
# Validate arguments
@@ -23,12 +24,12 @@ def eri(high, low, close, length=None, offset=None, **kwargs):
bear = bear.shift(offset)
# Handle fills
if 'fillna' in kwargs:
bull.fillna(kwargs['fillna'], inplace=True)
bear.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
bull.fillna(method=kwargs['fill_method'], inplace=True)
bear.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
bull.fillna(kwargs["fillna"], inplace=True)
bear.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
bull.fillna(method=kwargs["fill_method"], inplace=True)
bear.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
bull.name = f"BULLP_{length}"
@@ -44,9 +45,7 @@ def eri(high, low, close, length=None, offset=None, **kwargs):
return df
eri.__doc__ = \
"""Elder Ray Index (ERI)
eri.__doc__ = """Elder Ray Index (ERI)
Elder's Bulls Ray Index contains his Bull and Bear Powers. Which are useful ways
to look at the price and see the strength behind the market. Bull Power
@@ -56,7 +55,7 @@ consensus of value.
Bears Power measures the capability of sellers, to drag prices below an average
consensus of value. Using them in tandem with a measure of trend allows you to
identify favourable entry points. We hope you've found this to be a useful
discussion of the Bulls and Bears Power indicators.
discussion of the Bulls and Bears Power indicators.
Sources:
https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator
@@ -82,4 +81,4 @@ Kwargs:
Returns:
pd.DataFrame: bull power and bear power columns.
"""
"""
+7 -6
View File
@@ -5,6 +5,7 @@ from pandas import DataFrame, Series
from pandas_ta.overlap import ema, hl2
from pandas_ta.utils import get_offset, high_low_range, verify_series, zero
def fisher(high, low, length=None, signal=None, offset=None, **kwargs):
"""Indicator: Fisher Transform (FISHT)"""
# Validate Arguments
@@ -29,8 +30,10 @@ def fisher(high, low, length=None, signal=None, offset=None, **kwargs):
result = [npNaN for _ in range(0, length - 1)] + [0]
for i in range(length, m):
v = 0.66 * position[i] + 0.67 * v
if v < -0.99: v = -0.999
if v > 0.99: v = 0.999
if v < -0.99:
v = -0.999
if v > 0.99:
v = 0.999
result.append(0.5 * (nplog((1 + v) / (1 - v)) + result[i - 1]))
fisher = Series(result, index=high.index)
signalma = fisher.shift(signal)
@@ -63,9 +66,7 @@ def fisher(high, low, length=None, signal=None, offset=None, **kwargs):
return df
fisher.__doc__ = \
"""Fisher Transform (FISHT)
fisher.__doc__ = """Fisher Transform (FISHT)
Attempts to identify significant price reversals by normalizing prices over a
user-specified number of periods. A reversal signal is suggested when the the
@@ -110,4 +111,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+39 -11
View File
@@ -3,7 +3,21 @@ from pandas_ta.overlap import linreg
from pandas_ta.volatility import rvi
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
def inertia(close=None, high=None, low=None, length=None, rvi_length=None, scalar=None, refined=None, thirds=None, mamode=None, drift=None, offset=None, **kwargs):
def inertia(
close=None,
high=None,
low=None,
length=None,
rvi_length=None,
scalar=None,
refined=None,
thirds=None,
mamode=None,
drift=None,
offset=None,
**kwargs,
):
"""Indicator: Inertia (INERTIA)"""
# Validate Arguments
close = verify_series(close)
@@ -22,10 +36,26 @@ def inertia(close=None, high=None, low=None, length=None, rvi_length=None, scala
# Calculate Result
_mode = ""
if refined:
rvi_ = rvi(close, high=high, low=low, length=rvi_length, scalar=scalar, refined=refined, mamode=mamode)
rvi_ = rvi(
close,
high=high,
low=low,
length=rvi_length,
scalar=scalar,
refined=refined,
mamode=mamode,
)
_mode = "r"
elif thirds:
rvi_ = rvi(close, high=high, low=low, length=rvi_length, scalar=scalar, thirds=thirds, mamode=mamode)
rvi_ = rvi(
close,
high=high,
low=low,
length=rvi_length,
scalar=scalar,
thirds=thirds,
mamode=mamode,
)
_mode = "t"
else:
rvi_ = rvi(close, length=rvi_length, scalar=scalar, mamode=mamode)
@@ -37,10 +67,10 @@ def inertia(close=None, high=None, low=None, length=None, rvi_length=None, scala
inertia = inertia.shift(offset)
# Handle fills
if 'fillna' in kwargs:
inertia.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
inertia.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
inertia.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
inertia.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
_props = f"_{length}_{rvi_length}"
@@ -50,9 +80,7 @@ def inertia(close=None, high=None, low=None, length=None, rvi_length=None, scala
return inertia
inertia.__doc__ = \
"""Inertia (INERTIA)
inertia.__doc__ = """Inertia (INERTIA)
Inertia was developed by Donald Dorsey and was introduced his article
in September, 1995. It is the Relative Vigor Index smoothed by the Least
@@ -85,4 +113,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+22 -16
View File
@@ -3,7 +3,14 @@ from pandas import DataFrame
from ..overlap.rma import rma
from ..utils import get_offset, non_zero_range, verify_series
def kdj(high=None, low=None, close=None, length=None, signal=None, offset=None, **kwargs):
def kdj(high=None,
low=None,
close=None,
length=None,
signal=None,
offset=None,
**kwargs):
"""Indicator: KDJ (KDJ)"""
# Validate Arguments
high = verify_series(high)
@@ -17,7 +24,8 @@ def kdj(high=None, low=None, close=None, length=None, signal=None, offset=None,
highest_high = high.rolling(length).max()
lowest_low = low.rolling(length).min()
fastk = 100 * (close - lowest_low) / non_zero_range(highest_high, lowest_low)
fastk = 100 * (close - lowest_low) / non_zero_range(highest_high,
lowest_low)
k = rma(fastk, length=signal)
d = rma(k, length=signal)
@@ -30,33 +38,31 @@ def kdj(high=None, low=None, close=None, length=None, signal=None, offset=None,
j = j.shift(offset)
# Handle fills
if 'fillna' in kwargs:
k.fillna(kwargs['fillna'], inplace=True)
d.fillna(kwargs['fillna'], inplace=True)
j.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
k.fillna(method=kwargs['fill_method'], inplace=True)
d.fillna(method=kwargs['fill_method'], inplace=True)
j.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
k.fillna(kwargs["fillna"], inplace=True)
d.fillna(kwargs["fillna"], inplace=True)
j.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
k.fillna(method=kwargs["fill_method"], inplace=True)
d.fillna(method=kwargs["fill_method"], inplace=True)
j.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_params = f"_{length}_{signal}"
k.name = f"K{_params}"
d.name = f"D{_params}"
j.name = f"J{_params}"
k.category = d.category = j.category = 'momentum'
k.category = d.category = j.category = "momentum"
# Prepare DataFrame to return
kdjdf = DataFrame({k.name: k, d.name: d, j.name: j})
kdjdf.name = f"KDJ{_params}"
kdjdf.category = 'momentum'
kdjdf.category = "momentum"
return kdjdf
kdj.__doc__ = \
"""KDJ (KDJ)
kdj.__doc__ = """KDJ (KDJ)
The KDJ indicator is actually a derived form of the Slow
Stochastic with the only difference being an extra line
@@ -94,4 +100,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+24 -11
View File
@@ -3,7 +3,22 @@ from pandas import DataFrame
from .roc import roc
from ..utils import get_drift, get_offset, verify_series
def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None, sma3=None, sma4=None, signal=None, drift=None, offset=None, **kwargs):
def kst(
close,
roc1=None,
roc2=None,
roc3=None,
roc4=None,
sma1=None,
sma2=None,
sma3=None,
sma4=None,
signal=None,
drift=None,
offset=None,
**kwargs,
):
"""Indicator: 'Know Sure Thing' (KST)"""
# Validate arguments
close = verify_series(close)
@@ -36,12 +51,12 @@ def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None,
kst_signal = kst_signal.shift(offset)
# Handle fills
if 'fillna' in kwargs:
kst.fillna(kwargs['fillna'], inplace=True)
kst_signal.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
kst.fillna(method=kwargs['fill_method'], inplace=True)
kst_signal.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
kst.fillna(kwargs["fillna"], inplace=True)
kst_signal.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
kst.fillna(method=kwargs["fill_method"], inplace=True)
kst_signal.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
kst.name = f"KST_{roc1}_{roc2}_{roc3}_{roc4}_{sma1}_{sma2}_{sma3}_{sma4}"
@@ -57,9 +72,7 @@ def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None,
return kstdf
kst.__doc__ = \
"""'Know Sure Thing' (KST)
kst.__doc__ = """'Know Sure Thing' (KST)
The 'Know Sure Thing' is a momentum based oscillator and based on ROC.
@@ -101,4 +114,4 @@ Kwargs:
Returns:
pd.DataFrame: kst and kst_signal columns
"""
"""
+4 -5
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame, concat
from ..overlap.ema import ema
from ..utils import get_offset, verify_series, signals
def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
"""Indicator: Moving Average, Convergence/Divergence (MACD)"""
# Validate arguments
@@ -79,7 +80,7 @@ def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
offset=offset,
),
],
axis=1
axis=1,
)
return signalsdf
@@ -87,9 +88,7 @@ def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
return df
macd.__doc__ = \
"""Moving Average Convergence Divergence (MACD)
macd.__doc__ = """Moving Average Convergence Divergence (MACD)
The MACD is a popular indicator to that is used to identify a security's trend.
While APO and MACD are the same calculation, MACD also returns two more series
@@ -120,4 +119,4 @@ Kwargs:
Returns:
pd.DataFrame: macd, histogram, signal columns.
"""
"""
+8 -9
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def mom(close, length=None, offset=None, **kwargs):
"""Indicator: Momentum (MOM)"""
# Validate Arguments
@@ -16,21 +17,19 @@ def mom(close, length=None, offset=None, **kwargs):
mom = mom.shift(offset)
# Handle fills
if 'fillna' in kwargs:
mom.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
mom.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
mom.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
mom.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
mom.name = f"MOM_{length}"
mom.category = 'momentum'
mom.category = "momentum"
return mom
mom.__doc__ = \
"""Momentum (MOM)
mom.__doc__ = """Momentum (MOM)
Momentum is an indicator used to measure a security's speed (or strength) of
movement. Or simply the change in price.
@@ -54,4 +53,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+7 -8
View File
@@ -3,6 +3,7 @@ from pandas_ta.overlap import ema, sma
from pandas_ta.volatility import atr
from pandas_ta.utils import get_offset, verify_series
def pgo(high, low, close, length=None, offset=None, **kwargs):
"""Indicator: Pretty Good Oscillator (PGO)"""
# Validate arguments
@@ -21,10 +22,10 @@ def pgo(high, low, close, length=None, offset=None, **kwargs):
pgo = pgo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
pgo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
pgo.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
pgo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
pgo.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
pgo.name = f"PGO_{length}"
@@ -33,9 +34,7 @@ def pgo(high, low, close, length=None, offset=None, **kwargs):
return pgo
pgo.__doc__ = \
"""Pretty Good Oscillator (PGO)
pgo.__doc__ = """Pretty Good Oscillator (PGO)
The Pretty Good Oscillator indicator was created by Mark Johnson to measure the distance of the current close from its N-day Simple Moving Average, expressed in terms of an average true range over a similar period. Johnson's approach was to
use it as a breakout system for longer term trades. Long if greater than 3.0 and
@@ -66,4 +65,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+20 -14
View File
@@ -3,7 +3,14 @@ from pandas import DataFrame
from pandas_ta.overlap import ema, sma
from pandas_ta.utils import get_offset, verify_series
def ppo(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
def ppo(close,
fast=None,
slow=None,
signal=None,
scalar=None,
offset=None,
**kwargs):
"""Indicator: Percentage Price Oscillator (PPO)"""
# Validate Arguments
close = verify_series(close)
@@ -13,7 +20,8 @@ def ppo(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kw
scalar = float(scalar) if scalar else 100
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else fast)
offset = get_offset(offset)
# Calculate Result
@@ -32,14 +40,14 @@ def ppo(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kw
signalma = signalma.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ppo.fillna(kwargs['fillna'], inplace=True)
histogram.fillna(kwargs['fillna'], inplace=True)
signalma.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ppo.fillna(method=kwargs['fill_method'], inplace=True)
histogram.fillna(method=kwargs['fill_method'], inplace=True)
signalma.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
ppo.fillna(kwargs["fillna"], inplace=True)
histogram.fillna(kwargs["fillna"], inplace=True)
signalma.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
ppo.fillna(method=kwargs["fill_method"], inplace=True)
histogram.fillna(method=kwargs["fill_method"], inplace=True)
signalma.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_props = f"_{fast}_{slow}_{signal}"
@@ -57,9 +65,7 @@ def ppo(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kw
return df
ppo.__doc__ = \
"""Percentage Price Oscillator (PPO)
ppo.__doc__ = """Percentage Price Oscillator (PPO)
The Percentage Price Oscillator is similar to MACD in measuring momentum.
@@ -91,4 +97,4 @@ Kwargs:
Returns:
pd.DataFrame: ppo, histogram, signal columns
"""
"""
+16 -11
View File
@@ -2,7 +2,14 @@
from numpy import sign as npSign
from ..utils import get_drift, get_offset, verify_series
def psl(close, open_=None, length=None, scalar=None, drift=None, offset=None, **kwargs):
def psl(close,
open_=None,
length=None,
scalar=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: Psychological Line (PSL)"""
# Validate Arguments
close = verify_series(close)
@@ -19,7 +26,7 @@ def psl(close, open_=None, length=None, scalar=None, drift=None, offset=None, **
diff = npSign(close.diff(drift))
diff.fillna(0, inplace=True)
diff[diff <= 0] = 0 # Zero negative values
diff[diff <= 0] = 0 # Zero negative values
psl = scalar * diff.rolling(length).sum()
psl /= length
@@ -29,22 +36,20 @@ def psl(close, open_=None, length=None, scalar=None, drift=None, offset=None, **
psl = psl.shift(offset)
# Handle fills
if 'fillna' in kwargs:
psl.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
psl.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
psl.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
psl.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_props = f"_{length}"
psl.name = f"PSL{_props}"
psl.category = 'momentum'
psl.category = "momentum"
return psl
psl.__doc__ = \
"""Psychological Line (PSL)
psl.__doc__ = """Psychological Line (PSL)
The Psychological Line is an oscillator-type indicator that compares the
number of the rising periods to the total number of periods. In other
@@ -82,4 +87,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+17 -12
View File
@@ -3,7 +3,14 @@ from pandas import DataFrame
from pandas_ta.overlap import ema
from pandas_ta.utils import get_offset, verify_series
def pvo(volume, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
def pvo(volume,
fast=None,
slow=None,
signal=None,
scalar=None,
offset=None,
**kwargs):
"""Indicator: Percentage Volume Oscillator (PVO)"""
# Validate Arguments
volume = verify_series(volume)
@@ -31,14 +38,14 @@ def pvo(volume, fast=None, slow=None, signal=None, scalar=None, offset=None, **k
signalma = signalma.shift(offset)
# Handle fills
if 'fillna' in kwargs:
pvo.fillna(kwargs['fillna'], inplace=True)
histogram.fillna(kwargs['fillna'], inplace=True)
signalma.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
pvo.fillna(method=kwargs['fill_method'], inplace=True)
histogram.fillna(method=kwargs['fill_method'], inplace=True)
signalma.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
pvo.fillna(kwargs["fillna"], inplace=True)
histogram.fillna(kwargs["fillna"], inplace=True)
signalma.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
pvo.fillna(method=kwargs["fill_method"], inplace=True)
histogram.fillna(method=kwargs["fill_method"], inplace=True)
signalma.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_props = f"_{fast}_{slow}_{signal}"
@@ -56,9 +63,7 @@ def pvo(volume, fast=None, slow=None, signal=None, scalar=None, offset=None, **k
return df
pvo.__doc__ = \
"""Percentage Volume Oscillator (PVO)
pvo.__doc__ = """Percentage Volume Oscillator (PVO)
Percentage Volume Oscillator is a Momentum Oscillator for Volume.
+10 -10
View File
@@ -2,12 +2,14 @@
from .mom import mom
from ..utils import get_offset, verify_series
def roc(close, length=None, offset=None, **kwargs):
"""Indicator: Rate of Change (ROC)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -18,21 +20,19 @@ def roc(close, length=None, offset=None, **kwargs):
roc = roc.shift(offset)
# Handle fills
if 'fillna' in kwargs:
roc.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
roc.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
roc.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
roc.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
roc.name = f"ROC_{length}"
roc.category = 'momentum'
roc.category = "momentum"
return roc
roc.__doc__ = \
"""Rate of Change (ROC)
roc.__doc__ = """Rate of Change (ROC)
Rate of Change is an indicator is also referred to as Momentum (yeah, confusingly).
It is a pure momentum oscillator that measures the percent change in price with the
@@ -58,4 +58,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+4 -5
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame, concat
from pandas_ta.overlap import rma
from pandas_ta.utils import get_drift, get_offset, verify_series, signals
def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
"""Indicator: Relative Strength Index (RSI)"""
# Validate arguments
@@ -55,7 +56,7 @@ def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
offset=offset,
),
],
axis=1
axis=1,
)
return signalsdf
@@ -63,9 +64,7 @@ def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
return rsi
rsi.__doc__ = \
"""Relative Strength Index (RSI)
rsi.__doc__ = """Relative Strength Index (RSI)
The Relative Strength Index is popular momentum oscillator used to measure the
velocity as well as the magnitude of directional price movements.
@@ -100,4 +99,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+19 -13
View File
@@ -3,7 +3,15 @@ from pandas import DataFrame
from pandas_ta.overlap import swma
from pandas_ta.utils import get_offset, non_zero_range, verify_series
def rvgi(open_, high, low, close, length=None, swma_length=None, offset=None, **kwargs):
def rvgi(open_,
high,
low,
close,
length=None,
swma_length=None,
offset=None,
**kwargs):
"""Indicator: Relative Vigor Index (RVGI)"""
# Validate Arguments
open_ = verify_series(open_)
@@ -19,7 +27,7 @@ def rvgi(open_, high, low, close, length=None, swma_length=None, offset=None, **
# Calculate Result
numerator = swma(close_open_range, length=swma_length).rolling(length).sum()
denominator = swma(high_low_range, length=swma_length).rolling(length).sum()
rvgi = numerator / denominator
signal = swma(rvgi, length=swma_length)
@@ -29,12 +37,12 @@ def rvgi(open_, high, low, close, length=None, swma_length=None, offset=None, **
signal = signal.shift(offset)
# Handle fills
if 'fillna' in kwargs:
rvgi.fillna(kwargs['fillna'], inplace=True)
signal.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
rvgi.fillna(method=kwargs['fill_method'], inplace=True)
signal.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
rvgi.fillna(kwargs["fillna"], inplace=True)
signal.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
rvgi.fillna(method=kwargs["fill_method"], inplace=True)
signal.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
rvgi.name = f"RVGI_{length}_{swma_length}"
@@ -49,12 +57,10 @@ def rvgi(open_, high, low, close, length=None, swma_length=None, offset=None, **
return df
rvgi.__doc__ = \
"""Relative Vigor Index (RVGI)
rvgi.__doc__ = """Relative Vigor Index (RVGI)
The Relative Vigor Index attempts to measure the strength of a trend relative to
its closing price to its trading range. It is based on the belief that it tends
its closing price to its trading range. It is based on the belief that it tends
to close higher than they open in uptrends or close lower than they open in
downtrends.
@@ -84,4 +90,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+14 -6
View File
@@ -2,7 +2,16 @@
from math import atan, pi
from pandas_ta.utils import get_offset, verify_series
def slope(close, length=None, as_angle=None, to_degrees=None, vertical=None, offset=None, **kwargs):
def slope(
close,
length=None,
as_angle=None,
to_degrees=None,
vertical=None,
offset=None,
**kwargs,
):
"""Indicator: Slope"""
# Validate arguments
close = verify_series(close)
@@ -29,15 +38,14 @@ def slope(close, length=None, as_angle=None, to_degrees=None, vertical=None, off
slope.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
slope.name = f"SLOPE_{length}" if not as_angle else f"ANGLE{'d' if to_degrees else 'r'}_{length}"
slope.name = (f"SLOPE_{length}" if not as_angle else
f"ANGLE{'d' if to_degrees else 'r'}_{length}")
slope.category = "momentum"
return slope
slope.__doc__ = \
"""Slope
slope.__doc__ = """Slope
Returns the slope of a series of length n. Can convert the slope to angle. Default: slope.
@@ -66,4 +74,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -5
View File
@@ -4,7 +4,14 @@ from .tsi import tsi
from pandas_ta.overlap import ema
from pandas_ta.utils import get_offset, verify_series, signals
def smi(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
def smi(close,
fast=None,
slow=None,
signal=None,
scalar=None,
offset=None,
**kwargs):
"""Indicator: SMI Ergodic Indicator (SMIIO)"""
# Validate arguments
close = verify_series(close)
@@ -54,9 +61,7 @@ def smi(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kw
return df
smi.__doc__ = \
"""SMI Ergodic Indicator (SMI)
smi.__doc__ = """SMI Ergodic Indicator (SMI)
The SMI Ergodic Indicator is the same as the True Strength Index (TSI) developed
by William Blau, except the SMI includes a signal line. The SMI uses double
@@ -95,4 +100,4 @@ Kwargs:
Returns:
pd.DataFrame: smi, signal, oscillator columns.
"""
"""
+30 -11
View File
@@ -10,7 +10,21 @@ from pandas_ta.volatility import bbands, kc, true_range
from pandas_ta.utils import get_drift, get_offset, high_low_range
from pandas_ta.utils import unsigned_differences, verify_series
def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_scalar=None, mom_length=None, mom_smooth=None, use_tr=None, offset=None, **kwargs):
def squeeze(
high,
low,
close,
bb_length=None,
bb_std=None,
kc_length=None,
kc_scalar=None,
mom_length=None,
mom_smooth=None,
use_tr=None,
offset=None,
**kwargs,
):
"""Indicator: Squeeze Momentum (SQZ)"""
# Validate arguments
high = verify_series(high)
@@ -19,7 +33,7 @@ def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_sc
offset = get_offset(offset)
bb_length = int(bb_length) if bb_length and bb_length > 0 else 20
bb_std = float(bb_std) if bb_std and bb_std > 0 else 2.
bb_std = float(bb_std) if bb_std and bb_std > 0 else 2.0
kc_length = int(kc_length) if kc_length and kc_length > 0 else 20
kc_scalar = float(kc_scalar) if kc_scalar and kc_scalar > 0 else 1.5
mom_length = int(mom_length) if mom_length and mom_length > 0 else 12
@@ -33,11 +47,17 @@ def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_sc
def simplify_columns(df, n=3):
df.columns = df.columns.str.lower()
return [c.split('_')[0][n-1:n] for c in df.columns]
return [c.split("_")[0][n - 1:n] for c in df.columns]
# Calculate Result
bbd = bbands(close, length=bb_length, std=bb_std, mamode=mamode)
kch = kc(high, low, close, length=kc_length, scalar=kc_scalar, mamode=mamode, tr=use_tr)
kch = kc(high,
low,
close,
length=kc_length,
scalar=kc_scalar,
mamode=mamode,
tr=use_tr)
# Simplify KC and BBAND column names for dynamic access
bbd.columns = simplify_columns(bbd)
@@ -45,8 +65,8 @@ def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_sc
if lazybear:
highest_high = high.rolling(kc_length).max()
lowest_low = low.rolling(kc_length).min()
avg_ = 0.25 * (highest_high + lowest_low) + 0.5 * kch.b
lowest_low = low.rolling(kc_length).min()
avg_ = 0.25 * (highest_high + lowest_low) + 0.5 * kch.b
squeeze = linreg(close - avg_, length=kc_length)
@@ -91,7 +111,7 @@ def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_sc
squeeze.name: squeeze,
f"SQZ_ON": squeeze_on.astype(int) if asint else squeeze_on,
f"SQZ_OFF": squeeze_off.astype(int) if asint else squeeze_off,
f"SQZ_NO": no_squeeze.astype(int) if asint else no_squeeze
f"SQZ_NO": no_squeeze.astype(int) if asint else no_squeeze,
}
df = DataFrame(data)
df.name = squeeze.name
@@ -146,8 +166,7 @@ def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_sc
return df
squeeze.__doc__ = \
"""Squeeze (SQZ)
squeeze.__doc__ = """Squeeze (SQZ)
The default is based on John Carter's "TTM Squeeze" indicator, as discussed
in his book "Mastering the Trade" (chapter 11). The Squeeze indicator attempts
@@ -209,7 +228,7 @@ Kwargs:
tr (value, optional): Use True Range for Keltner Channels. Default: True
asint (value, optional): Use integers instead of bool. Default: True
mamode (value, optional): Which MA to use. Default: "sma"
lazybear (value, optional): Use LazyBear's TradingView implementation.
lazybear (value, optional): Use LazyBear's TradingView implementation.
Default: False
detailed (value, optional): Return additional variations of SQZ for
visualization. Default: False
@@ -219,4 +238,4 @@ Kwargs:
Returns:
pd.DataFrame: SQZ, SQZ_ON, SQZ_OFF, NO_SQZ columns by default. More
detailed columns if 'detailed' kwarg is True.
"""
"""
+13 -7
View File
@@ -3,7 +3,15 @@ from pandas import DataFrame
from pandas_ta.overlap import sma
from pandas_ta.utils import get_offset, non_zero_range, verify_series
def stoch(high, low, close, k=None, d=None, smooth_k=None, offset=None, **kwargs):
def stoch(high,
low,
close,
k=None,
d=None,
smooth_k=None,
offset=None,
**kwargs):
"""Indicator: Stochastic Oscillator (STOCH)"""
# Validate arguments
high = verify_series(high)
@@ -15,10 +23,10 @@ def stoch(high, low, close, k=None, d=None, smooth_k=None, offset=None, **kwargs
offset = get_offset(offset)
# Calculate Result
lowest_low = low.rolling(k).min()
lowest_low = low.rolling(k).min()
highest_high = high.rolling(k).max()
stoch = 100 * (close - lowest_low)
stoch = 100 * (close - lowest_low)
stoch /= non_zero_range(highest_high, lowest_low)
stoch_k = sma(stoch, length=smooth_k)
@@ -53,9 +61,7 @@ def stoch(high, low, close, k=None, d=None, smooth_k=None, offset=None, **kwargs
return df
stoch.__doc__ = \
"""Stochastic (STOCH)
stoch.__doc__ = """Stochastic (STOCH)
The Stochastic Oscillator (STOCH) was developed by George Lane in the 1950's.
He believed this indicator was a good way to measure momentum because changes in
@@ -96,4 +102,4 @@ Kwargs:
Returns:
pd.DataFrame: %K, %D columns.
"""
"""
+12 -7
View File
@@ -4,7 +4,14 @@ from .rsi import rsi
from pandas_ta.overlap import sma
from pandas_ta.utils import get_offset, non_zero_range, verify_series
def stochrsi(close, length=None, rsi_length=None, k=None, d=None, offset=None, **kwargs):
def stochrsi(close,
length=None,
rsi_length=None,
k=None,
d=None,
offset=None,
**kwargs):
"""Indicator: Stochastic RSI Oscillator (STOCHRSI)"""
# Validate arguments
close = verify_series(close)
@@ -16,10 +23,10 @@ def stochrsi(close, length=None, rsi_length=None, k=None, d=None, offset=None, *
# Calculate Result
rsi_ = rsi(close, length=rsi_length)
lowest_rsi = rsi_.rolling(length).min()
lowest_rsi = rsi_.rolling(length).min()
highest_rsi = rsi_.rolling(length).max()
stoch = 100 * (rsi_ - lowest_rsi)
stoch = 100 * (rsi_ - lowest_rsi)
stoch /= non_zero_range(highest_rsi, lowest_rsi)
stochrsi_k = sma(stoch, length=k)
@@ -54,9 +61,7 @@ def stochrsi(close, length=None, rsi_length=None, k=None, d=None, offset=None, *
return df
stochrsi.__doc__ = \
"""Stochastic (STOCHRSI)
stochrsi.__doc__ = """Stochastic (STOCHRSI)
"Stochastic RSI and Dynamic Momentum Index" was created by Tushar Chande and Stanley Kroll and published in Stock & Commodities V.11:5 (189-199)
@@ -99,4 +104,4 @@ Kwargs:
Returns:
pd.DataFrame: RSI %K, RSI %D columns.
"""
"""
+18 -12
View File
@@ -3,14 +3,22 @@ from pandas import DataFrame
from pandas_ta.overlap.ema import ema
from pandas_ta.utils import get_drift, get_offset, verify_series
def trix(close, length=None, signal=None, scalar=None, drift=None, offset=None, **kwargs):
def trix(close,
length=None,
signal=None,
scalar=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: Trix (TRIX)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
signal = int(signal) if signal and signal > 0 else 9
scalar = float(scalar) if scalar else 100
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
drift = get_drift(drift)
offset = get_offset(offset)
@@ -28,12 +36,12 @@ def trix(close, length=None, signal=None, scalar=None, drift=None, offset=None,
trix_signal = trix_signal.shift(offset)
# Handle fills
if 'fillna' in kwargs:
trix.fillna(kwargs['fillna'], inplace=True)
trix_signal.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
trix.fillna(method=kwargs['fill_method'], inplace=True)
trix_signal.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
trix.fillna(kwargs["fillna"], inplace=True)
trix_signal.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
trix.fillna(method=kwargs["fill_method"], inplace=True)
trix_signal.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
trix.name = f"TRIX_{length}_{signal}"
@@ -48,9 +56,7 @@ def trix(close, length=None, signal=None, scalar=None, drift=None, offset=None,
return df
trix.__doc__ = \
"""Trix (TRIX)
trix.__doc__ = """Trix (TRIX)
TRIX is a momentum oscillator to identify divergences.
@@ -81,4 +87,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -5
View File
@@ -2,7 +2,14 @@
from pandas_ta.overlap import ema
from pandas_ta.utils import get_drift, get_offset, verify_series
def tsi(close, fast=None, slow=None, scalar=None, drift=None, offset=None, **kwargs):
def tsi(close,
fast=None,
slow=None,
scalar=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: True Strength Index (TSI)"""
# Validate Arguments
close = verify_series(close)
@@ -42,9 +49,7 @@ def tsi(close, fast=None, slow=None, scalar=None, drift=None, offset=None, **kwa
return tsi
tsi.__doc__ = \
"""True Strength Index (TSI)
tsi.__doc__ = """True Strength Index (TSI)
The True Strength Index is a momentum indicator used to identify short-term
swings while in the direction of the trend as well as determining overbought
@@ -81,4 +86,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+32 -15
View File
@@ -2,7 +2,21 @@
from pandas import DataFrame
from ..utils import get_drift, get_offset, verify_series
def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_w=None, slow_w=None, drift=None, offset=None, **kwargs):
def uo(
high,
low,
close,
fast=None,
medium=None,
slow=None,
fast_w=None,
medium_w=None,
slow_w=None,
drift=None,
offset=None,
**kwargs,
):
"""Indicator: Ultimate Oscillator (UO)"""
# Validate arguments
high = verify_series(high)
@@ -21,9 +35,13 @@ def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_
slow_w = float(slow_w) if slow_w and slow_w > 0 else 1.0
# Calculate Result
tdf = DataFrame({'high': high, 'low': low, f"close_{drift}": close.shift(drift)})
max_h_or_pc = tdf.loc[:, ['high', f"close_{drift}"]].max(axis=1)
min_l_or_pc = tdf.loc[:, ['low', f"close_{drift}"]].min(axis=1)
tdf = DataFrame({
"high": high,
"low": low,
f"close_{drift}": close.shift(drift)
})
max_h_or_pc = tdf.loc[:, ["high", f"close_{drift}"]].max(axis=1)
min_l_or_pc = tdf.loc[:, ["low", f"close_{drift}"]].min(axis=1)
del tdf
bp = close - min_l_or_pc
@@ -33,8 +51,9 @@ def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_
medium_avg = bp.rolling(medium).sum() / tr.rolling(medium).sum()
slow_avg = bp.rolling(slow).sum() / tr.rolling(slow).sum()
total_weight = fast_w + medium_w + slow_w
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w * slow_avg)
total_weight = fast_w + medium_w + slow_w
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w *
slow_avg)
uo = 100 * weights / total_weight
# Offset
@@ -42,21 +61,19 @@ def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_
uo = uo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
uo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
uo.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
uo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
uo.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
uo.name = f"UO_{fast}_{medium}_{slow}"
uo.category = 'momentum'
uo.category = "momentum"
return uo
uo.__doc__ = \
"""Ultimate Oscillator (UO)
uo.__doc__ = """Ultimate Oscillator (UO)
The Ultimate Oscillator is a momentum indicator over three different
periods. It attempts to correct false divergence trading signals.
@@ -101,4 +118,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -5
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas_ta.utils import get_drift, get_offset, verify_series
def willr(high, low, close, length=None, offset=None, **kwargs):
"""Indicator: William's Percent R (WILLR)"""
# Validate arguments
@@ -8,7 +9,8 @@ def willr(high, low, close, length=None, offset=None, **kwargs):
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 14
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -34,9 +36,7 @@ def willr(high, low, close, length=None, offset=None, **kwargs):
return willr
willr.__doc__ = \
"""William's Percent R (WILLR)
willr.__doc__ = """William's Percent R (WILLR)
William's Percent R is a momentum oscillator similar to the RSI that
attempts to identify overbought and oversold conditions.
@@ -65,4 +65,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+1 -1
View File
@@ -25,4 +25,4 @@ from .vwap import vwap
from .vwma import vwma
from .wcp import wcp
from .wma import wma
from .zlma import zlma
from .zlma import zlma
+3 -4
View File
@@ -2,6 +2,7 @@
from .ema import ema
from pandas_ta.utils import get_offset, verify_series
def dema(close, length=None, offset=None, **kwargs):
"""Indicator: Double Exponential Moving Average (DEMA)"""
# Validate Arguments
@@ -25,9 +26,7 @@ def dema(close, length=None, offset=None, **kwargs):
return dema
dema.__doc__ = \
"""Double Exponential Moving Average (DEMA)
dema.__doc__ = """Double Exponential Moving Average (DEMA)
The Double Exponential Moving Average attempts to a smoother average with less
lag than the normal Exponential Moving Average (EMA).
@@ -55,4 +54,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+7 -8
View File
@@ -2,15 +2,16 @@
from numpy import NaN as npNaN
from ..utils import get_offset, verify_series
def ema(close, length=None, offset=None, **kwargs):
"""Indicator: Exponential Moving Average (EMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
# min_periods = kwargs.pop('min_periods', length)
adjust = kwargs.pop('adjust', False)
sma = kwargs.pop('sma', True)
win_type = kwargs.pop('win_type', None)
adjust = kwargs.pop("adjust", False)
sma = kwargs.pop("sma", True)
win_type = kwargs.pop("win_type", None)
offset = get_offset(offset)
# Calculate Result
@@ -27,14 +28,12 @@ def ema(close, length=None, offset=None, **kwargs):
# Name & Category
ema.name = f"EMA_{length}"
ema.category = 'overlap'
ema.category = "overlap"
return ema
ema.__doc__ = \
"""Exponential Moving Average (EMA)
ema.__doc__ = """Exponential Moving Average (EMA)
The Exponential Moving Average is more responsive moving average compared to the
Simple Moving Average (SMA). The weights are determined by alpha which is
@@ -68,4 +67,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -9
View File
@@ -1,18 +1,21 @@
# -*- coding: utf-8 -*-
from ..utils import fibonacci, get_offset, verify_series, weights
def fwma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Fibonacci's Weighted Moving Average (FWMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
# Calculate Result
fibs = fibonacci(n=length, weighted=True)
fwma = close.rolling(length, min_periods=length).apply(weights(fibs), raw=True)
fwma = close.rolling(length, min_periods=length).apply(weights(fibs),
raw=True)
# Offset
if offset != 0:
@@ -20,14 +23,12 @@ def fwma(close, length=None, asc=None, offset=None, **kwargs):
# Name & Category
fwma.name = f"FWMA_{length}"
fwma.category = 'overlap'
fwma.category = "overlap"
return fwma
fwma.__doc__ = \
"""Fibonacci's Weighted Moving Average (FWMA)
fwma.__doc__ = """Fibonacci's Weighted Moving Average (FWMA)
Fibonacci's Weighted Moving Average is similar to a Weighted Moving Average
(WMA) where the weights are based on the Fibonacci Sequence.
@@ -36,7 +37,7 @@ Source: Kevin Johnson
Calculation:
Default Inputs:
length=10,
length=10,
def weights(w):
def _compute(x):
@@ -58,4 +59,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+21 -10
View File
@@ -6,7 +6,17 @@ from .hma import hma
from .sma import sma
from pandas_ta.utils import get_offset, verify_series
def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offset=None, **kwargs):
def hilo(
high,
low,
close,
high_length=None,
low_length=None,
mamode=None,
offset=None,
**kwargs,
):
"""Indicator: Gann HiLo (HiLo)"""
# Validate Arguments
high = verify_series(high)
@@ -29,7 +39,7 @@ def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offse
if mamode == "hma":
high_ma = hma(high, high_length)
low_ma = hma(low, low_length)
else: # "sma"
else: # "sma"
high_ma = sma(high, high_length)
low_ma = sma(low, low_length)
@@ -55,11 +65,14 @@ def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offse
# Name & Category
_props = f"_{high_length}_{low_length}"
df = DataFrame({
f"HILO{_props}": hilo,
f"HILOl{_props}": long,
f"HILOs{_props}": short
}, index=close.index)
df = DataFrame(
{
f"HILO{_props}": hilo,
f"HILOl{_props}": long,
f"HILOs{_props}": short
},
index=close.index,
)
df.name = f"HILO{_props}"
df.category = "overlap"
@@ -67,9 +80,7 @@ def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offse
return df
hilo.__doc__ = \
"""Gann HiLo Activator(HiLo)
hilo.__doc__ = """Gann HiLo Activator(HiLo)
The Gann High Low Activator Indicator was created by Robert Krausz in a 1998
issue of Stocks & Commodities Magazine. It is a moving average based trend
+3 -2
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def hl2(high, low, offset=None, **kwargs):
"""Indicator: HL2 """
# Validate Arguments
@@ -17,6 +18,6 @@ def hl2(high, low, offset=None, **kwargs):
# Name & Category
hl2.name = "HL2"
hl2.category = 'overlap'
hl2.category = "overlap"
return hl2
return hl2
+4 -3
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def hlc3(high, low, close, offset=None, **kwargs):
"""Indicator: HLC3"""
# Validate Arguments
@@ -10,7 +11,7 @@ def hlc3(high, low, close, offset=None, **kwargs):
offset = get_offset(offset)
# Calculate Result
hlc3 = (high + low + close) / 3.
hlc3 = (high + low + close) / 3.0
# Offset
if offset != 0:
@@ -18,6 +19,6 @@ def hlc3(high, low, close, offset=None, **kwargs):
# Name & Category
hlc3.name = "HLC3"
hlc3.category = 'overlap'
hlc3.category = "overlap"
return hlc3
return hlc3
+6 -6
View File
@@ -3,12 +3,14 @@ from math import sqrt
from .wma import wma
from ..utils import get_offset, verify_series
def hma(close, length=None, offset=None, **kwargs):
"""Indicator: Hull Moving Average (HMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -25,14 +27,12 @@ def hma(close, length=None, offset=None, **kwargs):
# Name & Category
hma.name = f"HMA_{length}"
hma.category = 'overlap'
hma.category = "overlap"
return hma
hma.__doc__ = \
"""Hull Moving Average (HMA)
hma.__doc__ = """Hull Moving Average (HMA)
The Hull Exponential Moving Average attempts to reduce or remove lag in moving
averages.
@@ -62,4 +62,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+32 -20
View File
@@ -3,7 +3,15 @@ from pandas import date_range, DataFrame, RangeIndex, Timedelta
from .midprice import midprice
from ..utils import get_offset, verify_series
def ichimoku(high, low, close, tenkan=None, kijun=None, senkou=None, offset=None, **kwargs):
def ichimoku(high,
low,
close,
tenkan=None,
kijun=None,
senkou=None,
offset=None,
**kwargs):
"""Indicator: Ichimoku Kinkō Hyō (Ichimoku)"""
high = verify_series(high)
low = verify_series(low)
@@ -36,14 +44,14 @@ def ichimoku(high, low, close, tenkan=None, kijun=None, senkou=None, offset=None
chikou_span = chikou_span.shift(offset)
# Handle fills
if 'fillna' in kwargs:
span_a.fillna(kwargs['fillna'], inplace=True)
span_b.fillna(kwargs['fillna'], inplace=True)
chikou_span.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
span_a.fillna(method=kwargs['fill_method'], inplace=True)
span_b.fillna(method=kwargs['fill_method'], inplace=True)
chikou_span.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
span_a.fillna(kwargs["fillna"], inplace=True)
span_b.fillna(kwargs["fillna"], inplace=True)
chikou_span.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
span_a.fillna(method=kwargs["fill_method"], inplace=True)
span_b.fillna(method=kwargs["fill_method"], inplace=True)
chikou_span.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
span_a.name = f"ISA_{tenkan}"
@@ -52,39 +60,43 @@ def ichimoku(high, low, close, tenkan=None, kijun=None, senkou=None, offset=None
kijun_sen.name = f"IKS_{kijun}"
chikou_span.name = f"ICS_{kijun}"
chikou_span.category = kijun_sen.category = tenkan_sen.category = 'trend'
chikou_span.category = kijun_sen.category = tenkan_sen.category = "trend"
span_b.category = span_a.category = chikou_span
# Prepare Ichimoku DataFrame
data = {span_a.name: span_a, span_b.name: span_b, tenkan_sen.name: tenkan_sen, kijun_sen.name: kijun_sen, chikou_span.name: chikou_span}
data = {
span_a.name: span_a,
span_b.name: span_b,
tenkan_sen.name: tenkan_sen,
kijun_sen.name: kijun_sen,
chikou_span.name: chikou_span,
}
ichimokudf = DataFrame(data)
ichimokudf.name = f"ICHIMOKU_{tenkan}_{kijun}_{senkou}"
ichimokudf.category = 'overlap'
ichimokudf.category = "overlap"
# Prepare Span DataFrame
last = close.index[-1]
if close.index.dtype == 'int64':
if close.index.dtype == "int64":
ext_index = RangeIndex(start=last + 1, stop=last + kijun + 1)
spandf = DataFrame(index=ext_index, columns=[span_a.name, span_b.name])
_span_a.index = _span_b.index = ext_index
else:
df_freq = close.index.value_counts().mode()[0]
tdelta = Timedelta(df_freq, unit='d')
new_dt = date_range(start=last + tdelta, periods=kijun, freq='B')
tdelta = Timedelta(df_freq, unit="d")
new_dt = date_range(start=last + tdelta, periods=kijun, freq="B")
spandf = DataFrame(index=new_dt, columns=[span_a.name, span_b.name])
_span_a.index = _span_b.index = new_dt
spandf[span_a.name] = _span_a
spandf[span_b.name] = _span_b
spandf.name = f"ICHISPAN_{tenkan}_{kijun}"
spandf.category = 'overlap'
spandf.category = "overlap"
return ichimokudf, spandf
ichimoku.__doc__ = \
"""Ichimoku Kinkō Hyō (ichimoku)
ichimoku.__doc__ = """Ichimoku Kinkō Hyō (ichimoku)
Developed Pre WWII as a forecasting model for financial markets.
@@ -123,4 +135,4 @@ Returns:
For the visible period: spanA, spanB, tenkan_sen, kijun_sen,
and chikou_span columns
For the forward looking period: spanA and spanB columns
"""
"""
+12 -6
View File
@@ -3,7 +3,14 @@ from numpy import NaN as npNaN
from pandas import Series, DataFrame
from ..utils import get_drift, get_offset, non_zero_range, verify_series
def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kwargs):
def kama(close,
length=None,
fast=None,
slow=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: Kaufman's Adaptive Moving Average (HMA)"""
# Validate Arguments
close = verify_series(close)
@@ -15,6 +22,7 @@ def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kw
# Calculate Result
m = close.size
def weight(length: int) -> float:
return 2 / (length + 1)
@@ -31,7 +39,7 @@ def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kw
result = [npNaN for _ in range(0, length - 1)] + [0]
for i in range(length, m):
result.append(sc[i] * close[i] + (1 - sc[i]) * result[i - 1])
kama = Series(result, index=close.index)
# Offset
@@ -45,9 +53,7 @@ def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kw
return kama
kama.__doc__ = \
"""Kaufman's Adaptive Moving Average (KAMA)
kama.__doc__ = """Kaufman's Adaptive Moving Average (KAMA)
Developed by Perry Kaufman, Kaufman's Adaptive Moving Average (KAMA) is a moving average
designed to account for market noise or volatility. KAMA will closely follow prices when
@@ -76,4 +82,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+17 -12
View File
@@ -2,12 +2,14 @@
import math
from pandas_ta.utils import get_offset, verify_series
def linreg(close, length=None, offset=None, **kwargs):
"""Indicator: Linear Regression"""
# Validate arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 14
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
angle = kwargs.pop("angle", False)
intercept = kwargs.pop("intercept", False)
@@ -17,7 +19,7 @@ def linreg(close, length=None, offset=None, **kwargs):
tsf = kwargs.pop("tsf", False)
# Calculate Result
x = range(1, length + 1) # [1, 2, ..., n] from 1 to n keeps Sum(xy) low
x = range(1, length + 1) # [1, 2, ..., n] from 1 to n keeps Sum(xy) low
x_sum = 0.5 * length * (length + 1)
x2_sum = x_sum * (2 * length + 1) / 3
divisor = length * x2_sum - x_sum * x_sum
@@ -38,7 +40,7 @@ def linreg(close, length=None, offset=None, **kwargs):
if degrees:
theta *= 180 / math.pi
return theta
if r:
y2_sum = (series * series).sum()
rn = length * xy_sum - x_sum * y_sum
@@ -47,7 +49,8 @@ def linreg(close, length=None, offset=None, **kwargs):
return m * length + b if tsf else m * (length - 1) + b
linreg = close.rolling(length, min_periods=length).apply(linear_regression, raw=False)
linreg = close.rolling(length, min_periods=length).apply(linear_regression,
raw=False)
# Offset
if offset != 0:
@@ -61,19 +64,21 @@ def linreg(close, length=None, offset=None, **kwargs):
# Name and Categorize it
linreg.name = f"LR"
if slope: linreg.name += "m"
if intercept: linreg.name += "b"
if angle: linreg.name += "a"
if r: linreg.name += "r"
if slope:
linreg.name += "m"
if intercept:
linreg.name += "b"
if angle:
linreg.name += "a"
if r:
linreg.name += "r"
linreg.name += f"_{length}"
linreg.category = "overlap"
return linreg
linreg.__doc__ = \
"""Linear Regression Moving Average (linreg)
linreg.__doc__ = """Linear Regression Moving Average (linreg)
Linear Regression Moving Average (LINREG). This is a simplified version of a
Standard Linear Regression. LINREG is a rolling regression of one variable. A
@@ -117,4 +122,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+9 -7
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def midpoint(close, length=None, offset=None, **kwargs):
"""Indicator: Midpoint"""
# Validate arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 2
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -19,13 +21,13 @@ def midpoint(close, length=None, offset=None, **kwargs):
midpoint = midpoint.shift(offset)
# Handle fills
if 'fillna' in kwargs:
midpoint.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
midpoint.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
midpoint.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
midpoint.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
midpoint.name = f"MIDPOINT_{length}"
midpoint.category = 'overlap'
midpoint.category = "overlap"
return midpoint
return midpoint
+9 -7
View File
@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def midprice(high, low, length=None, offset=None, **kwargs):
"""Indicator: Midprice"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
length = int(length) if length and length > 0 else 2
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -20,13 +22,13 @@ def midprice(high, low, length=None, offset=None, **kwargs):
midprice = midprice.shift(offset)
# Handle fills
if 'fillna' in kwargs:
midprice.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
midprice.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
midprice.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
midprice.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
midprice.name = f"MIDPRICE_{length}"
midprice.category = 'overlap'
midprice.category = "overlap"
return midprice
return midprice
+3 -2
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def ohlc4(open_, high, low, close, offset=None, **kwargs):
"""Indicator: OHLC4"""
# Validate Arguments
@@ -19,6 +20,6 @@ def ohlc4(open_, high, low, close, offset=None, **kwargs):
# Name & Category
ohlc4.name = "OHLC4"
ohlc4.category = 'overlap'
ohlc4.category = "overlap"
return ohlc4
return ohlc4
+8 -7
View File
@@ -1,18 +1,21 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, pascals_triangle, verify_series, weights
def pwma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Pascals Weighted Moving Average (PWMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
triangle = pascals_triangle(n=length - 1, weighted=True)
pwma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
pwma = close.rolling(length, min_periods=length).apply(weights(triangle),
raw=True)
# Offset
if offset != 0:
@@ -20,14 +23,12 @@ def pwma(close, length=None, asc=None, offset=None, **kwargs):
# Name & Category
pwma.name = f"PWMA_{length}"
pwma.category = 'overlap'
pwma.category = "overlap"
return pwma
pwma.__doc__ = \
"""Pascal's Weighted Moving Average (PWMA)
pwma.__doc__ = """Pascal's Weighted Moving Average (PWMA)
Pascal's Weighted Moving Average is similar to a symmetric triangular
window except PWMA's weights are based on Pascal's Triangle.
@@ -58,4 +59,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def rma(close, length=None, offset=None, **kwargs):
"""Indicator: wildeR's Moving Average (RMA)"""
# Validate Arguments
@@ -23,9 +24,7 @@ def rma(close, length=None, offset=None, **kwargs):
return rma
rma.__doc__ = \
"""wildeR's Moving Average (RMA)
rma.__doc__ = """wildeR's Moving Average (RMA)
The WildeR's Moving Average is simply an Exponential Moving Average (EMA)
with a modified alpha = 1 / length.
@@ -51,4 +50,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+8 -7
View File
@@ -4,19 +4,22 @@ from math import sin
from pandas import Series
from ..utils import get_offset, pascals_triangle, verify_series, weights
def sinwma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Sine Weighted Moving Average (SINWMA) by Everget of TradingView"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 14
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
sines = Series([sin((i + 1) * pi / (length + 1)) for i in range(0, length)])
w = sines / sines.sum()
sinwma = close.rolling(length, min_periods=length).apply(weights(w), raw=True)
sinwma = close.rolling(length, min_periods=length).apply(weights(w),
raw=True)
# Offset
if offset != 0:
@@ -24,14 +27,12 @@ def sinwma(close, length=None, asc=None, offset=None, **kwargs):
# Name & Category
sinwma.name = f"SINWMA_{length}"
sinwma.category = 'overlap'
sinwma.category = "overlap"
return sinwma
sinwma.__doc__ = \
"""Sine Weighted Moving Average (SWMA)
sinwma.__doc__ = """Sine Weighted Moving Average (SWMA)
A weighted average using sine cycles. The middle term(s) of the average have the highest
weight(s).
@@ -64,4 +65,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -10
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def sma(close, length=None, offset=None, **kwargs):
"""Indicator: Simple Moving Average (SMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -15,23 +17,21 @@ def sma(close, length=None, offset=None, **kwargs):
# Offset
if offset != 0:
sma = sma.shift(offset)
# Handle fills
if 'fillna' in kwargs:
sma.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
sma.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
sma.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
sma.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
sma.name = f"SMA_{length}"
sma.category = 'overlap'
sma.category = "overlap"
return sma
sma.__doc__ = \
"""Simple Moving Average (SMA)
sma.__doc__ = """Simple Moving Average (SMA)
The Simple Moving Average is the classic moving average that is the equally
weighted average over n periods.
+19 -11
View File
@@ -6,14 +6,20 @@ from pandas_ta.volatility import atr
from pandas_ta.utils import get_offset, verify_series
def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kwargs):
def supertrend(high,
low,
close,
length=None,
multiplier=None,
offset=None,
**kwargs):
"""Indicator: Supertrend"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 7
multiplier = float(multiplier) if multiplier and multiplier > 0 else 3.
multiplier = float(multiplier) if multiplier and multiplier > 0 else 3.0
offset = get_offset(offset)
# Calculate Results
@@ -37,7 +43,7 @@ def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kw
lowerband.iloc[i] = lowerband.iloc[i - 1]
if dir_[i] < 0 and upperband.iloc[i] > upperband.iloc[i - 1]:
upperband.iloc[i] = upperband.iloc[i - 1]
if dir_[i] > 0:
trend[i] = long[i] = lowerband.iloc[i]
else:
@@ -45,12 +51,15 @@ def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kw
# Prepare DataFrame to return
_props = f"_{length}_{multiplier}"
df = DataFrame({
f"SUPERT{_props}": trend,
f"SUPERTd{_props}": dir_,
f"SUPERTl{_props}": long,
f"SUPERTs{_props}": short
}, index=close.index)
df = DataFrame(
{
f"SUPERT{_props}": trend,
f"SUPERTd{_props}": dir_,
f"SUPERTl{_props}": long,
f"SUPERTs{_props}": short,
},
index=close.index,
)
df.name = f"SUPERT{_props}"
df.category = "overlap"
@@ -69,8 +78,7 @@ def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kw
return df
supertrend.__doc__ = \
"""Supertrend (supertrend)
supertrend.__doc__ = """Supertrend (supertrend)
Supertrend is an overlap indicator. It is used to help identify trend
direction, setting stop loss, identify support and resistance, and/or
+9 -8
View File
@@ -1,18 +1,21 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, symmetric_triangle, verify_series, weights
def swma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Symmetric Weighted Moving Average (SWMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
triangle = symmetric_triangle(length, weighted=True)
swma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
swma = close.rolling(length, min_periods=length).apply(weights(triangle),
raw=True)
# Offset
if offset != 0:
@@ -20,20 +23,18 @@ def swma(close, length=None, asc=None, offset=None, **kwargs):
# Name & Category
swma.name = f"SWMA_{length}"
swma.category = 'overlap'
swma.category = "overlap"
return swma
swma.__doc__ = \
"""Symmetric Weighted Moving Average (SWMA)
swma.__doc__ = """Symmetric Weighted Moving Average (SWMA)
Symmetric Weighted Moving Average where weights are based on a symmetric
triangle. For example: n=3 -> [1, 2, 1], n=4 -> [1, 2, 2, 1], etc... This moving
average has variable length in contrast to TradingView's fixed length of 4.
Source:
Source:
https://www.tradingview.com/study-script-reference/#fun_swma
Calculation:
@@ -60,4 +61,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -10
View File
@@ -2,20 +2,22 @@
from .ema import ema
from ..utils import get_offset, verify_series
def t3(close, length=None, a=None, offset=None, **kwargs):
"""Indicator: T3"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
a = float(a) if a and a > 0 and a < 1 else 0.7
offset = get_offset(offset)
# Calculate Result
c1 = -a * a ** 2
c2 = 3 * a ** 2 + 3 * a ** 3
c3 = -6 * a ** 2 - 3 * a - 3 * a ** 3
c4 = a ** 3 + 3 * a ** 2 + 3 * a + 1
c1 = -a * a**2
c2 = 3 * a**2 + 3 * a**3
c3 = -6 * a**2 - 3 * a - 3 * a**3
c4 = a**3 + 3 * a**2 + 3 * a + 1
e1 = ema(close=close, length=length, **kwargs)
e2 = ema(close=e1, length=length, **kwargs)
@@ -31,14 +33,12 @@ def t3(close, length=None, a=None, offset=None, **kwargs):
# Name & Category
t3.name = f"T3_{length}_{a}"
t3.category = 'overlap'
t3.category = "overlap"
return t3
t3.__doc__ = \
"""Tim Tillson's T3 Moving Average (T3)
t3.__doc__ = """Tim Tillson's T3 Moving Average (T3)
Tim Tillson's T3 Moving Average is considered a smoother and more responsive
moving average relative to other moving averages.
@@ -76,4 +76,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+6 -6
View File
@@ -2,12 +2,14 @@
from .ema import ema
from ..utils import get_offset, verify_series
def tema(close, length=None, offset=None, **kwargs):
"""Indicator: Triple Exponential Moving Average (TEMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -22,14 +24,12 @@ def tema(close, length=None, offset=None, **kwargs):
# Name & Category
tema.name = f"TEMA_{length}"
tema.category = 'overlap'
tema.category = "overlap"
return tema
tema.__doc__ = \
"""Triple Exponential Moving Average (TEMA)
tema.__doc__ = """Triple Exponential Moving Average (TEMA)
A less laggy Exponential Moving Average.
@@ -58,4 +58,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+6 -6
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def trima(close, length=None, offset=None, **kwargs):
"""Indicator: Triangular Moving Average (TRIMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -20,14 +22,12 @@ def trima(close, length=None, offset=None, **kwargs):
# Name & Category
trima.name = f"TRIMA_{length}"
trima.category = 'overlap'
trima.category = "overlap"
return trima
trima.__doc__ = \
"""Triangular Moving Average (TRIMA)
trima.__doc__ = """Triangular Moving Average (TRIMA)
A weighted moving average where the shape of the weights are triangular and the
greatest weight is in the middle of the period.
@@ -57,4 +57,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -4
View File
@@ -2,6 +2,7 @@
from .hlc3 import hlc3
from ..utils import get_offset, is_datetime_ordered, verify_series
def vwap(high, low, close, volume, offset=None, **kwargs):
"""Indicator: Volume Weighted Average Price (VWAP)"""
# Validate Arguments
@@ -12,7 +13,9 @@ def vwap(high, low, close, volume, offset=None, **kwargs):
offset = get_offset(offset)
if not is_datetime_ordered(volume):
print(f"[!] VWAP volume series is not datetime ordered. Results may not be as expected.")
print(
f"[!] VWAP volume series is not datetime ordered. Results may not be as expected."
)
# Calculate Result
tp = hlc3(high=high, low=low, close=close)
@@ -29,9 +32,7 @@ def vwap(high, low, close, volume, offset=None, **kwargs):
return vwap
vwap.__doc__ = \
"""Volume Weighted Average Price (VWAP)
vwap.__doc__ = """Volume Weighted Average Price (VWAP)
The Volume Weighted Average Price that measures the average typical price
by volume. It is typically used with intraday charts to identify general
+4 -5
View File
@@ -2,6 +2,7 @@
from .sma import sma
from ..utils import get_offset, verify_series
def vwma(close, volume, length=None, offset=None, **kwargs):
"""Indicator: Volume Weighted Moving Average (VWMA)"""
# Validate Arguments
@@ -20,14 +21,12 @@ def vwma(close, volume, length=None, offset=None, **kwargs):
# Name & Category
vwma.name = f"VWMA_{length}"
vwma.category = 'overlap'
vwma.category = "overlap"
return vwma
vwma.__doc__ = \
"""Volume Weighted Moving Average (VWMA)
vwma.__doc__ = """Volume Weighted Moving Average (VWMA)
Volume Weighted Moving Average.
@@ -53,4 +52,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+4 -5
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def wcp(high, low, close, offset=None, **kwargs):
"""Indicator: Weighted Closing Price (WCP)"""
# Validate Arguments
@@ -18,14 +19,12 @@ def wcp(high, low, close, offset=None, **kwargs):
# Name & Category
wcp.name = "WCP"
wcp.category = 'overlap'
wcp.category = "overlap"
return wcp
wcp.__doc__ = \
"""Weighted Closing Price (WCP)
wcp.__doc__ = """Weighted Closing Price (WCP)
Weighted Closing Price is the weighted price given: high, low
and double the close.
@@ -48,4 +47,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+7 -5
View File
@@ -4,12 +4,14 @@ from numpy import dot as npdot
from pandas import Series
from ..utils import get_offset, verify_series
def wma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Weighted Moving Average (WMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
asc = asc if asc else True
offset = get_offset(offset)
@@ -19,8 +21,10 @@ def wma(close, length=None, asc=None, offset=None, **kwargs):
weights = weights_ if asc else weights_[::-1]
def linear(w):
def _compute(x):
return npdot(x, w) / total_weight
return _compute
close_ = close.rolling(length, min_periods=length)
@@ -32,14 +36,12 @@ def wma(close, length=None, asc=None, offset=None, **kwargs):
# Name & Category
wma.name = f"WMA_{length}"
wma.category = 'overlap'
wma.category = "overlap"
return wma
wma.__doc__ = \
"""Weighted Moving Average (WMA)
wma.__doc__ = """Weighted Moving Average (WMA)
The Weighted Moving Average where the weights are linearly increasing and
the most recent data has the heaviest weight.
+11 -11
View File
@@ -6,12 +6,14 @@ from .sma import sma
from .wma import wma
from ..utils import get_offset, verify_series
def zlma(close, length=None, mamode=None, offset=None, **kwargs):
"""Indicator: Zero Lag Moving Average (ZLMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
mamode = mamode.lower() if mamode else None
@@ -19,15 +21,15 @@ def zlma(close, length=None, mamode=None, offset=None, **kwargs):
lag = int(0.5 * (length - 1))
close = 2 * close - close.shift(lag)
if mamode is None or mamode == 'ema':
if mamode is None or mamode == "ema":
zlma = ema(close, length=length, **kwargs)
if mamode == 'hma':
if mamode == "hma":
zlma = hma(close, length=length, **kwargs)
if mamode == 'rma':
if mamode == "rma":
zlma = rma(close, length=length, **kwargs)
if mamode == 'sma':
if mamode == "sma":
zlma = sma(close, length=length, **kwargs)
if mamode == 'wma':
if mamode == "wma":
zlma = wma(close, length=length, **kwargs)
# Offset
@@ -36,14 +38,12 @@ def zlma(close, length=None, mamode=None, offset=None, **kwargs):
# Name & Category
zlma.name = f"ZL_{zlma.name}"
zlma.category = 'overlap'
zlma.category = "overlap"
return zlma
zlma.__doc__ = \
"""Zero Lag Moving Average (ZLMA)
zlma.__doc__ = """Zero Lag Moving Average (ZLMA)
The Zero Lag Moving Average attempts to eliminate the lag associated
with moving averages. This is an adaption created by John Ehler and Ric Way.
@@ -72,4 +72,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
from .log_return import log_return
from .percent_return import percent_return
from .trend_return import trend_return
from .trend_return import trend_return
+4 -5
View File
@@ -2,6 +2,7 @@
from numpy import log as nplog
from pandas_ta.utils import get_offset, verify_series
def log_return(close, length=None, cumulative=False, offset=None, **kwargs):
"""Indicator: Log Return"""
# Validate Arguments
@@ -18,13 +19,13 @@ def log_return(close, length=None, cumulative=False, offset=None, **kwargs):
# Offset
if offset != 0:
log_return = log_return.shift(offset)
# Handle fills
if "fillna" in kwargs:
log_return.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
log_return.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
log_return.name = f"{'CUM' if cumulative else ''}LOGRET_{length}"
log_return.category = "performance"
@@ -32,9 +33,7 @@ def log_return(close, length=None, cumulative=False, offset=None, **kwargs):
return log_return
log_return.__doc__ = \
"""Log Return
log_return.__doc__ = """Log Return
Calculates the logarithmic return of a Series.
See also: help(df.ta.log_return) for additional **kwargs a valid 'df'.
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas_ta.utils import get_offset, verify_series
def percent_return(close, length=None, cumulative=False, offset=None, **kwargs):
"""Indicator: Percent Return"""
# Validate Arguments
@@ -25,9 +26,7 @@ def percent_return(close, length=None, cumulative=False, offset=None, **kwargs):
return pct_return
percent_return.__doc__ = \
"""Percent Return
percent_return.__doc__ = """Percent Return
Calculates the percent return of a Series.
See also: help(df.ta.percent_return) for additional **kwargs a valid 'df'.
@@ -53,4 +52,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+24 -13
View File
@@ -4,13 +4,22 @@ from .log_return import log_return
from .percent_return import percent_return
from pandas_ta.utils import get_offset, verify_series, zero
def trend_return(close, trend, log=True, cumulative=None, trend_reset=0, offset=None, **kwargs):
def trend_return(close,
trend,
log=True,
cumulative=None,
trend_reset=0,
offset=None,
**kwargs):
"""Indicator: Trend Return"""
# Validate Arguments
close = verify_series(close)
trend = verify_series(trend)
cumulative = cumulative if cumulative is not None and isinstance(cumulative, bool) else False
trend_reset = int(trend_reset) if trend_reset and isinstance(trend_reset, int) else 0
cumulative = (cumulative if cumulative is not None and
isinstance(cumulative, bool) else False)
trend_reset = (int(trend_reset)
if trend_reset and isinstance(trend_reset, int) else 0)
offset = get_offset(offset)
# Calculate Result
@@ -20,7 +29,7 @@ def trend_return(close, trend, log=True, cumulative=None, trend_reset=0, offset=
returns = percent_return(close, cumulative=False)
trends = trend.astype(int)
returns = (trends * returns).apply(zero)
tsum = 0
m = trends.size
result = []
@@ -39,12 +48,15 @@ def trend_return(close, trend, log=True, cumulative=None, trend_reset=0, offset=
_log = "L" if log else "P"
_returns = "LOGRET" if log else "PCTRET"
_props = f"{_cumulative}{_log}TR"
df = DataFrame({
_props: result,
f"TR_{_returns}": returns,
f"{_props}_Trends": trends,
f"{_props}_Trades": trends.diff().shift(1).fillna(0).astype(int),
}, index=close.index)
df = DataFrame(
{
_props: result,
f"TR_{_returns}": returns,
f"{_props}_Trends": trends,
f"{_props}_Trades": trends.diff().shift(1).fillna(0).astype(int),
},
index=close.index,
)
# Offset
if offset != 0:
@@ -57,8 +69,7 @@ def trend_return(close, trend, log=True, cumulative=None, trend_reset=0, offset=
return df
trend_return.__doc__ = \
"""Trend Return
trend_return.__doc__ = """Trend Return
Calculates the (Cumulative) Returns of a Trend as defined by a sequence of booleans called a 'trend'. One popular example in TA literature is to be long
when the 'close' > 'moving average'. In which case, the trend= close > sma(close, 50). By default it calculates log returns but can also use percent change.
@@ -107,4 +118,4 @@ Kwargs:
Returns:
pd.DataFrame: Returns columns: Trend Return, Close Return, Trends, and
Trades (Enter: 1, Exit: -1, Otherwise: 0).
"""
"""
+1 -1
View File
@@ -7,4 +7,4 @@ from .quantile import quantile
from .skew import skew
from .stdev import stdev
from .variance import variance
from .zscore import zscore
from .zscore import zscore
+5 -6
View File
@@ -2,12 +2,13 @@
from numpy import log as npLog
from ..utils import get_offset, verify_series
def entropy(close, length=None, base=None, offset=None, **kwargs):
"""Indicator: Entropy (ENTP)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
base = float(base) if base and base > 0 else 2.
base = float(base) if base and base > 0 else 2.0
offset = get_offset(offset)
# Calculate Result
@@ -25,9 +26,7 @@ def entropy(close, length=None, base=None, offset=None, **kwargs):
return entropy
entropy.__doc__ = \
"""Entropy (ENTP)
entropy.__doc__ = """Entropy (ENTP)
Introduced by Claude Shannon in 1948, entropy measures the unpredictability
of the data, or equivalently, of its average information. A die has higher
@@ -39,7 +38,7 @@ Sources:
Calculation:
Default Inputs:
length=10, base=2
P = close / SUM(close, length)
E = SUM(-P * npLog(P) / npLog(base), length)
@@ -55,4 +54,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -5
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def kurtosis(close, length=None, offset=None, **kwargs):
"""Indicator: Kurtosis"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -23,9 +25,7 @@ def kurtosis(close, length=None, offset=None, **kwargs):
return kurtosis
kurtosis.__doc__ = \
"""Rolling Kurtosis
kurtosis.__doc__ = """Rolling Kurtosis
Sources:
@@ -45,4 +45,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -5
View File
@@ -2,12 +2,14 @@
from numpy import fabs as npfabs
from ..utils import get_offset, verify_series
def mad(close, length=None, offset=None, **kwargs):
"""Indicator: Mean Absolute Deviation"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -28,9 +30,7 @@ def mad(close, length=None, offset=None, **kwargs):
return mad
mad.__doc__ = \
"""Rolling Mean Absolute Deviation
mad.__doc__ = """Rolling Mean Absolute Deviation
Sources:
@@ -50,4 +50,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -5
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def median(close, length=None, offset=None, **kwargs):
"""Indicator: Median"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -23,9 +25,7 @@ def median(close, length=None, offset=None, **kwargs):
return median
median.__doc__ = \
"""Rolling Median
median.__doc__ = """Rolling Median
Rolling Median of over 'n' periods. Sibling of a Simple Moving Average.
@@ -48,4 +48,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -5
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def quantile(close, length=None, q=None, offset=None, **kwargs):
"""Indicator: Quantile"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
q = float(q) if q and q > 0 and q < 1 else 0.5
offset = get_offset(offset)
@@ -24,9 +26,7 @@ def quantile(close, length=None, q=None, offset=None, **kwargs):
return quantile
quantile.__doc__ = \
"""Rolling Quantile
quantile.__doc__ = """Rolling Quantile
Sources:
@@ -47,4 +47,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+10 -10
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def skew(close, length=None, offset=None, **kwargs):
"""Indicator: Skew"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -15,13 +17,13 @@ def skew(close, length=None, offset=None, **kwargs):
# Offset
if offset != 0:
skew = skew.shift(offset)
# Handle fills
if 'fillna' in kwargs:
skew.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
skew.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
skew.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
skew.fillna(method=kwargs["fill_method"], inplace=True)
# Name & Category
skew.name = f"SKEW_{length}"
skew.category = "statistics"
@@ -29,9 +31,7 @@ def skew(close, length=None, offset=None, **kwargs):
return skew
skew.__doc__ = \
"""Rolling Skew
skew.__doc__ = """Rolling Skew
Sources:
+5 -6
View File
@@ -3,6 +3,7 @@ from numpy import sqrt as npsqrt
from .variance import variance
from ..utils import get_offset, verify_series
def stdev(close, length=None, ddof=1, offset=None, **kwargs):
"""Indicator: Standard Deviation"""
# Validate Arguments
@@ -25,9 +26,7 @@ def stdev(close, length=None, ddof=1, offset=None, **kwargs):
return stdev
stdev.__doc__ = \
"""Rolling Standard Deviation
stdev.__doc__ = """Rolling Standard Deviation
Sources:
@@ -40,9 +39,9 @@ Calculation:
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 1
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
+7 -7
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def variance(close, length=None, ddof=1, offset=None, **kwargs):
"""Indicator: Variance"""
# Validate Arguments
@@ -8,7 +9,8 @@ def variance(close, length=None, ddof=1, offset=None, **kwargs):
length = int(length) if length and length > 1 else 30
ddof = int(ddof) if ddof >= 0 and ddof < length else 1
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
offset = get_offset(offset)
# Calculate Result
@@ -25,9 +27,7 @@ def variance(close, length=None, ddof=1, offset=None, **kwargs):
return variance
variance.__doc__ = \
"""Rolling Variance
variance.__doc__ = """Rolling Variance
Sources:
@@ -39,9 +39,9 @@ Calculation:
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 1
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
+3 -4
View File
@@ -3,6 +3,7 @@ from ..overlap.sma import sma
from .stdev import stdev
from ..utils import get_offset, verify_series
def zscore(close, length=None, std=None, offset=None, **kwargs):
"""Indicator: Z Score"""
# Validate Arguments
@@ -27,9 +28,7 @@ def zscore(close, length=None, std=None, offset=None, **kwargs):
return zscore
zscore.__doc__ = \
"""Rolling Z Score
zscore.__doc__ = """Rolling Z Score
Sources:
@@ -54,4 +53,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+15 -9
View File
@@ -4,7 +4,15 @@ from pandas_ta.overlap import rma
from pandas_ta.volatility import atr
from pandas_ta.utils import get_drift, get_offset, verify_series, zero
def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs):
def adx(high,
low,
close,
length=None,
scalar=None,
drift=None,
offset=None,
**kwargs):
"""Indicator: ADX"""
# Validate Arguments
high = verify_series(high)
@@ -18,8 +26,8 @@ def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **k
# Calculate Result
atr_ = atr(high=high, low=low, close=close, length=length)
up = high - high.shift(drift) # high.diff(drift)
dn = low.shift(drift) - low # low.diff(-drift).shift(drift)
up = high - high.shift(drift) # high.diff(drift)
dn = low.shift(drift) - low # low.diff(-drift).shift(drift)
pos = ((up > dn) & (up > 0)) * up
neg = ((dn > up) & (dn > 0)) * dn
@@ -55,20 +63,18 @@ def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **k
dmp.name = f"DMP_{length}"
dmn.name = f"DMN_{length}"
adx.category = dmp.category = dmn.category = 'trend'
adx.category = dmp.category = dmn.category = "trend"
# Prepare DataFrame to return
data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn}
adxdf = DataFrame(data)
adxdf.name = f"ADX_{length}"
adxdf.category = 'trend'
adxdf.category = "trend"
return adxdf
adx.__doc__ = \
"""Average Directional Movement (ADX)
adx.__doc__ = """Average Directional Movement (ADX)
Average Directional Movement is meant to quantify trend strength by measuring
the amount of movement in a single direction.
@@ -142,4 +148,4 @@ Kwargs:
Returns:
pd.DataFrame: adx, dmp, dmn columns.
"""
"""
+10 -4
View File
@@ -5,7 +5,14 @@ from .short_run import short_run
from pandas_ta.overlap import ema, hma, linreg, rma, sma, wma
from pandas_ta.utils import get_offset, verify_series
def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs):
def amat(close=None,
fast=None,
slow=None,
mamode=None,
lookback=None,
offset=None,
**kwargs):
"""Indicator: Archer Moving Averages Trends (AMAT)"""
# Validate Arguments
close = verify_series(close)
@@ -31,11 +38,10 @@ def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=No
elif mamode == "wma":
fast_ma = wma(close=close, length=fast, **kwargs)
slow_ma = wma(close=close, length=slow, **kwargs)
else: # "ema"
else: # "ema"
fast_ma = ema(close=close, length=fast, **kwargs)
slow_ma = ema(close=close, length=slow, **kwargs)
mas_long = long_run(fast_ma, slow_ma, length=lookback)
mas_short = short_run(fast_ma, slow_ma, length=lookback)
@@ -63,4 +69,4 @@ def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=No
amatdf.name = f"AMAT_{mamode.upper()}_{fast}_{slow}_{lookback}"
amatdf.category = "trend"
return amatdf
return amatdf
+15 -9
View File
@@ -1,6 +1,12 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from pandas_ta.utils import get_offset, recent_maximum_index, recent_minimum_index, verify_series
from pandas_ta.utils import (
get_offset,
recent_maximum_index,
recent_minimum_index,
verify_series,
)
def aroon(high, low, length=None, scalar=None, offset=None, **kwargs):
"""Indicator: Aroon & Aroon Oscillator"""
@@ -12,12 +18,14 @@ def aroon(high, low, length=None, scalar=None, offset=None, **kwargs):
offset = get_offset(offset)
# Calculate Result
periods_from_hh = high.rolling(length + 1).apply(recent_maximum_index, raw=True)
periods_from_ll = low.rolling(length + 1).apply(recent_minimum_index, raw=True)
periods_from_hh = high.rolling(length + 1).apply(recent_maximum_index,
raw=True)
periods_from_ll = low.rolling(length + 1).apply(recent_minimum_index,
raw=True)
aroon_up = aroon_down = scalar
aroon_up *= (1 - (periods_from_hh / length))
aroon_down *= (1 - (periods_from_ll / length))
aroon_up *= 1 - (periods_from_hh / length)
aroon_down *= 1 - (periods_from_ll / length)
aroon_osc = aroon_up - aroon_down
# Handle fills
@@ -47,7 +55,7 @@ def aroon(high, low, length=None, scalar=None, offset=None, **kwargs):
data = {
aroon_down.name: aroon_down,
aroon_up.name: aroon_up,
aroon_osc.name: aroon_osc
aroon_osc.name: aroon_osc,
}
aroondf = DataFrame(data)
aroondf.name = f"AROON_{length}"
@@ -56,9 +64,7 @@ def aroon(high, low, length=None, scalar=None, offset=None, **kwargs):
return aroondf
aroon.__doc__ = \
"""Aroon & Aroon Oscillator (AROON)
aroon.__doc__ = """Aroon & Aroon Oscillator (AROON)
Aroon attempts to identify if a security is trending and how strong.
+16 -6
View File
@@ -4,14 +4,26 @@ from pandas import DataFrame
from pandas_ta.volatility import atr
from pandas_ta.utils import get_offset, get_drift, verify_series
def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None, offset=None, **kwargs):
def chop(
high,
low,
close,
length=None,
atr_length=None,
scalar=None,
drift=None,
offset=None,
**kwargs,
):
"""Indicator: Choppiness Index (CHOP)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 14
atr_length = int(atr_length) if atr_length is not None and atr_length > 0 else 1
atr_length = int(
atr_length) if atr_length is not None and atr_length > 0 else 1
scalar = float(scalar) if scalar else 100
drift = get_drift(drift)
offset = get_offset(offset)
@@ -42,9 +54,7 @@ def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None
return chop
chop.__doc__ = \
"""Choppiness Index (CHOP)
chop.__doc__ = """Choppiness Index (CHOP)
The Choppiness Index was created by Australian commodity trader
E.W. Dreiss and is designed to determine if the market is choppy
@@ -82,4 +92,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+3 -4
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame
from pandas_ta.volatility import atr
from pandas_ta.utils import get_offset, verify_series
def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
"""Indicator: Chande Kroll Stop (CKSP)"""
# Validate Arguments
@@ -50,9 +51,7 @@ def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
return ckspdf
cksp.__doc__ = \
"""Chande Kroll Stop (CKSP)
cksp.__doc__ = """Chande Kroll Stop (CKSP)
The Tushar Chande and Stanley Kroll in their book
“The New Technical Trader”. It is a trend-following indicator,
@@ -86,4 +85,4 @@ Kwargs:
Returns:
pd.DataFrame: long and short columns.
"""
"""
+5 -6
View File
@@ -3,6 +3,7 @@ from math import exp
from pandas import DataFrame
from pandas_ta.utils import get_offset, verify_series
def decay(close, kind=None, length=None, mode=None, offset=None, **kwargs):
"""Indicator: Decay"""
# Validate Arguments
@@ -16,7 +17,7 @@ def decay(close, kind=None, length=None, mode=None, offset=None, **kwargs):
if mode == "exp" or kind == "exponential":
_mode = "EXP"
diff = close.shift(1) - exp(-length)
else: # "linear"
else: # "linear"
diff = close.shift(1) - (1 / length)
diff[0] = close[0]
tdf = DataFrame({"close": close, "diff": diff, "0": 0})
@@ -32,16 +33,14 @@ def decay(close, kind=None, length=None, mode=None, offset=None, **kwargs):
if "fill_method" in kwargs:
ld.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
# Name and Categorize it
ld.name = f"{_mode}DECAY_{length}"
ld.category = "trend"
return ld
decay.__doc__ = \
"""Decay
decay.__doc__ = """Decay
Creates a decay moving forward from prior signals like crosses. The default is
"linear". Exponential is optional as "exponential" or "exp".
@@ -70,4 +69,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas_ta.utils import get_offset, verify_series
def decreasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Decreasing"""
# Validate Arguments
@@ -30,9 +31,7 @@ def decreasing(close, length=None, asint=True, offset=None, **kwargs):
return decreasing
decreasing.__doc__ = \
"""Decreasing
decreasing.__doc__ = """Decreasing
Returns True or False if the series is decreasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
@@ -56,4 +55,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+5 -6
View File
@@ -2,6 +2,7 @@
from pandas_ta.overlap import sma
from pandas_ta.utils import get_offset, verify_series
def dpo(close, length=None, centered=True, offset=None, **kwargs):
"""Indicator: Detrend Price Oscillator (DPO)"""
# Validate Arguments
@@ -12,7 +13,7 @@ def dpo(close, length=None, centered=True, offset=None, **kwargs):
# Calculate Result
t = int(0.5 * length) + 1
ma = sma(close, length)
dpo = close - ma.shift(t)
if centered:
dpo = (close.shift(t) - ma).shift(-t)
@@ -34,9 +35,7 @@ def dpo(close, length=None, centered=True, offset=None, **kwargs):
return dpo
dpo.__doc__ = \
"""Detrend Price Oscillator (DPO)
dpo.__doc__ = """Detrend Price Oscillator (DPO)
Is an indicator designed to remove trend from price and make it easier to
identify cycles.
@@ -51,7 +50,7 @@ Calculation:
length=20, centered=True
SMA = Simple Moving Average
t = int(0.5 * length) + 1
DPO = close.shift(t) - SMA(close, length)
if centered:
DPO = DPO.shift(-t)
@@ -68,4 +67,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+3 -4
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas_ta.utils import get_offset, verify_series
def increasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Increasing"""
# Validate Arguments
@@ -30,9 +31,7 @@ def increasing(close, length=None, asint=True, offset=None, **kwargs):
return increasing
increasing.__doc__ = \
"""Increasing
increasing.__doc__ = """Increasing
Returns True or False if the series is increasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
@@ -56,4 +55,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+6 -3
View File
@@ -3,6 +3,7 @@ from .decreasing import decreasing
from .increasing import increasing
from pandas_ta.utils import get_offset, verify_series
def long_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Long Run"""
# Validate Arguments
@@ -12,8 +13,10 @@ def long_run(fast, slow, length=None, offset=None, **kwargs):
offset = get_offset(offset)
# Calculate Result
pb = increasing(fast, length) & decreasing(slow, length) # potential bottom or bottom
bi = increasing(fast, length) & increasing(slow, length) # fast and slow are increasing
pb = increasing(fast, length) & decreasing(
slow, length) # potential bottom or bottom
bi = increasing(fast, length) & increasing(
slow, length) # fast and slow are increasing
long_run = pb | bi
# Offset
@@ -30,4 +33,4 @@ def long_run(fast, slow, length=None, offset=None, **kwargs):
long_run.name = f"LR_{length}"
long_run.category = "trend"
return long_run
return long_run
+4 -5
View File
@@ -3,6 +3,7 @@ from numpy import NaN as npNaN
from pandas import DataFrame, Series
from pandas_ta.utils import get_offset, verify_series
def psar(high, low, close=None, af=None, max_af=None, offset=None, **kwargs):
"""Indicator: Parabolic Stop and Reverse (PSAR)"""
# Validate Arguments
@@ -101,7 +102,7 @@ def psar(high, low, close=None, af=None, max_af=None, offset=None, **kwargs):
f"PSARl{_params}": long,
f"PSARs{_params}": short,
f"PSARaf{_params}": _af,
f"PSARr{_params}": reversal
f"PSARr{_params}": reversal,
}
psardf = DataFrame(data)
psardf.name = f"PSAR{_params}"
@@ -110,9 +111,7 @@ def psar(high, low, close=None, af=None, max_af=None, offset=None, **kwargs):
return psardf
psar.__doc__ = \
"""Parabolic Stop and Reverse (psar)
psar.__doc__ = """Parabolic Stop and Reverse (psar)
Parabolic Stop and Reverse
@@ -138,4 +137,4 @@ Kwargs:
Returns:
pd.DataFrame: long, short, af, and reversal columns.
"""
"""
+13 -9
View File
@@ -2,6 +2,7 @@
from pandas_ta.overlap import dema, ema, hma, rma, sma
from pandas_ta.utils import get_offset, non_zero_range, verify_series
def qstick(open_, close, length=None, offset=None, **kwargs):
"""Indicator: Q Stick"""
# Validate Arguments
@@ -14,11 +15,16 @@ def qstick(open_, close, length=None, offset=None, **kwargs):
# Calculate Result
diff = non_zero_range(close, open_)
if ma in [None, "sma"]: qstick = sma(diff, length=length)
if ma == "dema": qstick = dema(diff, length=length, **kwargs)
if ma == "ema": qstick = ema(diff, length=length, **kwargs)
if ma == "hma": qstick = hma(diff, length=length)
if ma == "rma": qstick = rma(diff, length=length)
if ma in [None, "sma"]:
qstick = sma(diff, length=length)
if ma == "dema":
qstick = dema(diff, length=length, **kwargs)
if ma == "ema":
qstick = ema(diff, length=length, **kwargs)
if ma == "hma":
qstick = hma(diff, length=length)
if ma == "rma":
qstick = rma(diff, length=length)
# Offset
if offset != 0:
@@ -37,9 +43,7 @@ def qstick(open_, close, length=None, offset=None, **kwargs):
return qstick
qstick.__doc__ = \
"""Q Stick
qstick.__doc__ = """Q Stick
The Q Stick indicator, developed by Tushar Chande, attempts to quantify and identify
trends in candlestick charts.
@@ -66,4 +70,4 @@ Kwargs:
Returns:
pd.Series: New feature generated.
"""
"""
+6 -3
View File
@@ -3,6 +3,7 @@ from .decreasing import decreasing
from .increasing import increasing
from pandas_ta.utils import get_offset, verify_series
def short_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Short Run"""
# Validate Arguments
@@ -12,8 +13,10 @@ def short_run(fast, slow, length=None, offset=None, **kwargs):
offset = get_offset(offset)
# Calculate Result
pt = decreasing(fast, length) & increasing(slow, length) # potential top or top
bd = decreasing(fast, length) & decreasing(slow, length) # fast and slow are decreasing
pt = decreasing(fast, length) & increasing(slow,
length) # potential top or top
bd = decreasing(fast, length) & decreasing(
slow, length) # fast and slow are decreasing
short_run = pt | bd
# Offset
@@ -30,4 +33,4 @@ def short_run(fast, slow, length=None, offset=None, **kwargs):
short_run.name = f"SR_{length}"
short_run.category = "trend"
return short_run
return short_run
+2 -3
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame
from pandas_ta.overlap import hl2
from pandas_ta.utils import get_offset, verify_series
def ttm_trend(high, low, close, length=None, offset=None, **kwargs):
"""Indicator: TTM Trend (TTM_TRND)"""
# Validate arguments
@@ -45,9 +46,7 @@ def ttm_trend(high, low, close, length=None, offset=None, **kwargs):
return df
ttm_trend.__doc__ = \
"""TTM Trend (TTM_TRND)
ttm_trend.__doc__ = """TTM Trend (TTM_TRND)
This indicator is from John Carters book “Mastering the Trade” and plots the
bars green or red. It checks if the price is above or under the average price of
+5 -5
View File
@@ -3,6 +3,7 @@ from pandas import DataFrame
from pandas_ta.volatility import true_range
from pandas_ta.utils import get_drift, get_offset, verify_series, zero
def vortex(high, low, close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Vortex"""
# Validate arguments
@@ -10,7 +11,8 @@ def vortex(high, low, close, length=None, drift=None, offset=None, **kwargs):
low = verify_series(low)
close = verify_series(close)
length = length if length and length > 0 else 14
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
min_periods = (int(kwargs["min_periods"]) if "min_periods" in kwargs and
kwargs["min_periods"] is not None else length)
drift = get_drift(drift)
offset = get_offset(offset)
@@ -51,9 +53,7 @@ def vortex(high, low, close, length=None, drift=None, offset=None, **kwargs):
return vtxdf
vortex.__doc__ = \
"""Vortex
vortex.__doc__ = """Vortex
Two oscillators that capture positive and negative trend movement.
@@ -88,4 +88,4 @@ Kwargs:
Returns:
pd.DataFrame: vip and vim columns
"""
"""
+1 -1
View File
@@ -3,4 +3,4 @@ from ._candles import *
from ._core import *
from ._math import *
from ._signals import *
from ._time import *
from ._time import *

Some files were not shown because too many files have changed in this diff Show More