diff --git a/pandas_ta/candles/cdl_doji.py b/pandas_ta/candles/cdl_doji.py index cdb5847..ce6f483 100644 --- a/pandas_ta/candles/cdl_doji.py +++ b/pandas_ta/candles/cdl_doji.py @@ -27,7 +27,8 @@ def cdl_doji( length (int): The period. Default: 10 factor (float): Doji value. Default: 100 scalar (float): How much to magnify. Default: 100 - asint (bool): Keep results numerical instead of boolean. Default: True + asint (bool): Keep results numerical instead of boolean. + Default: True Kwargs: naive (bool, optional): If True, prefills potential Doji less than diff --git a/pandas_ta/candles/cdl_inside.py b/pandas_ta/candles/cdl_inside.py index 16075cc..e06bd36 100644 --- a/pandas_ta/candles/cdl_inside.py +++ b/pandas_ta/candles/cdl_inside.py @@ -10,13 +10,14 @@ def cdl_inside( ) -> Series: """Candle Type: Inside Bar - An Inside Bar is a bar that is engulfed by the prior highs and lows of it's - previous bar. In other words, the current bar is smaller than it's previous - bar. + An Inside Bar is a bar that is engulfed by the prior highs and lows of + it's previous bar. In other words, the current bar is smaller than it's + previous bar. - Set asbool=True if you want to know if it is an Inside Bar. Note by default - asbool=False so this returns a 0 if it is not an Inside Bar, 1 if it is an - Inside Bar and close > open, and -1 if it is an Inside Bar but close < open. + Set asbool=True if you want to know if it is an Inside Bar. Note by + default asbool=False so this returns a 0 if it is not an Inside Bar, 1 if + it is an Inside Bar and close > open, and -1 if it is an Inside Bar + but close < open. Sources: https://www.tradingview.com/script/IyIGN1WO-Inside-Bar/ diff --git a/pandas_ta/candles/cdl_pattern.py b/pandas_ta/candles/cdl_pattern.py index 4a89b77..ab394f2 100644 --- a/pandas_ta/candles/cdl_pattern.py +++ b/pandas_ta/candles/cdl_pattern.py @@ -38,11 +38,11 @@ def cdl_pattern( df = df.ta.cdl_pattern(name="all") Get only one pattern:: - + df = df.ta.cdl_pattern(name="doji") Get some patterns:: - + df = df.ta.cdl_pattern(name=["doji", "inside"]) Args: diff --git a/pandas_ta/candles/ha.py b/pandas_ta/candles/ha.py index a049ed6..4e730e5 100644 --- a/pandas_ta/candles/ha.py +++ b/pandas_ta/candles/ha.py @@ -52,7 +52,8 @@ def ha( }) for i in range(1, m): - df["HA_open"].iloc[i] = 0.5 * (df["HA_open"].iloc[i - 1] + df["HA_close"].iloc[i - 1]) + df["HA_open"].iloc[i] = 0.5 * (df["HA_open"].iloc[i - 1] \ + + df["HA_close"].iloc[i - 1]) df["HA_high"] = df[["HA_open", "HA_high", "HA_close"]].max(axis=1) df["HA_low"] = df[["HA_open", "HA_low", "HA_close"]].min(axis=1) diff --git a/pandas_ta/cycles/ebsw.py b/pandas_ta/cycles/ebsw.py index ed3d52f..fbd9091 100644 --- a/pandas_ta/cycles/ebsw.py +++ b/pandas_ta/cycles/ebsw.py @@ -11,20 +11,23 @@ def ebsw( ) -> Series: """Even Better SineWave (EBSW) - This indicator measures market cycles and uses a low pass filter to remove noise. - Its output is bound signal between -1 and 1 and the maximum length of a detected - trend is limited by its length input. + This indicator measures market cycles and uses a low pass filter to + remove noise. Its output is bound signal between -1 and 1 and the + maximum length of a detected trend is limited by its length input. - Written by rengel8 for Pandas TA based on a publication at 'prorealcode.com' and - a book by J.F.Ehlers. According to the suggestion by Squigglez2* and major differences between - the initial version's output close to the implementation from Ehler's, the default version is now - more closely related to the code from pro-realcode. + Written by rengel8 for Pandas TA based on a publication at + 'prorealcode.com' and a book by J.F.Ehlers. According to the suggestion + by Squigglez2* and major differences between the initial version's + output close to the implementation from Ehler's, the default version is + now more closely related to the code from pro-realcode. Remark: - The default version is now more cycle oriented and tends to be less whipsaw-prune. Thus the older version - might offer earlier signals at medium and stronger reversals. - A test against the version at TradingView showed very close results with the advantage to be one bar/candle - faster, than the corresponding reference value. This might be pre-roll related and was not further investigated. + The default version is now more cycle oriented and tends to be less + whipsaw-prune. Thus the older version might offer earlier signals at + medium and stronger reversals. A test against the version at TradingView + showed very close results with the advantage to be one bar/candle faster, + than the corresponding reference value. This might be pre-roll related + and was not further investigated. * https://github.com/twopirllc/pandas-ta/issues/350 Sources: @@ -33,8 +36,8 @@ def ebsw( Args: close (pd.Series): Series of 'close's - length (int): It's max cycle/trend period. Values between 40-48 work like - expected with minimum value: 39. Default: 40. + length (int): It's max cycle/trend period. Values between 40-48 + work like expected with minimum value: 39. Default: 40. bars (int): Period of low pass filtering. Default: 10 drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -89,11 +92,11 @@ def ebsw( # 3 Bar average of wave amplitude and power wave = (filter_ + filtHist[1] + filtHist[0]) / 3 - power_ = ( - filter_ * filter_ + filtHist[1] * filtHist[1] + filtHist[0] * filtHist[0]) / 3 - + power_ = filter_ * filter_ + filtHist[1] * filtHist[1] \ + + filtHist[0] * filtHist[0] + power_ /= 3 # Normalize the Average Wave to Square Root of the Average Power - wave = wave / np.sqrt(power_) + wave = wave / sqrt(power_) # update storage, result filtHist.append(filter_) # append new filter_ value diff --git a/pandas_ta/cycles/reflex.py b/pandas_ta/cycles/reflex.py index 013cab5..adea56a 100644 --- a/pandas_ta/cycles/reflex.py +++ b/pandas_ta/cycles/reflex.py @@ -49,13 +49,15 @@ def reflex( """Reflex (reflex) John F. Ehlers introduced two indicators within the article - "Reflex: A New Zero-Lag Indicator” in February 2020, TASC magazine. One of which - is the Reflex, a lag reduced cycle indicator. Both indicators (Reflex/Trendflex) - are oscillators and complement each other with the focus for cycle and trend. + "Reflex: A New Zero-Lag Indicator” in February 2020, TASC magazine. One + of which is the Reflex, a lag reduced cycle indicator. Both indicators + (Reflex/Trendflex) are oscillators and complement each other with the + focus for cycle and trend. - Written for Pandas TA by rengel8 (2021-08-11) based on the implementation on - ProRealCode (see Sources). Beyond the mentioned source, this implementation has - a separate control parameter for the internal applied SuperSmoother. + Written for Pandas TA by rengel8 (2021-08-11) based on the implementation + on ProRealCode (see Sources). Beyond the mentioned source, this + implementation has a separate control parameter for the internal + applied SuperSmoother. Sources: http://traders.com/Documentation/FEEDbk_docs/2020/02/TradersTips.html diff --git a/pandas_ta/momentum/ao.py b/pandas_ta/momentum/ao.py index 67a6ebf..534bd46 100644 --- a/pandas_ta/momentum/ao.py +++ b/pandas_ta/momentum/ao.py @@ -10,8 +10,9 @@ def ao( ) -> Series: """Awesome Oscillator (AO) - The Awesome Oscillator is an indicator used to measure a security's momentum. - AO is generally used to affirm trends or to anticipate possible reversals. + The Awesome Oscillator is an indicator used to measure a security's + momentum. AO is generally used to affirm trends or to anticipate + possible reversals. Sources: https://www.tradingview.com/wiki/Awesome_Oscillator_(AO) diff --git a/pandas_ta/momentum/apo.py b/pandas_ta/momentum/apo.py index 9f6f4f2..82ba968 100644 --- a/pandas_ta/momentum/apo.py +++ b/pandas_ta/momentum/apo.py @@ -12,9 +12,10 @@ def apo( ) -> Series: """Absolute Price Oscillator (APO) - The Absolute Price Oscillator is an indicator used to measure a security's - momentum. It is simply the difference of two Exponential Moving Averages - (EMA) of two different periods. Note: APO and MACD lines are equivalent. + The Absolute Price Oscillator is an indicator used to measure a + security's momentum. It is simply the difference of two Exponential + Moving Averages (EMA) of two different periods. Note: APO and MACD lines + are equivalent. Sources: https://www.tradingtechnologies.com/xtrader-help/x-study/technical-indicator-definitions/absolute-price-oscillator-apo/ @@ -24,8 +25,8 @@ def apo( fast (int): The short period. Default: 12 slow (int): The long period. Default: 26 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/bop.py b/pandas_ta/momentum/bop.py index cc97b69..80f1434 100644 --- a/pandas_ta/momentum/bop.py +++ b/pandas_ta/momentum/bop.py @@ -22,8 +22,8 @@ def bop( low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's scalar (float): How much to magnify. Default: 1 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/cci.py b/pandas_ta/momentum/cci.py index 46caebc..bbd8bc1 100644 --- a/pandas_ta/momentum/cci.py +++ b/pandas_ta/momentum/cci.py @@ -13,8 +13,8 @@ def cci( ) -> Series: """Commodity Channel Index (CCI) - Commodity Channel Index is a momentum oscillator used to primarily identify - overbought and oversold levels relative to a mean. + Commodity Channel Index is a momentum oscillator used to primarily + identify overbought and oversold levels relative to a mean. Sources: https://www.tradingview.com/wiki/Commodity_Channel_Index_(CCI) @@ -25,8 +25,8 @@ def cci( close (pd.Series): Series of 'close's length (int): It's period. Default: 14 c (float): Scaling Constant. Default: 0.015 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/cfo.py b/pandas_ta/momentum/cfo.py index db9f3dc..cecf8e2 100644 --- a/pandas_ta/momentum/cfo.py +++ b/pandas_ta/momentum/cfo.py @@ -11,8 +11,9 @@ def cfo( ) -> Series: """Chande Forcast Oscillator (CFO) - The Forecast Oscillator calculates the percentage difference between the actual - price and the Time Series Forecast (the endpoint of a linear regression line). + The Forecast Oscillator calculates the percentage difference between + the actual price and the Time Series Forecast (the endpoint of a + linear regression line). Sources: https://www.fmlabs.com/reference/default.htm?url=ForecastOscillator.htm diff --git a/pandas_ta/momentum/cg.py b/pandas_ta/momentum/cg.py index 89954af..9169e71 100644 --- a/pandas_ta/momentum/cg.py +++ b/pandas_ta/momentum/cg.py @@ -9,8 +9,8 @@ def cg( ) -> Series: """Center of Gravity (CG) - The Center of Gravity Indicator by John Ehlers attempts to identify turning - points while exhibiting zero lag and smoothing. + The Center of Gravity Indicator by John Ehlers attempts to identify + turning points while exhibiting zero lag and smoothing. Sources: http://www.mesasoftware.com/papers/TheCGOscillator.pdf diff --git a/pandas_ta/momentum/cmo.py b/pandas_ta/momentum/cmo.py index e497a9d..b84d154 100644 --- a/pandas_ta/momentum/cmo.py +++ b/pandas_ta/momentum/cmo.py @@ -22,14 +22,15 @@ def cmo( Args: close (pd.Series): Series of 'close's scalar (float): How much to magnify. Default: 100 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. If TA Lib is not installed but talib is True, it runs the Python - version TA Lib. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. If TA Lib is not installed but talib is True, + it runs the Python version TA Lib. 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 + 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 diff --git a/pandas_ta/momentum/coppock.py b/pandas_ta/momentum/coppock.py index af5bc7f..249f62a 100644 --- a/pandas_ta/momentum/coppock.py +++ b/pandas_ta/momentum/coppock.py @@ -11,11 +11,11 @@ def coppock( ) -> Series: """Coppock Curve (COPC) - Coppock Curve (originally called the "Trendex Model") is a momentum indicator - is designed for use on a monthly time scale. Although designed for monthly - use, a daily calculation over the same period can be made, converting the - periods to 294-day and 231-day rate of changes, and a 210-day weighted - moving average. + Coppock Curve (originally called the "Trendex Model") is a momentum + indicator is designed for use on a monthly time scale. Although designed + for monthly use, a daily calculation over the same period can be made, + converting the periods to 294-day and 231-day rate of changes, + and a 210-day WMA. Sources: https://en.wikipedia.org/wiki/Coppock_curve diff --git a/pandas_ta/momentum/cti.py b/pandas_ta/momentum/cti.py index 6225a57..3071788 100644 --- a/pandas_ta/momentum/cti.py +++ b/pandas_ta/momentum/cti.py @@ -10,10 +10,11 @@ def cti( ) -> Series: """Correlation Trend Indicator (CTI) - The Correlation Trend Indicator is an oscillator created by John Ehler in 2020. - It assigns a value depending on how close prices in that range are to following - a positively- or negatively-sloping straight line. Values range from -1 to 1. - This is a wrapper for ta.linreg(close, r=True). + The Correlation Trend Indicator is an oscillator created + by John Ehler in 2020. It assigns a value depending on how close prices + in that range are to following a positively- or negatively-sloping + straight line. Values range from -1 to 1. This is a wrapper + for ta.linreg(close, r=True). Args: close (pd.Series): Series of 'close's diff --git a/pandas_ta/momentum/dm.py b/pandas_ta/momentum/dm.py index a42852a..23bbfe6 100644 --- a/pandas_ta/momentum/dm.py +++ b/pandas_ta/momentum/dm.py @@ -12,9 +12,9 @@ def dm( ) -> DataFrame: """Directional Movement (DM) - The Directional Movement was developed by J. Welles Wilder in 1978 attempts to - determine which direction the price of an asset is moving. It compares prior - highs and lows to yield to two series +DM and -DM. + The Directional Movement was developed by J. Welles Wilder in 1978 + attempts to determine which direction the price of an asset is moving. + It compares prior highs and lows to yield to two series +DM and -DM. Sources: https://www.tradingview.com/pine-script-reference/#fun_dmi @@ -24,8 +24,8 @@ def dm( high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's mamode (str): See ``help(ta.ma)``. Default: 'rma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 diff --git a/pandas_ta/momentum/er.py b/pandas_ta/momentum/er.py index 525e4a7..c3b2e67 100644 --- a/pandas_ta/momentum/er.py +++ b/pandas_ta/momentum/er.py @@ -9,9 +9,12 @@ def er( ) -> Series: """Efficiency Ratio (ER) - The Efficiency Ratio was invented by Perry J. Kaufman and presented in his book "New Trading Systems and Methods". It is designed to account for market noise or volatility. + The Efficiency Ratio was invented by Perry J. Kaufman and presented in + his book "New Trading Systems and Methods". It is designed to account + for market noise or volatility. - It is calculated by dividing the net change in price movement over N periods by the sum of the absolute net changes over the same N periods. + It is calculated by dividing the net change in price movement over + N periods by the sum of the absolute net changes over the same N periods. Sources: https://help.tc2000.com/m/69404/l/749623-kaufman-efficiency-ratio diff --git a/pandas_ta/momentum/eri.py b/pandas_ta/momentum/eri.py index 703d7f1..03afbca 100644 --- a/pandas_ta/momentum/eri.py +++ b/pandas_ta/momentum/eri.py @@ -10,15 +10,14 @@ def eri( ) -> DataFrame: """Elder Ray Index (ERI) - Elder's Bulls Ray Index contains his Bull and Bear Powers. Which are useful ways - to look at the price and see the strength behind the market. Bull Power - measures the capability of buyers in the market, to lift prices above an average - consensus of value. + Elder's Bulls Ray Index contains his Bull and Bear Powers. Which are + useful ways to look at the price and see the strength behind the market. + Bull Power measures the capability of buyers in the market, to lift + prices above an average consensus of value. - Bears Power measures the capability of sellers, to drag prices below an average - consensus of value. Using them in tandem with a measure of trend allows you to - identify favourable entry points. We hope you've found this to be a useful - discussion of the Bulls and Bears Power indicators. + Bears Power measures the capability of sellers, to drag prices below + an average consensus of value. Using them in tandem with a measure of + trend allows you to identify favourable entry points. Sources: https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator diff --git a/pandas_ta/momentum/fisher.py b/pandas_ta/momentum/fisher.py index 4ec3432..911cec3 100644 --- a/pandas_ta/momentum/fisher.py +++ b/pandas_ta/momentum/fisher.py @@ -11,9 +11,9 @@ def fisher( ) -> Series: """Fisher Transform (FISHT) - Attempts to identify significant price reversals by normalizing prices over a - user-specified number of periods. A reversal signal is suggested when the the - two lines cross. + Attempts to identify significant price reversals by normalizing prices + over a user-specified number of periods. A reversal signal is suggested + when the the two lines cross. Sources: TradingView (Correlation >99%) diff --git a/pandas_ta/momentum/macd.py b/pandas_ta/momentum/macd.py index d3a5c76..c3dfd07 100644 --- a/pandas_ta/momentum/macd.py +++ b/pandas_ta/momentum/macd.py @@ -11,10 +11,10 @@ def macd( ) -> DataFrame: """Moving Average Convergence Divergence (MACD) - The MACD is a popular indicator to that is used to identify a security's trend. - While APO and MACD are the same calculation, MACD also returns two more series - called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is - the difference of MACD and Signal. + The MACD is a popular indicator to that is used to identify a security's + trend. While APO and MACD are the same calculation, MACD also returns + two more series called Signal and Histogram. The Signal is an EMA of + MACD and the Histogram is the difference of MACD and Signal. Sources: https://www.tradingview.com/wiki/MACD_(Moving_Average_Convergence/Divergence) @@ -25,8 +25,8 @@ def macd( fast (int): The short period. Default: 12 slow (int): The long period. Default: 26 signal (int): The signal period. Default: 9 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -62,14 +62,14 @@ def macd( slowma = ema(close, length=slow, talib=mode_tal) macd = fastma - slowma - signalma = ema( - close=macd.loc[macd.first_valid_index():, ], length=signal, talib=mode_tal) + macd_fvi = macd.loc[macd.first_valid_index():, ] + signalma = ema(close=macd_fvi, length=signal, talib=mode_tal) histogram = macd - signalma if as_mode: macd = macd - signalma - signalma = ema( - close=macd.loc[macd.first_valid_index():, ], length=signal, talib=mode_tal) + macd_fvi = macd.loc[macd.first_valid_index():, ] + signalma = ema(close=macd_fvi, length=signal, talib=mode_tal) histogram = macd - signalma # Offset diff --git a/pandas_ta/momentum/mom.py b/pandas_ta/momentum/mom.py index 42156ba..78726be 100644 --- a/pandas_ta/momentum/mom.py +++ b/pandas_ta/momentum/mom.py @@ -10,8 +10,8 @@ def mom( ) -> Series: """Momentum (MOM) - Momentum is an indicator used to measure a security's speed (or strength) of - movement. Or simply the change in price. + Momentum is an indicator used to measure a security's speed + (or strength) of movement or simply the change in price. Sources: http://www.onlinetradingconcepts.com/TechnicalAnalysis/Momentum.html @@ -19,8 +19,8 @@ def mom( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 1 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/pgo.py b/pandas_ta/momentum/pgo.py index 8ece450..fb7257c 100644 --- a/pandas_ta/momentum/pgo.py +++ b/pandas_ta/momentum/pgo.py @@ -11,9 +11,11 @@ def pgo( ) -> Series: """Pretty Good Oscillator (PGO) - The Pretty Good Oscillator indicator was created by Mark Johnson to measure the distance of the current close from its N-day Simple Moving Average, expressed in terms of an average true range over a similar period. Johnson's approach was to - use it as a breakout system for longer term trades. Long if greater than 3.0 and - short if less than -3.0. + The Pretty Good Oscillator indicator was created by Mark Johnson to + measure the distance of the current close from its N-day SMA, expressed + in terms of an average true range over a similar period. Johnson's + approach was to use it as a breakout system for longer term trades. + Long if greater than 3.0 and short if less than -3.0. Sources: https://library.tradingtechnologies.com/trade/chrt-ti-pretty-good-oscillator.html diff --git a/pandas_ta/momentum/ppo.py b/pandas_ta/momentum/ppo.py index f2c0381..f23bd0f 100644 --- a/pandas_ta/momentum/ppo.py +++ b/pandas_ta/momentum/ppo.py @@ -24,8 +24,8 @@ def ppo( signal(int): The signal period. Default: 9 scalar (float): How much to magnify. Default: 100 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset(int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/qqe.py b/pandas_ta/momentum/qqe.py index 3491d9f..9b970fa 100644 --- a/pandas_ta/momentum/qqe.py +++ b/pandas_ta/momentum/qqe.py @@ -14,9 +14,17 @@ def qqe( ) -> DataFrame: """Quantitative Qualitative Estimation (QQE) - The Quantitative Qualitative Estimation (QQE) is similar to SuperTrend but uses a Smoothed RSI with an upper and lower bands. The band width is a combination of a one period True Range of the Smoothed RSI which is double smoothed using Wilder's smoothing length (2 * rsiLength - 1) and multiplied by the default factor of 4.236. A Long trend is determined when the Smoothed RSI crosses the previous upperband and a Short trend when the Smoothed RSI crosses the previous lowerband. + The Quantitative Qualitative Estimation (QQE) is similar to SuperTrend + but uses a Smoothed RSI with an upper and lower bands. The band width + is a combination of a one period True Range of the Smoothed RSI which + is double smoothed using Wilder's smoothing length (2 * rsiLength - 1) + and multiplied by the default factor of 4.236. A Long trend is + determined when the Smoothed RSI crosses the previous upperband and + a Short trend when the Smoothed RSI crosses the previous lowerband. - Based on QQE.mq5 by EarnForex Copyright © 2010, based on version by Tim Hyder (2008), based on version by Roman Ignatov (2006) + Based on QQE.mq5 by EarnForex Copyright © 2010 + based on version by Tim Hyder (2008), + based on version by Roman Ignatov (2006) Sources: https://www.tradingview.com/script/IYfA9R2k-QQE-MT4/ @@ -37,7 +45,7 @@ def qqe( fill_method (value, optional): Type of fill method Returns: - pd.DataFrame: QQE, RSI_MA (basis), QQEl (long), and QQEs (short) columns. + pd.DataFrame: QQE, RSI_MA (basis), QQEl (long), QQEs (short) columns. """ # Validate length = int(length) if isinstance(length, int) and length > 0 else 14 @@ -103,11 +111,12 @@ def qqe( # Trend & QQE Calculation # Long: Current RSI_MA value Crosses the Prior Short Line Value # Short: Current RSI_MA Crosses the Prior Long Line Value - if (c_rsi > c_short and p_rsi < p_short) or ( - c_rsi <= c_short and p_rsi >= p_short): + if (c_rsi > c_short and p_rsi < p_short) or \ + (c_rsi <= c_short and p_rsi >= p_short): trend.iloc[i] = 1 qqe.iloc[i] = qqe_long.iloc[i] = long.iloc[i] - elif (c_rsi > c_long and p_rsi < p_long) or (c_rsi <= c_long and p_rsi >= p_long): + elif (c_rsi > c_long and p_rsi < p_long) or \ + (c_rsi <= c_long and p_rsi >= p_long): trend.iloc[i] = -1 qqe.iloc[i] = qqe_short.iloc[i] = short.iloc[i] else: diff --git a/pandas_ta/momentum/roc.py b/pandas_ta/momentum/roc.py index 6416840..4ceb390 100644 --- a/pandas_ta/momentum/roc.py +++ b/pandas_ta/momentum/roc.py @@ -12,9 +12,10 @@ def roc( ) -> Series: """Rate of Change (ROC) - Rate of Change is an indicator is also referred to as Momentum (yeah, confusingly). - It is a pure momentum oscillator that measures the percent change in price with the - previous price 'n' (or length) periods ago. + Rate of Change is an indicator is also referred to as Momentum + (yeah, confusingly). It is a pure momentum oscillator that measures the + percent change in price with the previous price 'n' (or length) + periods ago. Sources: https://www.tradingview.com/wiki/Rate_of_Change_(ROC) @@ -23,8 +24,8 @@ def roc( close (pd.Series): Series of 'close's length (int): It's period. Default: 1 scalar (float): How much to magnify. Default: 100 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -49,8 +50,8 @@ def roc( from talib import ROC roc = ROC(close, length) else: - roc = scalar * mom(close=close, length=length, - talib=mode_tal) / close.shift(length) + roc = scalar * mom(close=close, length=length, talib=mode_tal) + roc /= close.shift(length) # Offset if offset != 0: diff --git a/pandas_ta/momentum/rsi.py b/pandas_ta/momentum/rsi.py index d6690d2..40a9b8f 100644 --- a/pandas_ta/momentum/rsi.py +++ b/pandas_ta/momentum/rsi.py @@ -12,8 +12,9 @@ def rsi( ) -> Series: """Relative Strength Index (RSI) - The Relative Strength Index is popular momentum oscillator used to measure the - velocity as well as the magnitude of directional price movements. + The Relative Strength Index is popular momentum oscillator used to + measure the velocity as well as the magnitude of directional price + movements. Sources: https://www.tradingview.com/wiki/Relative_Strength_Index_(RSI) @@ -22,8 +23,8 @@ def rsi( close (pd.Series): Series of 'close's length (int): It's period. Default: 14 scalar (float): How much to magnify. Default: 100 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 diff --git a/pandas_ta/momentum/rsx.py b/pandas_ta/momentum/rsx.py index e5ac1af..9cb4f0f 100644 --- a/pandas_ta/momentum/rsx.py +++ b/pandas_ta/momentum/rsx.py @@ -10,11 +10,11 @@ def rsx( ) -> Series: """Relative Strength Xtra (rsx) - The Relative Strength Xtra is based on the popular RSI indicator and inspired - by the work Jurik Research. The code implemented is based on published code - found at 'prorealcode.com'. This enhanced version of the rsi reduces noise and - provides a clearer, only slightly delayed insight on momentum and velocity of - price movements. + The Relative Strength Xtra is based on the popular RSI indicator and + inspired by the work Jurik Research. The code implemented is based on + published code found at 'prorealcode.com'. This enhanced version of the + rsi reduces noise and provides a clearer, only slightly delayed insight + on momentum and velocity of price movements. Sources: http://www.jurikres.com/catalog1/ms_rsx.htm diff --git a/pandas_ta/momentum/rvgi.py b/pandas_ta/momentum/rvgi.py index bcb5bb9..e5003aa 100644 --- a/pandas_ta/momentum/rvgi.py +++ b/pandas_ta/momentum/rvgi.py @@ -11,10 +11,10 @@ def rvgi( ) -> Series: """Relative Vigor Index (RVGI) - The Relative Vigor Index attempts to measure the strength of a trend relative to - its closing price to its trading range. It is based on the belief that it tends - to close higher than they open in uptrends or close lower than they open in - downtrends. + The Relative Vigor Index attempts to measure the strength of a trend + relative to its closing price to its trading range. It is based on the + belief that it tends to close higher than they open in uptrends or close + lower than they open in downtrends. Sources: https://www.investopedia.com/terms/r/relative_vigor_index.asp @@ -52,11 +52,11 @@ def rvgi( # Calculate numerator = swma( - close_open_range, - length=swma_length).rolling(length).sum() + close_open_range, length=swma_length + ).rolling(length).sum() denominator = swma( - high_low_range, - length=swma_length).rolling(length).sum() + high_low_range, length=swma_length + ).rolling(length).sum() rvgi = numerator / denominator signal = swma(rvgi, length=swma_length) diff --git a/pandas_ta/momentum/slope.py b/pandas_ta/momentum/slope.py index 5b9662d..947c8c2 100644 --- a/pandas_ta/momentum/slope.py +++ b/pandas_ta/momentum/slope.py @@ -30,7 +30,8 @@ def slope( 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 + to_degrees (value, optional): Converts slope angle to degrees. + Default: False offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/momentum/smi.py b/pandas_ta/momentum/smi.py index d1b4995..49f3486 100644 --- a/pandas_ta/momentum/smi.py +++ b/pandas_ta/momentum/smi.py @@ -11,13 +11,14 @@ def smi( ) -> DataFrame: """SMI Ergodic Indicator (SMI) - The SMI Ergodic Indicator is the same as the True Strength Index (TSI) developed - by William Blau, except the SMI includes a signal line. The SMI uses double - moving averages of price minus previous price over 2 time frames. The signal - line, which is an EMA of the SMI, is plotted to help trigger trading signals. - The trend is bullish when crossing above zero and bearish when crossing below - zero. This implementation includes both the SMI Ergodic Indicator and SMI - Ergodic Oscillator. + The SMI Ergodic Indicator is the same as the True Strength Index (TSI) + developed by William Blau, except the SMI includes a signal line. + The SMI uses double moving averages of price minus previous price + over 2 time frames. The signal line, which is an EMA of the SMI, is + plotted to help trigger trading signals. The trend is bullish when + crossing above zero and bearish when crossing below zero. This + implementation includes both the SMI Ergodic Indicator and + SMI Ergodic Oscillator. Sources: https://www.motivewave.com/studies/smi_ergodic_indicator.htm diff --git a/pandas_ta/momentum/squeeze.py b/pandas_ta/momentum/squeeze.py index 1612402..ee3b3de 100644 --- a/pandas_ta/momentum/squeeze.py +++ b/pandas_ta/momentum/squeeze.py @@ -3,7 +3,7 @@ from numpy import nan from pandas import DataFrame, Series from pandas_ta.overlap import ema, linreg, sma from pandas_ta.trend import decreasing, increasing -from pandas_ta.utils import get_offset, unsigned_differences, verify_series +from pandas_ta.utils import get_offset, simplify_columns, unsigned_differences, verify_series from pandas_ta.volatility import bbands, kc from .mom import mom @@ -18,12 +18,13 @@ def squeeze( ) -> DataFrame: """Squeeze (SQZ) - The default is based on John Carter's "TTM Squeeze" indicator, as discussed - in his book "Mastering the Trade" (chapter 11). The Squeeze indicator attempts - to capture the relationship between two studies: Bollinger Bands® and Keltner's - Channels. When the volatility increases, so does the distance between the bands, - conversely, when the volatility declines, the distance also decreases. It finds - sections of the Bollinger Bands® study which fall inside the Keltner's Channels. + The default is based on John Carter's "TTM Squeeze" indicator, as + discussed in his book "Mastering the Trade" (chapter 11). The Squeeze + indicator attempts to capture the relationship between two studies: + Bollinger Bands® and Keltner's Channels. When the volatility increases, + so does the distance between the bands, conversely, when the volatility + declines, the distance also decreases. It finds sections of the + Bollinger Bands® study which fall inside the Keltner's Channels. Sources: https://tradestation.tradingappstore.com/products/TTMSqueeze @@ -44,7 +45,8 @@ def squeeze( offset (int): How many periods to offset the result. Default: 0 Kwargs: - tr (value, optional): Use True Range for Keltner Channels. Default: True + tr (value, optional): Use True Range for Keltner Channels. + Default: True asint (value, optional): Use integers instead of bool. Default: True mamode (value, optional): Which MA to use. Default: "sma" lazybear (value, optional): Use LazyBear's TradingView implementation. @@ -80,20 +82,12 @@ def squeeze( lazybear = kwargs.pop("lazybear", False) mamode = mamode if isinstance(mamode, str) else "sma" - def simplify_columns(df, n=3): - df.columns = df.columns.str.lower() - return [c.split("_")[0][n - 1:n] for c in df.columns] - # Calculate bbd = bbands(close, length=bb_length, std=bb_std, mamode=mamode) kch = kc( - high, - low, - close, - length=kc_length, - scalar=kc_scalar, - mamode=mamode, - tr=use_tr) + high, low, close, length=kc_length, scalar=kc_scalar, + mamode=mamode, tr=use_tr + ) # Simplify KC and BBAND column names for dynamic access bbd.columns = simplify_columns(bbd) diff --git a/pandas_ta/momentum/squeeze_pro.py b/pandas_ta/momentum/squeeze_pro.py index 739c07e..0369fb7 100644 --- a/pandas_ta/momentum/squeeze_pro.py +++ b/pandas_ta/momentum/squeeze_pro.py @@ -5,7 +5,7 @@ from pandas_ta.momentum import mom from pandas_ta.overlap import ema, sma from pandas_ta.trend import decreasing, increasing from pandas_ta.volatility import bbands, kc -from pandas_ta.utils import get_offset, unsigned_differences, verify_series +from pandas_ta.utils import get_offset, simplify_columns, unsigned_differences, verify_series def squeeze_pro( @@ -20,12 +20,13 @@ def squeeze_pro( """Squeeze PRO(SQZPRO) This indicator is an extended version of "TTM Squeeze" from John Carter. - The default is based on John Carter's "TTM Squeeze" indicator, as discussed - in his book "Mastering the Trade" (chapter 11). The Squeeze indicator attempts - to capture the relationship between two studies: Bollinger Bands® and Keltner's - Channels. When the volatility increases, so does the distance between the bands, - conversely, when the volatility declines, the distance also decreases. It finds - sections of the Bollinger Bands® study which fall inside the Keltner's Channels. + The default is based on John Carter's "TTM Squeeze" indicator, as + discussed in his book "Mastering the Trade" (chapter 11). The Squeeze + indicator attempts to capture the relationship between two studies: + Bollinger Bands® and Keltner's Channels. When the volatility increases, + so does the distance between the bands, conversely, when the volatility + declines, the distance also decreases. It finds sections of the + Bollinger Bands® study which fall inside the Keltner's Channels. Sources: https://usethinkscript.com/threads/john-carters-squeeze-pro-indicator-for-thinkorswim-free.4021/ @@ -38,16 +39,20 @@ def squeeze_pro( bb_length (int): Bollinger Bands period. Default: 20 bb_std (float): Bollinger Bands Std. Dev. Default: 2 kc_length (int): Keltner Channel period. Default: 20 - kc_scalar_wide (float): Keltner Channel scalar for wider channel. Default: 2 - kc_scalar_normal (float): Keltner Channel scalar for normal channel. Default: 1.5 - kc_scalar_narrow (float): Keltner Channel scalar for narrow channel. Default: 1 + kc_scalar_wide (float): Keltner Channel scalar for wider channel. + Default: 2 + kc_scalar_normal (float): Keltner Channel scalar for normal channel. + Default: 1.5 + kc_scalar_narrow (float): Keltner Channel scalar for narrow channel. + Default: 1 mom_length (int): Momentum Period. Default: 12 mom_smooth (int): Smoothing Period of Momentum. Default: 6 mamode (str): Only "ema" or "sma". Default: "sma" offset (int): How many periods to offset the result. Default: 0 Kwargs: - tr (value, optional): Use True Range for Keltner Channels. Default: True + tr (value, optional): Use True Range for Keltner Channels. + Default: True asint (value, optional): Use integers instead of bool. Default: True mamode (value, optional): Which MA to use. Default: "sma" detailed (value, optional): Return additional variations of SQZ for @@ -56,19 +61,30 @@ def squeeze_pro( fill_method (value, optional): Type of fill method Returns: - pd.DataFrame: SQZPRO, SQZPRO_ON_WIDE, SQZPRO_ON_NORMAL, SQZPRO_ON_NARROW, SQZPRO_OFF_WIDE, SQZPRO_NO columns by default. More - detailed columns if 'detailed' kwarg is True. + pd.DataFrame: SQZPRO, SQZPRO_ON_WIDE, SQZPRO_ON_NORMAL, + SQZPRO_ON_NARROW, SQZPRO_OFF_WIDE, SQZPRO_NO columns by default. + More detailed columns if 'detailed' kwarg is True. """ # Validate bb_length = int(bb_length) if bb_length and bb_length > 0 else 20 bb_std = float(bb_std) if bb_std and bb_std > 0 else 2.0 kc_length = int(kc_length) if kc_length and kc_length > 0 else 20 - kc_scalar_wide = float( - kc_scalar_wide) if kc_scalar_wide and kc_scalar_wide > 0 else 2 - kc_scalar_normal = float( - kc_scalar_normal) if kc_scalar_normal and kc_scalar_normal > 0 else 1.5 - kc_scalar_narrow = float( - kc_scalar_narrow) if kc_scalar_narrow and kc_scalar_narrow > 0 else 1 + + if kc_scalar_wide and kc_scalar_wide > 0: + kc_scalar_wide = float(kc_scalar_wide) + else: + kc_scalar_wide = 2 + + if kc_scalar_normal and kc_scalar_normal > 0: + kc_scalar_normal = float(kc_scalar_normal) + else: + kc_scalar_normal = 1.5 + + if kc_scalar_narrow and kc_scalar_narrow > 0: + kc_scalar_narrow = float(kc_scalar_narrow) + else: + kc_scalar_narrow = 1 + mom_length = int(mom_length) if mom_length and mom_length > 0 else 12 mom_smooth = int(mom_smooth) if mom_smooth and mom_smooth > 0 else 6 @@ -90,36 +106,20 @@ def squeeze_pro( detailed = kwargs.pop("detailed", False) mamode = mamode if isinstance(mamode, str) else "sma" - def simplify_columns(df, n=3): - df.columns = df.columns.str.lower() - return [c.split("_")[0][n - 1:n] for c in df.columns] - # Calculate bbd = bbands(close, length=bb_length, std=bb_std, mamode=mamode) kch_wide = kc( - high, - low, - close, - length=kc_length, - scalar=kc_scalar_wide, - mamode=mamode, - tr=use_tr) + high, low, close, length=kc_length, scalar=kc_scalar_wide, + mamode=mamode, tr=use_tr + ) kch_normal = kc( - high, - low, - close, - length=kc_length, - scalar=kc_scalar_normal, - mamode=mamode, - tr=use_tr) + high, low, close, length=kc_length, scalar=kc_scalar_normal, + mamode=mamode, tr=use_tr + ) kch_narrow = kc( - high, - low, - close, - length=kc_length, - scalar=kc_scalar_narrow, - mamode=mamode, - tr=use_tr) + high, low, close, length=kc_length, scalar=kc_scalar_narrow, + mamode=mamode, tr=use_tr + ) # Simplify KC and BBAND column names for dynamic access bbd.columns = simplify_columns(bbd) diff --git a/pandas_ta/momentum/stc.py b/pandas_ta/momentum/stc.py index 21f1065..376cd2f 100644 --- a/pandas_ta/momentum/stc.py +++ b/pandas_ta/momentum/stc.py @@ -11,14 +11,15 @@ def stc( ) -> DataFrame: """Schaff Trend Cycle (STC) - The Schaff Trend Cycle is an evolution of the popular MACD incorportating two - cascaded stochastic calculations with additional smoothing. + The Schaff Trend Cycle is an evolution of the popular MACD + incorportating two cascaded stochastic calculations with additional + smoothing. - The STC returns also the beginning MACD result as well as the result after the - first stochastic including its smoothing. This implementation has been extended - for Pandas TA to also allow for separatly feeding any other two moving Averages - (as ma1 and ma2) or to skip this to feed an oscillator (osc), based on which the - Schaff Trend Cycle should be calculated. + The STC returns also the beginning MACD result as well as the result + after the first stochastic including its smoothing. This implementation + has been extended for Pandas TA to also allow for separatly feeding any + other two moving Averages (as ma1 and ma2) or to skip this to feed an + oscillator, based on which the Schaff Trend Cycle should be calculated. Feed external moving averages: Internally calculation.. @@ -35,17 +36,19 @@ def stc( https://www.prorealcode.com/prorealtime-indicators/schaff-trend-cycle2/ Args: - close (pd.Series): Series of 'close's, used for indexing Series, mandatory - tclen (int): SchaffTC Signal-Line length. Default: 10 (adjust to the half of cycle) - fast (int): The short period. Default: 12 - slow (int): The long period. Default: 26 - factor (float): smoothing factor for last stoch. calculation. Default: 0.5 - offset (int): How many periods to offset the result. Default: 0 + close (pd.Series): Series of 'close's + tclen (int): SchaffTC Signal-Line length. + Default: 10 (adjust to the half of cycle) + fast (int): The short period. Default: 12 + slow (int): The long period. Default: 26 + factor (float): smoothing factor for last stoch. calculation. + Default: 0.5 + offset (int): How many periods to offset the result. Default: 0 Kwargs: - ma1: 1st moving average provided externally (mandatory in conjuction with ma2) - ma2: 2nd moving average provided externally (mandatory in conjuction with ma1) - osc: an externally feeded osillator + ma1: External MA (mandatory in conjuction with ma2) + ma2: External MA (mandatory in conjuction with ma1) + osc: External osillator fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): Type of fill method diff --git a/pandas_ta/momentum/stoch.py b/pandas_ta/momentum/stoch.py index 9752026..e7624d7 100644 --- a/pandas_ta/momentum/stoch.py +++ b/pandas_ta/momentum/stoch.py @@ -13,14 +13,15 @@ def stoch( ) -> DataFrame: """Stochastic (STOCH) - The Stochastic Oscillator (STOCH) was developed by George Lane in the 1950's. - He believed this indicator was a good way to measure momentum because changes in - momentum precede changes in price. + The Stochastic Oscillator (STOCH) was developed by George Lane in the + 1950's. He believed this indicator was a good way to measure momentum + because changes in momentum precede changes in price. It is a range-bound oscillator with two lines moving between 0 and 100. - The first line (%K) displays the current close in relation to the period's - high/low range. The second line (%D) is a Simple Moving Average of the %K line. - The most common choices are a 14 period %K and a 3 period SMA for %D. + The first line (%K) displays the current close in relation to the + period's high/low range. The second line (%D) is a Simple Moving Average + of the %K line. The most common choices are a 14 period %K and a 3 period + SMA for %D. Sources: https://www.tradingview.com/wiki/Stochastic_(STOCH) @@ -34,8 +35,8 @@ def stoch( d (int): The Slow %D period. Default: 3 smooth_k (int): The Slow %K period. Default: 3 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -64,14 +65,8 @@ def stoch( if Imports["talib"] and mode_tal: from talib import STOCH stoch_ = STOCH( - high, - low, - close, - k, - d, - tal_ma(mamode), - d, - tal_ma(mamode)) + high, low, close, k, d, tal_ma(mamode), d, tal_ma(mamode) + ) stoch_k, stoch_d = stoch_[0], stoch_[1] else: lowest_low = low.rolling(k).min() @@ -80,10 +75,11 @@ def stoch( stoch = 100 * (close - lowest_low) stoch /= non_zero_range(highest_high, lowest_low) - stoch_k = ma( - mamode, stoch.loc[stoch.first_valid_index():, ], length=smooth_k) - stoch_d = ma( - mamode, stoch_k.loc[stoch_k.first_valid_index():, ], length=d) + stoch_fvi = stoch.loc[stoch.first_valid_index():, ] + stoch_k = ma(mamode, stoch_fvi, length=smooth_k) + + stochk_fvi = stoch_k.loc[stoch_k.first_valid_index():, ] + stoch_d = ma(mamode, stochk_fvi, length=d) # Offset if offset != 0: diff --git a/pandas_ta/momentum/stochf.py b/pandas_ta/momentum/stochf.py index 224b7e8..b4fecfd 100644 --- a/pandas_ta/momentum/stochf.py +++ b/pandas_ta/momentum/stochf.py @@ -12,9 +12,9 @@ def stochf( ) -> DataFrame: """Fast Stochastic (STOCHF) - The Fast Stochastic Oscillator (STOCHF) was developed by George Lane in the - 1950's. This STOCHF is more volatile than STOCH (help(ta.stoch)) and it's - calculation is similar to STOCH. + The Fast Stochastic Oscillator (STOCHF) was developed by George Lane + in the 1950's. This STOCHF is more volatile than STOCH (help(ta.stoch)) + and it's calculation is similar to STOCH. Sources: https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=333&Name=KD_-_Fast @@ -27,8 +27,8 @@ def stochf( k (int): The Fast %K period. Default: 14 d (int): The Slow %D period. Default: 3 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -63,11 +63,8 @@ def stochf( stochf_k = 100 * (close - lowest_low) stochf_k /= non_zero_range(highest_high, lowest_low) - stochf_d = ma(mamode, - stochf_k.loc[stochf_k.first_valid_index():, - ], - length=d, - talib=mode_tal) + stochfk_fvi = stochf_k.loc[stochf_k.first_valid_index():, ] + stochf_d = ma(mamode, stochfk_fvi, length=d, talib=mode_tal) # Offset if offset != 0: diff --git a/pandas_ta/momentum/stochrsi.py b/pandas_ta/momentum/stochrsi.py index 008aeca..f707aa9 100644 --- a/pandas_ta/momentum/stochrsi.py +++ b/pandas_ta/momentum/stochrsi.py @@ -12,12 +12,14 @@ def stochrsi( ) -> DataFrame: """Stochastic (STOCHRSI) - "Stochastic RSI and Dynamic Momentum Index" was created by Tushar Chande and Stanley Kroll and published in Stock & Commodities V.11:5 (189-199) + "Stochastic RSI and Dynamic Momentum Index" was created by Tushar Chande + and Stanley Kroll and published in Stock & Commodities V.11:5 (189-199) It is a range-bound oscillator with two lines moving between 0 and 100. The first line (%K) displays the current RSI in relation to the period's - high/low range. The second line (%D) is a Simple Moving Average of the %K line. - The most common choices are a 14 period %K and a 3 period SMA for %D. + high/low range. The second line (%D) is a Simple Moving Average of the + %K line. The most common choices are a 14 period %K and a 3 period + SMA for %D. Sources: https://www.tradingview.com/wiki/Stochastic_(STOCH) diff --git a/pandas_ta/momentum/tsi.py b/pandas_ta/momentum/tsi.py index ece45f3..5594114 100644 --- a/pandas_ta/momentum/tsi.py +++ b/pandas_ta/momentum/tsi.py @@ -12,9 +12,9 @@ def tsi( ) -> DataFrame: """True Strength Index (TSI) - The True Strength Index is a momentum indicator used to identify short-term - swings while in the direction of the trend as well as determining overbought - and oversold conditions. + The True Strength Index is a momentum indicator used to identify + short-term swings while in the direction of the trend as well as + determining overbought and oversold conditions. Sources: https://www.investopedia.com/terms/t/tsi.asp diff --git a/pandas_ta/momentum/uo.py b/pandas_ta/momentum/uo.py index 59078fb..4160b9f 100644 --- a/pandas_ta/momentum/uo.py +++ b/pandas_ta/momentum/uo.py @@ -29,8 +29,8 @@ def uo( fast_w (float): The Fast %K period. Default: 4.0 medium_w (float): The Slow %K period. Default: 2.0 slow_w (float): The Slow %D period. Default: 1.0 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -64,10 +64,9 @@ def uo( from talib import ULTOSC uo = ULTOSC(high, low, close, fast, medium, slow) else: + close_drift = close.shift(drift) tdf = DataFrame({ - "high": high, - "low": low, - f"close_{drift}": close.shift(drift) + "high": high, "low": low, f"close_{drift}": close_drift }) max_h_or_pc = tdf.loc[:, ["high", f"close_{drift}"]].max(axis=1) min_l_or_pc = tdf.loc[:, ["low", f"close_{drift}"]].min(axis=1) @@ -81,8 +80,8 @@ def uo( slow_avg = bp.rolling(slow).sum() / tr.rolling(slow).sum() total_weight = fast_w + medium_w + slow_w - weights = (fast_w * fast_avg) + (medium_w * - medium_avg) + (slow_w * slow_avg) + weights = (fast_w * fast_avg) + (medium_w * medium_avg) \ + + (slow_w * slow_avg) uo = 100 * weights / total_weight # Offset diff --git a/pandas_ta/momentum/willr.py b/pandas_ta/momentum/willr.py index fe4f1e3..7a28230 100644 --- a/pandas_ta/momentum/willr.py +++ b/pandas_ta/momentum/willr.py @@ -22,8 +22,8 @@ def willr( low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's length (int): It's period. Default: 14 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -35,8 +35,10 @@ def willr( """ # Validate 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 + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length _length = max(length, min_periods) high = verify_series(high, _length) low = verify_series(low, _length) diff --git a/pandas_ta/overlap/alligator.py b/pandas_ta/overlap/alligator.py index f9840c5..e914442 100644 --- a/pandas_ta/overlap/alligator.py +++ b/pandas_ta/overlap/alligator.py @@ -11,13 +11,14 @@ def alligator( ) -> DataFrame: """Bill Williams Alligator (ALLIGATOR) - The Alligator Indicator was developed by Bill Williams and combines moving - averages with fractal geometry and the lines are meant to resemeble an alligator - opening and closing his mouth.. It attempts to identify if an asset is trending. - It consists of 3 lines: the Alligator's Jaw, Teeth, and Lips. Each have - different lookback periods and but require the user to offset the results; this - is avoid data leaks by Pandas TA. See help(ta.ichimoku) or help(ta.dpo) to - offset the resultant lines. + The Alligator Indicator was developed by Bill Williams and combines + moving averages with fractal geometry and the lines are meant to + resemeble an alligator opening and closing his mouth.. It attempts to + identify if an asset is trending. It consists of 3 lines: the + Alligator's Jaw, Teeth, and Lips. Each have different lookback periods + and but require the user to offset the results; this is avoid data leaks + by Pandas TA. See help(ta.ichimoku) or help(ta.dpo) to offset the + resultant lines. Sources: https://www.tradingview.com/scripts/alligator/ @@ -28,8 +29,8 @@ def alligator( jaw (int): The Jaw period. Default: 13 teeth (int): The Teeth period. Default: 8 lips (int): The Lips period. Default: 5 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/alma.py b/pandas_ta/overlap/alma.py index bbdfb44..f4b1fdb 100644 --- a/pandas_ta/overlap/alma.py +++ b/pandas_ta/overlap/alma.py @@ -12,11 +12,11 @@ def alma( ) -> Series: """Arnaud Legoux Moving Average (ALMA) - The ALMA moving average uses the curve of the Normal (Gauss) distribution, which - can be shifted from 0 to 1. This allows regulating the smoothness and high - sensitivity of the indicator. Sigma is another parameter that is responsible for - the shape of the curve coefficients. This moving average reduces lag of the data - in conjunction with smoothing to reduce noise. + The ALMA moving average uses the curve of the Normal (Gauss) distribution, + which can be shifted from 0 to 1. This allows regulating the smoothness + and high sensitivity of the indicator. Sigma is another parameter that is + responsible for the shape of the curve coefficients. This moving average + reduces lag of the data in conjunction with smoothing to reduce noise. Sources: https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=475&Name=Moving_Average_-_Arnaud_Legoux @@ -26,8 +26,8 @@ def alma( close (pd.Series): Series of 'close's length (int): It's period, window size. Default: 9 sigma (float): Smoothing value. Default 6.0 - dist_offset (float): Value to offset the distribution where min 0 (smoother), - max 1 (more responsive). Default 0.85 + dist_offset (float): Value to offset the distribution where + min 0 (smoother), max 1 (more responsive). Default 0.85 offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -40,8 +40,7 @@ def alma( # Validate length = int(length) if isinstance(length, int) and length > 0 else 9 sigma = float(sigma) if isinstance(sigma, float) and sigma > 0 else 6.0 - if isinstance(dist_offset, - float) and dist_offset >= 0 and dist_offset <= 1: + if isinstance(dist_offset, float) and 0 <= dist_offset <= 1: offset_ = float(dist_offset) else: offset_ = 0.85 diff --git a/pandas_ta/overlap/dema.py b/pandas_ta/overlap/dema.py index e32ffa9..dbc98a1 100644 --- a/pandas_ta/overlap/dema.py +++ b/pandas_ta/overlap/dema.py @@ -11,8 +11,8 @@ def dema( ) -> Series: """Double Exponential Moving Average (DEMA) - The Double Exponential Moving Average attempts to a smoother average with less - lag than the normal Exponential Moving Average (EMA). + The Double Exponential Moving Average attempts to a smoother average + with less lag than the normal Exponential Moving Average (EMA). Sources: https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/ @@ -20,8 +20,8 @@ def dema( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/ema.py b/pandas_ta/overlap/ema.py index 37b4c5b..57aac86 100644 --- a/pandas_ta/overlap/ema.py +++ b/pandas_ta/overlap/ema.py @@ -29,12 +29,12 @@ def ema( ) -> Series: """Exponential Moving Average (EMA) - The Exponential Moving Average is a more responsive moving average compared - to the Simple Moving Average (SMA). The weights are determined by alpha - which is proportional to it's length. There are several different methods - of calculating EMA. One method uses just the standard definition of EMA and - another uses the SMA to generate the initial value for the rest of the - calculation. + The Exponential Moving Average is a more responsive moving average + compared to the Simple Moving Average (SMA). The weights are determined + by alpha which is proportional to it's length. There are several + different methods of calculating EMA. One method uses just the standard + definition of EMA and another uses the SMA to generate the initial value + for the rest of the calculation. Sources: https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages @@ -43,10 +43,10 @@ def ema( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib=True, it returns the - TA Lib values. Default: True - presma (bool, optional): If True, uses SMA for initial value like TA Lib. - Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True + presma (bool, optional): If True, uses SMA for initial value like + TA Lib. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/fwma.py b/pandas_ta/overlap/fwma.py index d980f76..f31a5cb 100644 --- a/pandas_ta/overlap/fwma.py +++ b/pandas_ta/overlap/fwma.py @@ -9,8 +9,8 @@ def fwma( ) -> Series: """Fibonacci's Weighted Moving Average (FWMA) - Fibonacci's Weighted Moving Average is similar to a Weighted Moving Average - (WMA) where the weights are based on the Fibonacci Sequence. + Fibonacci's Weighted Moving Average is similar to a Weighted Moving + Average (WMA) where the weights are based on the Fibonacci Sequence. Source: Kevin Johnson @@ -38,11 +38,8 @@ def fwma( # Calculate fibs = fibonacci(n=length, weighted=True) - fwma = close.rolling( - length, - min_periods=length).apply( - weights(fibs), - raw=True) + fwma = close.rolling(length, min_periods=length) \ + .apply(weights(fibs), raw=True) # Offset if offset != 0: diff --git a/pandas_ta/overlap/hilo.py b/pandas_ta/overlap/hilo.py index 1ce8676..aff1204 100644 --- a/pandas_ta/overlap/hilo.py +++ b/pandas_ta/overlap/hilo.py @@ -12,12 +12,12 @@ def hilo( ) -> DataFrame: """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 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. + 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. diff --git a/pandas_ta/overlap/hl2.py b/pandas_ta/overlap/hl2.py index e48aac1..7809ded 100644 --- a/pandas_ta/overlap/hl2.py +++ b/pandas_ta/overlap/hl2.py @@ -25,7 +25,8 @@ def hl2( offset = get_offset(offset) # Calculate - hl2 = Series(0.5 * (high.values + low.values), index=high.index) + avg = 0.5 * (high.values + low.values) + hl2 = Series(avg, index=high.index) # Offset if offset != 0: diff --git a/pandas_ta/overlap/hlc3.py b/pandas_ta/overlap/hlc3.py index 0643c16..598c670 100644 --- a/pandas_ta/overlap/hlc3.py +++ b/pandas_ta/overlap/hlc3.py @@ -33,9 +33,8 @@ def hlc3( from talib import TYPPRICE hlc3 = TYPPRICE(high, low, close) else: - hlc3 = Series( - (high.values + low.values + close.values) / 3.0, - index=close.index) + avg = (high.values + low.values + close.values) / 3.0 + hlc3 = Series(avg, index=close.index) # Offset if offset != 0: diff --git a/pandas_ta/overlap/hma.py b/pandas_ta/overlap/hma.py index 7a33572..ddb57c0 100644 --- a/pandas_ta/overlap/hma.py +++ b/pandas_ta/overlap/hma.py @@ -11,8 +11,8 @@ def hma( ) -> Series: """Hull Moving Average (HMA) - The Hull Exponential Moving Average attempts to reduce or remove lag in moving - averages. + The Hull Exponential Moving Average attempts to reduce or remove lag + in moving averages. Sources: https://alanhull.com/hull-moving-average diff --git a/pandas_ta/overlap/hwma.py b/pandas_ta/overlap/hwma.py index 8968739..8c536d3 100644 --- a/pandas_ta/overlap/hwma.py +++ b/pandas_ta/overlap/hwma.py @@ -9,9 +9,9 @@ def hwma( ) -> Series: """HWMA (Holt-Winter Moving Average) - Indicator HWMA (Holt-Winter Moving Average) is a three-parameter moving average - by the Holt-Winter method; the three parameters should be selected to obtain a - forecast. + Indicator HWMA (Holt-Winter Moving Average) is a three-parameter + moving average by the Holt-Winter method; the three parameters should + be selected to obtain a forecast. This version has been implemented for Pandas TA by rengel8 based on a publication for MetaTrader 5. @@ -66,8 +66,7 @@ def hwma( hwma.fillna(method=kwargs["fill_method"], inplace=True) # Name and Category - suffix = f"{na}_{nb}_{nc}" - hwma.name = f"HWMA_{suffix}" + hwma.name = f"HWMA_{na}_{nb}_{nc}" hwma.category = "overlap" return hwma diff --git a/pandas_ta/overlap/ichimoku.py b/pandas_ta/overlap/ichimoku.py index 2fc56d1..48362e5 100644 --- a/pandas_ta/overlap/ichimoku.py +++ b/pandas_ta/overlap/ichimoku.py @@ -24,7 +24,8 @@ def ichimoku( tenkan (int): Tenkan period. Default: 9 kijun (int): Kijun period. Default: 26 senkou (int): Senkou period. Default: 52 - include_chikou (bool): Whether to include chikou component. Default: True + include_chikou (bool): Whether to include chikou component. + Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/jma.py b/pandas_ta/overlap/jma.py index 291f386..3dcb812 100644 --- a/pandas_ta/overlap/jma.py +++ b/pandas_ta/overlap/jma.py @@ -12,9 +12,9 @@ def jma( ) -> Series: """Jurik Moving Average Average (JMA) - Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the "true" - underlying activity. It has extremely low lag, is very smooth and is responsive - to market gaps. + Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see + the "true" underlying activity. It has extremely low lag, is very + smooth and is responsive to market gaps. Sources: https://c.mql5.com/forextsd/forum/164/jurik_1.pdf @@ -94,7 +94,7 @@ def jma( ma2 = ma1 + pr * det0 # 3rd stage - final smoothing by unique Jurik adaptive filter - det1 = ((ma2 - jma[i - 1]) * (1 - alpha) * + det1 = ((ma2 - jma[i - 1]) * (1 - alpha) * \ (1 - alpha)) + (alpha * alpha * det1) jma[i] = jma[i - 1] + det1 diff --git a/pandas_ta/overlap/kama.py b/pandas_ta/overlap/kama.py index 450deef..10c0d29 100644 --- a/pandas_ta/overlap/kama.py +++ b/pandas_ta/overlap/kama.py @@ -12,11 +12,13 @@ def kama( ) -> Series: """Kaufman's Adaptive Moving Average (KAMA) - Developed by Perry Kaufman, Kaufman's Adaptive Moving Average (KAMA) is a moving average - designed to account for market noise or volatility. KAMA will closely follow prices when - the price swings are relatively small and the noise is low. KAMA will adjust when the - price swings widen and follow prices from a greater distance. This trend-following indicator - can be used to identify the overall trend, time turning points and filter price movements. + Developed by Perry Kaufman, Kaufman's Adaptive Moving Average (KAMA) is + a moving average designed to account for market noise or volatility. + KAMA will closely follow prices when the price swings are relatively + small and the noise is low. KAMA will adjust when the price swings widen + and follow prices from a greater distance. This trend-following + indicator can be used to identify the overall trend, time turning points + and filter price movements. Sources: https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:kaufman_s_adaptive_moving_average @@ -28,8 +30,8 @@ def kama( fast (int): Fast MA period. Default: 2 slow (int): Slow MA period. Default: 30 mamode (str): See ``help(ta.ma)``. Valid MAs that support initialize - the first value: 'ema', 'fwma', 'linreg', 'midpoint', 'pwma', 'rma', - 'sinwma', 'sma', 'swma', 'trima', 'wma'. Default: 'sma' + the first value: 'ema', 'fwma', 'linreg', 'midpoint', 'pwma', + 'rma', 'sinwma', 'sma', 'swma', 'trima', 'wma'. Default: 'sma' drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -77,8 +79,8 @@ def kama( ma0 = ma(mamode, close.iloc[:length], length=length, **kwargs).iloc[-1] result = [nan for _ in range(0, length - 1)] + [ma0] for i in range(length, m): - result.append(sc.iloc[i] * close.iloc[i] + - (1 - sc.iloc[i]) * result[i - 1]) + result.append(sc.iloc[i] * close.iloc[i] \ + + (1 - sc.iloc[i]) * result[i - 1]) kama = Series(result, index=close.index) diff --git a/pandas_ta/overlap/linreg.py b/pandas_ta/overlap/linreg.py index c397d06..3d8a5a0 100644 --- a/pandas_ta/overlap/linreg.py +++ b/pandas_ta/overlap/linreg.py @@ -12,27 +12,28 @@ def linreg( ) -> Series: """Linear Regression Moving Average (linreg) - Linear Regression Moving Average (LINREG). This is a simplified version of a - Standard Linear Regression. LINREG is a rolling regression of one variable. A - Standard Linear Regression is between two or more variables. + Linear Regression Moving Average (LINREG). This is a simplified version + of a Standard Linear Regression. LINREG is a rolling regression of one + variable. A Standard Linear Regression is between two or more variables. Source: TA Lib Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: - angle (bool, optional): If True, returns the angle of the slope in radians. + angle (bool, optional): If True, returns the slope angle in radians. Default: False. - degrees (bool, optional): If True, returns the angle of the slope in + degrees (bool, optional): If True, returns the slope angle in degrees. Default: False. - intercept (bool, optional): If True, returns the angle of the slope in - radians. Default: False. - r (bool, optional): If True, returns it's correlation 'r'. Default: False. + intercept (bool, optional): If True, returns the intercept. + Default: False. + r (bool, optional): If True, returns it's correlation 'r'. + Default: False. slope (bool, optional): If True, returns the slope. Default: False. tsf (bool, optional): If True, returns the Time Series Forecast value. Default: False. @@ -80,6 +81,7 @@ def linreg( x2_sum = x_sum * (2 * length + 1) / 3 divisor = length * x2_sum - x_sum * x_sum + # Needs to be reworked outside the method def linear_regression(series): y_sum = series.sum() xy_sum = (x * series).sum() @@ -109,12 +111,14 @@ def linreg( from numpy.lib.stride_tricks import sliding_window_view linreg_ = [ linear_regression(_) for _ in sliding_window_view( - np_close, length)] + np_close, length) + ] else: linreg_ = [ linear_regression(_) for _ in strided_window( - np_close, length)] + np_close, length) + ] linreg = Series([nan] * (length - 1) + linreg_, index=close.index) diff --git a/pandas_ta/overlap/mcgd.py b/pandas_ta/overlap/mcgd.py index a19451f..674fd12 100644 --- a/pandas_ta/overlap/mcgd.py +++ b/pandas_ta/overlap/mcgd.py @@ -9,13 +9,14 @@ def mcgd( ) -> Series: """McGinley Dynamic Indicator - The McGinley Dynamic looks like a moving average line, yet it is actually a - smoothing mechanism for prices that minimizes price separation, price whipsaws, - and hugs prices much more closely. Because of the calculation, the Dynamic Line - speeds up in down markets as it follows prices yet moves more slowly in up - markets. The indicator was designed by John R. McGinley, a Certified Market - Technician and former editor of the Market Technicians Association's Journal - of Technical Analysis. + The McGinley Dynamic looks like a moving average line, yet it is + actually a smoothing mechanism for prices that minimizes price + separation, price whipsaws, and hugs prices much more closely. Because + of the calculation, the Dynamic Line speeds up in down markets as it + follows prices yet moves more slowly in up markets. The indicator was + designed by John R. McGinley, a Certified Market Technician and former + editor of the Market Technicians Association's Journal of Technical + Analysis. Sources: https://www.investopedia.com/articles/forex/09/mcginley-dynamic-indicator.asp @@ -23,7 +24,8 @@ def mcgd( Args: close (pd.Series): Series of 'close's length (int): Indicator's period. Default: 10 - c (float): Multiplier for the denominator, sometimes set to 0.6. Default: 1 + c (float): Multiplier for the denominator, sometimes set to 0.6. + Default: 1 offset (int): Number of periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/midpoint.py b/pandas_ta/overlap/midpoint.py index 3c7a745..ac572d4 100644 --- a/pandas_ta/overlap/midpoint.py +++ b/pandas_ta/overlap/midpoint.py @@ -15,8 +15,8 @@ def midpoint( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 2 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -28,8 +28,10 @@ def midpoint( """ # Validate length = int(length) if length and length > 0 else 2 - min_periods = int( - kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True diff --git a/pandas_ta/overlap/midprice.py b/pandas_ta/overlap/midprice.py index ccd760a..827794c 100644 --- a/pandas_ta/overlap/midprice.py +++ b/pandas_ta/overlap/midprice.py @@ -16,8 +16,8 @@ def midprice( high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's length (int): It's period. Default: 2 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -29,8 +29,10 @@ def midprice( """ # Validate length = int(length) if length and length > 0 else 2 - min_periods = int( - kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length _length = max(length, min_periods) high = verify_series(high, _length) low = verify_series(low, _length) diff --git a/pandas_ta/overlap/ohlc4.py b/pandas_ta/overlap/ohlc4.py index f5f393d..64bea08 100644 --- a/pandas_ta/overlap/ohlc4.py +++ b/pandas_ta/overlap/ohlc4.py @@ -29,10 +29,8 @@ def ohlc4( offset = get_offset(offset) # Calculate - ohlc4 = Series( - 0.25 * (open_.values + high.values + low.values + close.values), - index=close.index - ) + avg = 0.25 * (open_.values + high.values + low.values + close.values) + ohlc4 = Series(avg, index=close.index) # Offset if offset != 0: diff --git a/pandas_ta/overlap/pwma.py b/pandas_ta/overlap/pwma.py index 2e214ab..2f95e07 100644 --- a/pandas_ta/overlap/pwma.py +++ b/pandas_ta/overlap/pwma.py @@ -9,8 +9,8 @@ def pwma( ) -> Series: """Pascal's Weighted Moving Average (PWMA) - Pascal's Weighted Moving Average is similar to a symmetric triangular window - except PWMA's weights are based on Pascal's Triangle. + Pascal's Weighted Moving Average is similar to a symmetric triangular + window except PWMA's weights are based on Pascal's Triangle. Source: Kevin Johnson @@ -38,11 +38,8 @@ def pwma( # Calculate triangle = pascals_triangle(n=length - 1, weighted=True) - pwma = close.rolling( - length, - min_periods=length).apply( - weights(triangle), - raw=True) + pwma = close.rolling(length, min_periods=length) \ + .apply(weights(triangle), raw=True) # Offset if offset != 0: diff --git a/pandas_ta/overlap/rma.py b/pandas_ta/overlap/rma.py index 72eaccd..ceeed9a 100644 --- a/pandas_ta/overlap/rma.py +++ b/pandas_ta/overlap/rma.py @@ -9,8 +9,8 @@ def rma( ) -> Series: """wildeR's Moving Average (RMA) - The WildeR's Moving Average is simply an Exponential Moving Average (EMA) with - a modified alpha = 1 / length. + The WildeR's Moving Average is simply an EMA with a modified + alpha = 1 / length. Sources: https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing diff --git a/pandas_ta/overlap/sinwma.py b/pandas_ta/overlap/sinwma.py index 217c85f..aa8348a 100644 --- a/pandas_ta/overlap/sinwma.py +++ b/pandas_ta/overlap/sinwma.py @@ -10,8 +10,8 @@ def sinwma( ) -> Series: """Sine Weighted Moving Average (SWMA) - A weighted average using sine cycles. The middle term(s) of the average have the - highest weight(s). + A weighted average using sine cycles. The middle term(s) of the average + have the highest weight(s). Source: https://www.tradingview.com/script/6MWFvnPO-Sine-Weighted-Moving-Average/ @@ -42,11 +42,8 @@ def sinwma( for i in range(0, length)]) w = sines / sines.sum() - sinwma = close.rolling( - length, - min_periods=length).apply( - weights(w), - raw=True) + sinwma = close.rolling(length, min_periods=length) \ + .apply(weights(w), raw=True) # Offset if offset != 0: diff --git a/pandas_ta/overlap/sma.py b/pandas_ta/overlap/sma.py index bd10e2a..2d5a532 100644 --- a/pandas_ta/overlap/sma.py +++ b/pandas_ta/overlap/sma.py @@ -38,8 +38,8 @@ def sma( ) -> Series: """Simple Moving Average (SMA) - The Simple Moving Average is the classic moving average that is the equally - weighted average over n periods. + The Simple Moving Average is the classic moving average that is the + equally weighted average over its length. Sources: https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/ @@ -47,8 +47,8 @@ def sma( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -62,8 +62,10 @@ def sma( """ # Validate length = int(length) if length and length > 0 else 10 - min_periods = int( - kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True diff --git a/pandas_ta/overlap/smma.py b/pandas_ta/overlap/smma.py index 2bf83bb..9db5962 100644 --- a/pandas_ta/overlap/smma.py +++ b/pandas_ta/overlap/smma.py @@ -12,14 +12,15 @@ def smma( ) -> Series: """SMoothed Moving Average (SMMA) - The SMoothed Moving Average (SMMA) is bootstrapped by default with a Simple - Moving Average (SMA). It tries to reduce noise rather than reduce lag. The - SMMA takes all prices into account and uses a long lookback period. Old prices - are never removed from the calculation, but they have only a minimal impact on - the Moving Average due to a low assigned weight. By reducing the noise it - removes fluctuations and plots the prevailing trend. The SMMA can be used to - confirm trends and define areas of support and resistance. A core component of - Bill Williams Alligator indicator. + The SMoothed Moving Average (SMMA) is bootstrapped by default with a + Simple Moving Average (SMA). It tries to reduce noise rather than reduce + lag. The SMMA takes all prices into account and uses a long lookback + period. Old prices are never removed from the calculation, but they have + only a minimal impact on the Moving Average due to a low assigned + weight. By reducing the noise it removes fluctuations and plots the + prevailing trend. The SMMA can be used to confirm trends and define + areas of support and resistance. + A core component of Bill Williams Alligator indicator. Sources: https://www.tradingview.com/scripts/smma/ @@ -29,8 +30,8 @@ def smma( close (pd.Series): Series of 'close's length (int): It's period. Default: 10 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -42,8 +43,10 @@ def smma( """ # Validate length = int(length) if length and length > 0 else 7 - min_periods = int( - kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) mamode = mamode.lower() if isinstance(mamode, str) else "sma" @@ -56,14 +59,13 @@ def smma( m = close.size smma = close.copy() smma[:length - 1] = nan - smma.iloc[length - 1] = ma(mamode, - close[0:length], - length=length, - talib=mode_tal).iloc[-1] + smma.iloc[length - 1] = ma( + mamode, close[0:length], length=length, talib=mode_tal + ).iloc[-1] for i in range(length, m): - smma.iloc[i] = ((length - 1) * smma.iloc[i - 1] + - smma.iloc[i]) / length + smma.iloc[i] = ((length - 1) * smma.iloc[i - 1] + smma.iloc[i]) + smma.iloc[i] /= length # Offset if offset != 0: diff --git a/pandas_ta/overlap/ssf.py b/pandas_ta/overlap/ssf.py index 0e19c2e..c602f4b 100644 --- a/pandas_ta/overlap/ssf.py +++ b/pandas_ta/overlap/ssf.py @@ -50,10 +50,11 @@ def ssf( ) -> Series: """Ehler's Super Smoother Filter (SSF) © 2013 - John F. Ehlers's solution to reduce lag and remove aliasing noise with his - research in aerospace analog filter design. This implementation had two - poles. Since SSF is a (Resursive) Digital Filter, the number of poles - determine how many prior recursive SSF bars to include in the filter design. + John F. Ehlers's solution to reduce lag and remove aliasing noise with + his research in Aerospace analog filter design. This implementation had + two poles. Since SSF is a (Resursive) Digital Filter, the number of + poles determine how many prior recursive SSF bars to include in the + filter design. For Everget's calculation on TradingView, set arguments: pi = np.pi, sqrt2 = np.sqrt(2) @@ -66,8 +67,8 @@ def ssf( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 20 - everget (bool): Everget's implementation of ssf that uses pi instead of - 180 for the b factor of ssf. Default: False + everget (bool): Everget's implementation of ssf that uses pi + instead of 180 for the b factor of ssf. Default: False pi (float): The value of PI to use. The default is Ehler's truncated value 3.14159. Adjust the value for more precision. Default: 3.14159 diff --git a/pandas_ta/overlap/ssf3.py b/pandas_ta/overlap/ssf3.py index 6f639bf..2025932 100644 --- a/pandas_ta/overlap/ssf3.py +++ b/pandas_ta/overlap/ssf3.py @@ -37,10 +37,11 @@ def ssf3( ): """Ehler's 3 Pole Super Smoother Filter (SSF) © 2013 - John F. Ehlers's solution to reduce lag and remove aliasing noise with his - research in aerospace analog filter design. This is implementation has three - poles. Since SSF is a (Resursive) Digital Filter, the number of poles - determine how many prior recursive SSF bars to include in the filter design. + John F. Ehlers's solution to reduce lag and remove aliasing noise + with his research in aerospace analog filter design. This is + implementation has three poles. Since SSF is a (Resursive) Digital + Filter, the number of poles determine how many prior recursive SSF bars + to include in the filter design. For Everget's calculation on TradingView, set arguments: pi = np.pi, sqrt3 = 1.738 diff --git a/pandas_ta/overlap/supertrend.py b/pandas_ta/overlap/supertrend.py index 85c51f0..00c961f 100644 --- a/pandas_ta/overlap/supertrend.py +++ b/pandas_ta/overlap/supertrend.py @@ -34,7 +34,8 @@ def supertrend( fill_method (value, optional): Type of fill method Returns: - pd.DataFrame: SUPERT (trend), SUPERTd (direction), SUPERTl (long), SUPERTs (short) columns. + pd.DataFrame: SUPERT (trend), SUPERTd (direction), + SUPERTl (long), SUPERTs (short) columns. """ # Validate length = int(length) if length and length > 0 else 7 @@ -54,25 +55,25 @@ def supertrend( hl2_ = hl2(high, low) matr = multiplier * atr(high, low, close, length) - upperband = hl2_ + matr - lowerband = hl2_ - matr + ub = hl2_ + matr # Upperband + lb = hl2_ - matr # Lowerband for i in range(1, m): - if close.iloc[i] > upperband.iloc[i - 1]: + if close.iloc[i] > ub.iloc[i - 1]: dir_[i] = 1 - elif close.iloc[i] < lowerband.iloc[i - 1]: + elif close.iloc[i] < lb.iloc[i - 1]: dir_[i] = -1 else: dir_[i] = dir_[i - 1] - if dir_[i] > 0 and lowerband.iloc[i] < lowerband.iloc[i - 1]: - lowerband.iloc[i] = lowerband.iloc[i - 1] - if dir_[i] < 0 and upperband.iloc[i] > upperband.iloc[i - 1]: - upperband.iloc[i] = upperband.iloc[i - 1] + if dir_[i] > 0 and lb.iloc[i] < lb.iloc[i - 1]: + lb.iloc[i] = lb.iloc[i - 1] + if dir_[i] < 0 and ub.iloc[i] > ub.iloc[i - 1]: + ub.iloc[i] = ub.iloc[i - 1] if dir_[i] > 0: - trend[i] = long[i] = lowerband.iloc[i] + trend[i] = long[i] = lb.iloc[i] else: - trend[i] = short[i] = upperband.iloc[i] + trend[i] = short[i] = ub.iloc[i] _props = f"_{length}_{multiplier}" df = DataFrame({ diff --git a/pandas_ta/overlap/swma.py b/pandas_ta/overlap/swma.py index f5f3aae..b16e030 100644 --- a/pandas_ta/overlap/swma.py +++ b/pandas_ta/overlap/swma.py @@ -11,8 +11,8 @@ def swma( Symmetric Weighted Moving Average where weights are based on a symmetric triangle. For example: n=3 -> [1, 2, 1], n=4 -> [1, 2, 2, 1], etc... - This moving average has variable length in contrast to TradingView's fixed - length of 4. + This moving average has variable length in contrast to TradingView's + fixed length of 4. Source: https://www.tradingview.com/study-script-reference/#fun_swma @@ -40,11 +40,8 @@ def swma( # Calculate triangle = symmetric_triangle(length, weighted=True) - swma = close.rolling( - length, - min_periods=length).apply( - weights(triangle), - raw=True) + swma = close.rolling(length, min_periods=length) \ + .apply(weights(triangle), raw=True) # Offset if offset != 0: diff --git a/pandas_ta/overlap/t3.py b/pandas_ta/overlap/t3.py index f177cfc..2d07a2f 100644 --- a/pandas_ta/overlap/t3.py +++ b/pandas_ta/overlap/t3.py @@ -11,8 +11,8 @@ def t3( ) -> Series: """Tim Tillson's T3 Moving Average (T3) - Tim Tillson's T3 Moving Average is considered a smoother and more responsive - moving average relative to other moving averages. + Tim Tillson's T3 Moving Average is considered a smoother and more + responsive moving average relative to other moving averages. Sources: http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/ @@ -21,8 +21,8 @@ def t3( close (pd.Series): Series of 'close's length (int): It's period. Default: 10 a (float): 0 < a < 1. Default: 0.7 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/tema.py b/pandas_ta/overlap/tema.py index 5730b3d..4c2d29d 100644 --- a/pandas_ta/overlap/tema.py +++ b/pandas_ta/overlap/tema.py @@ -19,8 +19,8 @@ def tema( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/trima.py b/pandas_ta/overlap/trima.py index 5837e27..1bc7f2f 100644 --- a/pandas_ta/overlap/trima.py +++ b/pandas_ta/overlap/trima.py @@ -11,8 +11,8 @@ def trima( ) -> Series: """Triangular Moving Average (TRIMA) - A weighted moving average where the shape of the weights are triangular and the - greatest weight is in the middle of the period. + A weighted moving average where the shape of the weights are triangular + and the greatest weight is in the middle of the period. Sources: https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/ @@ -22,8 +22,8 @@ def trima( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 10 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/vidya.py b/pandas_ta/overlap/vidya.py index c65a6ec..9b4ede6 100644 --- a/pandas_ta/overlap/vidya.py +++ b/pandas_ta/overlap/vidya.py @@ -10,11 +10,11 @@ def vidya( ) -> Series: """Variable Index Dynamic Average (VIDYA) - Variable Index Dynamic Average (VIDYA) was developed by Tushar Chande. It is - similar to an Exponential Moving Average but it has a dynamically adjusted - lookback period dependent on relative price volatility as measured by Chande - Momentum Oscillator (CMO). When volatility is high, VIDYA reacts faster to - price changes. It is often used as moving average or trend identifier. + Variable Index Dynamic Average (VIDYA) was developed by Tushar Chande. + It is similar to an EMA but it has a dynamically adjusted lookback + period dependent on relative price volatility as measured by CMO. When + volatility is high, VIDYA reacts faster to price changes. + It is often used as moving average or trend identifier. Sources: https://www.tradingview.com/script/hdrf0fXV-Variable-Index-Dynamic-Average-VIDYA/ @@ -26,9 +26,12 @@ def vidya( offset (int): How many periods to offset the result. Default: 0 Kwargs: - adjust (bool, optional): Use adjust option for EMA calculation. Default: False - sma (bool, optional): If True, uses SMA for initial value for EMA calculation. Default: True - talib (bool): If True, uses TA-Libs implementation for CMO. Otherwise uses EMA version. Default: True + adjust (bool, optional): Use adjust option for EMA calculation. + Default: False + sma (bool, optional): If True, uses SMA for initial value for EMA + calculation. Default: True + talib (bool): If True, uses TA-Libs implementation for CMO. + Otherwise uses EMA version. Default: True fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): Type of fill method diff --git a/pandas_ta/overlap/vwap.py b/pandas_ta/overlap/vwap.py index aa2d9e4..abc9657 100644 --- a/pandas_ta/overlap/vwap.py +++ b/pandas_ta/overlap/vwap.py @@ -25,8 +25,9 @@ def vwap( low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's - anchor (str): How to anchor VWAP. Depending on the index values, it will - implement various Timeseries Offset Aliases as listed here: + anchor (str): How to anchor VWAP. Depending on the index values, + it will implement various Timeseries Offset Aliases + as listed here: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases Default: "D". offset (int): How many periods to offset the result. Default: 0 @@ -49,11 +50,11 @@ def vwap( typical_price = hlc3(high=high, low=low, close=close) if not is_datetime_ordered(volume): - print( - f"[!] VWAP volume series is not datetime ordered. Results may not be as expected.") + _s = "[!] VWAP volume series is not datetime ordered." + print(f"{_s} Results may not be as expected.") if not is_datetime_ordered(typical_price): - print( - f"[!] VWAP price series is not datetime ordered. Results may not be as expected.") + _s = "[!] VWAP price series is not datetime ordered." + print(f"{_s} Results may not be as expected.") # Calculate wp = typical_price * volume diff --git a/pandas_ta/overlap/wcp.py b/pandas_ta/overlap/wcp.py index 57d1f93..d4cc775 100644 --- a/pandas_ta/overlap/wcp.py +++ b/pandas_ta/overlap/wcp.py @@ -20,8 +20,8 @@ def wcp( high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -43,9 +43,8 @@ def wcp( from talib import WCLPRICE wcp = WCLPRICE(high, low, close) else: - wcp = Series( - (high.values + low.values + 2 * close.values), - index=close.index) + weight = high.values + low.values + 2 * close.values + wcp = Series(weight, index=close.index) # Offset if offset != 0: diff --git a/pandas_ta/overlap/wma.py b/pandas_ta/overlap/wma.py index 1216e28..961efcf 100644 --- a/pandas_ta/overlap/wma.py +++ b/pandas_ta/overlap/wma.py @@ -5,12 +5,15 @@ from pandas_ta.maps import Imports from pandas_ta.utils import get_offset, verify_series -def wma(close: Series, length: int = None, asc: bool = None, talib: bool = None, offset: int = None, - **kwargs) -> Series: +def wma( + close: Series, length: int = None, + asc: bool = None, talib: bool = None, + offset: int = None, **kwargs +) -> Series: """Weighted Moving Average (WMA) - The Weighted Moving Average where the weights are linearly increasing and - the most recent data has the heaviest weight. + The Weighted Moving Average where the weights are linearly increasing + and the most recent data has the heaviest weight. Sources: https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average @@ -19,8 +22,8 @@ def wma(close: Series, length: int = None, asc: bool = None, talib: bool = None, close (pd.Series): Series of 'close's length (int): It's period. Default: 10 asc (bool): Recent values weigh more. Default: True - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/overlap/zlma.py b/pandas_ta/overlap/zlma.py index 6a28795..36719c3 100644 --- a/pandas_ta/overlap/zlma.py +++ b/pandas_ta/overlap/zlma.py @@ -27,7 +27,8 @@ def zlma( """Zero Lag Moving Average (ZLMA) The Zero Lag Moving Average attempts to eliminate the lag associated - with moving averages. This is an adaption created by John Ehler and Ric Way. + with moving averages. This is an adaption created by John Ehler + and Ric Way. Sources: https://en.wikipedia.org/wiki/Zero_lag_exponential_moving_average diff --git a/pandas_ta/performance/drawdown.py b/pandas_ta/performance/drawdown.py index 4c5d29d..97a80f9 100644 --- a/pandas_ta/performance/drawdown.py +++ b/pandas_ta/performance/drawdown.py @@ -9,9 +9,9 @@ def drawdown( ) -> DataFrame: """Drawdown (DD) - Drawdown is a peak-to-trough decline during a specific period for an investment, - trading account, or fund. It is usually quoted as the percentage between the - peak and the subsequent trough. + Drawdown is a peak-to-trough decline during a specific period for an + investment, trading account, or fund. It is usually quoted as the + percentage between the peak and the subsequent trough. Sources: https://www.investopedia.com/terms/d/drawdown.asp diff --git a/pandas_ta/performance/log_return.py b/pandas_ta/performance/log_return.py index 95c58ca..582f47f 100644 --- a/pandas_ta/performance/log_return.py +++ b/pandas_ta/performance/log_return.py @@ -19,7 +19,8 @@ def log_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: @@ -31,8 +32,10 @@ def log_return( """ # Validate length = int(length) if length and length > 0 else 1 - cumulative = bool( - cumulative) if cumulative is not None and cumulative else False + if cumulative is not None and cumulative: + cumulative = bool(cumulative) + else: + cumulative = False close = verify_series(close, length) offset = get_offset(offset) diff --git a/pandas_ta/statistics/entropy.py b/pandas_ta/statistics/entropy.py index c750872..a8960f7 100644 --- a/pandas_ta/statistics/entropy.py +++ b/pandas_ta/statistics/entropy.py @@ -5,14 +5,14 @@ from pandas_ta.utils import get_offset, verify_series def entropy( - close: Series, length: int = None, base: float = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, base: float = None, + offset: int = None, **kwargs +) -> Series: """Entropy (ENTP) - Introduced by Claude Shannon in 1948, entropy measures the unpredictability - of the data, or equivalently, of its average information. A die has higher - entropy (p=1/6) versus a coin (p=1/2). + Introduced by Claude Shannon in 1948, entropy measures the + unpredictability of the data, or equivalently, of its average + information. A die has higher entropy (p=1/6) versus a coin (p=1/2). Sources: https://en.wikipedia.org/wiki/Entropy_(information_theory) @@ -36,7 +36,8 @@ def entropy( close = verify_series(close, length) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate p = close / close.rolling(length).sum() diff --git a/pandas_ta/statistics/kurtosis.py b/pandas_ta/statistics/kurtosis.py index 6cce2eb..7e12958 100644 --- a/pandas_ta/statistics/kurtosis.py +++ b/pandas_ta/statistics/kurtosis.py @@ -4,9 +4,9 @@ from pandas_ta.utils import get_offset, verify_series def kurtosis( - close: Series, length: int = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + offset: int = None, **kwargs +) -> Series: """Rolling Kurtosis Calculates the Kurtosis over a rolling period. @@ -25,7 +25,10 @@ def kurtosis( """ # Validate length = int(length) if length and length > 0 else 30 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) diff --git a/pandas_ta/statistics/mad.py b/pandas_ta/statistics/mad.py index c84bbd0..ada5899 100644 --- a/pandas_ta/statistics/mad.py +++ b/pandas_ta/statistics/mad.py @@ -5,9 +5,9 @@ from pandas_ta.utils import get_offset, verify_series def mad( - close: Series, length: int = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + offset: int = None, **kwargs +) -> Series: """Rolling Mean Absolute Deviation Calculates the Mean Absolute Deviation over a rolling period. @@ -26,11 +26,15 @@ def mad( """ # Validate length = int(length) if length and length > 0 else 30 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate def mad_(series): diff --git a/pandas_ta/statistics/median.py b/pandas_ta/statistics/median.py index 84396dc..dc79b9e 100644 --- a/pandas_ta/statistics/median.py +++ b/pandas_ta/statistics/median.py @@ -4,12 +4,12 @@ from pandas_ta.utils import get_offset, verify_series def median( - close: Series, length: int = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + offset: int = None, **kwargs +) -> Series: """Rolling Median - Calculates the Median over a rolling period. Sibling of a Simple Moving Average. + Calculates the Median over a rolling period. Sources: https://www.incrediblecharts.com/indicators/median_price.php @@ -28,11 +28,15 @@ def median( """ # Validate length = int(length) if length and length > 0 else 30 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate median = close.rolling(length, min_periods=min_periods).median() diff --git a/pandas_ta/statistics/quantile.py b/pandas_ta/statistics/quantile.py index 039a6b2..8a9478b 100644 --- a/pandas_ta/statistics/quantile.py +++ b/pandas_ta/statistics/quantile.py @@ -4,9 +4,9 @@ from pandas_ta.utils import get_offset, verify_series def quantile( - close: Series, length: int = None, q: float = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, q: float = None, + offset: int = None, **kwargs +) -> Series: """Rolling Quantile Calculates the Quantile over a rolling period. @@ -26,12 +26,16 @@ def quantile( """ # Validate length = int(length) if length and length > 0 else 30 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length q = float(q) if q and q > 0 and q < 1 else 0.5 close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate quantile = close.rolling(length, min_periods=min_periods).quantile(q) diff --git a/pandas_ta/statistics/skew.py b/pandas_ta/statistics/skew.py index 47cb87c..b226a04 100644 --- a/pandas_ta/statistics/skew.py +++ b/pandas_ta/statistics/skew.py @@ -4,9 +4,9 @@ from pandas_ta.utils import get_offset, verify_series def skew( - close: Series, length: int = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + offset: int = None, **kwargs +) -> Series: """Rolling Skew Calculates the Skew over a rolling period. @@ -25,11 +25,15 @@ def skew( """ # Validate length = int(length) if length and length > 0 else 30 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate skew = close.rolling(length, min_periods=min_periods).skew() diff --git a/pandas_ta/statistics/stdev.py b/pandas_ta/statistics/stdev.py index fd33af6..dd3889a 100644 --- a/pandas_ta/statistics/stdev.py +++ b/pandas_ta/statistics/stdev.py @@ -7,10 +7,10 @@ from .variance import variance def stdev( - close: Series, length: int = None, - ddof: int = None, talib: bool = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + ddof: int = None, talib: bool = None, + offset: int = None, **kwargs +) -> Series: """Rolling Standard Deviation Calculates the Standard Deviation over a rolling period. @@ -20,10 +20,11 @@ def stdev( length (int): It's period. Default: 30 ddof (int): Delta Degrees of Freedom. The divisor used in calculations is N - ddof, - where N represents the number of elements. The 'talib' argument - must be false for 'ddof' to work. Default: 1 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. TA Lib does not have a 'ddof' argument. Default: True + where N represents the number of elements. The 'talib' + argument must be false for 'ddof' to work. Default: 1 + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. TA Lib does not have a 'ddof' argument. + Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -35,19 +36,25 @@ def stdev( """ # Validate length = int(length) if isinstance(length, int) and length > 0 else 30 - ddof = int(ddof) if isinstance(ddof, int) and ddof >= 0 and ddof < length else 1 + if isinstance(ddof, int) and ddof >= 0 and ddof < length: + ddof = int(ddof) + else: + ddof = 1 close = verify_series(close, length) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True - if close is None: return + if close is None: + return # Calculate if Imports["talib"] and mode_tal: from talib import STDDEV stdev = STDDEV(close, length) else: - stdev = variance(close=close, length=length, ddof=ddof, talib=mode_tal).apply(sqrt) + stdev = variance( + close=close, length=length, ddof=ddof, talib=mode_tal + ).apply(sqrt) # Offset if offset != 0: diff --git a/pandas_ta/statistics/tos_stdevall.py b/pandas_ta/statistics/tos_stdevall.py index 227d60c..63d5274 100644 --- a/pandas_ta/statistics/tos_stdevall.py +++ b/pandas_ta/statistics/tos_stdevall.py @@ -5,15 +5,15 @@ from pandas_ta.utils import get_offset, verify_series def tos_stdevall( - close: Series, length: int = None, - stds: list = None, ddof: int = None, - offset: int = None, **kwargs - ) -> DataFrame: + close: Series, length: int = None, + stds: list = None, ddof: int = None, + offset: int = None, **kwargs +) -> DataFrame: """TD Ameritrade's Think or Swim Standard Deviation All (TOS_STDEV) - A port of TD Ameritrade's Think or Swim Standard Deviation All indicator which - returns the standard deviation of data for the entire plot or for the interval - of the last bars defined by the length parameter. + A port of TD Ameritrade's Think or Swim Standard Deviation All indicator + which returns the standard deviation of data for the entire plot or for + the interval of the last bars defined by the length parameter. Sources: https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/StDevAll @@ -54,7 +54,8 @@ def tos_stdevall( close = verify_series(close, length) - if close is None: return + if close is None: + return # Calculate X = src_index = close.index diff --git a/pandas_ta/statistics/variance.py b/pandas_ta/statistics/variance.py index 3b1771e..0c5d134 100644 --- a/pandas_ta/statistics/variance.py +++ b/pandas_ta/statistics/variance.py @@ -5,10 +5,10 @@ from pandas_ta.utils import get_offset, verify_series def variance( - close: Series, length: int = None, - ddof: int = None, talib: bool = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, + ddof: int = None, talib: bool = None, + offset: int = None, **kwargs +) -> Series: """Rolling Variance Calculates the Variance over a rolling period. @@ -18,10 +18,12 @@ def variance( length (int): It's period. Default: 30 ddof (int): Delta Degrees of Freedom. The divisor used in calculations is N - ddof, - where N represents the number of elements. The 'talib' argument - must be false for 'ddof' to work. Default: 1 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. TA Lib does not have a 'ddof' argument. Default: True + where N represents the number of elements. + The 'talib' argument must be false for 'ddof' to work. + Default: 1 + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Note: TA Lib does not have a 'ddof' argument. + Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -34,12 +36,16 @@ def variance( # Validate length = int(length) if isinstance(length, int) and length > 1 else 30 ddof = int(ddof) if isinstance(ddof, int) and ddof >= 0 and ddof < length else 1 - min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length close = verify_series(close, max(length, min_periods)) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True - if close is None: return + if close is None: + return # Calculate if Imports["talib"] and mode_tal: diff --git a/pandas_ta/statistics/zscore.py b/pandas_ta/statistics/zscore.py index 3addb45..b6dbc89 100644 --- a/pandas_ta/statistics/zscore.py +++ b/pandas_ta/statistics/zscore.py @@ -6,9 +6,9 @@ from pandas_ta.utils import get_offset, verify_series def zscore( - close: Series, length: int = None, std: float = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, length: int = None, std: float = None, + offset: int = None, **kwargs +) -> Series: """Rolling Z Score Calculates the Z Score over a rolling period. @@ -32,7 +32,8 @@ def zscore( close = verify_series(close, length) offset = get_offset(offset) - if close is None: return + if close is None: + return # Calculate std *= stdev(close=close, length=length, **kwargs) diff --git a/pandas_ta/transform/cube.py b/pandas_ta/transform/cube.py index 53accf0..9444afe 100644 --- a/pandas_ta/transform/cube.py +++ b/pandas_ta/transform/cube.py @@ -4,9 +4,9 @@ from pandas_ta.utils import get_offset, verify_series def cube( - close: Series, cubing_exponent: float = None, signal_offset: int = None, - offset: int = None, **kwargs - ) -> DataFrame: + close: Series, cubing_exponent: float = None, signal_offset: int = None, + offset: int = None, **kwargs +) -> DataFrame: """ Indicator: Cube Transform diff --git a/pandas_ta/transform/ifisher.py b/pandas_ta/transform/ifisher.py index 25e587a..499dd45 100644 --- a/pandas_ta/transform/ifisher.py +++ b/pandas_ta/transform/ifisher.py @@ -6,10 +6,10 @@ from .remap import remap def ifisher( - close: Series, - amp: float = None, signal_offset: int = None, - offset: int = None, **kwargs - ) -> DataFrame: + close: Series, + amp: float = None, signal_offset: int = None, + offset: int = None, **kwargs +) -> DataFrame: """ Indicator: Inverse Fisher Transform diff --git a/pandas_ta/transform/remap.py b/pandas_ta/transform/remap.py index a52ebaf..d334092 100644 --- a/pandas_ta/transform/remap.py +++ b/pandas_ta/transform/remap.py @@ -4,10 +4,10 @@ from pandas_ta.utils import get_offset, verify_series def remap( - close: Series, from_min: float = None, from_max: float = None, - to_min: float = None, to_max: float = None, - offset: int = None, **kwargs - ) -> Series: + close: Series, from_min: float = None, from_max: float = None, + to_min: float = None, to_max: float = None, + offset: int = None, **kwargs +) -> Series: """ Indicator: ReMap (REMAP) diff --git a/pandas_ta/trend/adx.py b/pandas_ta/trend/adx.py index fd58cc0..1636da0 100644 --- a/pandas_ta/trend/adx.py +++ b/pandas_ta/trend/adx.py @@ -13,8 +13,8 @@ def adx( ) -> DataFrame: """Average Directional Movement (ADX) - Average Directional Movement is meant to quantify trend strength by measuring - the amount of movement in a single direction. + Average Directional Movement is meant to quantify trend strength by + measuring the amount of movement in a single direction. Sources: TA Lib Correlation: >99% @@ -25,7 +25,8 @@ def adx( low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's length (int): It's period. Default: 14 - lensig (int): Signal Length. Like TradingView's default ADX. Default: length + lensig (int): Signal Length. Like TradingView's default ADX. + Default: length scalar (float): How much to magnify. Default: 100 mamode (str): See ``help(ta.ma)``. Default: 'rma' drift (int): The difference period. Default: 1 diff --git a/pandas_ta/trend/amat.py b/pandas_ta/trend/amat.py index 6b7b507..93b04a1 100644 --- a/pandas_ta/trend/amat.py +++ b/pandas_ta/trend/amat.py @@ -16,8 +16,8 @@ def amat( Archer Moving Averages Trends (AMAT) developed by Kevin Johnson provides creates both long run ``help(ta.long_run)`` and short run ``help(ta.short_run)`` trend signals given two moving average speeds, - fast and slow. The long runs and short runs are binary Series where '1' is - a trend and '0' is not a trend. + fast and slow. The long runs and short runs are binary Series where '1' + is a trend and '0' is not a trend. Sources: https://www.tradingview.com/script/Z2mq63fE-Trade-Archer-Moving-Averages-v1-4F/ diff --git a/pandas_ta/trend/aroon.py b/pandas_ta/trend/aroon.py index 64dc4a8..e8e5e4b 100644 --- a/pandas_ta/trend/aroon.py +++ b/pandas_ta/trend/aroon.py @@ -22,8 +22,8 @@ def aroon( close (pd.Series): Series of 'close's length (int): It's period. Default: 14 scalar (float): How much to magnify. Default: 100 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -50,16 +50,10 @@ def aroon( aroon_down, aroon_up = AROON(high, low, length) aroon_osc = AROONOSC(high, low, length) else: - periods_from_hh = high.rolling( - length + - 1).apply( - recent_maximum_index, - raw=True) - periods_from_ll = low.rolling( - length + - 1).apply( - recent_minimum_index, - raw=True) + periods_from_hh = high.rolling(length + 1) \ + .apply(recent_maximum_index,raw=True) + periods_from_ll = low.rolling(length + 1) \ + .apply(recent_minimum_index,raw=True) aroon_up = aroon_down = scalar aroon_up *= 1 - (periods_from_hh / length) diff --git a/pandas_ta/trend/chop.py b/pandas_ta/trend/chop.py index dc066df..35aee0f 100644 --- a/pandas_ta/trend/chop.py +++ b/pandas_ta/trend/chop.py @@ -43,8 +43,10 @@ def chop( """ # Validate length = int(length) if length and length > 0 else 14 - atr_length = int( - atr_length) if atr_length is not None and atr_length > 0 else 1 + if atr_length is not None and atr_length > 0: + atr_length = int(atr_length) + else: + atr_length = 1 ln = bool(ln) if isinstance(ln, bool) else False scalar = float(scalar) if scalar else 100 high = verify_series(high, length) diff --git a/pandas_ta/trend/cksp.py b/pandas_ta/trend/cksp.py index 39c84eb..ab1f9fd 100644 --- a/pandas_ta/trend/cksp.py +++ b/pandas_ta/trend/cksp.py @@ -16,10 +16,10 @@ def cksp( “The New Technical Trader”. It is a trend-following indicator, identifying your stop by calculating the average true range of the recent market volatility. The indicator defaults to the implementation - found on tradingview but it provides the original book implementation as well, - which differs by the default periods and moving average mode. While the trading - view implementation uses the Welles Wilder moving average, the book uses a - simple moving average. + found on tradingview but it provides the original book implementation as + well, which differs by the default periods and moving average mode. While + the trading view implementation uses the Welles Wilder moving average, the + book uses a simple moving average. Defaults: Book: p=10, x=3, q=20 @@ -88,8 +88,9 @@ def cksp( short_stop.name = f"CKSPs{_props}" long_stop.category = short_stop.category = "trend" - ckspdf = DataFrame( - {long_stop.name: long_stop, short_stop.name: short_stop}) + ckspdf = DataFrame({ + long_stop.name: long_stop, short_stop.name: short_stop + }) ckspdf.name = f"CKSP{_props}" ckspdf.category = long_stop.category diff --git a/pandas_ta/trend/decay.py b/pandas_ta/trend/decay.py index 9f044fe..c7d666a 100644 --- a/pandas_ta/trend/decay.py +++ b/pandas_ta/trend/decay.py @@ -10,8 +10,9 @@ def decay( ) -> Series: """Decay - Creates a decay moving forward from prior signals like crosses. The default is - "linear". Exponential is optional as "exponential" or "exp". + Creates a decay moving forward from prior signals like crosses. + The default is "linear". + Exponential is optional as "exponential" or "exp". Sources: https://tulipindicators.org/decay diff --git a/pandas_ta/trend/decreasing.py b/pandas_ta/trend/decreasing.py index 80cbab4..aa62597 100644 --- a/pandas_ta/trend/decreasing.py +++ b/pandas_ta/trend/decreasing.py @@ -11,14 +11,15 @@ def decreasing( """Decreasing Returns True if the series is decreasing over a period, False otherwise. - If the kwarg 'strict' is True, it returns True if it is continuously decreasing - over the period. When using the kwarg 'asint', then it returns 1 for True - or 0 for False. + If the kwarg 'strict' is True, it returns True if it is continuously + decreasing over the period. When using the kwarg 'asint', then it + returns 1 for True or 0 for False. Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 1 - strict (bool): If True, checks if the series is continuously decreasing over the period. Default: False + strict (bool): If True, checks if the series is continuously + decreasing over the period. Default: False percent (float): Percent as an integer. Default: None asint (bool): Returns as binary. Default: True drift (int): The difference period. Default: 1 @@ -49,8 +50,7 @@ def decreasing( # Returns value as float64? Have to cast to bool decreasing = close < close_.shift(drift) for x in range(3, length + 1): - decreasing = decreasing & (close.shift( - x - (drift + 1)) < close_.shift(x - drift)) + decreasing &= (close.shift(x - (drift + 1)) < close_.shift(x - drift)) decreasing.fillna(0, inplace=True) decreasing = decreasing.astype(bool) diff --git a/pandas_ta/trend/dpo.py b/pandas_ta/trend/dpo.py index 0e42d99..92b7442 100644 --- a/pandas_ta/trend/dpo.py +++ b/pandas_ta/trend/dpo.py @@ -21,7 +21,8 @@ def dpo( Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 1 - centered (bool): Shift the dpo back by int(0.5 * length) + 1. Default: True + centered (bool): Shift the dpo back by int(0.5 * length) + 1. + Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/trend/increasing.py b/pandas_ta/trend/increasing.py index f722126..add9e83 100644 --- a/pandas_ta/trend/increasing.py +++ b/pandas_ta/trend/increasing.py @@ -11,14 +11,15 @@ def increasing( """Increasing Returns True if the series is increasing over a period, False otherwise. - If the kwarg 'strict' is True, it returns True if it is continuously increasing - over the period. When using the kwarg 'asint', then it returns 1 for True - or 0 for False. + If the kwarg 'strict' is True, it returns True if it is continuously + increasing over the period. When using the kwarg 'asint', then it + returns 1 for True or 0 for False. Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 1 - strict (bool): If True, checks if the series is continuously increasing over the period. Default: False + strict (bool): If True, checks if the series is continuously increasing + over the period. Default: False percent (float): Percent as an integer. Default: None asint (bool): Returns as binary. Default: True drift (int): The difference period. Default: 1 @@ -49,8 +50,7 @@ def increasing( # Returns value as float64? Have to cast to bool increasing = close > close_.shift(drift) for x in range(3, length + 1): - increasing = increasing & (close.shift( - x - (drift + 1)) > close_.shift(x - drift)) + increasing &= (close.shift(x - (drift + 1)) > close_.shift(x - drift)) increasing.fillna(0, inplace=True) increasing = increasing.astype(bool) diff --git a/pandas_ta/trend/long_run.py b/pandas_ta/trend/long_run.py index 4c91482..fce303b 100644 --- a/pandas_ta/trend/long_run.py +++ b/pandas_ta/trend/long_run.py @@ -48,10 +48,10 @@ def long_run( return # Calculate - pb = increasing(fast, length) & decreasing( - slow, length) # potential bottom or bottom - bi = increasing(fast, length) & increasing( - slow, length) # fast and slow are increasing + # potential bottom or bottom + pb = increasing(fast, length) & decreasing(slow, length) + # fast and slow are increasing + bi = increasing(fast, length) & increasing(slow, length) long_run = pb | bi # Offset diff --git a/pandas_ta/trend/psar.py b/pandas_ta/trend/psar.py index a5bbbec..24a5591 100644 --- a/pandas_ta/trend/psar.py +++ b/pandas_ta/trend/psar.py @@ -11,15 +11,16 @@ def psar( ) -> DataFrame: """Parabolic Stop and Reverse (psar) - Parabolic Stop and Reverse (PSAR) was developed by J. Wells Wilder, that is used - to determine trend direction and it's potential reversals in price. PSAR uses a - trailing stop and reverse method called "SAR," or stop and reverse, to identify - possible entries and exits. It is also known as SAR. + Parabolic Stop and Reverse (PSAR) was developed by J. Wells Wilder, that + is used to determine trend direction and it's potential reversals in + price. PSAR uses a trailing stop and reverse method called "SAR," or stop + and reverse, to identify possible entries and exits. It is also known + as SAR. - PSAR indicator typically appears on a chart as a series of dots, either above or - below an asset's price, depending on the direction the price is moving. A dot is - placed below the price when it is trending upward, and above the price when it - is trending downward. + PSAR indicator typically appears on a chart as a series of dots, either + above or below an asset's price, depending on the direction the price is + moving. A dot is placed below the price when it is trending upward, and + above the price when it is trending downward. Sources: https://www.tradingview.com/pine-script-reference/#fun_sar @@ -49,14 +50,6 @@ def psar( max_af = float(max_af) if max_af and max_af > 0 else 0.2 offset = get_offset(offset) - def _falling(high, low, drift: int = 1): - """Returns the last -DM value""" - # Not to be confused with ta.falling() - up = high - high.shift(drift) - dn = low.shift(drift) - low - _dmn = (((dn > up) & (dn > 0)) * dn).apply(zero).iloc[-1] - return _dmn > 0 - # Falling if the first NaN -DM is positive falling = _falling(high.iloc[:2], low.iloc[:2]) if falling: @@ -149,3 +142,11 @@ def psar( psardf.category = long.category = short.category = "trend" return psardf + +def _falling(high, low, drift: int = 1): + """Returns the last -DM value""" + # Not to be confused with ta.falling() + up = high - high.shift(drift) + dn = low.shift(drift) - low + _dmn = (((dn > up) & (dn > 0)) * dn).apply(zero).iloc[-1] + return _dmn > 0 diff --git a/pandas_ta/trend/qstick.py b/pandas_ta/trend/qstick.py index d4e687e..542f3dc 100644 --- a/pandas_ta/trend/qstick.py +++ b/pandas_ta/trend/qstick.py @@ -10,8 +10,8 @@ def qstick( ) -> Series: """Q Stick - The Q Stick indicator, developed by Tushar Chande, attempts to quantify and - identify trends in candlestick charts. + The Q Stick indicator, developed by Tushar Chande, attempts to quantify + and identify trends in candlestick charts. Sources: https://library.tradingtechnologies.com/trade/chrt-ti-qstick.html @@ -20,7 +20,8 @@ def qstick( open (pd.Series): Series of 'open's close (pd.Series): Series of 'close's length (int): It's period. Default: 1 - ma (str): The type of moving average to use. Default: None, which is 'sma' + ma (str): The type of moving average to use. + Default: None, which is 'sma' offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/trend/short_run.py b/pandas_ta/trend/short_run.py index 18d063e..eb9cf23 100644 --- a/pandas_ta/trend/short_run.py +++ b/pandas_ta/trend/short_run.py @@ -48,11 +48,10 @@ def short_run( return # Calculate - pt = decreasing( - fast, length) & increasing( - slow, length) # potential top or top - bd = decreasing(fast, length) & decreasing( - slow, length) # fast and slow are decreasing + # potential top or top + pt = decreasing( fast, length) & increasing(slow, length) + # fast and slow are decreasing + bd = decreasing(fast, length) & decreasing(slow, length) short_run = pt | bd # Offset diff --git a/pandas_ta/trend/trendflex.py b/pandas_ta/trend/trendflex.py index b0873e5..c56fc98 100644 --- a/pandas_ta/trend/trendflex.py +++ b/pandas_ta/trend/trendflex.py @@ -11,8 +11,9 @@ except ImportError: @njit -def np_trendflex(x: ndarray, n: int, k: int, - alpha: float, pi: float, sqrt2: float): +def np_trendflex( + x: ndarray, n: int, k: int, alpha: float, pi: float, sqrt2: float +): """Ehler's Trendflex http://traders.com/Documentation/FEEDbk_docs/2020/02/TradersTips.html""" m, ratio = x.size, 2 * sqrt2 / k @@ -50,12 +51,14 @@ def trendflex( John F. Ehlers introduced two indicators within the article "Reflex: A New Zero-Lag Indicator” in February 2020, TASC magazine. One of which is the - Trendflex, a lag reduced trend indicator. Both indicators (Reflex/Trendflex) are - oscillators and complement each other with the focus for cycle and trend. + Trendflex, a lag reduced trend indicator. + Both indicators (Reflex/Trendflex) are oscillators and complement each + other with the focus for cycle and trend. - Written for Pandas TA by rengel8 (2021-08-11) based on the implementation on - ProRealCode (see Sources). Beyond the mentioned source, this implementation has - a separate control parameter for the internal applied SuperSmoother. + Written for Pandas TA by rengel8 (2021-08-11) based on the implementation + on ProRealCode (see Sources). Beyond the mentioned source, this + implementation has a separate control parameter for the internal applied + SuperSmoother. Sources: http://traders.com/Documentation/FEEDbk_docs/2020/02/TradersTips.html diff --git a/pandas_ta/trend/tsignals.py b/pandas_ta/trend/tsignals.py index ca94b53..320108d 100644 --- a/pandas_ta/trend/tsignals.py +++ b/pandas_ta/trend/tsignals.py @@ -10,31 +10,33 @@ def tsignals( ) -> DataFrame: """Trend Signals - Given a Trend, Trend Signals returns the Trend, Trades, Entries and Exits as - boolean integers. When 'asbool=True', it returns Trends, Entries and Exits as - boolean values which is helpful when combined with the vectorbt backtesting - package. + Given a Trend, Trend Signals returns the Trend, Trades, Entries and + Exits as boolean integers. When 'asbool=True', it returns Trends, Entries + and Exits as boolean values which is helpful when combined with the + vectorbt backtesting package. - A Trend can be a simple as: 'close' > 'moving average' or something more complex - whose values are boolean or integers (0 or 1). + A Trend can be a simple as: 'close' > 'moving average' or something more + complex whose values are boolean or integers (0 or 1). Examples: ta.tsignals(close > ta.sma(close, 50), asbool=False) ta.tsignals(ta.ema(close, 8) > ta.ema(close, 21), asbool=True) - Source: + Source: Kevin Johnson Args: - trend (pd.Series): Series of 'trend's. The trend can be either a boolean or - integer series of '0's and '1's - asbool (bool): If True, it converts the Trends, Entries and Exits columns to - booleans. When boolean, it is also useful for backtesting with - vectorbt's Portfolio.from_signal(close, entries, exits) Default: False - trend_reset (value): Value used to identify if a trend has ended. Default: 0 - trade_offset (value): Value used shift the trade entries/exits Use 1 for - backtesting and 0 for live. Default: 0 + trend (pd.Series): Series of 'trend's. The trend can be either a + boolean or integer series of '0's and '1's + asbool (bool): If True, it converts the Trends, Entries and Exits + columns to booleans. When boolean, it is also useful for + backtesting with vectorbt's + Portfolio.from_signal(close, entries, exits) Default: False + trend_reset (value): Value used to identify if a trend has ended. + Default: 0 + trade_offset (value): Value used shift the trade entries/exits + use 1 for backtesting and 0 for live. Default: 0 drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -44,17 +46,23 @@ def tsignals( Returns: pd.DataFrame with columns: - Trends (trend: 1, no trend: 0), Trades (Enter: 1, Exit: -1, Otherwise: 0), - Entries (entry: 1, nothing: 0), Exits (exit: 1, nothing: 0) + Trends (trend: 1, no trend: 0), + Trades (Enter: 1, Exit: -1, Otherwise: 0), + Entries (entry: 1, nothing: 0), + Exits (exit: 1, nothing: 0) """ # Validate trend = verify_series(trend) asbool = bool(asbool) if isinstance(asbool, bool) else False - trend_reset = int(trend_reset) if trend_reset and isinstance( - trend_reset, int) else 0 + if trend_reset and isinstance(trend_reset, int): + trend_reset = int(trend_reset) + else: + trend_reset = 0 if trade_offset != 0: - trade_offset = int(trade_offset) if trade_offset and isinstance( - trade_offset, int) else 0 + if trade_offset and isinstance(trade_offset, int): + trade_offset = int(trade_offset) + else: + trade_offset = 0 drift = get_drift(drift) offset = get_offset(offset) diff --git a/pandas_ta/trend/ttm_trend.py b/pandas_ta/trend/ttm_trend.py index 253ec43..6c69f30 100644 --- a/pandas_ta/trend/ttm_trend.py +++ b/pandas_ta/trend/ttm_trend.py @@ -10,10 +10,11 @@ def ttm_trend( ) -> DataFrame: """TTM Trend (TTM_TRND) - This indicator is from John Carters book “Mastering the Trade” and plots the - bars green or red. It checks if the price is above or under the average price of - the previous 5 bars. The indicator should hep you stay in a trade until the - colors chance. Two bars of the opposite color is the signal to get in or out. + This indicator is from John Carters book “Mastering the Trade” and + plots the bars green or red. It checks if the price is above or under + the average price of the previous 5 bars. The indicator should hep you + stay in a trade until the colors chance. Two bars of the opposite color + is the signal to get in or out. Sources: https://www.prorealcode.com/prorealtime-indicators/ttm-trend-price/ diff --git a/pandas_ta/trend/vortex.py b/pandas_ta/trend/vortex.py index c47f465..eb1cdaf 100644 --- a/pandas_ta/trend/vortex.py +++ b/pandas_ta/trend/vortex.py @@ -33,8 +33,10 @@ def vortex( """ # Validate length = length if length and length > 0 else 14 - min_periods = int( - kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length + if "min_periods" in kwargs and kwargs["min_periods"] is not None: + min_periods = int(kwargs["min_periods"]) + else: + min_periods = length _length = max(length, min_periods) high = verify_series(high, _length) low = verify_series(low, _length) diff --git a/pandas_ta/utils/_math.py b/pandas_ta/utils/_math.py index 7741016..8e223e2 100644 --- a/pandas_ta/utils/_math.py +++ b/pandas_ta/utils/_math.py @@ -7,7 +7,6 @@ from typing import List, Optional, Union from numpy import all, append, array, corrcoef, dot, exp, fabs from numpy import log, nan, ndarray, ones, seterr, sqrt, sum, triu -# from numpy import array as npArray from pandas import DataFrame, Series from pandas_ta.maps import Imports from pandas_ta.utils._core import verify_series @@ -130,8 +129,7 @@ def linear_regression(x: Series, y: Series) -> dict: m, n = x.size, y.size if m != n: - print( - f"[X] Linear Regression X and y have unequal total observations: {m} != {n}") + print(f"[X] X and y have unequal total observations: {m} != {n}") return {} if Imports["sklearn"]: @@ -231,7 +229,8 @@ def weights(w: ndarray): def zero(x: Union[int, float]) -> Union[int, float]: - """If the value is close to zero, then return zero. Otherwise return itself.""" + """If the value is close to zero, then return zero. + Otherwise return itself.""" return 0 if abs(x) < sflt.epsilon else x @@ -260,7 +259,8 @@ def df_error_analysis(dfA: DataFrame, dfB: DataFrame, **kwargs) -> DataFrame: # PRIVATE def _linear_regression_np(x: Series, y: Series) -> dict: - """Simple Linear Regression in Numpy for two 1d arrays for environments without the sklearn package.""" + """Simple Linear Regression in Numpy + for two 1d arrays for environments without the sklearn package.""" result = {"a": nan, "b": nan, "r": nan, "t": nan, "line": nan} x_sum = x.sum() y_sum = y.sum() diff --git a/pandas_ta/utils/_metrics.py b/pandas_ta/utils/_metrics.py index 91bc411..b21d9ca 100644 --- a/pandas_ta/utils/_metrics.py +++ b/pandas_ta/utils/_metrics.py @@ -24,8 +24,9 @@ def cagr(close: Series) -> float: return ((end / start) ** (1 / total_time(close))) - 1 -def calmar_ratio(close: Series, method: str = "percent", - years: int = 3) -> float: +def calmar_ratio( + close: Series, method: str = "percent", years: int = 3 +) -> float: """The Calmar Ratio is the percent Max Drawdown Ratio 'typically' over the past three years. @@ -49,7 +50,8 @@ def calmar_ratio(close: Series, method: str = "percent", def downside_deviation( - returns: Series, benchmark_rate: float = 0.0, tf: str = "years") -> float: + returns: Series, benchmark_rate: float = 0.0, tf: str = "years" +) -> float: """Downside Deviation for the Sortino ratio. Benchmark rate is assumed to be annualized. Adjusted according for the number of periods per year seen in the data. @@ -103,8 +105,9 @@ def log_max_drawdown(close: Series) -> float: return log_return - max_drawdown(close, method="log") -def max_drawdown(close: Series, method: str = None, - all: bool = False) -> float: +def max_drawdown( + close: Series, method: str = None, all: bool = False +) -> float: """Maximum Drawdown from close. Default: 'dollar'. Args: @@ -132,16 +135,18 @@ def max_drawdown(close: Series, method: str = None, return max_dd_["dollar"] -def optimal_leverage(close: Series, benchmark_rate: float = 0.0, - period: Union[float, int] = RATE["TRADING_DAYS_PER_YEAR"], - log: bool = False, capital: float = 1., **kwargs) -> float: +def optimal_leverage( + close: Series, benchmark_rate: float = 0.0, + period: Union[float, int] = RATE["TRADING_DAYS_PER_YEAR"], + log: bool = False, capital: float = 1., **kwargs +) -> float: """Optimal Leverage of a series. NOTE: Incomplete. Do NOT use. Args: close (pd.Series): Series of 'close's benchmark_rate (float): Benchmark Rate to use. Default: 0.0 - period (int, float): Period to use to calculate Mean Annual Return and - Annual Standard Deviation. + period (int, float): Period to use to calculate Mean Annual Return + and Annual Standard Deviation. Default: None or the default sharpe_ratio.period() log (bool): If True, calculates log_return. Otherwise it returns percent_return. Default: False @@ -184,8 +189,10 @@ def pure_profit_score(close: Series) -> Union[float, int]: return 0 -def sharpe_ratio(close: Series, benchmark_rate: float = 0.0, log: bool = False, use_cagr: bool = False, - period: int = RATE["TRADING_DAYS_PER_YEAR"]) -> float: +def sharpe_ratio( + close: Series, benchmark_rate: float = 0.0, log: bool = False, + use_cagr: bool = False, period: int = RATE["TRADING_DAYS_PER_YEAR"] +) -> float: """Sharpe Ratio of a series. Args: @@ -213,8 +220,9 @@ def sharpe_ratio(close: Series, benchmark_rate: float = 0.0, log: bool = False, return (period_mu - benchmark_rate) / period_std -def sortino_ratio(close: Series, benchmark_rate: float = 0.0, - log: bool = False) -> float: +def sortino_ratio( + close: Series, benchmark_rate: float = 0.0, log: bool = False +) -> float: """Sortino Ratio of a series. Args: @@ -235,21 +243,22 @@ def sortino_ratio(close: Series, benchmark_rate: float = 0.0, return result -def volatility(close: Series, tf: str = "years", - returns: bool = False, log: bool = False, **kwargs) -> float: +def volatility( + close: Series, tf: str = "years", returns: bool = False, log: bool = False +) -> float: """Volatility of a series. Default: 'years' Args: close (pd.Series): Series of 'close's tf (str): Time Frame options: 'days', 'weeks', 'months', and 'years'. Default: 'years' - returns (bool): If True, then it replace the close Series with the user - defined Series; typically user generated returns or percent returns - or log returns. Default: False + returns (bool): If True, then it replace the close Series with the + user defined Series; typically user generated returns or percent + returns or log returns. Default: False log (bool): If True, calculates log_return. Otherwise it calculates percent_return. Default: False - >>> result = ta.volatility(close, tf="years", returns=False, log=False, **kwargs) + >>> result = ta.volatility(close, tf="years", returns=False, log=False) """ close = verify_series(close) diff --git a/pandas_ta/utils/_signals.py b/pandas_ta/utils/_signals.py index 606e47f..ba21e79 100644 --- a/pandas_ta/utils/_signals.py +++ b/pandas_ta/utils/_signals.py @@ -41,8 +41,9 @@ def above( series_a: Series, series_b: Series, asint: bool = True, offset: int = None, **kwargs ) -> Series: - return _above_below(series_a, series_b, above=True, - asint=asint, offset=offset, **kwargs) + return _above_below( + series_a, series_b, above=True, asint=asint, offset=offset, **kwargs + ) def above_value( @@ -53,22 +54,21 @@ def above_value( print("[X] value is not a number") return series_b = Series( - value, - index=series_a.index, - name=f"{value}".replace( - ".", - "_")) + value, index=series_a.index, name=f"{value}".replace(".", "_") + ) - return _above_below(series_a, series_b, above=True, - asint=asint, offset=offset, **kwargs) + return _above_below( + series_a, series_b, above=True, asint=asint, offset=offset, **kwargs + ) def below( series_a: Series, series_b: Series, asint: bool = True, offset: int = None, **kwargs ) -> Series: - return _above_below(series_a, series_b, above=False, - asint=asint, offset=offset, **kwargs) + return _above_below( + series_a, series_b, above=False, asint=asint, offset=offset, **kwargs + ) def below_value( @@ -79,13 +79,11 @@ def below_value( print("[X] value is not a number") return series_b = Series( - value, - index=series_a.index, - name=f"{value}".replace( - ".", - "_")) - return _above_below(series_a, series_b, above=False, - asint=asint, offset=offset, **kwargs) + value, index=series_a.index, name=f"{value}".replace(".", "_") + ) + return _above_below( + series_a, series_b, above=False, asint=asint, offset=offset, **kwargs + ) def cross_value( @@ -93,11 +91,8 @@ def cross_value( offset: int = None, **kwargs ) -> Series: series_b = Series( - value, - index=series_a.index, - name=f"{value}".replace( - ".", - "_")) + value, index=series_a.index, name=f"{value}".replace(".", "_") + ) return cross(series_a, series_b, above, asint, offset, **kwargs) diff --git a/pandas_ta/utils/_time.py b/pandas_ta/utils/_time.py index f39fca6..3cf9d44 100644 --- a/pandas_ta/utils/_time.py +++ b/pandas_ta/utils/_time.py @@ -50,8 +50,9 @@ def final_time(stime: float) -> str: return f"{time_diff * 1000:2.4f} ms ({time_diff:2.4f} s)" -def get_time(exchange: str = "NYSE", full: bool = True, - to_string: bool = False) -> Union[None, str]: +def get_time( + exchange: str = "NYSE", full: bool = True, to_string: bool = False +) -> Union[None, str]: """Returns Current Time, Day of the Year and Percentage, and the current time of the selected Exchange.""" tz = EXCHANGE_TZ["NYSE"] # Default is NYSE (Eastern Time Zone) diff --git a/pandas_ta/utils/data/alphavantage.py b/pandas_ta/utils/data/alphavantage.py index e89455e..b4dd0d5 100644 --- a/pandas_ta/utils/data/alphavantage.py +++ b/pandas_ta/utils/data/alphavantage.py @@ -12,7 +12,10 @@ def av(ticker: str, **kwargs) -> DataFrame: show = kwargs.pop("show", None) # last = kwargs.pop("last", RATE["TRADING_DAYS_PER_YEAR"]) - ticker = ticker.upper() if ticker is not None and isinstance(ticker, str) else None + if ticker is not None and isinstance(ticker, str): + ticker = ticker.upper() + else: + ticker = None if Imports["alphaVantage-api"] and ticker is not None: # from alphaVantageAPI import alphavantage @@ -22,7 +25,8 @@ def av(ticker: str, **kwargs) -> DataFrame: "clean": True, "export": False, "output_size": "full", - "premium": False} + "premium": False + } _config = kwargs.pop("av_kwargs", AVC) av = AV.AlphaVantage(**_config) diff --git a/pandas_ta/utils/data/polygon_api.py b/pandas_ta/utils/data/polygon_api.py index bbd150e..50ccc4e 100644 --- a/pandas_ta/utils/data/polygon_api.py +++ b/pandas_ta/utils/data/polygon_api.py @@ -9,20 +9,24 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: r""" polygon_api - polygon.io API helper function. - It returns OCHLV data from polygon (requires a valid subscription of course). To install the - `polygon library `__ , use - ``pip install polygon``. - You can customize the range of data using kwargs ``from_date``, ``to_date``, ``timespan`` and ``multiplier``. For a - description of these arguments, see + It returns OCHLV data from polygon (A valid subscription is required). + To install the `polygon library `__ , + use ``pip install polygon``. + You can customize the range of data using kwargs ``from_date``, + ``to_date``, ``timespan`` and ``multiplier``. For a description of + these arguments, see `Here `__ - To view additional information about the ticker symbols, you can use the **kwarg** ``kind``, defaulting to - ``None`` which doesn't pull/display any additional info. + To view additional information about the ticker symbols, you can use + the **kwarg** ``kind``, defaulting to ``None`` which doesn't + pull/display any additional info. - **The function will always return the OCHLV dataframe no matter what additional info you ask it to pull.** The - additional information is used for display only (yet?) + **The function will always return the OCHLV dataframe no matter what + additional info you ask it to pull.** The additional information is + used for display only (yet?) - Other options for kwarg ``kind`` are as described (in format: ``value_to_supply: description of that info type``): + Other options for kwarg ``kind`` are as described + in format: ``value_to_supply: description of that info type``): * ``all`` OR ``info``: Everything below is displayed * ``option_chains`` OR ``oc``: Option chains information @@ -32,20 +36,29 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: Described Below :Keyword Arguments: - * ``api_key`` - REQUIRED. Your polygon API key. Visit your dashboard to get this key. - * ``show`` - How many last rows of Chart History to show. Default: None - * ``kind`` - options described above. Defaults to None - * ``desc`` - whether to print the description of company or not. Defaults to False. - * ``start_date`` - start date of time range to get data for. Defaults to roughly a year back. Can be supplied - as a ``datetime`` or ``date`` object or string ``YYYY-MM-DD`` - * ``to_date`` - end date of time range to get data for. Defaults to up to most recent data available. Can be - supplied as a ``datetime`` or ``date`` object or string ``YYYY-MM-DD`` - * ``limit`` - max number of base candles to aggregate from. Defaults to 50000 (also the maximum value). - * ``timespan`` - Type of candles' granularity. Defaults to ``day`` which returns day candles. - * ``multiplier`` - multiplier of granularity. defaults to 1. so defaults candles are of `1Day` granularity. - * ``contract_type`` - default to all contract types. Can be changed to ``call`` OR ``put``. Only applicable - when displaying option chains data - * ``contract_limit`` - max number of contracts to display from option chains information. Defaults to 10 + * ``api_key`` - REQUIRED. Your polygon API key. + Visit your dashboard to get this key. + * ``show`` - How many last rows of Chart History to show. + Default: None + * ``kind`` - Options described above. Default: None + * ``desc`` - Company description. Default: False + * ``start_date`` - Start Date for the time range. + Defaults to roughly a year back. Can be supplied as a + ``datetime`` or ``date`` object or string ``YYYY-MM-DD`` + * ``to_date`` - End date for the time range. + Defaults to up to most recent data available. Can be supplied as + a ``datetime`` or ``date`` object or string ``YYYY-MM-DD`` + * ``limit`` - Max number of candles to aggregate. + Default: 50000 (also the maximum value). + * ``timespan`` - Type of candles' granularity. + Default: ``day`` (Daily Candles) + * ``multiplier`` - Multiplier of granularity. Default: 1. + Defaults candles are of `1Day` granularity. + * ``contract_type`` - Can be changed to ``call`` OR ``put``. + Only applicable when displaying option chains data. + Default: both + * ``contract_limit`` - Max number of Contracts to display from + Option Chains. Default: 10 * ``verbose`` - Prints Company Information "info" and a Chart History header to the screen. Default: False """ @@ -69,10 +82,8 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: f"Ticker symbol name must be a valid name string. Eg: \'AMD\'") start_date = kwargs.pop( - "start_date", - (datetime.date.today() - - datetime.timedelta( - days=525))) + "start_date", (datetime.date.today() - datetime.timedelta(days=525)) + ) end_date = kwargs.pop("end_date", datetime.date.today()) limit = kwargs.pop("limit", 50000) multiplier = kwargs.pop("multiplier", 1) @@ -85,8 +96,10 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: import polygon as polyapi with polyapi.StocksClient(api_key) as polygon_client: - resp = polygon_client.get_aggregate_bars(ticker, start_date, end_date, limit=limit, - multiplier=multiplier, timespan=timespan) + resp = polygon_client.get_aggregate_bars( + ticker, start_date, end_date, limit=limit, + multiplier=multiplier, timespan=timespan + ) df = DataFrame() if "results" in resp.keys(): @@ -126,7 +139,7 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: else: print(f"{details_vx['ticker']}") - # TODO: polygon returns hell lotta data for market info across a few endpoints. I don't know which ones to + # TODO: polygon returns a lot of data for market info across a few endpoints. I don't know which ones to # include here lol. I wrote the ones i felt were important. Feel free to suggest more. # Yeah. It needs some additional modifications since details and details_vx are # not equal and sparse depending on asset of ticker @@ -265,15 +278,14 @@ def polygon_api(ticker: str, **kwargs) -> DataFrame: if contract_type is None: alldf = merge( - calldf.reset_index(), - putdf.reset_index(), - on="Strike") + calldf.reset_index(), putdf.reset_index(), on="Strike" + ) alldf.rename( columns={ "Contract_x": "Calls", "Contract_y": "Puts", - "Exp. Date_x": "Exp. Date"}, - inplace=True + "Exp. Date_x": "Exp. Date" + }, inplace=True ) alldf.set_index("Exp. Date", inplace=True) alldf = alldf[["Calls", "Strike", "Puts"]] diff --git a/pandas_ta/utils/data/processes.py b/pandas_ta/utils/data/processes.py index fc7e3dc..d134e71 100644 --- a/pandas_ta/utils/data/processes.py +++ b/pandas_ta/utils/data/processes.py @@ -21,14 +21,15 @@ class sample(object): To get the most out of sample(), install the 'stochastic' package: $ pip install stochastic - The following stochastic package noise and processes have been implemented: + The following stochastic package noise and processes have been + implemented: * Noise[9]: Blue "b", Brownian "br, Fractal Gaussian "fg", Gaussian "g", Pink "p", Red "r", Violet "v", Wiener "w", Random "rand", or None * Processes[11]: Brownian Bridge "bb", Brownian Excursion "be", - Brownian Meander "bm", Brownian Motion "bmo", Cox Ingersoll Ross "cir", - Fractional Brownian Motion "fbm", Geometric Brownian Motion "gbm", - Ornstein Uhlenbeck "ou", Random Walk "rw", Wiener "w", Random "rand" - or None. + Brownian Meander "bm", Brownian Motion "bmo", + Cox Ingersoll Ross "cir", Fractional Brownian Motion "fbm", + Geometric Brownian Motion "gbm", Ornstein Uhlenbeck "ou", + Random Walk "rw", Wiener "w", Random "rand" or None. * If the stochastic process is not installed, a Simple Random Walk is realized without noise. * When argument process="rand", a process is chosen at random. @@ -40,16 +41,19 @@ class sample(object): Args: * Basic options name (str): Set a ticker name. Default: A random ticker like 'SMPL'. - process (str): The process to realize. See options above. Default: None + process (str): The process to realize. See options above. + Default: None noise (str): Noise to apply. See options above. Default: None length (int): How many observations to generate. Default: ta.RATE["TRADING_DAYS_PER_YEAR"] (252) * Additional transformations - orient (str): Applies either a Reversal, Inversion or Inverted Reversal - of the realization. Default: None. - positive (bool): If the resultant process is non-negative. Default: True - scale (str): Applies either Mean, Normal or Standard scale. Default: None. + orient (str): Applies either a Reversal, Inversion or + Inverted Reversal of the realization. Default: None. + positive (bool): If the resultant process is non-negative. + Default: True + scale (str): Applies either Mean, Normal or Standard scale. + Default: None. noise_percent (float): Percentage of noise to apply. (Not implemented) Default: 1.0 @@ -73,10 +77,10 @@ class sample(object): * Misc. Options future (bool): Whether the resultant DataFrame Index has a future date range or a past date range. Default: True - freq (str): The frequency to use for the generated DataFrame date range - index. (Not implemented) In Default: "D" - intraday (str): If intraday is 'full', 24 hours, or is an 'equity' with - 6.5 hours. (Not implemented) Default: "full" + freq (str): The frequency to use for the generated DataFrame + date range index. (Not implemented) In Default: "D" + intraday (str): If intraday is 'full', 24 hours, or is an 'equity' + with 6.5 hours. (Not implemented) Default: "full" date_fmt (str): Date Format for Daterange. Default: '%Y-%m-%d' precision (int): How many decimals to round when printing to stdout. Default: 6 @@ -119,29 +123,20 @@ class sample(object): _noises = ["b", "br", "fg", "g", "p", "r", "v", "w", None, "rand"] _orientations = ["i", "r", "ir", "ri", None, "rand"] _processes = [ - "bb", - "be", - "bm", - "bmo", - "cir", - "fbm", - "gbm", - "ou", - "rw", - "w", - None, - "rand"] + "bb", "be", "bm", "bmo", "cir", "fbm", + "gbm", "ou", "rw", "w", None, "rand" + ] _scales = ["m", "n", "s", None] def __init__(self, - name=None, process=None, noise=None, length=None, - s0=None, b=None, t=None, drift=None, volatility=None, - speed=None, hurst=None, steps=None, random_number=None, - orient=None, positive=None, scale=None, - future=None, freq=None, intraday=None, - noise_percent=None, - date_fmt=None, precision=None, verbose=None - ): + name=None, process=None, noise=None, length=None, + s0=None, b=None, t=None, drift=None, volatility=None, + speed=None, hurst=None, steps=None, random_number=None, + orient=None, positive=None, scale=None, + future=None, freq=None, intraday=None, + noise_percent=None, + date_fmt=None, precision=None, verbose=None + ): """Validation and initialization of arguments and then runs the _generate() method to build a sample realization with the given arguments. @@ -362,16 +357,9 @@ class sample(object): if up < down: down, up = up, down - x = concatenate( - ([0.0], - where( - randint( - 0, - 2, - size=self.length - - 1) == 0, - down, - up))) + x = concatenate(([0.0], + where(randint(0, 2, size=self.length - 1) == 0, down, up) + )) return cumsum(x).astype(float) def _stoch_noise(self): diff --git a/pandas_ta/utils/data/yahoofinance.py b/pandas_ta/utils/data/yahoofinance.py index 2c376aa..370e71d 100644 --- a/pandas_ta/utils/data/yahoofinance.py +++ b/pandas_ta/utils/data/yahoofinance.py @@ -37,8 +37,8 @@ def yf(ticker: str, **kwargs) -> DataFrame: ticker (str): Any string for a ticker you would use with yfinance. Default: "SPY" Kwargs: - calls (bool): When True, prints only Option Calls for the Option Chain. - Default: None + calls (bool): When True, prints only Option Calls for the + Option Chain. Default: None desc (bool): Will print Company Description when printing Company Information. Default: False exp (str): Used to print other Option Chains for the given Expiration diff --git a/pandas_ta/volatility/atr.py b/pandas_ta/volatility/atr.py index 298d4d1..6fb788b 100644 --- a/pandas_ta/volatility/atr.py +++ b/pandas_ta/volatility/atr.py @@ -13,8 +13,8 @@ def atr( ) -> Series: """Average True Range (ATR) - Averge True Range is used to measure volatility, especially volatility caused by - gaps or limit moves. + Averge True Range is used to measure volatility, especially volatility + caused by gaps or limit moves. Sources: https://www.tradingview.com/wiki/Average_True_Range_(ATR) @@ -25,8 +25,8 @@ def atr( close (pd.Series): Series of 'close's length (int): It's period. Default: 14 mamode (str): See ``help(ta.ma)``. Default: 'rma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns the + TA Lib version. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -57,11 +57,8 @@ def atr( atr = ATR(high, low, close, length) else: tr = true_range( - high=high, - low=low, - close=close, - drift=drift, - talib=mode_tal) + high=high, low=low, close=close, drift=drift, talib=mode_tal + ) atr = ma(mamode, tr, length=length, talib=mode_tal) percentage = kwargs.pop("percent", False) diff --git a/pandas_ta/volatility/bbands.py b/pandas_ta/volatility/bbands.py index b4e635f..e94a96b 100644 --- a/pandas_ta/volatility/bbands.py +++ b/pandas_ta/volatility/bbands.py @@ -24,11 +24,11 @@ def bbands( std (int): The long period. Default: 2 ddof (int): Degrees of Freedom to use. Default: 0 mamode (str): See ``help(ta.ma)``. Default: 'sma' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True ddof (int): Delta Degrees of Freedom. - The divisor used in calculations is N - ddof, - where N represents the number of elements. The 'talib' argument + The divisor used in calculations is N - ddof, where N + represents the number of elements. The 'talib' argument must be false for 'ddof' to work. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -43,8 +43,10 @@ def bbands( length = int(length) if length and length > 0 else 5 std = float(std) if std and std > 0 else 2.0 mamode = mamode if isinstance(mamode, str) else "sma" - ddof = int(ddof) if isinstance( - ddof, int) and ddof >= 0 and ddof < length else 1 + if isinstance(ddof, int) and ddof >= 0 and ddof < length: + ddof = int(ddof) + else: + ddof = 1 close = verify_series(close, length) offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True @@ -58,10 +60,8 @@ def bbands( upper, mid, lower = BBANDS(close, length, std, std, tal_ma(mamode)) else: standard_deviation = stdev( - close=close, - length=length, - ddof=ddof, - talib=mode_tal) + close=close, length=length, ddof=ddof, talib=mode_tal + ) deviations = std * standard_deviation # deviations = std * standard_deviation.loc[standard_deviation.first_valid_index():,] diff --git a/pandas_ta/volatility/donchian.py b/pandas_ta/volatility/donchian.py index ac9f909..24fb06b 100644 --- a/pandas_ta/volatility/donchian.py +++ b/pandas_ta/volatility/donchian.py @@ -31,19 +31,29 @@ def donchian( pd.DataFrame: lower, mid, upper columns. """ # Validate - lower_length = int( - lower_length) if lower_length and lower_length > 0 else 20 - upper_length = int( - upper_length) if upper_length and upper_length > 0 else 20 - lower_min_periods = int( - kwargs["lower_min_periods"]) if "lower_min_periods" in kwargs and kwargs["lower_min_periods"] is not None else lower_length - upper_min_periods = int( - kwargs["upper_min_periods"]) if "upper_min_periods" in kwargs and kwargs["upper_min_periods"] is not None else upper_length + if lower_length and lower_length > 0: + lower_length = int(lower_length) + else: + lower_length = 20 + + if upper_length and upper_length > 0: + upper_length = int(upper_length) + else: + upper_length = 20 + + if "lower_min_periods" in kwargs and kwargs["lower_min_periods"] is not None: + lower_min_periods = int(kwargs["lower_min_periods"]) + else: + lower_min_periods = lower_length + + if "upper_min_periods" in kwargs and kwargs["upper_min_periods"] is not None: + upper_min_periods = int(kwargs["upper_min_periods"]) + else: + upper_min_periods = upper_length + _length = max( - lower_length, - lower_min_periods, - upper_length, - upper_min_periods) + lower_length, lower_min_periods, upper_length, upper_min_periods + ) high = verify_series(high, _length) low = verify_series(low, _length) offset = get_offset(offset) diff --git a/pandas_ta/volatility/hwc.py b/pandas_ta/volatility/hwc.py index 4e9cf1d..8c61ef6 100644 --- a/pandas_ta/volatility/hwc.py +++ b/pandas_ta/volatility/hwc.py @@ -5,9 +5,10 @@ from pandas_ta.utils import get_offset, verify_series def hwc( - close: Series, scalar: float = None, channel_eval: bool = None, - na: float = None, nb: float = None, nc: float = None, nd: float = None, - offset: int = None, **kwargs) -> DataFrame: + close: Series, scalar: float = None, channel_eval: bool = None, + na: float = None, nb: float = None, nc: float = None, nd: float = None, + offset: int = None, **kwargs +) -> DataFrame: """HWC (Holt-Winter Channel) Channel indicator HWC (Holt-Winters Channel) based on HWMA - a three-parameter @@ -44,8 +45,10 @@ def hwc( nc = float(nc) if nc and nc > 0 else 0.1 nd = float(nd) if nd and nd > 0 else 0.1 scalar = float(scalar) if scalar and scalar > 0 else 1 - channel_eval = bool( - channel_eval) if channel_eval and channel_eval else False + if isinstance(channel_eval, bool) and channel_eval: + channel_eval = bool(channel_eval) + else: + channel_eval = False close = verify_series(close) offset = get_offset(offset) @@ -62,8 +65,8 @@ def hwc( A = (1.0 - nc) * last_a + nc * (V - last_v) result.append((F + V + 0.5 * A)) - var = (1.0 - nd) * last_var + nd * (last_price - - last_result) * (last_price - last_result) + var = (1.0 - nd) * last_var + \ + nd * (last_price - last_result) * (last_price - last_result) stddev = sqrt(last_var) upper.append(result[i] + scalar * stddev) lower.append(result[i] - scalar * stddev) @@ -72,9 +75,7 @@ def hwc( # channel width chan_width.append(upper[i] - lower[i]) # channel percentage price position - chan_pct_width.append( - (close[i] - lower[i]) / (upper[i] - lower[i])) - # print('channel_eval (width|percentageWidth):', chan_width[i], chan_pct_width[i]) + chan_pct_width.append((close[i] - lower[i]) / (upper[i] - lower[i])) # update values last_price = close[i] @@ -119,28 +120,28 @@ def hwc( hwc_pctwidth.fillna(method=kwargs["fill_method"], inplace=True) # Name and Category - # suffix = f'{str(na).replace(".", "")}-{str(nb).replace(".", "")}-{str(nc).replace(".", "")}' - hwc.name = "HWM" - hwc_upper.name = "HWU" - hwc_lower.name = "HWL" + _props = f"_{scalar}" + hwc.name = f"HWM{_props}" + hwc_upper.name = f"HWU{_props}" + hwc_lower.name = f"HWL{_props}" hwc.category = hwc_upper.category = hwc_lower.category = "volatility" - if channel_eval: - hwc_width.name = "HWW" - hwc_pctwidth.name = "HWPCT" if channel_eval: - data = {hwc.name: hwc, hwc_upper.name: hwc_upper, hwc_lower.name: hwc_lower, - hwc_width.name: hwc_width, hwc_pctwidth.name: hwc_pctwidth} - df = DataFrame(data) - df.name = "HWC" - df.category = hwc.category + data = { + hwc.name: hwc, + hwc_upper.name: hwc_upper, + hwc_lower.name: hwc_lower, + f"HWW{_props}": hwc_width, + f"HWPCT{_props}": hwc_pctwidth + } else: data = { hwc.name: hwc, hwc_upper.name: hwc_upper, - hwc_lower.name: hwc_lower} - df = DataFrame(data) - df.name = "HWC" - df.category = hwc.category + hwc_lower.name: hwc_lower + } + df = DataFrame(data) + df.name = f"HWC_{scalar}" + df.category = hwc.category return df diff --git a/pandas_ta/volatility/kc.py b/pandas_ta/volatility/kc.py index 85539d1..82bc6a4 100644 --- a/pandas_ta/volatility/kc.py +++ b/pandas_ta/volatility/kc.py @@ -28,8 +28,9 @@ def kc( 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 + 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 diff --git a/pandas_ta/volatility/massi.py b/pandas_ta/volatility/massi.py index d89503f..43a495c 100644 --- a/pandas_ta/volatility/massi.py +++ b/pandas_ta/volatility/massi.py @@ -10,8 +10,9 @@ def massi( ) -> Series: """Mass Index (MASSI) - The Mass Index is a non-directional volatility indicator that utilitizes the - High-Low Range to identify trend reversals based on range expansions. + The Mass Index is a non-directional volatility indicator that + utilitizes the High-Low Range to identify trend reversals based on + range expansions. Sources: https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:mass_index diff --git a/pandas_ta/volatility/natr.py b/pandas_ta/volatility/natr.py index 30af53e..c567452 100644 --- a/pandas_ta/volatility/natr.py +++ b/pandas_ta/volatility/natr.py @@ -25,8 +25,8 @@ def natr( length (int): The short period. Default: 20 scalar (float): How much to magnify. Default: 100 mamode (str): See ``help(ta.ma)``. Default: 'ema' - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/volatility/rvi.py b/pandas_ta/volatility/rvi.py index da895d6..d8cf3f0 100644 --- a/pandas_ta/volatility/rvi.py +++ b/pandas_ta/volatility/rvi.py @@ -15,9 +15,9 @@ def rvi( ) -> Series: """Relative Volatility Index (RVI) - The Relative Volatility Index (RVI) was created in 1993 and revised in 1995. - Instead of adding up price changes like RSI based on price direction, the RVI - adds up standard deviations based on price direction. + The Relative Volatility Index (RVI) was created in 1993 and revised + in 1995. Instead of adding up price changes like RSI based on price + direction, the RVI adds up standard deviations based on price direction. Sources: https://www.tradingview.com/wiki/Keltner_Channels_(KC) diff --git a/pandas_ta/volatility/thermo.py b/pandas_ta/volatility/thermo.py index fcfc93b..af7c2f3 100644 --- a/pandas_ta/volatility/thermo.py +++ b/pandas_ta/volatility/thermo.py @@ -91,7 +91,8 @@ def thermo( thermo_ma.name = f"THERMOma{_props}" thermo_long.name = f"THERMOl{_props}" thermo_short.name = f"THERMOs{_props}" - thermo.category = thermo_ma.category = thermo_long.category = thermo_short.category = "volatility" + thermo.category = thermo_ma.category = "volatility" + thermo_long.category = thermo_short.category = thermo.category data = { thermo.name: thermo, diff --git a/pandas_ta/volatility/true_range.py b/pandas_ta/volatility/true_range.py index c682f89..93de895 100644 --- a/pandas_ta/volatility/true_range.py +++ b/pandas_ta/volatility/true_range.py @@ -22,8 +22,8 @@ def true_range( high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True drift (int): The shift period. Default: 1 offset (int): How many periods to offset the result. Default: 0 diff --git a/pandas_ta/volatility/ui.py b/pandas_ta/volatility/ui.py index 112c232..4bea824 100644 --- a/pandas_ta/volatility/ui.py +++ b/pandas_ta/volatility/ui.py @@ -11,8 +11,9 @@ def ui( ) -> Series: """Ulcer Index (UI) - The Ulcer Index by Peter Martin measures the downside volatility with the use of - the Quadratic Mean, which has the effect of emphasising large drawdowns. + The Ulcer Index by Peter Martin measures the downside volatility with + the use of the Quadratic Mean, which has the effect of emphasising + large drawdowns. Sources: https://library.tradingtechnologies.com/trade/chrt-ti-ulcer-index.html diff --git a/pandas_ta/volume/ad.py b/pandas_ta/volume/ad.py index d041a70..f169d2a 100644 --- a/pandas_ta/volume/ad.py +++ b/pandas_ta/volume/ad.py @@ -12,7 +12,7 @@ def ad( """Accumulation/Distribution (AD) Accumulation/Distribution indicator utilizes the relative position - of the close to it's High-Low range with volume. Then it is cumulated. + of the close to it's High-Low range with volume then cummulated. Sources: https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/accumulationdistribution-ad/ @@ -23,8 +23,8 @@ def ad( close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's open_ (pd.Series): Series of 'open's - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/volume/adosc.py b/pandas_ta/volume/adosc.py index 7042731..0fea823 100644 --- a/pandas_ta/volume/adosc.py +++ b/pandas_ta/volume/adosc.py @@ -29,8 +29,8 @@ def adosc( volume (pd.Series): Series of 'volume's fast (int): The short period. Default: 12 slow (int): The long period. Default: 26 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -62,12 +62,9 @@ def adosc( adosc = ADOSC(high, low, close, volume, fast, slow) else: ad_ = ad( - high=high, - low=low, - close=close, - volume=volume, - open_=open_, - talib=mode_tal) + high=high, low=low, close=close, volume=volume, + open_=open_, talib=mode_tal + ) fast_ad = ema(close=ad_, length=fast, **kwargs, talib=mode_tal) slow_ad = ema(close=ad_, length=slow, **kwargs, talib=mode_tal) adosc = fast_ad - slow_ad diff --git a/pandas_ta/volume/aobv.py b/pandas_ta/volume/aobv.py index 650e180..d889f6e 100644 --- a/pandas_ta/volume/aobv.py +++ b/pandas_ta/volume/aobv.py @@ -43,10 +43,17 @@ def aobv( # Validate fast = int(fast) if fast and fast > 0 else 4 slow = int(slow) if slow and slow > 0 else 12 - max_lookback = int( - max_lookback) if max_lookback and max_lookback > 0 else 2 - min_lookback = int( - min_lookback) if min_lookback and min_lookback > 0 else 2 + + if max_lookback and max_lookback > 0: + max_lookback = int(max_lookback) + else: + max_lookback = 2 + + if min_lookback and min_lookback > 0: + min_lookback = int(min_lookback) + else: + min_lookback = 2 + if slow < fast: fast, slow = slow, fast mamode = mamode if isinstance(mamode, str) else "ema" diff --git a/pandas_ta/volume/mfi.py b/pandas_ta/volume/mfi.py index 0b02a33..85bbf6a 100644 --- a/pandas_ta/volume/mfi.py +++ b/pandas_ta/volume/mfi.py @@ -12,8 +12,8 @@ def mfi( ) -> Series: """Money Flow Index (MFI) - Money Flow Index is an oscillator indicator that is used to measure buying and - selling pressure by utilizing both price and volume. + Money Flow Index is an oscillator indicator that is used to measure + buying and selling pressure by utilizing both price and volume. Sources: https://www.tradingview.com/wiki/Money_Flow_(MFI) @@ -24,8 +24,8 @@ def mfi( close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's length (int): The sum period. Default: 14 - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 @@ -57,7 +57,9 @@ 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 diff --git a/pandas_ta/volume/obv.py b/pandas_ta/volume/obv.py index 2dc4ba7..f27c597 100644 --- a/pandas_ta/volume/obv.py +++ b/pandas_ta/volume/obv.py @@ -21,8 +21,8 @@ def obv( Args: close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's - talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib - version. Default: True + talib (bool): If TA Lib is installed and talib is True, Returns + the TA Lib version. Default: True offset (int): How many periods to offset the result. Default: 0 Kwargs: diff --git a/pandas_ta/volume/pvi.py b/pandas_ta/volume/pvi.py index 2733b91..72209ee 100644 --- a/pandas_ta/volume/pvi.py +++ b/pandas_ta/volume/pvi.py @@ -43,8 +43,8 @@ def pvi( # Calculate signed_volume = signed_series(volume, 1) - pvi = roc(close=close, length=length) * \ - signed_volume[signed_volume > 0].abs() + _roc = roc(close=close, length=length) + pvi = _roc * signed_volume[signed_volume > 0].abs() pvi.fillna(0, inplace=True) pvi.iloc[0] = initial pvi = pvi.cumsum() diff --git a/pandas_ta/volume/wb_tsv.py b/pandas_ta/volume/wb_tsv.py index ba58f63..786683c 100644 --- a/pandas_ta/volume/wb_tsv.py +++ b/pandas_ta/volume/wb_tsv.py @@ -12,12 +12,12 @@ def wb_tsv( ) -> DataFrame: """Time Segmented Value (TSV) - TSV is a proprietary technical indicator developed by Worden Brothers Inc., - classified as an oscillator. It compares various time segments of both price - and volume. It measures the amount money flowing at various time segments - for price and time; similar to On Balance Volume. The zero line is called - the baseline. Entry and exit points are commonly determined when crossing - the baseline. + TSV is a proprietary technical indicator developed by Worden Brothers + Inc., classified as an oscillator. It compares various time segments of + both price and volume. It measures the amount money flowing at various + time segments for price and time; similar to On Balance Volume. The zero + line is called the baseline. Entry and exit points are commonly + determined when crossing the baseline. Sources: https://www.tradingview.com/script/6GR4ht9X-Time-Segmented-Volume/ diff --git a/tests/test_ext_indicator_cycles.py b/tests/test_ext_indicator_cycles.py index 4abb395..8997b5f 100644 --- a/tests/test_ext_indicator_cycles.py +++ b/tests/test_ext_indicator_cycles.py @@ -23,6 +23,10 @@ class TestCylesExtension(TestCase): self.assertIsInstance(self.data, DataFrame) self.assertEqual(self.data.columns[-1], "EBSW_40_10") + self.data.ta.ebsw(append=True, initial_version=True) + self.assertIsInstance(self.data, DataFrame) + self.assertEqual(self.data.columns[-1], "EBSW_40_10") + def test_reflex_ext(self): self.data.ta.reflex(append=True) self.assertIsInstance(self.data, DataFrame) diff --git a/tests/test_indicator_volatility.py b/tests/test_indicator_volatility.py index 38bb831..d7bf6df 100644 --- a/tests/test_indicator_volatility.py +++ b/tests/test_indicator_volatility.py @@ -114,6 +114,16 @@ class TestVolatility(TestCase): self.assertIsInstance(result, DataFrame) self.assertEqual(result.name, "DC_20_5") + def test_hwc(self): + """Volatility: HWC""" + result = pandas_ta.hwc(self.close) + self.assertIsInstance(result, DataFrame) + self.assertEqual(result.name, "HWC_1") + + result = pandas_ta.hwc(self.close, channel_eval=True) + self.assertIsInstance(result, DataFrame) + self.assertEqual(result.name, "HWC_1") + def test_kc(self): """Volatility: KC""" result = pandas_ta.kc(self.high, self.low, self.close)