mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-06-26 16:00:54 +08:00
formatting fixes, PEP8 etc
This commit is contained in:
+33
-37
@@ -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
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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'.
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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).
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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,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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user