BUG #520 ENH lowerbound guardrails MAINT refactor

This commit is contained in:
Kevin Johnson
2022-05-02 16:08:16 -07:00
parent 8373fc9ed2
commit bfb9654738
101 changed files with 2743 additions and 2237 deletions
+6 -11
View File
@@ -96,7 +96,7 @@ Performance
-----------
* Pandas TA is fast, with or without **TA Lib** or **Numba** installed, but one is not penalized if they are installed.
* **TA Lib** computations are **enabled** by default. They can be disabled per indicator.
* The library includes a performance method, ```help(ta.performance)```, to check runtime indicator performance for a given _ohlcv_ DataFrame.
* The library includes a performance method, ```help(ta.speed_test)```, to check runtime indicator performance for a given _ohlcv_ DataFrame.
* Optionable **Multiprocessing** for a Pandas TA ```Study```.
* Check Indicator Speeds on your system with the [Indicator Speed Check Notebook](https://github.com/twopirllc/pandas-ta/tree/main/examples/Speed_Check.ipynb).
@@ -145,15 +145,10 @@ Pandas TA is used by Applications and Services like
<br/>
[Gamestonk Terminal](https://github.com/GamestonkTerminal/GamestonkTerminal)
[Open BB](https://openbb.co/) (previously Gamestonk Terminal)
-------------------
> Gamestonk Terminal is an awesome stock and crypto market terminal that has been developed for fun, while I saw my GME shares tanking. But hey, I like the stock 💎🙌.
<br/>
[MarketMaker Lite](https://github.com/MarketMakerLite)
-------------------
> Make the market you deserve. Market alerts, statistics and analytics, delivered through an innovative interface, made for retail investors.
> OpenBB is a leading open source investment analysis company.
We represent millions of investors who want to leverage state-of-the-art data science and machine learning technologies to make sense of raw unrefined data. Our mission is to make investment research effective, powerful and accessible to everyone.
<br/>
@@ -198,7 +193,7 @@ $ pip install pandas_ta[full]
Latest Version
--------------
Best choice! Version: *0.3.63b*
Best choice! Version: *0.3.64b*
* Includes all fixes and updates between **pypi** and what is covered in this README.
```sh
$ pip install -U git+https://github.com/twopirllc/pandas-ta
@@ -1305,7 +1300,7 @@ Back to [Contents](#contents)
# **Support**
Feeling generous, like the package or want to see it become more a mature package?
Like the package, want more indicators and features? Continued Support?
* Donations help cover data and API costs so platform indicators (like [TradingView](https://github.com/tradingview/)) are accurate.
* I appreciate **ALL** of those that have bought me Coffee/Beer/Wine et al. I greatly appreciate it! 😎
File diff suppressed because one or more lines are too long
+509 -507
View File
File diff suppressed because it is too large Load Diff
+286 -269
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+87 -86
View File
File diff suppressed because one or more lines are too long
+14 -12
View File
@@ -7,18 +7,20 @@ from pandas_ta.candles import cdl_doji, cdl_inside
ALL_PATTERNS = [
"2crows", "3blackcrows", "3inside", "3linestrike", "3outside", "3starsinsouth",
"3whitesoldiers", "abandonedbaby", "advanceblock", "belthold", "breakaway",
"closingmarubozu", "concealbabyswall", "counterattack", "darkcloudcover", "doji",
"dojistar", "dragonflydoji", "engulfing", "eveningdojistar", "eveningstar",
"gapsidesidewhite", "gravestonedoji", "hammer", "hangingman", "harami",
"haramicross", "highwave", "hikkake", "hikkakemod", "homingpigeon",
"identical3crows", "inneck", "inside", "invertedhammer", "kicking", "kickingbylength",
"ladderbottom", "longleggeddoji", "longline", "marubozu", "matchinglow", "mathold",
"morningdojistar", "morningstar", "onneck", "piercing", "rickshawman",
"risefall3methods", "separatinglines", "shootingstar", "shortline", "spinningtop",
"stalledpattern", "sticksandwich", "takuri", "tasukigap", "thrusting", "tristar",
"unique3river", "upsidegap2crows", "xsidegap3methods"
"2crows", "3blackcrows", "3inside", "3linestrike", "3outside",
"3starsinsouth", "3whitesoldiers", "abandonedbaby", "advanceblock",
"belthold", "breakaway", "closingmarubozu", "concealbabyswall",
"counterattack", "darkcloudcover", "doji", "dojistar", "dragonflydoji",
"engulfing", "eveningdojistar", "eveningstar", "gapsidesidewhite",
"gravestonedoji", "hammer", "hangingman", "harami", "haramicross",
"highwave", "hikkake", "hikkakemod", "homingpigeon", "identical3crows",
"inneck", "inside", "invertedhammer", "kicking", "kickingbylength",
"ladderbottom", "longleggeddoji", "longline", "marubozu", "matchinglow",
"mathold", "morningdojistar", "morningstar", "onneck", "piercing",
"rickshawman", "risefall3methods", "separatinglines", "shootingstar",
"shortline", "spinningtop", "stalledpattern", "sticksandwich", "takuri",
"tasukigap", "thrusting", "tristar", "unique3river", "upsidegap2crows",
"xsidegap3methods"
]
+4 -2
View File
@@ -13,7 +13,8 @@ except ImportError:
@njit
def np_reflex(
x: Array, n: Int, k: Int, alpha: IntFloat, pi: IntFloat, sqrt2: IntFloat
x: Array, n: Int, k: Int,
alpha: IntFloat, pi: IntFloat, sqrt2: IntFloat
):
m, ratio = x.size, 2 * sqrt2 / k
a = exp(-pi * ratio)
@@ -88,7 +89,8 @@ def reflex(
# Validate
length = v_pos_default(length, 20)
smooth = v_pos_default(smooth, 20)
close = v_series(close, max(length, smooth))
_length = max(length, smooth) + 1
close = v_series(close, _length)
if close is None:
return
+7 -1
View File
@@ -2,7 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.utils import non_zero_range, v_offset, v_scalar, v_series, v_talib
from pandas_ta.utils import (
non_zero_range,
v_offset,
v_scalar,
v_series,
v_talib
)
def bop(
+8 -2
View File
@@ -1,8 +1,14 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import non_zero_range, v_drift, v_offset
from pandas_ta.utils import v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
non_zero_range,
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series
)
def brar(
+7 -1
View File
@@ -2,7 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap import linreg
from pandas_ta.utils import v_drift, v_offset, v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series
)
def cfo(
+9 -3
View File
@@ -3,8 +3,14 @@ from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.overlap import rma
from pandas_ta.utils import v_drift, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, v_talib
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
@@ -42,7 +48,7 @@ def cmo(
"""
# Validate
length = v_pos_default(length, 14)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+3 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.overlap import wma
@@ -39,7 +40,8 @@ def coppock(
length = v_pos_default(length, 10)
fast = v_pos_default(fast, 11)
slow = v_pos_default(slow, 14)
close = v_series(close, max(length, fast, slow))
_length = length + fast + slow
close = v_series(close, _length)
if close is None:
return
+9 -2
View File
@@ -3,8 +3,15 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.maps import Imports
from pandas_ta.utils import v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_series, v_talib, zero
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib,
zero
)
def dm(
+8 -2
View File
@@ -1,7 +1,13 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame, concat, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import signals, v_drift, v_offset, v_pos_default, v_series
from pandas_ta.utils import (
signals,
v_drift,
v_offset,
v_pos_default,
v_series
)
def er(
@@ -34,7 +40,7 @@ def er(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+10 -3
View File
@@ -2,8 +2,15 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap import linreg
from pandas_ta.utils import v_bool, v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_bool,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series
)
from pandas_ta.volatility import rvi
@@ -48,7 +55,7 @@ def inertia(
# Validate
length = v_pos_default(length, 20)
rvi_length = v_pos_default(rvi_length, 14)
_length = max(length, rvi_length)
_length = 2 * max(length, rvi_length) - min(length, rvi_length) // 2 - 1
close = v_series(close, _length)
if close is None:
+8 -3
View File
@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import non_zero_range, rma_pandas, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
rma_pandas,
v_offset,
v_pos_default,
v_series
)
def kdj(
@@ -40,7 +45,7 @@ def kdj(
# Validate
length = v_pos_default(length, 9)
signal = v_pos_default(signal, 3)
_length = max(length, signal)
_length = length + signal + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
+3 -1
View File
@@ -53,7 +53,9 @@ def kst(
sma4 = int(sma4) if sma4 and sma4 > 0 else 15
signal = v_pos_default(signal, 9)
_length = max(roc1, roc2, roc3, roc4, sma1, sma2, sma3, sma4, signal)
_rmax = max(roc1, roc2, roc3, roc4)
_smax = max(sma1, sma2, sma3, sma4)
_length = _rmax + _smax
close = v_series(close, _length)
if close is None:
+9 -3
View File
@@ -3,8 +3,13 @@ from pandas import concat, DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.overlap import ema
from pandas_ta.utils import signals, v_offset, v_mamode
from pandas_ta.utils import v_pos_default, v_series, v_talib
from pandas_ta.utils import (
signals,
v_offset,
v_pos_default,
v_series,
v_talib
)
def macd(
@@ -47,7 +52,8 @@ def macd(
signal = v_pos_default(signal, 9)
if slow < fast:
fast, slow = slow, fast
close = v_series(close, slow + signal)
_length = slow + signal - 1
close = v_series(close, _length)
if close is None:
return
+1 -1
View File
@@ -33,7 +33,7 @@ def mom(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+4 -3
View File
@@ -37,9 +37,10 @@ def pgo(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
_length = 2 * length
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
if high is None or low is None or close is None:
return
+11 -3
View File
@@ -3,8 +3,15 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.maps import Imports
from pandas_ta.utils import tal_ma, v_mamode, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, v_talib
from pandas_ta.utils import (
tal_ma,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
def ppo(
@@ -43,7 +50,8 @@ def ppo(
signal = v_pos_default(signal, 9)
if slow < fast:
fast, slow = slow, fast
close = v_series(close, max(fast, slow, signal))
_length = max(fast, slow, signal)
close = v_series(close, _length)
if close is None:
return
+7 -1
View File
@@ -2,7 +2,13 @@
from numpy import sign
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import v_drift, v_offset, v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series
)
def psl(
+11 -4
View File
@@ -3,8 +3,14 @@ from numpy import isnan, maximum, minimum, nan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.utils import v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series
)
from .rsi import rsi
@@ -53,7 +59,8 @@ def qqe(
length = v_pos_default(length, 14)
smooth = v_pos_default(smooth, 5)
wilders_length = 2 * length - 1
close = v_series(close, smooth + wilders_length)
_length = wilders_length + smooth
close = v_series(close, _length)
if close is None:
return
@@ -80,7 +87,7 @@ def qqe(
return # Emergency Break
dar = factor * ma("ema", smoothed_rsi_tr_ma, length=wilders_length)
if all(isnan(dar)):
return # Emergency Break
return # Emergency Break
# Create the Upper and Lower Bands around RSI MA.
upperband = rsi_ma + dar
+8 -3
View File
@@ -2,8 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.utils import v_offset, v_pos_default, v_scalar
from pandas_ta.utils import v_series, v_talib
from pandas_ta.utils import (
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
from .mom import mom
@@ -39,7 +44,7 @@ def roc(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+10 -3
View File
@@ -3,8 +3,15 @@ from pandas import DataFrame, concat, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.overlap import rma
from pandas_ta.utils import signals, v_drift, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, v_talib
from pandas_ta.utils import (
signals,
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
def rsi(
@@ -39,7 +46,7 @@ def rsi(
"""
# Validate
length = v_pos_default(length, 14)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+8 -2
View File
@@ -2,7 +2,13 @@
from numpy import nan
from pandas_ta._typing import DictLike, Int
from pandas import concat, DataFrame, Series
from pandas_ta.utils import v_drift, v_offset, v_pos_default, v_series, signals
from pandas_ta.utils import (
signals,
v_drift,
v_offset,
v_pos_default,
v_series
)
def rsx(
@@ -53,7 +59,7 @@ def rsx(
f40, f48, f50, f58, f60, f68, f70, f78 = 0, 0, 0, 0, 0, 0, 0, 0
f80, f88, f90 = 0, 0, 0
result = [nan for _ in range(0, length - 1)] + [0]
result = [nan for _ in range(0, length - 1)] + [50]
for i in range(length, m):
if f90 == 0:
f90 = 1.0
+1 -1
View File
@@ -39,7 +39,7 @@ def rvgi(
# Validate
length = v_pos_default(length, 14)
swma_length = v_pos_default(swma_length, 4)
_length = max(length, swma_length)
_length = length + swma_length - 1
open_ = v_series(open_, _length)
high = v_series(high, _length)
low = v_series(low, _length)
+5 -4
View File
@@ -30,9 +30,10 @@ def slope(
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
as_angle (value, optional): Converts slope to an angle. Default: False
to_degrees (value, optional): Converts slope angle to degrees.
Default: False
as_angle (value, optional): Converts slope to an angle in radians
per np.arctan(). Default: False
to_degrees (value, optional): If as_angle=True, it converts the slope
angle to degrees. Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
@@ -44,7 +45,7 @@ def slope(
"""
# Validate
length = v_pos_default(length, 1)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+8 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import v_offset, v_pos_default, v_scalar, v_series
@@ -47,7 +48,8 @@ def smi(
signal = v_pos_default(signal, 5)
if slow < fast:
fast, slow = slow, fast
close = v_series(close, max(fast, slow, signal))
_length = slow + signal + 1
close = v_series(close, _length)
if close is None:
return
@@ -57,8 +59,13 @@ def smi(
# Calculate
tsi_df = tsi(close, fast=fast, slow=slow, signal=signal, scalar=scalar)
if tsi_df is None:
return # Emergency Break
smi = tsi_df.iloc[:, 0]
signalma = tsi_df.iloc[:, 1]
if all(isnan(signalma)):
return # Emergency Break
osc = smi - signalma
# Offset
+28 -6
View File
@@ -4,8 +4,15 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap import ema, linreg, sma
from pandas_ta.trend import decreasing, increasing
from pandas_ta.utils import simplify_columns, unsigned_differences, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
simplify_columns,
unsigned_differences,
v_bool,
v_mamode,
v_offset,
v_pos_default,
v_series
)
from pandas_ta.volatility import bbands, kc
from .mom import mom
@@ -16,6 +23,7 @@ def squeeze(
kc_length: Int = None, kc_scalar: IntFloat = None,
mom_length: Int = None, mom_smooth: Int = None,
use_tr: bool = None, mamode: str = None,
prenan: bool = None,
offset: Int = None, **kwargs: DictLike
) -> DataFrame:
"""Squeeze (SQZ)
@@ -44,6 +52,8 @@ def squeeze(
mom_length (int): Momentum Period. Default: 12
mom_smooth (int): Smoothing Period of Momentum. Default: 6
mamode (str): Only "ema" or "sma". Default: "sma"
prenan (bool): If True, sets nan for all columns up the first
valid squeeze value. Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
@@ -67,7 +77,7 @@ def squeeze(
kc_length = v_pos_default(kc_length, 20)
mom_length = v_pos_default(mom_length, 12)
mom_smooth = v_pos_default(mom_smooth, 6)
_length = max(bb_length, kc_length, mom_length, mom_smooth)
_length = max(bb_length, kc_length, mom_length, mom_smooth) + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
@@ -78,6 +88,7 @@ def squeeze(
bb_std = v_pos_default(bb_std, 2.0)
kc_scalar = v_pos_default(kc_scalar, 1.5)
mamode = v_mamode(mamode, "sma")
prenan = v_bool(prenan, False)
offset = v_offset(offset)
use_tr = kwargs.pop("tr", True)
@@ -140,11 +151,22 @@ def squeeze(
_props += "_LB" if lazybear else ""
squeeze.name = f"SQZ{_props}"
if asint:
squeeze_on = squeeze_on.astype(int)
squeeze_off = squeeze_off.astype(int)
no_squeeze = no_squeeze.astype(int)
if prenan:
nanlength = max(bb_length, kc_length) - 2
squeeze_on[:nanlength] = nan
squeeze_off[:nanlength] = nan
no_squeeze[:nanlength] = nan
data = {
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_ON": squeeze_on,
f"SQZ_OFF": squeeze_off,
f"SQZ_NO": no_squeeze,
}
df = DataFrame(data)
df.name = squeeze.name
+36 -9
View File
@@ -4,11 +4,19 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.momentum import mom
# from pandas_ta.overlap import ema, sma
from pandas_ta.trend import decreasing, increasing
from pandas_ta.utils import (
simplify_columns,
unsigned_differences,
v_bool,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series
)
from pandas_ta.volatility import bbands, kc
from pandas_ta.utils import simplify_columns, unsigned_differences, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_scalar, v_series
def squeeze_pro(
high: Series, low: Series, close: Series,
@@ -17,6 +25,7 @@ def squeeze_pro(
kc_scalar_normal: IntFloat = None, kc_scalar_narrow: IntFloat = None,
mom_length: Int = None, mom_smooth: Int = None,
use_tr: bool = None, mamode: str = None,
prenan: bool = None,
offset: Int = None, **kwargs: DictLike
) -> DataFrame:
"""Squeeze PRO(SQZPRO)
@@ -50,6 +59,8 @@ def squeeze_pro(
mom_length (int): Momentum Period. Default: 12
mom_smooth (int): Smoothing Period of Momentum. Default: 6
mamode (str): Only "ema" or "sma". Default: "sma"
prenan (bool): If True, sets nan for all columns up the first
valid squeeze value. Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
@@ -72,7 +83,7 @@ def squeeze_pro(
kc_length = v_pos_default(kc_length, 20)
mom_length = v_pos_default(mom_length, 12)
mom_smooth = v_pos_default(mom_smooth, 6)
_length = max(bb_length, kc_length, mom_length, mom_smooth)
_length = max(bb_length, kc_length, mom_length, mom_smooth) + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
@@ -83,6 +94,7 @@ def squeeze_pro(
kc_scalar_narrow = v_scalar(kc_scalar_narrow, 1)
kc_scalar_normal = v_scalar(kc_scalar_normal, 1.5)
kc_scalar_wide = v_scalar(kc_scalar_wide, 2)
prenan = v_bool(prenan, False)
valid_kc_scaler = kc_scalar_wide > kc_scalar_normal \
and kc_scalar_normal > kc_scalar_narrow
@@ -157,13 +169,28 @@ def squeeze_pro(
_props += f"_{bb_length}_{bb_std}_{kc_length}_{kc_scalar_wide}_{kc_scalar_normal}_{kc_scalar_narrow}"
squeeze.name = f"SQZPRO{_props}"
if asint:
squeeze_on_wide = squeeze_on_wide.astype(int)
squeeze_on_narrow = squeeze_on_narrow.astype(int)
squeeze_on_normal = squeeze_on_normal.astype(int)
squeeze_off_wide = squeeze_off_wide.astype(int)
no_squeeze = no_squeeze.astype(int)
if prenan:
nanlength = max(bb_length, kc_length) - 2
squeeze_on_wide[:nanlength] = nan
squeeze_on_narrow[:nanlength] = nan
squeeze_on_normal[:nanlength] = nan
squeeze_off_wide[:nanlength] = nan
no_squeeze[:nanlength] = nan
data = {
squeeze.name: squeeze,
f"SQZPRO_ON_WIDE": squeeze_on_wide.astype(int) if asint else squeeze_on_wide,
f"SQZPRO_ON_NORMAL": squeeze_on_normal.astype(int) if asint else squeeze_on_normal,
f"SQZPRO_ON_NARROW": squeeze_on_narrow.astype(int) if asint else squeeze_on_narrow,
f"SQZPRO_OFF": squeeze_off_wide.astype(int) if asint else squeeze_off_wide,
f"SQZPRO_NO": no_squeeze.astype(int) if asint else no_squeeze,
f"SQZPRO_ON_WIDE": squeeze_on_wide,
f"SQZPRO_ON_NORMAL": squeeze_on_normal,
f"SQZPRO_ON_NARROW": squeeze_on_narrow,
f"SQZPRO_OFF": squeeze_off_wide,
f"SQZPRO_NO": no_squeeze,
}
df = DataFrame(data)
df.name = squeeze.name
+16 -3
View File
@@ -1,9 +1,14 @@
# -*- coding: utf-8 -*-
from numpy import nan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap import ema
from pandas_ta.utils import non_zero_range, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_offset,
v_pos_default,
v_series
)
def stc(
@@ -106,10 +111,14 @@ def stc(
xmacd = fastma - slowma
pff, pf = schaff_tc(close, xmacd, tclength, factor)
pf[:_length - 1] = nan
stc = Series(pff, index=close.index)
macd = Series(xmacd, index=close.index)
stoch = Series(pf, index=close.index)
stc.iloc[:_length - 1] = nan
# Offset
if offset != 0:
stc = stc.shift(offset)
@@ -133,7 +142,11 @@ def stc(
stoch.name = f"STCstoch{_props}"
stc.category = macd.category = stoch.category = "momentum"
data = {stc.name: stc, macd.name: macd, stoch.name: stoch}
data = {
stc.name: stc,
macd.name: macd,
stoch.name: stoch
}
df = DataFrame(data)
df.name = f"STC{_props}"
df.category = stc.category
+9 -2
View File
@@ -3,8 +3,15 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.maps import Imports
from pandas_ta.utils import non_zero_range, tal_ma, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
non_zero_range,
tal_ma,
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib
)
def stoch(
+10 -3
View File
@@ -3,8 +3,15 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.maps import Imports
from pandas_ta.utils import non_zero_range, tal_ma, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
non_zero_range,
tal_ma,
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib
)
def stochf(
@@ -44,7 +51,7 @@ def stochf(
# Validate
k = v_pos_default(k, 14)
d = v_pos_default(d, 3)
_length = max(k, d)
_length = k + d - 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
+9 -3
View File
@@ -3,8 +3,13 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.momentum import rsi
from pandas_ta.utils import non_zero_range, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def stochrsi(
@@ -49,7 +54,8 @@ def stochrsi(
rsi_length = v_pos_default(rsi_length, 14)
k = v_pos_default(k, 3)
d = v_pos_default(d, 3)
close = v_series(close, length + rsi_length + k + d)
_length = length + rsi_length + 2
close = v_series(close, _length)
if close is None:
return
+1 -1
View File
@@ -32,7 +32,7 @@ def td_seq(
pd.DataFrame: New feature generated.
"""
# Validate
close = v_series(close)
close = v_series(close, 5)
if close is None:
return
+18 -7
View File
@@ -1,9 +1,15 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap.ema import ema
from pandas_ta.utils import v_drift, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series
)
def trix(
@@ -35,26 +41,31 @@ def trix(
"""
# Validate
length = v_pos_default(length, 30)
_length = 3 * length - 2
signal = v_pos_default(signal, 9)
if length < signal:
length, signal = signal, length
_length = 3 * length - 1
close = v_series(close, _length)
if close is None:
return
signal = v_pos_default(signal, 9)
scalar = v_scalar(scalar, 100)
drift = v_drift(drift)
offset = v_offset(offset)
# Calculate
ema1 = ema(close=close, length=length, **kwargs)
# if all(isnan(ema1)): return # Emergency Break
if all(isnan(ema1)):
return # Emergency Break
ema2 = ema(close=ema1, length=length, **kwargs)
# if all(isnan(ema2)): return # Emergency Break
if all(isnan(ema2)):
return # Emergency Break
ema3 = ema(close=ema2, length=length, **kwargs)
# if all(isnan(ema3)): return # Emergency Break
if all(isnan(ema3)):
return # Emergency Break
trix = scalar * ema3.pct_change(drift)
trix_signal = trix.rolling(signal).mean()
+21 -4
View File
@@ -1,10 +1,17 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.overlap import ema
from pandas_ta.utils import v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series
)
def tsi(
@@ -43,14 +50,18 @@ def tsi(
# Validate
fast = v_pos_default(fast, 13)
slow = v_pos_default(slow, 25)
close = v_series(close, max(fast, slow))
signal = v_pos_default(signal, 13)
if slow < fast:
fast, slow = slow, fast
_length = slow + signal + 1
close = v_series(close, _length)
if "length" in kwargs:
kwargs.pop("length")
if close is None:
return
signal = v_pos_default(signal, 13)
scalar = v_scalar(scalar, 100)
mamode = v_mamode(mamode, "ema")
drift = v_drift(drift)
@@ -59,13 +70,19 @@ def tsi(
# Calculate
diff = close.diff(drift)
slow_ema = ema(close=diff, length=slow, **kwargs)
if all(isnan(slow_ema)):
return # Emergency Break
fast_slow_ema = ema(close=slow_ema, length=fast, **kwargs)
abs_diff = diff.abs()
abs_slow_ema = ema(close=abs_diff, length=slow, **kwargs)
if all(isnan(abs_slow_ema)):
return # Emergency Break
abs_fast_slow_ema = ema(close=abs_slow_ema, length=fast, **kwargs)
tsi = scalar * fast_slow_ema / abs_fast_slow_ema
if all(isnan(tsi)):
return # Emergency Break
tsi_signal = ma(mamode, tsi, length=signal)
# Offset
+8 -2
View File
@@ -2,7 +2,13 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.utils import v_drift, v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_series,
v_talib
)
def uo(
@@ -46,7 +52,7 @@ def uo(
fast = v_pos_default(fast, 7)
medium = v_pos_default(medium, 14)
slow = v_pos_default(slow, 28)
_length = max(fast, medium, slow)
_length = max(fast, medium, slow) + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
+3 -2
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from numpy import append, arange, array, exp, floor, nan, tensordot
from numpy.version import version as npVersion
from numpy.version import version as np_version
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas import Series
from pandas_ta.utils import strided_window, v_offset, v_pos_default, v_series
@@ -46,6 +46,7 @@ def alma(
return
sigma = v_pos_default(sigma, 6.0)
if isinstance(dist_offset, float) and 0 <= dist_offset <= 1:
offset_ = float(dist_offset)
else:
@@ -60,7 +61,7 @@ def alma(
weights = exp(-0.5 * ((sigma / length) * (x - k)) ** 2)
weights /= weights.sum()
if npVersion >= "1.20.0":
if np_version >= "1.20.0":
from numpy.lib.stride_tricks import sliding_window_view
window = sliding_window_view(np_close, length)
else:
+8 -2
View File
@@ -3,7 +3,13 @@ from numpy import nan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import v_bool, v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
v_bool,
v_offset,
v_pos_default,
v_series,
v_talib
)
try:
from numba import njit
@@ -71,7 +77,7 @@ def ema(
adjust = kwargs.setdefault("adjust", False)
# Calculate
if Imports["talib"] and mode_tal:
if Imports["talib"] and mode_tal and length > 1:
from talib import EMA
ema = EMA(close, length)
else:
+8 -2
View File
@@ -1,8 +1,14 @@
# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import fibonacci, v_ascending, v_offset
from pandas_ta.utils import v_pos_default, v_series, weights
from pandas_ta.utils import (
fibonacci,
v_ascending,
v_offset,
v_pos_default,
v_series,
weights
)
def fwma(
+1 -1
View File
@@ -49,7 +49,7 @@ def hilo(
# Validate
high_length = v_pos_default(high_length, 13)
low_length = v_pos_default(low_length, 21)
_length = max(high_length, low_length)
_length = max(high_length, low_length) + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
+1 -1
View File
@@ -32,7 +32,7 @@ def hma(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, length + 2)
if close is None:
return
+8 -2
View File
@@ -3,8 +3,14 @@ from numpy import nan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import non_zero_range, v_drift, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def kama(
+10 -6
View File
@@ -1,12 +1,16 @@
# -*- coding: utf-8 -*-
from numpy import arctan, nan, pi, zeros_like
from numpy.version import version
from numpy.version import version as np_version
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import strided_window, v_offset, v_pos_default
from pandas_ta.utils import v_series, v_talib
from pandas_ta.utils import (
strided_window,
v_offset,
v_pos_default,
v_series,
v_talib
)
def linreg(
close: Series, length: Int = None, talib: bool = None,
@@ -111,7 +115,7 @@ def linreg(
return m * length + b if not tsf else m * (length - 1) + b
if version >= "1.20.0":
if np_version >= "1.20.0":
from numpy.lib.stride_tricks import sliding_window_view
linreg_ = [
linear_regression(_) for _ in sliding_window_view(
@@ -137,7 +141,7 @@ def linreg(
linreg.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Category
linreg.name = f"LR"
linreg.name = f"LINREG"
if slope:
linreg.name += "m"
if intercept:
+6 -2
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import arctan, nan, zeros_like
from numpy import arctan, isnan, nan, zeros_like
from pandas import DataFrame, Series
from pandas_ta._typing import Array, DictLike, Int, IntFloat
from pandas_ta.maps import Imports
@@ -14,7 +14,8 @@ except ImportError:
@njit
def np_mama(
x: Array, fastlimit: IntFloat, slowlimit: IntFloat, prenan: Int
x: Array, fastlimit: IntFloat, slowlimit: IntFloat,
prenan: Int
):
"""Ehler's Mother of Adaptive Moving Averages
http://traders.com/documentation/feedbk_docs/2014/01/traderstips.html
@@ -155,6 +156,9 @@ def mama(
else:
mama, fama = np_mama(np_close, fastlimit, slowlimit, prenan)
if all(isnan(mama)) or all(isnan(fama)):
return # Emergency Break
# Name and Category
_props = f"_{fastlimit}_{slowlimit}"
df = DataFrame({
+9 -2
View File
@@ -1,8 +1,15 @@
# -*- coding: utf-8 -*-
# from numpy.version import version as np_version
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import pascals_triangle, v_offset
from pandas_ta.utils import v_ascending, v_pos_default, v_series, weights
from pandas_ta.utils import (
pascals_triangle,
v_offset,
v_ascending,
v_pos_default,
v_series,
weights
)
def pwma(
+7 -2
View File
@@ -3,8 +3,13 @@ from numpy import convolve, ndarray, ones
from pandas import Series
from pandas_ta._typing import Array, DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import np_prepend, v_offset, v_pos_default
from pandas_ta.utils import v_series, v_talib
from pandas_ta.utils import (
np_prepend,
v_offset,
v_pos_default,
v_series,
v_talib
)
try:
+7 -2
View File
@@ -3,8 +3,13 @@ from numpy import nan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import v_mamode, v_offset, v_pos_default
from pandas_ta.utils import v_series, v_talib
from pandas_ta.utils import (
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib
)
def smma(
+3 -3
View File
@@ -40,9 +40,9 @@ def supertrend(
"""
# Validate
length = v_pos_default(length, 7)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
high = v_series(high, length + 1)
low = v_series(low, length + 1)
close = v_series(close, length + 1)
if high is None or low is None or close is None:
return
+7 -2
View File
@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import symmetric_triangle, v_offset, v_pos_default
from pandas_ta.utils import v_series, weights
from pandas_ta.utils import (
symmetric_triangle,
v_offset,
v_pos_default,
v_series,
weights
)
def swma(
+2 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
@@ -37,7 +38,7 @@ def t3(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, 5 * (length + 1))
if close is None:
return
+1 -1
View File
@@ -35,7 +35,7 @@ def tema(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, 3 * length)
if close is None:
return
+1 -1
View File
@@ -41,7 +41,7 @@ def vidya(
"""
# Validate
length = v_pos_default(length, 14)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+7 -2
View File
@@ -3,8 +3,13 @@ from numpy import arange, dot
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import v_ascending, v_offset, v_pos_default
from pandas_ta.utils import v_series, v_talib
from pandas_ta.utils import (
v_ascending,
v_offset,
v_pos_default,
v_series,
v_talib
)
def wma(
+4
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import v_mamode, v_offset, v_pos_default, v_series
from .dema import dema
from .ema import ema
from .fwma import fwma
@@ -104,6 +106,8 @@ def zlma(
kwargs.update({"length": length})
zlma = _ma(mamode, **kwargs)
if zlma is None or all(isnan(zlma)):
return # Emergency Break
# Offset
if offset != 0:
+1 -1
View File
@@ -33,7 +33,7 @@ def log_return(
"""
# Validate
length = v_pos_default(length, 1)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+3 -2
View File
@@ -20,7 +20,8 @@ def percent_return(
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 20
cumulative (bool): If True, returns the cumulative returns. Default: False
cumulative (bool): If True, returns the cumulative returns.
Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
@@ -32,7 +33,7 @@ def percent_return(
"""
# Validate
length = v_pos_default(length, 1)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+1 -1
View File
@@ -33,7 +33,7 @@ def entropy(
"""
# Validate
length = v_pos_default(length, 10)
close = v_series(close, length)
close = v_series(close, 2 * length - 1)
if close is None:
return
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import v_offset, v_pos_default, v_series
+1 -1
View File
@@ -46,7 +46,7 @@ def tos_stdevall(
close = close.iloc[-length:]
_props = f"{_props}_{length}"
close = v_series(close, length)
close = v_series(close, 2)
if close is None:
return
+3 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import exp, logical_and, max, min
from numpy import exp, isnan, logical_and, max, min
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import v_int, v_offset, v_scalar, v_series
@@ -60,6 +60,8 @@ def ifisher(
if not all(is_remapped):
np_max, np_min = max(np_close), min(np_close)
close_map = remap(close, from_min=np_min, from_max=np_max, to_min=-1, to_max=1)
if close_map is None or all(isnan(close_map.values)):
return # Emergency Break
np_close = close_map.values
amped = exp(amp * np_close)
result = (amped - 1) / (amped + 1)
+16 -3
View File
@@ -1,9 +1,17 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.utils import v_drift, v_mamode, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, zero
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series,
zero
)
from pandas_ta.volatility import atr
@@ -58,7 +66,12 @@ def adx(
offset = v_offset(offset)
# Calculate
atr_ = atr(high=high, low=low, close=close, length=length)
atr_ = atr(
high=high, low=low, close=close,
length=length, prenan=kwargs.pop("prenan", True)
)
if atr_ is None or all(isnan(atr_)):
return
up = high - high.shift(drift) # high.diff(drift)
dn = low.shift(drift) - low # low.diff(-drift).shift(drift)
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import v_mamode, v_offset, v_pos_default, v_series
from .long_run import long_run
+11 -5
View File
@@ -2,9 +2,15 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.utils import v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, v_talib
from pandas_ta.utils import recent_maximum_index, recent_minimum_index
from pandas_ta.utils import (
recent_maximum_index,
recent_minimum_index,
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
def aroon(
@@ -37,8 +43,8 @@ def aroon(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
high = v_series(high, length + 1)
low = v_series(low, length + 1)
if high is None or low is None:
return
+11 -5
View File
@@ -2,8 +2,14 @@
from numpy import log, log10
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import v_bool, v_drift, v_offset
from pandas_ta.utils import v_pos_default, v_scalar, v_series
from pandas_ta.utils import (
v_bool,
v_drift,
v_offset,
v_pos_default,
v_scalar,
v_series,
)
from pandas_ta.volatility import atr
@@ -45,9 +51,9 @@ def chop(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
high = v_series(high, length + 1)
low = v_series(low, length + 1)
close = v_series(close, length + 1)
if high is None or low is None or close is None:
return
+11 -3
View File
@@ -1,8 +1,14 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import v_mamode, v_offset, v_pos_default
from pandas_ta.utils import v_series, v_tradingview
from pandas_ta.utils import (
v_mamode,
v_offset,
v_pos_default,
v_series,
v_tradingview
)
from pandas_ta.volatility import atr
@@ -53,7 +59,7 @@ def cksp(
# TODO: clean up x and q
x = float(x) if isinstance(x, float) and x > 0 else 1 if tvmode is True else 3
q = int(q) if isinstance(q, float) and q > 0 else 9 if tvmode is True else 20
_length = max(p, q, x)
_length = p + q
high = v_series(high, _length)
low = v_series(low, _length)
@@ -67,6 +73,8 @@ def cksp(
# Calculate
atr_ = atr(high=high, low=low, close=close, length=p, mamode=mamode)
if atr_ is None or all(isnan(atr_)):
return
long_stop_ = high.rolling(p).max() - x * atr_
long_stop = long_stop_.rolling(q).max()
+8 -2
View File
@@ -1,8 +1,14 @@
# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import is_percent, v_bool, v_drift, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
is_percent,
v_bool,
v_drift,
v_offset,
v_pos_default,
v_series
)
def decreasing(
+1 -1
View File
@@ -35,7 +35,7 @@ def dpo(
"""
# Validate
length = v_pos_default(length, 20)
close = v_series(close, length)
close = v_series(close, length + 1)
if close is None:
return
+9 -2
View File
@@ -1,8 +1,15 @@
# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.utils import is_percent, v_bool, v_drift
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
is_percent,
v_bool,
v_drift,
v_offset,
v_pos_default,
v_series
)
def increasing(
close: Series, length: Int = None, strict: bool = None,
+7 -2
View File
@@ -2,8 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import non_zero_range, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def qstick(
+3 -2
View File
@@ -13,7 +13,8 @@ except ImportError:
@njit
def np_trendflex(
x: Array, n: Int, k: Int, alpha: IntFloat, pi: IntFloat, sqrt2: IntFloat
x: Array, n: Int, k: Int,
alpha: IntFloat, pi: IntFloat, sqrt2: IntFloat
):
"""Ehler's Trendflex
http://traders.com/Documentation/FEEDbk_docs/2020/02/TradersTips.html"""
@@ -88,7 +89,7 @@ def trendflex(
# Validate
length = v_pos_default(length, 20)
smooth = v_pos_default(smooth, 20)
close = v_series(close, max(length, smooth))
close = v_series(close, max(length, smooth) + 1)
if close is None:
return
+7 -2
View File
@@ -2,8 +2,13 @@
from numpy import inf, fabs, nan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import non_zero_range, v_drift, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_drift,
v_offset,
v_pos_default,
v_series
)
def vhf(
+9 -1
View File
@@ -8,7 +8,15 @@ from numpy import all, append, array, corrcoef, dot, exp, fabs
from numpy import log, nan, ndarray, ones, seterr, sign, sqrt, sum, triu
from pandas import DataFrame, Series
from pandas_ta._typing import Array, DictLike, Float, Int, IntFloat, List, Optional
from pandas_ta._typing import (
Array,
DictLike,
Float,
Int,
IntFloat,
List,
Optional
)
from pandas_ta.maps import Imports
from pandas_ta.utils._validate import v_series
+12 -6
View File
@@ -3,7 +3,13 @@ from functools import partial
from pandas import DataFrame, Series
from pandas.api.types import is_datetime64_any_dtype
from pandas_ta._typing import (
Float, Int, IntFloat, List, MaybeSeriesFrame, Optional, SeriesFrame
Float,
Int,
IntFloat,
List,
MaybeSeriesFrame,
Optional,
SeriesFrame
)
@@ -99,7 +105,7 @@ def v_offset(var: Int) -> Int:
def v_pos_default(
var: IntFloat, default: IntFloat = 0, strict: bool = True, complement: bool = False
) -> IntFloat:
return partial(v_lowerbound, bound=0)\
return partial(v_lowerbound, bound=0) \
(var=var, default=default, strict=strict, complement=complement)
def v_scalar(var: IntFloat, default: Optional[IntFloat] = 1) -> Float:
@@ -111,10 +117,10 @@ def v_scalar(var: IntFloat, default: Optional[IntFloat] = 1) -> Float:
def v_series(series: Series, length: Optional[IntFloat] = 0) -> Optional[Series]:
"""Returns None if the Pandas Series does not meet the minimum length
required for the indicator."""
if isinstance(series, Series) and series.empty and series.size >= length:
print("[X] Requires a Pandas Series or DataFrame.")
return None
return series
if series is not None and isinstance(series, Series):
if series.size >= v_pos_default(length, 0):
return series
return None
def v_talib(var: bool) -> bool:
"""Returns True by default"""
+1 -1
View File
@@ -49,7 +49,7 @@ def aberration(
# Validate
length = v_pos_default(length, 5)
atr_length = v_pos_default(atr_length, 15)
_length = max(atr_length, length)
_length = max(atr_length, length) + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
+8 -2
View File
@@ -2,8 +2,14 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.utils import non_zero_range, v_drift, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
non_zero_range,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def accbands(
+9 -6
View File
@@ -53,9 +53,10 @@ def atr(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
_length = length + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
if high is None or low is None or close is None:
return
@@ -75,9 +76,11 @@ def atr(
high=high, low=low, close=close,
talib=mode_tal, prenan=prenan, drift=drift
)
sma_nth = tr[0:length].mean()
tr[:length - 1] = nan
tr.iloc[length - 1] = sma_nth
presma = kwargs.pop("presma", True)
if presma:
sma_nth = tr[0:length].mean()
tr[:length - 1] = nan
tr.iloc[length - 1] = sma_nth
atr = ma(mamode, tr, length=length, talib=mode_tal)
percent = kwargs.pop("percent", False)
+13 -7
View File
@@ -2,10 +2,16 @@
from numpy import nan, uintc, zeros_like
from pandas import Series
from pandas_ta._typing import Array, DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.ma import ma as _ma
from pandas_ta.maps import Imports
from pandas_ta.utils import v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_series, v_talib
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib
)
from pandas_ta.volatility import atr
@@ -16,7 +22,7 @@ except ImportError:
@njit
def np_atrts(x: Array, ma_: Array, atr_: Array, length: Int, ma_length: Int):
def np_atrts(x: Array, ma: Array, atr_: Array, length: Int, ma_length: Int):
m = x.size
k = max(length, ma_length)
@@ -24,7 +30,7 @@ def np_atrts(x: Array, ma_: Array, atr_: Array, length: Int, ma_length: Int):
up = zeros_like(x, dtype=uintc)
dn = zeros_like(x, dtype=uintc)
expn = x > ma_
expn = x > ma
up[expn], dn[~expn] = 1, 1
up[:k], dn[:k] = 0, 0
result[:k] = nan
@@ -90,7 +96,7 @@ def atrts(
# Validate
length = v_pos_default(length, 14)
ma_length = v_pos_default(ma_length, 20)
_length = max(length, ma_length)
_length = length + ma_length
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
@@ -116,7 +122,7 @@ def atrts(
)
atr_ *= multiplier
ma_ = ma(mamode, close, length=ma_length, talib=mode_tal)
ma_ = _ma(mamode, close, length=ma_length, talib=mode_tal)
np_close, np_ma, np_atr = close.values, ma_.values, atr_.values
np_atrts_, _, _ = np_atrts(np_close, np_ma, np_atr, length, ma_length)
+9 -2
View File
@@ -4,8 +4,15 @@ from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.maps import Imports
from pandas_ta.statistics import stdev
from pandas_ta.utils import non_zero_range, tal_ma, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
non_zero_range,
tal_ma,
v_mamode,
v_offset,
v_pos_default,
v_series,
v_talib
)
def bbands(
+12 -5
View File
@@ -2,8 +2,14 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.utils import high_low_range, v_bool, v_offset
from pandas_ta.utils import v_mamode, v_pos_default, v_series
from pandas_ta.utils import (
high_low_range,
v_bool,
v_mamode,
v_offset,
v_pos_default,
v_series
)
from .true_range import true_range
@@ -42,9 +48,10 @@ def kc(
"""
# Validate
length = v_pos_default(length, 20)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
_length = length + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
if high is None or low is None or close is None:
return
+8 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.overlap import ema
@@ -37,7 +38,7 @@ def massi(
slow = v_pos_default(slow, 25)
if slow < fast:
fast, slow = slow, fast
_length = max(fast, slow)
_length = 2 * max(fast, slow) - min(fast, slow)
high = v_series(high, _length)
low = v_series(low, _length)
@@ -51,10 +52,16 @@ def massi(
# Calculate
high_low_range = non_zero_range(high, low)
hl_ema1 = ema(close=high_low_range, length=fast, **kwargs)
if all(isnan(hl_ema1)):
return # Emergency Break
hl_ema2 = ema(close=hl_ema1, length=fast, **kwargs)
if all(isnan(hl_ema2)):
return # Emergency Break
hl_ratio = hl_ema1 / hl_ema2
massi = hl_ratio.rolling(slow, min_periods=slow).sum()
if all(isnan(massi)):
return # Emergency Break
# Offset
if offset != 0:
+13 -5
View File
@@ -2,8 +2,15 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.maps import Imports
from pandas_ta.utils import v_drift, v_mamode, v_offset, v_pos_default
from pandas_ta.utils import v_scalar, v_series, v_talib
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_scalar,
v_series,
v_talib
)
from pandas_ta.volatility import atr
@@ -40,9 +47,10 @@ def natr(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
_length = length + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
if high is None or low is None or close is None:
return
+8 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.utils import non_zero_range, v_drift, v_offset, v_series
@@ -32,18 +33,24 @@ def pdist(
pd.Series: New feature generated.
"""
# Validate
drift = v_drift(drift)
open_ = v_series(open_)
high = v_series(high)
low = v_series(low)
close = v_series(close)
drift = v_drift(drift)
offset = v_offset(offset)
# Calculate
pdist = 2 * non_zero_range(high, low)
if all(isnan(pdist)):
return # Emergency Break
pdist += non_zero_range(open_, close.shift(drift)).abs()
pdist -= non_zero_range(close, open_).abs()
if all(isnan(pdist)):
return # Emergency Break
# Offset
if offset != 0:
pdist = pdist.shift(offset)
+14 -3
View File
@@ -1,10 +1,18 @@
# -*- coding: utf-8 -*-
from numpy import isnan
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.ma import ma
from pandas_ta.statistics import stdev
from pandas_ta.utils import unsigned_differences, v_bool, v_drift
from pandas_ta.utils import v_mamode, v_offset, v_pos_default, v_series
from pandas_ta.utils import (
unsigned_differences,
v_bool,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def _rvi(source, length, scalar, mode, drift):
@@ -62,7 +70,7 @@ def rvi(
"""
# Validate
length = v_pos_default(length, 14)
close = v_series(close, length)
close = v_series(close, length + 2)
if close is None:
return
@@ -94,6 +102,9 @@ def rvi(
else:
rvi = _rvi(close, length, scalar, mamode, drift)
if all(isnan(rvi)):
return # Emergency Break
# Offset
if offset != 0:
rvi = rvi.shift(offset)
+10 -4
View File
@@ -2,8 +2,14 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import v_bool, v_drift, v_mamode
from pandas_ta.utils import v_offset, v_pos_default, v_series
from pandas_ta.utils import (
v_bool,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def thermo(
@@ -40,8 +46,8 @@ def thermo(
"""
# Validate
length = v_pos_default(length, 20)
high = v_series(high, length)
low = v_series(low, length)
high = v_series(high, length + 1)
low = v_series(low, length + 1)
if high is None or low is None:
return
+14 -4
View File
@@ -1,10 +1,16 @@
# -*- coding: utf-8 -*-
from numpy import nan
from numpy import isnan, nan
from pandas import concat, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import non_zero_range, v_bool, v_drift
from pandas_ta.utils import v_offset, v_series, v_talib
from pandas_ta.utils import (
non_zero_range,
v_bool,
v_drift,
v_offset,
v_series,
v_talib
)
def true_range(
@@ -39,12 +45,13 @@ def true_range(
pd.Series: New feature
"""
# Validate
drift = v_drift(drift)
high = v_series(high)
low = v_series(low)
close = v_series(close)
mode_tal = v_talib(talib)
prenan = v_bool(prenan, False)
drift = v_drift(drift)
offset = v_offset(offset)
# Calculate
@@ -60,6 +67,9 @@ def true_range(
if prenan:
true_range.iloc[:drift] = nan
if all(isnan(true_range)):
return # Emergency Break
# Offset
if offset != 0:
true_range = true_range.shift(offset)
+4 -3
View File
@@ -40,7 +40,7 @@ def ui(
# Validate
length = v_pos_default(length, 14)
scalar = v_pos_default(scalar, 100)
close = v_series(close, length)
close = v_series(close, 2 * length - 1)
if close is None:
return
@@ -56,9 +56,10 @@ def ui(
everget = kwargs.pop("everget", False)
if everget:
# Everget uses SMA instead of SUM for calculation
ui = (sma(d2, length) / length).apply(sqrt)
_ui = sma(d2, length)
else:
ui = (d2.rolling(length).sum() / length).apply(sqrt)
_ui = d2.rolling(length).sum()
ui = sqrt(_ui / length)
# Offset
if offset != 0:
+1 -1
View File
@@ -50,7 +50,7 @@ def aobv(
if slow < fast:
fast, slow = slow, fast
_length = max(fast, slow, max_lookback, min_lookback)
_length = max(max_lookback, min_lookback) + slow
close = v_series(close, _length)
volume = v_series(volume, _length)
+7 -2
View File
@@ -2,8 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def efi(
+12 -6
View File
@@ -2,8 +2,13 @@
from pandas import Series
from pandas_ta._typing import DictLike, Int, IntFloat
from pandas_ta.overlap import hl2, sma
from pandas_ta.utils import non_zero_range, v_drift
from pandas_ta.utils import v_pos_default, v_offset, v_series
from pandas_ta.utils import (
non_zero_range,
v_drift,
v_pos_default,
v_offset,
v_series
)
def eom(
@@ -41,10 +46,11 @@ def eom(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
volume = v_series(volume, length)
_length = length + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
volume = v_series(volume, _length)
if high is None or low is None or close is None or volume is None:
return
+10 -4
View File
@@ -4,8 +4,14 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.overlap import hlc3
from pandas_ta.utils import signed_series, v_drift, v_mamode, v_offset
from pandas_ta.utils import v_pos_default, v_series
from pandas_ta.utils import (
signed_series,
v_drift,
v_mamode,
v_offset,
v_pos_default,
v_series
)
def kvo(
@@ -44,7 +50,8 @@ def kvo(
# Validate
fast = v_pos_default(fast, 34)
slow = v_pos_default(slow, 55)
_length = max(fast, slow - 1)
signal = v_pos_default(signal, 13)
_length = max(fast, slow) + signal
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
@@ -53,7 +60,6 @@ def kvo(
if high is None or low is None or close is None or volume is None:
return
signal = v_pos_default(signal, 13)
mamode = v_mamode(mamode, "ema")
drift = v_drift(drift)
offset = v_offset(offset)
+18 -8
View File
@@ -3,7 +3,13 @@ from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.overlap import hlc3
from pandas_ta.utils import v_drift, v_offset, v_pos_default, v_series, v_talib
from pandas_ta.utils import (
v_drift,
v_offset,
v_pos_default,
v_series,
v_talib
)
def mfi(
@@ -39,10 +45,11 @@ def mfi(
"""
# Validate
length = v_pos_default(length, 14)
high = v_series(high, length)
low = v_series(low, length)
close = v_series(close, length)
volume = v_series(volume, length)
_length = length + 1
high = v_series(high, _length)
low = v_series(low, _length)
close = v_series(close, _length)
volume = v_series(volume, _length)
if high is None or low is None or close is None or volume is None:
return
@@ -59,9 +66,12 @@ def mfi(
typical_price = hlc3(high=high, low=low, close=close, talib=mode_tal)
raw_money_flow = typical_price * volume
tdf = DataFrame(
{"diff": 0, "rmf": raw_money_flow, "+mf": 0, "-mf": 0}
)
tdf = DataFrame({
"diff": 0,
"rmf": raw_money_flow,
"+mf": 0,
"-mf": 0
})
tdf.loc[(typical_price.diff(drift) > 0), "diff"] = 1
tdf.loc[tdf["diff"] == 1, "+mf"] = raw_money_flow
+3 -2
View File
@@ -32,8 +32,9 @@ def pvt(
"""
# Validate
drift = v_drift(drift)
close = v_series(close, drift)
volume = v_series(volume, drift)
_drift = drift + 1
close = v_series(close, _drift)
volume = v_series(volume, _drift)
if close is None or volume is None:
return
+11 -3
View File
@@ -2,8 +2,15 @@
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import signed_series, v_drift, v_mamode
from pandas_ta.utils import v_pos_default, v_offset, v_series, zero
from pandas_ta.utils import (
signed_series,
v_drift,
v_mamode,
v_pos_default,
v_offset,
v_series,
zero
)
def wb_tsv(
@@ -45,7 +52,8 @@ def wb_tsv(
# Validate
length = v_pos_default(length, 18)
signal = v_pos_default(signal, 10)
close = v_series(close, max(length, signal))
_length = max(length, signal) - 2
close = v_series(close, _length)
if close is None:
return
+1 -1
View File
@@ -20,7 +20,7 @@ setup(
"pandas_ta.volatility",
"pandas_ta.volume"
],
version=".".join(("0", "3", "63b")),
version=".".join(("0", "3", "64b")),
description=long_description,
long_description=long_description,
author="Kevin Johnson",
+1 -1
View File
@@ -88,7 +88,7 @@ _tdpy = pandas_ta.RATE["TRADING_DAYS_PER_YEAR"]
sample_data = load(
n = [
-2 * _tdpy, -_tdpy,
-90, 0, 90,
-89, 0, 89,
_tdpy, 2 * _tdpy
][0],
verbose=VERBOSE
+1 -1
View File
@@ -86,7 +86,7 @@ class TestOverlapExtension(TestCase):
def test_linreg_ext(self):
self.data.ta.linreg(append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "LR_14")
self.assertEqual(self.data.columns[-1], "LINREG_14")
def test_mama_ext(self):
self.data.ta.mama(append=True)

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