mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-07-29 11:24:14 +08:00
DOC readme update MAINT refactoring
This commit is contained in:
@@ -4,12 +4,18 @@
|
||||
[](https://pypistats.org/packages/pandas_ta)
|
||||
|
||||
# **Pandas TA**
|
||||
# Pandas Technical Analysis Library in _Python 3_
|
||||
|
||||

|
||||
|
||||
## A Pandas Technical Analysis Library in _Python 3_
|
||||
|
||||
_Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that is built upon Python's Pandas library with more than 120 Indicators and Utility functions. These indicators are commonly used for financial time series datasets with columns or labels: datetime, _open_, _high_, _low_, _close_, _volume_, et al. Many commonly used indicators are included, such as: _Simple Moving Average_ (**sma**) _Moving Average Convergence Divergence_ (**macd**), _Hull Exponential Moving Average_ (**hma**), _Bollinger Bands_ (**bbands**), _On-Balance Volume_ (**obv**), _Aroon & Aroon Oscillator_ (**aroon**), _Squeeze_ (**squeeze**) and **many more**.
|
||||
|
||||
**Pandas TA** has three different ways of processing Technical Indicators as described below. The **primary** requirement to run indicators in [Pandas DataFrame Extension](https://pandas.pydata.org/pandas-docs/stable/extending.html) mode, is that _open, high, low, close, volume_ are **lowercase**. Depending on the indicator, they either return a named Series or a DataFrame in uppercase underscore parameter format. For example, MACD(fast=12, slow=26, signal=9) will return a DataFrame with columns: ['MACD_12_26_9', 'MACDh_12_26_9', 'MACDs_12_26_9'].
|
||||
* **Pandas TA** has multiple ways of processing Technical Indicators to fit your programming style.
|
||||
* The **primary** requirement to run indicators in [Pandas DataFrame Extension](https://pandas.pydata.org/pandas-docs/stable/extending.html) mode, is that _open, high, low, close, volume_ are **lowercase**.
|
||||
* Each indicator either returns a Series or a DataFrame in Uppercase Underscore format.
|
||||
* For example, ```df.ta.macd(fast=12, slow=26, signal=9)``` will return a DataFrame with columns: ```['MACD_12_26_9', 'MACDh_12_26_9', 'MACDs_12_26_9']```.
|
||||
* When in doubt, use help(): ```help(ta.macd)```
|
||||
|
||||
## Pandas TA Issues, Ideas and Contributions
|
||||
|
||||
@@ -35,24 +41,26 @@ Please take a moment to read **this** and the rest of this **README** before pos
|
||||
* The indicator does not match another website, library, broker platform, language, et al.
|
||||
* Can you contribute?
|
||||
|
||||
## __Contributors__
|
||||
Thank you for your contribution!
|
||||
|
||||
## __Features__
|
||||
[alexonab](https://github.com/alexonab) | [allahyarzadeh](https://github.com/allahyarzadeh) | [DrPaprikaa](https://github.com/DrPaprikaa) | [FGU1](https://github.com/FGU1) | [lluissalord](https://github.com/lluissalord) | [maxdignan](https://github.com/maxdignan) | [SoftDevDanial](https://github.com/SoftDevDanial) | [YuvalWein](https://github.com/YuvalWein)
|
||||
|
||||
# __Pandas TA__ Features
|
||||
|
||||
* Has 120+ indicators and utility functions.
|
||||
* Easily add prefixes or suffixes or both to columns names. Useful for building Custom Strategies.
|
||||
* Need _multiprocessing_ speed? Use the _strategy_ method.
|
||||
* Easily add _prefixes_ or _suffixes_ or both to columns names. Useful for building Custom Strategies.
|
||||
* __Extended Pandas DataFrame__ as 'ta'.
|
||||
* Indicators are tightly correlated with the de facto [TA Lib](https://mrjbq7.github.io/ta-lib/) if they share common indicators.
|
||||
* Example Jupyter Notebooks under the [examples](https://github.com/twopirllc/pandas-ta/tree/master/examples) directory, including how to create Custom Strategies using the new [__Strategy__ Class](https://github.com/twopirllc/pandas-ta/tree/master/examples/PandaTA_Strategy_Examples.ipynb)
|
||||
* A new 'ta' method called 'strategy'. By default, it runs __all__ the indicators or equivalent ta.AllStrategy.
|
||||
|
||||
|
||||
# Changes
|
||||
## __Recent Changes__
|
||||
* A __Strategy__ Class to help name and group your favorite indicators.
|
||||
* An experimental and independent __Watchlist__ Class located in the [Examples](https://github.com/twopirllc/pandas-ta/tree/master/examples/watchlist.py) Directory that can be used in conjunction with the new __Strategy__ Class.
|
||||
and _Weighted Moving Average_.
|
||||
* __Multiprocessing__ is automatically applied to df.ta.strategy() for __All__ indicators or a chosen __Category__ of indicators.
|
||||
* Improved the calculation performance of indicators: _Exponential Moving Averagage_
|
||||
* Updated *trend_return* utility to return a more pertinenet trade info for a _trend_. Example can be found in the [AI Example Notebook](https://github.com/twopirllc/pandas-ta/tree/master/examples/AIExample.ipynb). The notebook is still a work in progress and open to colloboration.
|
||||
|
||||
|
||||
## __Breaking Indicators__
|
||||
@@ -70,17 +78,10 @@ indicator consisting of two different simple moving averages.
|
||||
* _Inside Bar_ (**cdl_inside**) An Inside Bar is a bar contained within it's previous bar's high and low See: ```help(ta.cdl_inside)```
|
||||
|
||||
## __Updated Indicators__
|
||||
* _Average True Range_ (**atr**): Added option to return **atr** as a percentage. See: ```help(ta.atr)```
|
||||
* _Fisher Transform_ (**fisher**): Added Fisher's default **ema** signal line. To change the length of the signal line, use the argument: ```signal=5```. Default: 5
|
||||
* _Fisher Transform_ (**fisher**) and _Kaufman's Adaptive Moving Average_ (**kama**): Fixed a bug where their columns were not added to final DataFrame when using the _strategy_ method.
|
||||
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series.
|
||||
* _Average True Range_ (**atr**): Added option to return **atr** as a percentage. See: ```help(ta.atr)```
|
||||
|
||||
|
||||
## What is a Pandas DataFrame Extension?
|
||||
|
||||
A [Pandas DataFrame Extension](https://pandas.pydata.org/pandas-docs/stable/extending.html), extends a DataFrame allowing one to add more functionality and features to Pandas to suit your needs. As such, it is now easier to run Technical Analysis on existing Financial Time Series without leaving the current DataFrame. This extension by default returns the Indicator result or it can append the result to the existing DataFrame by including the parameter 'append=True' in the method call. Examples below.
|
||||
|
||||
|
||||
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series with pertinenet trade info for a _trend_. An example can be found in the [AI Example Notebook](https://github.com/twopirllc/pandas-ta/tree/master/examples/AIExample.ipynb). The notebook is still a work in progress and open to colloboration.
|
||||
|
||||
# __Getting Started and Examples__
|
||||
|
||||
@@ -135,9 +136,17 @@ help(ta.log_return)
|
||||
|
||||
## New Class: __Strategy__
|
||||
### What is a Pandas TA Strategy?
|
||||
A _Strategy_ is a simple way to name and group your favorite TA indicators. Technically, a _Strategy_ is a simple Data Class to contain list of indicators and their parameters. __Note__: _Strategy_ is experimental and subject to change. Pandas TA comes with two basic Strategies: __AllStrategy__ and __CommonStrategy__.
|
||||
A _Strategy_ is a simple way to name and group your favorite TA indicators. The _Strategy_ Class is a simple _Data Class_ to contain a list of indicators and their parameters.
|
||||
|
||||
* See the [Pandas TA Strategy Examples](https://github.com/twopirllc/pandas-ta/tree/master/examples/PandasTA_Strategy_Examples.ipynb) Notebook for more Examples including _Indicator Composition/Chaining_.
|
||||
* **Pandas** TA comes with two basic Strategies: __AllStrategy__ and __CommonStrategy__ to help you get started.
|
||||
|
||||
* A _Strategy_ Class can be as simple as the __CommonStrategy__ or more complex with a Composition of indicators such as the **ChainedTA** Example below.
|
||||
* You are using a Chained Strategy when you have the output of one indicator as input into one or more indicators in the same _Strategy_.
|
||||
* Use the 'prefix' and/or 'suffix' keywords to distuished the composed indicator from it's default Series.
|
||||
|
||||
* See the [Pandas TA Strategy Examples Notebook](https://github.com/twopirllc/pandas-ta/tree/master/examples/PandasTA_Strategy_Examples.ipynb) for examples including _Indicator Composition/Chaining_.
|
||||
|
||||
* __Note__: _Strategy_ is experimental and subject to change.
|
||||
|
||||
### Strategy Requirements:
|
||||
- _name_: Some short memorable string. _Note_: Case-insensitive "All" is reserved.
|
||||
@@ -150,16 +159,16 @@ A _Strategy_ is a simple way to name and group your favorite TA indicators. Tech
|
||||
#### Things to note:
|
||||
- A Strategy will __fail__ when consumed by Pandas TA if there is no {"kind": "indicator name"} attribute. __Remember__ to check your spelling.
|
||||
|
||||
#### Brief Examples
|
||||
#### Examples
|
||||
```python
|
||||
# The Builtin All Default Strategy
|
||||
# The Builtin "All" Strategy
|
||||
ta.AllStrategy = ta.Strategy(
|
||||
name="All",
|
||||
description="All the indicators with their default settings. Pandas TA default.",
|
||||
ta=None
|
||||
)
|
||||
|
||||
# The Builtin Default (Example) Strategy.
|
||||
# The Builtin "Common" Strategy with Volume Chaining
|
||||
ta.CommonStrategy = ta.Strategy(
|
||||
name="Common Price and Volume SMAs",
|
||||
description="Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.",
|
||||
@@ -172,27 +181,42 @@ ta.CommonStrategy = ta.Strategy(
|
||||
]
|
||||
)
|
||||
|
||||
# Your Custom Strategy or whatever your TA composition
|
||||
# Custom Strategy Example
|
||||
CustomStrategy = ta.Strategy(
|
||||
name="Momo and Volatility",
|
||||
description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20",
|
||||
description="SMA 50,200, BBANDS, RSI, and MACD and TTM Squeeze",
|
||||
ta=[
|
||||
{"kind": "sma", "length": 50},
|
||||
{"kind": "sma", "length": 200},
|
||||
{"kind": "bbands", "length": 20},
|
||||
{"kind": "rsi"},
|
||||
{"kind": "macd", "fast": 8, "slow": 21},
|
||||
{"kind": "sma", "close": "volume", "length": 20, "prefix": "VOLUME"},
|
||||
{"kind": "squeeze", "bb_std": 2.25, "mom_length": 10}
|
||||
]
|
||||
)
|
||||
|
||||
# Custom Chained Strategy
|
||||
ChainedTA = ta.Strategy({
|
||||
"name": "HMA BBANDS",
|
||||
"description": "Bollinger Bands of an HMA(10) Chain",
|
||||
"name": [
|
||||
{"kind": "hma", "length": 10},
|
||||
# BBands close is now linked to HMA(10)'s result column
|
||||
# A prefix is used to distinguish it from BBands default close column
|
||||
{"kind": "bbands", "close": "HMA_10", "length": 20, "prefix": "HMA10"},
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
## __DataFrame Method__: _strategy_ with Multiprocessing
|
||||
|
||||
The new __Pandas (TA)__ method __strategy__ is used to facilitate bulk indicator processing. By default, running ```df.ta.strategy()``` will append __all
|
||||
applicable__ indicators to DataFrame ```df```. Utility methods like ```above```, ```below``` et al are not included, however they can be included with Custom Strategies.
|
||||
The new __Pandas (TA)__ method __strategy__ utilizes **multiprocessing**, for all Strategy types, to facilitate bulk indicator processing.
|
||||
|
||||
* The ```ta.strategy()``` method is still __under development__ and subject to change until stable.
|
||||
* By default, this method will append __all applicable__ indicators to current DataFrame. I
|
||||
* Utility methods like ```above```, ```below``` et al are not included, however they can be included with Custom Strategies.
|
||||
* **Known Issue:** Changing the default core count with a Custom Strategy that has Composition/Chaining may not append all columns. See below: **DataFrame Property:** _cores_ for changing the number of cores to use for multiprocessing.
|
||||
* **Solution:** leave the default core count alone.
|
||||
* __Note__: The _strategy_ method is experimental and subject to change.
|
||||
|
||||
|
||||
```python
|
||||
@@ -230,10 +254,10 @@ df.columns
|
||||
# Running the Builtin CommonStrategy as mentioned above
|
||||
df.ta.strategy(ta.CommonStrategy)
|
||||
|
||||
# The Default Strategy is the ta.AllStrategy. The following are equivalent
|
||||
# df.ta.strategy(ta.AllStrategy)
|
||||
# df.ta.strategy("All")
|
||||
# The Default Strategy is the ta.AllStrategy. The following are equivalent:
|
||||
df.ta.strategy()
|
||||
df.ta.strategy("All")
|
||||
df.ta.strategy(ta.AllStrategy)
|
||||
```
|
||||
|
||||
### __Categorical__
|
||||
@@ -243,7 +267,7 @@ df.ta.categories
|
||||
|
||||
# Running a Categorical Strategy only requires the Category name
|
||||
df.ta.strategy("Momentum") # Default values for all Momentum indicators
|
||||
df.ta.strategy("overlap", length=27) # Override all 'length' attributes
|
||||
df.ta.strategy("overlap", length=42) # Override all 'length' attributes
|
||||
```
|
||||
|
||||
### __Custom__
|
||||
@@ -269,7 +293,7 @@ df.ta.strategy(CustomStrategy)
|
||||
|
||||
```python
|
||||
# List of Pandas TA categories
|
||||
df = df.ta.categories
|
||||
df.ta.categories
|
||||
```
|
||||
|
||||
## __DataFrame Property__: _cores_
|
||||
@@ -289,11 +313,11 @@ df.ta.cores
|
||||
# The 'datetime_ordered' property returns True if the DataFrame
|
||||
# index is of Pandas datetime64 and df.index[0] < df.index[-1]
|
||||
# Otherwise it returns False
|
||||
time_series_in_order = df.ta.datetime_ordered
|
||||
df.ta.datetime_ordered
|
||||
|
||||
# The 'reverse' is a helper property that returns the DataFrame
|
||||
# in reverse order
|
||||
df = df.ta.reverse
|
||||
df.ta.reverse
|
||||
```
|
||||
|
||||
## __DataFrame Property__: *adjusted*
|
||||
@@ -505,16 +529,14 @@ Use parameter: cumulative=**True** for cumulative results.
|
||||
|  |
|
||||
|
||||
|
||||
# Contributors
|
||||
* [alexonab](https://github.com/alexonab)
|
||||
* [allahyarzadeh](https://github.com/allahyarzadeh)
|
||||
* [DrPaprikaa](https://github.com/DrPaprikaa)
|
||||
* [FGU1](https://github.com/FGU1)
|
||||
* [lluissalord](https://github.com/lluissalord)
|
||||
* [SoftDevDanial](https://github.com/SoftDevDanial)
|
||||
* [YuvalWein](https://github.com/YuvalWein)
|
||||
# Sources
|
||||
* [Original TA-LIB](http://ta-lib.org/)
|
||||
* [TradingView](http://www.tradingview.com)
|
||||
* [Sierra Chart](https://search.sierrachart.com/?Query=indicators&submitted=true)
|
||||
* [FM Labs](https://www.fmlabs.com/reference/default.htm)
|
||||
* [User 42](https://user42.tuxfamily.org/chart/manual/index.html)
|
||||
|
||||
# Miscellaneous
|
||||
## What is a Pandas DataFrame Extension?
|
||||
|
||||
# Inspiration
|
||||
* Original TA-LIB: http://ta-lib.org/
|
||||
* TradingView: http://www.tradingview.com
|
||||
A [Pandas DataFrame Extension](https://pandas.pydata.org/pandas-docs/stable/extending.html), extends a DataFrame allowing one to add more functionality and features to Pandas to suit your needs. As such, it is now easier to run Technical Analysis on existing Financial Time Series without leaving the current DataFrame. This extension by default returns the Indicator result or it can append the result to the existing DataFrame by including the parameter 'append=True' in the method call. Examples below.
|
||||
+5
-2
@@ -23,7 +23,7 @@ from pandas_ta.volatility import *
|
||||
from pandas_ta.volume import *
|
||||
from pandas_ta.utils import *
|
||||
|
||||
version = ".".join(("0", "2", "06b"))
|
||||
version = ".".join(("0", "2", "07b"))
|
||||
|
||||
|
||||
# Strategy (Data)Class
|
||||
@@ -306,7 +306,10 @@ class AnalysisIndicators(BasePandasObject):
|
||||
@property
|
||||
def datetime_ordered(self) -> bool:
|
||||
"""Returns True if the index is a datetime and ordered."""
|
||||
return is_datetime_ordered(self._df)
|
||||
hasdf = hasattr(self, "_df")
|
||||
if hasdf:
|
||||
return is_datetime_ordered(self._df)
|
||||
return hasdf
|
||||
|
||||
@property
|
||||
def reverse(self) -> pd.DataFrame:
|
||||
|
||||
@@ -12,7 +12,7 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
|
||||
high_low_range = non_zero_range(high, low)
|
||||
length = int(length) if length and length > 0 else 20
|
||||
c = float(c) if c and c > 0 else 4
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
mamode = mamode.lower() if mamode else "sma"
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
@@ -51,7 +51,7 @@ def bbands(close, length=None, std=None, mamode=None, offset=None, **kwargs):
|
||||
data = {lower.name: lower, mid.name: mid, upper.name: upper}
|
||||
bbandsdf = DataFrame(data)
|
||||
bbandsdf.name = f"BBANDS_{length}_{std}"
|
||||
bbandsdf.category = "volatility"
|
||||
bbandsdf.category = mid.category
|
||||
|
||||
return bbandsdf
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwa
|
||||
low = verify_series(low)
|
||||
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
|
||||
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
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
@@ -19,14 +19,14 @@ def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwa
|
||||
mid = 0.5 * (lower + upper)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
lower.fillna(kwargs['fillna'], inplace=True)
|
||||
mid.fillna(kwargs['fillna'], inplace=True)
|
||||
upper.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
lower.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
mid.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
upper.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
lower.fillna(kwargs["fillna"], inplace=True)
|
||||
mid.fillna(kwargs["fillna"], inplace=True)
|
||||
upper.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
lower.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
mid.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
upper.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
@@ -38,13 +38,13 @@ def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwa
|
||||
lower.name = f"DCL_{lower_length}_{upper_length}"
|
||||
mid.name = f"DCM_{lower_length}_{upper_length}"
|
||||
upper.name = f"DCU_{lower_length}_{upper_length}"
|
||||
mid.category = upper.category = lower.category = 'volatility'
|
||||
mid.category = upper.category = lower.category = "volatility"
|
||||
|
||||
# Prepare DataFrame to return
|
||||
data = {lower.name: lower, mid.name: mid, upper.name: upper}
|
||||
dcdf = DataFrame(data)
|
||||
dcdf.name = f"DC_{lower_length}_{upper_length}"
|
||||
dcdf.category = 'volatility'
|
||||
dcdf.category = mid.category
|
||||
|
||||
return dcdf
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ def massi(high, low, fast=None, slow=None, offset=None, **kwargs):
|
||||
slow = int(slow) if slow and slow > 0 else 25
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else fast
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
@@ -27,14 +27,14 @@ def massi(high, low, fast=None, slow=None, offset=None, **kwargs):
|
||||
massi = massi.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
massi.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
massi.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
massi.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
massi.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
massi.name = f"MASSI_{fast}_{slow}"
|
||||
massi.category = 'volatility'
|
||||
massi.category = "volatility"
|
||||
|
||||
return massi
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ def natr(high, low, close, length=None, mamode=None, scalar=None, drift=None, of
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
mamode = mamode.lower() if mamode else 'ema'
|
||||
mamode = mamode.lower() if mamode else "ema"
|
||||
scalar = float(scalar) if scalar else 100
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
@@ -23,14 +23,14 @@ def natr(high, low, close, length=None, mamode=None, scalar=None, drift=None, of
|
||||
natr = natr.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
natr.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
natr.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
natr.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
natr.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
natr.name = f"NATR_{length}"
|
||||
natr.category = 'volatility'
|
||||
natr.category = "volatility"
|
||||
|
||||
return natr
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ def pdist(open_, high, low, close, drift=None, offset=None, **kwargs):
|
||||
|
||||
# Name & Category
|
||||
pdist.name = "PDIST"
|
||||
pdist.category = 'volatility'
|
||||
pdist.category = "volatility"
|
||||
|
||||
return pdist
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ def true_range(high, low, close, drift=None, offset=None, **kwargs):
|
||||
true_range = true_range.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
true_range.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
true_range.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
true_range.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
true_range.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
true_range.name = f"TRUERANGE_{drift}"
|
||||
true_range.category = 'volatility'
|
||||
true_range.category = "volatility"
|
||||
|
||||
return true_range
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ def adosc(high, low, close, volume, open_=None, fast=None, slow=None, offset=Non
|
||||
adosc = adosc.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
adosc.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
adosc.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
adosc.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
adosc.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
adosc.name = f"ADOSC_{fast}_{slow}"
|
||||
adosc.category = 'volume'
|
||||
adosc.category = "volume"
|
||||
|
||||
return adosc
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ def cmf(high, low, close, volume, open_=None, length=None, offset=None, **kwargs
|
||||
volume = verify_series(volume)
|
||||
high_low_range = non_zero_range(high, low)
|
||||
length = int(length) if length and length > 0 else 20
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
@@ -29,14 +29,14 @@ def cmf(high, low, close, volume, open_=None, length=None, offset=None, **kwargs
|
||||
cmf = cmf.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
cmf.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
cmf.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
cmf.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
cmf.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
cmf.name = f"CMF_{length}"
|
||||
cmf.category = 'volume'
|
||||
cmf.category = "volume"
|
||||
|
||||
return cmf
|
||||
|
||||
|
||||
+14
-14
@@ -18,33 +18,33 @@ def mfi(high, low, close, volume, length=None, drift=None, offset=None, **kwargs
|
||||
typical_price = hlc3(high=high, low=low, close=close)
|
||||
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
|
||||
tdf.loc[(typical_price.diff(drift) > 0), "diff"] = 1
|
||||
tdf.loc[tdf["diff"] == 1, "+mf"] = raw_money_flow
|
||||
|
||||
tdf.loc[(typical_price.diff(drift) < 0), 'diff'] = -1
|
||||
tdf.loc[tdf['diff'] == -1, '-mf'] = raw_money_flow
|
||||
tdf.loc[(typical_price.diff(drift) < 0), "diff"] = -1
|
||||
tdf.loc[tdf["diff"] == -1, "-mf"] = raw_money_flow
|
||||
|
||||
psum = tdf['+mf'].rolling(length).sum()
|
||||
nsum = tdf['-mf'].rolling(length).sum()
|
||||
tdf['mr'] = psum / nsum
|
||||
psum = tdf["+mf"].rolling(length).sum()
|
||||
nsum = tdf["-mf"].rolling(length).sum()
|
||||
tdf["mr"] = psum / nsum
|
||||
mfi = 100 * psum / (psum + nsum)
|
||||
tdf['mfi'] = mfi
|
||||
tdf["mfi"] = mfi
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
mfi = mfi.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
mfi.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
mfi.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
mfi.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
mfi.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
mfi.name = f"MFI_{length}"
|
||||
mfi.category = 'volume'
|
||||
mfi.category = "volume"
|
||||
|
||||
return mfi
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ def nvi(close, volume, length=None, initial=None, offset=None, **kwargs):
|
||||
close = verify_series(close)
|
||||
volume = verify_series(volume)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
initial = int(initial) if initial and initial > 0 else 1000
|
||||
offset = get_offset(offset)
|
||||
|
||||
@@ -25,14 +25,14 @@ def nvi(close, volume, length=None, initial=None, offset=None, **kwargs):
|
||||
nvi = nvi.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
nvi.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
nvi.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
nvi.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
nvi.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
nvi.name = f"NVI_{length}"
|
||||
nvi.category = 'volume'
|
||||
nvi.category = "volume"
|
||||
|
||||
return nvi
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ def obv(close, volume, offset=None, **kwargs):
|
||||
obv = obv.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
obv.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
obv.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
obv.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
obv.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
obv.name = f"OBV"
|
||||
obv.category = 'volume'
|
||||
obv.category = "volume"
|
||||
|
||||
return obv
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ def pvi(close, volume, length=None, initial=None, offset=None, **kwargs):
|
||||
close = verify_series(close)
|
||||
volume = verify_series(volume)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
initial = int(initial) if initial and initial > 0 else 1000
|
||||
offset = get_offset(offset)
|
||||
|
||||
@@ -25,14 +25,14 @@ def pvi(close, volume, length=None, initial=None, offset=None, **kwargs):
|
||||
pvi = pvi.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
pvi.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
pvi.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
pvi.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
pvi.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
pvi.name = f"PVI_{length}"
|
||||
pvi.category = 'volume'
|
||||
pvi.category = "volume"
|
||||
|
||||
return pvi
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ def pvol(close, volume, offset=None, **kwargs):
|
||||
close = verify_series(close)
|
||||
volume = verify_series(volume)
|
||||
offset = get_offset(offset)
|
||||
signed = kwargs.pop('signed', False)
|
||||
signed = kwargs.pop("signed", False)
|
||||
|
||||
# Calculate Result
|
||||
if signed:
|
||||
@@ -20,14 +20,14 @@ def pvol(close, volume, offset=None, **kwargs):
|
||||
pvol = pvol.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
pvol.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
pvol.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
pvol.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
pvol.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
pvol.name = f"PVOL"
|
||||
pvol.category = 'volume'
|
||||
pvol.category = "volume"
|
||||
|
||||
return pvol
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ def pvt(close, volume, drift=None, offset=None, **kwargs):
|
||||
pvt = pvt.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
pvt.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
pvt.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
pvt.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
pvt.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
pvt.name = f"PVT"
|
||||
pvt.category = 'volume'
|
||||
pvt.category = "volume"
|
||||
|
||||
return pvt
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ def vp(close, volume, width=None, **kwargs):
|
||||
close = verify_series(close)
|
||||
volume = verify_series(volume)
|
||||
width = int(width) if width and width > 0 else 10
|
||||
sort_close = kwargs.pop('sort_close', False)
|
||||
sort_close = kwargs.pop("sort_close", False)
|
||||
|
||||
# Setup
|
||||
signed_volume = signed_series(volume, initial=1)
|
||||
@@ -47,14 +47,14 @@ def vp(close, volume, width=None, **kwargs):
|
||||
vpdf[total_volume_col] = vpdf[pos_volume_col] + vpdf[neg_volume_col]
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
vpdf.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
vpdf.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
vpdf.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
vpdf.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
vpdf.name = f"VP_{width}"
|
||||
vpdf.category = 'volume'
|
||||
vpdf.category = "volume"
|
||||
|
||||
return vpdf
|
||||
|
||||
|
||||
Reference in New Issue
Block a user