diff --git a/pandas_ta/trend/ha.py b/pandas_ta/trend/ha.py index dc41edb..d72e4ce 100644 --- a/pandas_ta/trend/ha.py +++ b/pandas_ta/trend/ha.py @@ -7,23 +7,23 @@ from pandas_ta.utils import get_offset, verify_series def ha(open, high, low, close, offset=None, **kwargs): # indicator : Heikin Ashi # Validate Arguments - open = verify_series(open) + open_ = verify_series(open) high = verify_series(high) low = verify_series(low) close = verify_series(close) offset = get_offset(offset) - #calculate ha_close - ha_close = 0.25 * (open + high + low + close) + # calculate ha_close + ha_close = 0.25 * (open_ + high + low + close) # Initialization of the ha_open array ha_open = np.zeros(shape=(len(close))) # ha_open of the first element - ha_open[0] = 0.5 * (open[0] + close[0]) + ha_open[0] = 0.5 * (open_[0] + close[0]) - #calculate ha_open. Based on previous ha_open & ha_close - for i in range (1, len(close)): + # calculate ha_open. Based on previous ha_open & ha_close + for i in range(1, len(close)): ha_open[i] = 0.5 * (ha_open[i-1] + ha_close[i-1]) # calculation of ha_high & ha_low @@ -51,7 +51,7 @@ def ha(open, high, low, close, offset=None, **kwargs): ha.__doc__ = \ - """Heikin Ashi (HA) +"""Heikin Ashi (HA) The Heikin-Ashi technique averages price data to create a Japanese candlestick chart that filters out market noise. Heikin-Ashi charts, developed by Munehisa Homma in the 1700s, @@ -84,7 +84,7 @@ HA=Heikin-Ashi With the first HA calculated, it is now possible to continue computing the HA candles per the formulas. ​​ Args: - open (pd.Series): Series of 'open's + open_ (pd.Series): Series of 'open's high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's diff --git a/pandas_ta/trend/supertrend.py b/pandas_ta/trend/supertrend.py index f32b315..bf5ccee 100644 --- a/pandas_ta/trend/supertrend.py +++ b/pandas_ta/trend/supertrend.py @@ -4,57 +4,51 @@ from pandas import DataFrame from ..utils import get_offset, verify_series from ..volatility import atr -def supertrend(high, low, close, period=None, multiplier=None, mamode=None, drift=None, offset=None, **kwargs): + +def supertrend(high, low, close, length=None, multiplier=None, mamode=None, drift=None, offset=None, **kwargs): # indicator : supertrend # Validate Arguments high = verify_series(high) low = verify_series(low) close = verify_series(close) offset = get_offset(offset) - period = int(period) if period and period > 0 else 10 - multiplier = float(multiplier) if multiplier and multiplier > 0 else 1.5 + length = int(length) if length and length > 0 else 10 + multiplier = float(multiplier) if multiplier and multiplier > 0 else 3 min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs[ - 'min_periods'] is not None else period + 'min_periods'] is not None else length - st_updown = np.zeros(shape=(len(close))) + supertrend_dir = np.zeros(shape=(len(close))) strend = np.zeros(shape=(len(close))) # Bands initial calculation midrange = 0.5 * (high + low) - distance = multiplier * atr(high, low, close, period, mamode, drift, offset, min_periods=min_periods) + distance = multiplier * atr(high, low, close, length, mamode, drift, offset, min_periods=min_periods) lowerband = midrange - distance upperband = midrange + distance # final calculation loop for i in range(1, len(close)): - if close[i] > upperband[i-1]: - st_updown[i] = 1 - elif close[i] < lowerband[i-1]: - st_updown[i] = -1 + if close[i] > upperband[i - 1]: + supertrend_dir[i] = 1 + elif close[i] < lowerband[i - 1]: + supertrend_dir[i] = -1 else: - st_updown[i] = st_updown[i-1] - if st_updown[i] > 0 and lowerband[i] < lowerband[i-1]: - lowerband[i] = lowerband[i-1] - if st_updown[i] < 0 and upperband[i] > upperband[i-1]: - upperband[i] = upperband[i-1] - if st_updown[i] < 0 and st_updown[i-1] > 0: - upperband = midrange + distance - if st_updown[i] > 0 and st_updown[i-1] < 0: - lowerband = midrange - distance - if st_updown[i] < 0 : + supertrend_dir[i] = supertrend_dir[i - 1] + if supertrend_dir[i] > 0 and lowerband[i] < lowerband[i - 1]: + lowerband[i] = lowerband[i - 1] + if supertrend_dir[i] < 0 and upperband[i] > upperband[i - 1]: + upperband[i] = upperband[i - 1] + if supertrend_dir[i] < 0: strend[i] = upperband[i] else: strend[i] = lowerband[i] - # Prepare DataFrame to return - data = {f"supertrend_{period}_{multiplier}": strend, f"st_updown_{period}_{multiplier}": st_updown} + data = {f"supertrend_{length}_{multiplier}": strend, f"supertrend_dir_{length}_{multiplier}": supertrend_dir} supertrend_df = DataFrame(data) - supertrend_df.name = f"supertrend_{period}_{multiplier}" + supertrend_df.name = f"supertrend_{length}_{multiplier}" supertrend_df.category = 'trend' - - # Apply offset if needed if offset != 0: supertrend_df = supertrend_df.shift(offset) @@ -66,36 +60,45 @@ def supertrend(high, low, close, period=None, multiplier=None, mamode=None, drif if 'fill_method' in kwargs: supertrend_df.fillna(method=kwargs['fill_method'], inplace=True) - - return supertrend_df + supertrend.__doc__ = \ -"""Supertrend (supertrend) + """Supertrend (supertrend) -Supertrend is a trend indicator. It was created by Olivier Seban +Supertrend is a trend indicator. It is usually used to help identify trend direction, setting stop loss, +identify support and resistance, and / or generate buy & sell signals. +Calculation is in 2 steps : first a multiple of ATR is added and substracted to the middle of the high - low range. +This gives the upperband and lowerband. +The direction of the trend is then calculated : if close > previous upperband or < previous lowerband, +then trend direction is changed, else it is the same as previous value. +If trend direction is unchanged and down, upperband is set to minimum between current and previous value +If trend direction is unchanged and up, lowerband is set to maximum between current and previous value. -Sources: -https://www.abcbourse.com/apprendre/11_le_supertrend.html -(in french, but many other can be found using a search engine) +The final band is then choosen according to the direction of the trend : upperband if trend is downward, +lowerband if trend is upward. +Returned values are : float for final band level, int (1 : upward trend, -1 : downward trend) for trend direction Calculation: Default Inputs: - period = 10 - multiplier = 1.5 - + length = 10 + multiplier = 3 Args: high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's - + length (int) : length for ATR calculation. Default : 10 + multiplier : coefficient for upper and lower band distance to midrange. Default : 3 + mamode: parameter used for ATR calculation. See ATR documentation. Default : None (= ema) + drift : parameter used for ATR calculation. See ATR documentation. Default : None (= 1) offset (int): How many periods to offset the result. Default: 0 Kwargs: fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): Type of fill method + min_periods (int, optional) : parameter used for ATR calculation. See ATR documentation. Default : length Returns: - pd.DataFrame: supertrend, st_updown, slowk, slowd columns. -""" \ No newline at end of file + pd.DataFrame: supertrend (float), supertrend_dir (int) columns. +""" diff --git a/pandas_ta/volatility/atr.py b/pandas_ta/volatility/atr.py index c6474da..bd2ab80 100644 --- a/pandas_ta/volatility/atr.py +++ b/pandas_ta/volatility/atr.py @@ -75,6 +75,7 @@ Args: Kwargs: 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.