ENH Gann HiLo Activator added MAINT refactoring

This commit is contained in:
Kevin Johnson
2020-09-05 10:39:47 -07:00
parent a1df65746c
commit cd22bc5707
20 changed files with 817 additions and 657 deletions
+7 -2
View File
@@ -59,11 +59,15 @@ and _Weighted Moving Average_.
* _Squeeze_ (**squeeze**). A Momentum indicator. Both John Carter's TTM **and** Lazybear's TradingView versions are implemented. The default is John Carter's, or ```lazybear=False```. Set ```lazybear=True``` to enable Lazybear's.
* _TTM Trend_ (**ttm_trend**). A trend indicator inspired from John Carter's book "Mastering the Trade".
* _SMI Ergodic_ (**smi**) Developed by William Blau, the SMI Ergodic Indicator is the same as the True Strength Index (TSI) except the SMI includes a signal line and oscillator.
* _Gann High-Low 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
indicator consisting of two different simple moving averages.
## __Updated Indicators__
* _Fisher Transform_ (**fisher**): Added Fisher's default **ema** signal line. To change the length of the signal line, use the argument: ```signal=5```. Default: 5
* _Fisher Transform_ (**fisher**) and _Kaufman's Adaptive Moving Average_ (**kama**): Fixed a bug where their columns were not added to final DataFrame when using the _strategy_ method.
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series.
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series.
* _Average True Range_ (**atr**): Added option to return **atr** as a percentage. See: ```help(ta.atr)```
## What is a Pandas DataFrame Extension?
@@ -358,11 +362,12 @@ print(bothhl2.name) # "pre_HL2_post"
|:--------:|
| ![Example MACD](/images/SPY_MACD.png) |
## _Overlap_ (26)
## _Overlap_ (27)
* _Double Exponential Moving Average_: **dema**
* _Exponential Moving Average_: **ema**
* _Fibonacci's Weighted Moving Average_: **fwma**
* _Gann High-Low Activator_: **hilo**
* _High-Low Average_: **hl2**
* _High-Low-Close Average_: **hlc3**
* Commonly known as 'Typical Price' in Technical Analysis literature
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+112 -125
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -28,7 +28,7 @@ Category = {
"momentum": ["ao", "apo", "bias", "bop", "brar", "cci", "cg", "cmo", "coppock", "er", "eri", "fisher", "inertia", "kdj", "kst", "macd", "mom", "pgo", "ppo", "psl", "pvo", "roc", "rsi", "rvgi", "slope", "smi", "squeeze", "stoch", "trix", "tsi", "uo", "willr"],
# Overlap
"overlap": ["dema", "ema", "fwma", "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"],
+10 -1
View File
@@ -23,7 +23,7 @@ from pandas_ta.volatility import *
from pandas_ta.volume import *
from pandas_ta.utils import *
version = ".".join(("0", "1", "98b"))
version = ".".join(("0", "1", "99b"))
def mp_worker(args):
@@ -900,6 +900,15 @@ class AnalysisIndicators(BasePandasObject):
result = fwma(close=close, length=length, offset=offset, **kwargs)
return result
@finalize
def hilo(self, high=None, low=None, close=None, high_length=None, low_length=None, offset=None, **kwargs):
high = self._get_column(high, "high")
low = self._get_column(low, "low")
close = self._get_column(close, "close")
result = hilo(high=high, low=low, close=close, high_length=high_length, low_length=low_length, offset=offset, **kwargs)
return result
@finalize
def hl2(self, high=None, low=None, offset=None, **kwargs):
high = self._get_column(high, "high")
+6 -6
View File
@@ -33,14 +33,14 @@ def cmo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
cmo = cmo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
cmo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
cmo.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
cmo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
cmo.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
cmo.name = f"CMO_{length}"
cmo.category = 'momentum'
cmo.category = "momentum"
return cmo
@@ -65,11 +65,11 @@ Calculation:
Args:
close (pd.Series): Series of 'close's
scalar (float): How much to magnify. Default: 100
talib (bool): If True, uses TA-Libs implementation. Otherwise uses EMA version. Default: True
drift (int): The short period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
talib (bool): If True, uses TA-Libs implementation. Otherwise uses EMA version. Default: True
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
+1
View File
@@ -2,6 +2,7 @@
from .dema import dema
from .ema import ema
from .fwma import fwma
from .hilo import hilo
from .hl2 import hl2
from .hlc3 import hlc3
from .hma import hma
+133
View File
@@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
from numpy import NaN as npNaN
from pandas import DataFrame, Series
from .ema import ema
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):
"""Indicator: Gann HiLo (HiLo)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
high_length = int(high_length) if high_length and high_length > 0 else 13
low_length = int(low_length) if low_length and low_length > 0 else 21
mamode = mamode.lower() if mamode else "sma"
offset = get_offset(offset)
# Calculate Result
m = close.size
hilo = Series(npNaN, index=close.index)
long = Series(npNaN, index=close.index)
short = Series(npNaN, index=close.index)
if mamode == "ema":
high_ma = ema(high, high_length)
low_ma = ema(low, low_length)
if mamode == "hma":
high_ma = hma(high, high_length)
low_ma = hma(low, low_length)
else: # "sma"
high_ma = sma(high, high_length)
low_ma = sma(low, low_length)
for i in range(1, m):
if close.iloc[i] > high_ma.iloc[i - 1]:
hilo.iloc[i] = long.iloc[i] = low_ma.iloc[i]
elif close.iloc[i] < low_ma.iloc[i - 1]:
hilo.iloc[i] = short.iloc[i] = high_ma.iloc[i]
else:
hilo.iloc[i] = hilo.iloc[i - 1]
long.iloc[i] = short.iloc[i] = hilo.iloc[i - 1]
# Offset
if offset != 0:
hilo = hilo.shift(offset)
# Handle fills
if "fillna" in kwargs:
hilo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
hilo.fillna(method=kwargs["fill_method"], inplace=True)
# 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.name = f"HILO{_props}"
df.category = "overlap"
return df
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
indicator consisting of two different simple moving averages.
The indicator tracks both curves (of the highs and the lows). The close of the
bar defines which of the two gets plotted.
Increasing high_length and decreasing low_length better for short trades,
vice versa for long positions.
Sources:
https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=447&Name=Gann_HiLo_Activator
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
https://www.tradingview.com/script/XNQSLIYb-Gann-High-Low/
Calculation:
Default Inputs:
high_length=13, low_length=21, mamode="sma"
EMA = Exponential Moving Average
HMA = Hull Moving Average
SMA = Simple Moving Average # Default
if "ema":
high_ma = EMA(high, high_length)
low_ma = EMA(low, low_length)
elif "hma":
high_ma = HMA(high, high_length)
low_ma = HMA(low, low_length)
else: # "sma"
high_ma = SMA(high, high_length)
low_ma = SMA(low, low_length)
# Similar to Supertrend MA selection
hilo = Series(npNaN, index=close.index)
for i in range(1, m):
if close.iloc[i] > high_ma.iloc[i - 1]:
hilo.iloc[i] = low_ma.iloc[i]
elif close.iloc[i] < low_ma.iloc[i - 1]:
hilo.iloc[i] = high_ma.iloc[i]
else:
hilo.iloc[i] = hilo.iloc[i - 1]
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
high_length (int): It's period. Default: 13
low_length (int): It's period. Default: 21
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
presma (bool, optional): If True, uses SMA for initial value.
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: HILO (line), HILOl (long), HILOs (short) columns.
"""
+1 -1
View File
@@ -18,7 +18,7 @@ def rma(close, length=None, offset=None, **kwargs):
# Name & Category
rma.name = f"RMA_{length}"
rma.category = 'overlap'
rma.category = "overlap"
return rma
+4 -4
View File
@@ -60,11 +60,11 @@ def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kw
df = df.shift(offset)
# Handle fills
if 'fillna' in kwargs:
df.fillna(kwargs['fillna'], inplace=True)
if "fillna" in kwargs:
df.fillna(kwargs["fillna"], inplace=True)
if 'fill_method' in kwargs:
df.fillna(method=kwargs['fill_method'], inplace=True)
if "fill_method" in kwargs:
df.fillna(method=kwargs["fill_method"], inplace=True)
return df
+4 -2
View File
@@ -227,8 +227,7 @@ def signals(indicator, xa, xb, cross_values, xserie, xserie_a, xserie_b, cross_s
def df_error_analysis(dfA: pd.DataFrame, dfB: pd.DataFrame, **kwargs) -> pd.DataFrame:
""" """
col = kwargs.pop("col", None)
"""DataFrame Correlation Analysis helper"""
corr_method = kwargs.pop("corr_method", "pearson")
# Find their differences and correlation
@@ -241,6 +240,9 @@ def df_error_analysis(dfA: pd.DataFrame, dfB: pd.DataFrame, **kwargs) -> pd.Data
if diff[diff > 0].any():
diff.plot(kind="kde")
if kwargs.pop("triangular", False):
return corr.where(np.triu(np.ones(corr.shape)).astype(np.bool))
return corr
def fibonacci(**kwargs) -> np.ndarray:
+12 -12
View File
@@ -32,16 +32,16 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
atr_ = atr_.shift(offset)
# Handle fills
if 'fillna' in kwargs:
zg.fillna(kwargs['fillna'], inplace=True)
sg.fillna(kwargs['fillna'], inplace=True)
xg.fillna(kwargs['fillna'], inplace=True)
atr_.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
zg.fillna(method=kwargs['fill_method'], inplace=True)
sg.fillna(method=kwargs['fill_method'], inplace=True)
xg.fillna(method=kwargs['fill_method'], inplace=True)
atr_.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
zg.fillna(kwargs["fillna"], inplace=True)
sg.fillna(kwargs["fillna"], inplace=True)
xg.fillna(kwargs["fillna"], inplace=True)
atr_.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
zg.fillna(method=kwargs["fill_method"], inplace=True)
sg.fillna(method=kwargs["fill_method"], inplace=True)
xg.fillna(method=kwargs["fill_method"], inplace=True)
atr_.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_props = f"_{length}_{atr_length}"
@@ -49,7 +49,7 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
sg.name = f"ABER_SG{_props}"
xg.name = f"ABER_XG{_props}"
atr_.name = f"ABER_ATR{_props}"
zg.category = sg.category = 'volatility'
zg.category = sg.category = "volatility"
xg.category = atr_.category = zg.category
# Prepare DataFrame to return
@@ -61,7 +61,7 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
}
aberdf = DataFrame(data)
aberdf.name = f"ABER{_props}"
aberdf.category = 'volatility'
aberdf.category = zg.category
return aberdf
+24 -20
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..utils import get_drift, get_offset, non_zero_range, verify_series
from pandas_ta.overlap import ema, sma
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, offset=None, **kwargs):
"""Indicator: Acceleration Bands (ACCBANDS)"""
@@ -12,7 +13,7 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
length = int(length) if length and length > 0 else 20
c = float(c) if c and c > 0 else 4
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
mamode = mamode.lower() if mamode else 'sma'
mamode = mamode.lower() if mamode else "sma"
drift = get_drift(drift)
offset = get_offset(offset)
@@ -22,14 +23,17 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
_lower = low * (1 - hl_ratio)
_upper = high * (1 + hl_ratio)
if mamode is None or mamode == 'sma':
lower = _lower.rolling(length, min_periods=min_periods).mean()
mid = close.rolling(length, min_periods=min_periods).mean()
upper = _upper.rolling(length, min_periods=min_periods).mean()
elif mamode == 'ema':
lower = _lower.ewm(span=length, min_periods=min_periods).mean()
mid = close.ewm(span=length, min_periods=min_periods).mean()
upper = _upper.ewm(span=length, min_periods=min_periods).mean()
if mamode == "ema":
# lower = _lower.ewm(span=length, min_periods=min_periods).mean()
# mid = close.ewm(span=length, min_periods=min_periods).mean()
# upper = _upper.ewm(span=length, min_periods=min_periods).mean()
lower = ema(_lower, length=length)
mid = ema(close, length=length)
upper = ema(_upper, length=length)
else: # "sma"
lower = sma(_lower, length=length)
mid = sma(close, length=length)
upper = sma(_upper, length=length)
# Offset
if offset != 0:
@@ -38,26 +42,26 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
upper = upper.shift(offset)
# Handle fills
if 'fillna' in kwargs:
lower.fillna(kwargs['fillna'], inplace=True)
mid.fillna(kwargs['fillna'], inplace=True)
upper.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
lower.fillna(method=kwargs['fill_method'], inplace=True)
mid.fillna(method=kwargs['fill_method'], inplace=True)
upper.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
lower.fillna(kwargs["fillna"], inplace=True)
mid.fillna(kwargs["fillna"], inplace=True)
upper.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
lower.fillna(method=kwargs["fill_method"], inplace=True)
mid.fillna(method=kwargs["fill_method"], inplace=True)
upper.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
lower.name = f"ACCBL_{length}"
mid.name = f"ACCBM_{length}"
upper.name = f"ACCBU_{length}"
mid.category = upper.category = lower.category = 'volatility'
mid.category = upper.category = lower.category = "volatility"
# Prepare DataFrame to return
data = {lower.name: lower, mid.name: mid, upper.name: upper}
accbandsdf = DataFrame(data)
accbandsdf.name = f"ACCBANDS_{length}"
accbandsdf.category = 'volatility'
accbandsdf.category = mid.category
return accbandsdf
+28 -21
View File
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
# from ..overlap.ema import ema
from ..overlap.rma import rma
from pandas_ta.overlap import ema, rma
from .true_range import true_range
from ..utils import get_drift, get_offset, verify_series
from pandas_ta.utils import get_drift, get_offset, verify_series
def atr(high, low, close, length=None, mamode=None, drift=None, offset=None, **kwargs):
"""Indicator: Average True Range (ATR)"""
@@ -11,32 +10,37 @@ def atr(high, low, close, length=None, mamode=None, drift=None, offset=None, **k
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
mamode = mamode.lower() if mamode else 'ema'
mamode = mamode.lower() if mamode else "ema"
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
tr = true_range(high=high, low=low, close=close, drift=drift)
if mamode == 'ema':
alpha = (1.0 / length) if length > 0 else 0.5
atr = tr.ewm(alpha=alpha, min_periods=min_periods).mean()
if mamode == "ema":
# alpha = (1.0 / length) if length > 0 else 0.5
# atr = tr.ewm(alpha=alpha).mean()
atr = rma(tr, length=length)
else:
atr = tr.rolling(length, min_periods=min_periods).mean()
# atr = tr.rolling(length).mean()
atr = sma(tr, length=length)
percentage = kwargs.pop("percent", False)
if percentage:
atr *= 100 / close
# Offset
if offset != 0:
atr = atr.shift(offset)
# Handle fills
if 'fillna' in kwargs:
atr.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
atr.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
atr.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
atr.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
atr.name = f"ATR_{length}"
atr.category = 'volatility'
atr.name = f"ATR{'p' if percentage else ''}_{length}"
atr.category = "volatility"
return atr
@@ -53,7 +57,7 @@ Sources:
Calculation:
Default Inputs:
length=14, drift=1
length=14, drift=1, percent=False
SMA = Simple Moving Average
EMA = Exponential Moving Average
TR = True Range
@@ -63,19 +67,22 @@ Calculation:
else:
ATR = SMA(tr, length)
if percent:
ATR *= 100 / close
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): It's period. Default: 14
mamode (str): Two options: None or 'ema'. Default: 'ema'
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
length (int): It's period. Default: 14
mamode (str): Two options: None or 'ema'. Default: 'ema'
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
percent (bool, optional): Return as percentage. Default: False
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
min_periods (int, optional) : Minimum number of periods before calculating ATR. Default : length
Returns:
pd.Series: New feature generated.
+18 -16
View File
@@ -14,13 +14,12 @@ def kc(high, low, close, length=None, scalar=None, mamode=None, offset=None, **k
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 20
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
scalar = float(scalar) if scalar and scalar > 0 else 2
use_tr = kwargs.pop("tr", True)
mamode = mamode.lower() if mamode else None
offset = get_offset(offset)
# Calculate Result
use_tr = kwargs.pop("tr", True)
if use_tr:
range_ = true_range(high, low, close)
else:
@@ -82,21 +81,22 @@ Sources:
Calculation:
Default Inputs:
length=20, scalar=2, mamode=None
ATR = Average True Range
EMA = Exponential Moving Average
length=20, scalar=2, mamode=None, tr=True
TR = True Range
SMA = Simple Moving Average
EMA = Exponential Moving Average
if tr:
RANGE = TR(high, low, close)
else:
RANGE = high - low
BAND = ATR(high, low, close)
if mamode == "ema":
BASIS = EMA(close, length)
BASIS = sma(close, length)
BAND = sma(RANGE, length)
elif mamode == "sma":
BASIS = SMA(close, length)
else: # Typical Price
hl_range = high - low
tp = typical_price = hlc3(high, low, close)
BASIS = SMA(tp, length)
BAND = SMA(hl_range, length)
BASIS = sma(close, length)
BAND = sma(RANGE, length)
LOWER = BASIS - scalar * BAND
UPPER = BASIS + scalar * BAND
@@ -106,11 +106,13 @@ Args:
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): The short period. Default: 20
scalar (float): A positive float to scale the bands. Default: 2
mamode (str): Two options: None or "ema". Default: "ema"
offset (int): How many periods to offset the result. Default: 0
scalar (float): A positive float to scale the bands. Default: 2
mamode (str): Two options: "sma" or "ema". Default: "ema"
offset (int): How many periods to offset the result. Default: 0
Kwargs:
tr (bool): When True, it uses True Range for calculation. When False, use a
high - low as it's range calculation. Default: True
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
+8 -8
View File
@@ -30,10 +30,10 @@ def rvi(close, high=None, low=None, length=None, scalar=None, refined=None, thir
pos_std = pos * std
neg_std = neg * std
if mamode == 'sma':
if mamode == "sma":
pos_avg = sma(pos_std, length)
neg_avg = sma(neg_std, length)
else: # 'ema'
else: # "ema"
pos_avg = ema(pos_std, length)
neg_avg = ema(neg_std, length)
@@ -61,10 +61,10 @@ def rvi(close, high=None, low=None, length=None, scalar=None, refined=None, thir
rvi = rvi.shift(offset)
# Handle fills
if 'fillna' in kwargs:
rvi.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
rvi.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
rvi.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
rvi.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
rvi.name = f"RVI{_mode}_{length}"
@@ -103,9 +103,9 @@ Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): The short period. Default: 14
length (int): The short period. Default: 14
scalar (float): A positive float to scale the bands. Default: 100
mamode (str): Two options: None or 'ema'. Default: 'ema'
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
refined (bool): Use 'refined' calculation which is the average of
RVI(high) and RVI(low) instead of RVI(close). Default: False
thirds (bool): Average of high, low and close. Default: False
+4 -4
View File
@@ -30,10 +30,10 @@ def ui(close, length=None, scalar=None, offset=None, **kwargs):
ui = ui.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ui.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ui.fillna(method=kwargs['fill_method'], inplace=True)
if "fillna" in kwargs:
ui.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
ui.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
ui.name = f"UI{'' if not everget else 'e'}_{length}"
+5
View File
@@ -71,6 +71,11 @@ class TestOverlap(TestCase):
self.assertIsInstance(result, Series)
self.assertEqual(result.name, "FWMA_10")
def test_hilo(self):
result = pandas_ta.hilo(self.high, self.low, self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, "HILO_13_21")
def test_hl2(self):
result = pandas_ta.hl2(self.high, self.low)
self.assertIsInstance(result, Series)
+5
View File
@@ -38,6 +38,11 @@ class TestOverlapExtension(TestCase):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "FWMA_10")
def test_hilo_ext(self):
self.data.ta.hilo(append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(list(self.data.columns[-3:]), ["HILO_13_21", "HILOl_13_21", "HILOs_13_21"])
def test_hl2_ext(self):
self.data.ta.hl2(append=True)
self.assertIsInstance(self.data, DataFrame)