ENH cdl and cdl_pattern with talib compat added DOC cdl_pattern info + notebooks BUG yf extra output removed

This commit is contained in:
Kevin Johnson
2021-04-10 16:51:52 -07:00
parent 6f94d58ce7
commit d65bb5a7a0
15 changed files with 505 additions and 205 deletions
+2 -1
View File
@@ -143,4 +143,5 @@ data/SPY_D_TV2.csv
data/SPY_D_TV3.csv
data/TV_5min.csv
data/tulip.csv
examples/*.csv
examples/*.csv
examples/Chande_Kroll_Stop.ipynb
+93 -69
View File
@@ -15,7 +15,10 @@ Pandas TA - A Technical Analysis Library in Python 3
![Example Chart](/images/TA_Chart.png)
_Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that leverages the Pandas library with more than 130 Indicators and Utility functions. 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 Technical Analysis_ (**Pandas TA**) is an easy to use library that leverages the Pandas library with more than 130 Indicators and Utility functions and more than 60 TA Lib Candlestick Patterns. 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_**.
**Note:** _TA Lib_ must be installed to use **all** the Candlestick Patterns. ```pip install TA-Lib```. If _TA Lib_ is not installed, then only the builtin Candlestick Patterns will be available.
<br/>
@@ -36,7 +39,7 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
* [DataFrame Properties](#dataframe-properties)
* [DataFrame Methods](#dataframe-methods)
* [Indicators by Category](#indicators-by-category)
* [Candles](#candles-3)
* [Candles](#candles-63)
* [Cycles](#cycles-1)
* [Momentum](#momentum-37)
* [Overlap](#overlap-31)
@@ -63,13 +66,22 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
# **Features**
* Has 130+ indicators and utility functions.
* With **TA Lib** installed there are an additional 63 Chart Patterns available.
* Indicators are tightly correlated with the de facto [TA Lib](https://mrjbq7.github.io/ta-lib/) if they share common indicators.
* Have the need for speed? By using the DataFrame _strategy_ method, you get **multiprocessing** for free!
* Easily add _prefixes_ or _suffixes_ or both to columns names. Useful for Custom Chained Strategies.
* Easily add _prefixes_ or _suffixes_ or _both_ to columns names. Useful for Custom Chained Strategies.
* 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)
* Potential Data Leaks: **ichimoku** and **dpo**. See indicator list below for details.
* **UNDER DEVELOPMENT:** Performance Metrics
* **UNDER DEVELOPMENT:** Easy Downloading of _ohlcv_ data using [yfinance](https://github.com/ranaroussi/yfinance). See ```help(ta.ticker)``` and ```help(ta.yf)```
<br/>
**Under Development**
===================
**Pandas TA** checks if the user has some common trading packages installed including but not limited to: [**TA Lib**](https://mrjbq7.github.io/ta-lib/), [**Vector BT**](https://github.com/polakowo/vectorbt), [**YFinance**](https://github.com/ranaroussi/yfinance) ... Much of which is experimental and likely to break until it stabilizes more.
* If **TA Lib** installed, existing indicators will _eventually_ get a **TA Lib** version.
* Easy Downloading of _ohlcv_ data using [yfinance](https://github.com/ranaroussi/yfinance). See ```help(ta.ticker)``` and ```help(ta.yf)``` and examples below.
* Hopefully soon a Pandas TA _YAML_ configuration file contained in ```~/pandas_ta/``` can be implemented. To see the proposed specification and leave comments and suggestions on it's implementation, see Issue [#258](https://github.com/twopirllc/pandas-ta/issues/258).
* Some Common Performance Metrics
<br/>
@@ -85,7 +97,7 @@ $ pip install pandas_ta
Latest Version
--------------
Best choice! Version: *0.2.67b*
Best choice! Version: *0.2.68b*
```sh
$ pip install -U git+https://github.com/twopirllc/pandas-ta
```
@@ -556,79 +568,90 @@ help(ta.yf)
# **Indicators** (_by Category_)
### **Candles** (63)
* _Patterns_: cdl_pattern (Patterns that aren't bold, need TA-Lib to be installed: "```pip install TA-Lib```")
* 2crows
* 3blackcrows
* 3inside
* 3linestrike
* 3outside
* 3starsinsouth
* 3whitesoldiers
* abandonedbaby
* advanceblock
* belthold
* breakaway
* closingmarubozu
* concealbabyswall
* counterattack
* darkcloudcover
* **doji**
* dojistar
* dragonflydoji
* engulfing
* eveningdojistar
* eveningstar
* gapsidesidewhite
* gravestonedoji
* hammer
* hangingman
* harami
* haramicross
* highwave
* hikkake
* hikkakemod
* homingpigeon
* identical3crows
* inneck
* **inside**
* invertedhammer
* kicking
* kickingbylength
* ladderbottom
* longleggeddoji
* longline
* marubozu
* matchinglow
* mathold
* morningdojistar
* morningstar
* onneck
* piercing
* rickshawman
* risefall3methods
* separatinglines
* shootingstar
* shortline
* spinningtop
* stalledpattern
* sticksandwich
* takuri
* tasukigap
* thrusting
* tristar
* unique3river
* upsidegap2crows
* xsidegap3methods
_Candle Patterns_: ```ta.cdl_pattern``` or ```ta.cdl```
Patterns that are **not bold**, require TA-Lib to be installed: ```pip install TA-Lib```
* 2crows
* 3blackcrows
* 3inside
* 3linestrike
* 3outside
* 3starsinsouth
* 3whitesoldiers
* abandonedbaby
* advanceblock
* belthold
* breakaway
* closingmarubozu
* concealbabyswall
* counterattack
* darkcloudcover
* **doji**
* dojistar
* dragonflydoji
* engulfing
* eveningdojistar
* eveningstar
* gapsidesidewhite
* gravestonedoji
* hammer
* hangingman
* harami
* haramicross
* highwave
* hikkake
* hikkakemod
* homingpigeon
* identical3crows
* inneck
* **inside**
* invertedhammer
* kicking
* kickingbylength
* ladderbottom
* longleggeddoji
* longline
* marubozu
* matchinglow
* mathold
* morningdojistar
* morningstar
* onneck
* piercing
* rickshawman
* risefall3methods
* separatinglines
* shootingstar
* shortline
* spinningtop
* stalledpattern
* sticksandwich
* takuri
* tasukigap
* thrusting
* tristar
* unique3river
* upsidegap2crows
* xsidegap3methods
* _Heikin-Ashi_: **ha**
```python
# Get all candle patterns (This is the default behaviour)
df = df.ta.cdl_pattern(name="all")
# Or
df.ta.cdl("all", append=True) # = df.ta.cdl_pattern("all", append=True)
# Get only one pattern
df = df.ta.cdl_pattern(name="doji")
# Or
df.ta.cdl("doji", append=True)
# Get some patterns
df = df.ta.cdl_pattern(name=["doji", "inside"])
# Or
df.ta.cdl(["doji", "inside"], append=True)
```
<br/>
@@ -878,6 +901,7 @@ result = ta.cagr(df.close)
## **New Indicators**
* _Arnaud Legoux Moving Average_ (**alma**) uses the curve of the Normal (Gauss) distribution to allow regulating the smoothness and high sensitivity of the indicator. See: ```help(ta.alma)```
trading account, or fund. See: ```help(ta.drawdown)```
* _Candle Patterns_ (**cdl_pattern**) If TA Lib is installed, then all those Candle Patterns are available. See the list and examples above on how to call the patterns. See: ```help(ta.cdl_pattern)```
* _Even Better Sinewave_ (**ebsw**) measures market cycles and uses a low pass filter to remove noise. See: ```help(ta.ebsw)```
* _Tom DeMark's Sequential_ (**td_seq**) attempts to identify a price point where an uptrend or a downtrend exhausts itself and reverses. Currently exlcuded from ```df.ta.strategy()``` for performance reasons. See: ```help(ta.td_seq)```
<br/>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+14 -11
View File
@@ -64,9 +64,12 @@
"output_type": "stream",
"text": [
"Pandas TA - Technical Analysis Indicators - v0.2.64b0\n",
"Total Indicators: 134\n",
"Total Indicators: 196\n",
"Abbreviations:\n",
" aberration, above, above_value, accbands, ad, adosc, adx, alma, amat, ao, aobv, apo, aroon, atr, bbands, below, below_value, bias, bop, brar, cci, cdl_doji, cdl_inside, cfo, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, decay, decreasing, dema, donchian, dpo, ebsw, efi, ema, entropy, eom, er, eri, fisher, fwma, ha, hilo, hl2, hlc3, hma, hwc, hwma, ichimoku, increasing, inertia, kama, kc, kdj, kst, kurtosis, linreg, log_return, long_run, macd, mad, massi, mcgd, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, pgo, ppo, psar, psl, pvi, pvo, pvol, pvr, pvt, pwma, qqe, qstick, quantile, rma, roc, rsi, rsx, rvgi, rvi, short_run, sinwma, skew, slope, sma, smi, squeeze, ssf, stdev, stoch, stochrsi, supertrend, swma, t3, td_seq, tema, thermo, trend_return, trima, trix, true_range, tsi, ttm_trend, ui, uo, variance, vidya, vortex, vp, vwap, vwma, wcp, willr, wma, zlma, zscore\n"
" aberration, above, above_value, accbands, ad, adosc, adx, alma, amat, ao, aobv, apo, aroon, atr, bbands, below, below_value, bias, bop, brar, cci, cdl, cdl_pattern, cfo, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, decay, decreasing, dema, donchian, dpo, ebsw, efi, ema, entropy, eom, er, eri, fisher, fwma, ha, hilo, hl2, hlc3, hma, hwc, hwma, ichimoku, increasing, inertia, kama, kc, kdj, kst, kurtosis, linreg, log_return, long_run, macd, mad, massi, mcgd, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, pgo, ppo, psar, psl, pvi, pvo, pvol, pvr, pvt, pwma, qqe, qstick, quantile, rma, roc, rsi, rsx, rvgi, rvi, short_run, sinwma, skew, slope, sma, smi, squeeze, ssf, stdev, stoch, stochrsi, supertrend, swma, t3, td_seq, tema, thermo, trend_return, trima, trix, true_range, tsi, ttm_trend, ui, uo, variance, vidya, vortex, vp, vwap, vwma, wcp, willr, wma, zlma, zscore\n",
"\n",
"Candle Patterns:\n",
" 2crows, 3blackcrows, 3inside, 3linestrike, 3outside, 3starsinsouth, 3whitesoldiers, abandonedbaby, advanceblock, belthold, breakaway, closingmarubozu, concealbabyswall, counterattack, darkcloudcover, doji, dojistar, dragonflydoji, engulfing, eveningdojistar, eveningstar, gapsidesidewhite, gravestonedoji, hammer, hangingman, harami, haramicross, highwave, hikkake, hikkakemod, homingpigeon, identical3crows, inneck, inside, invertedhammer, kicking, kickingbylength, ladderbottom, longleggeddoji, longline, marubozu, matchinglow, mathold, morningdojistar, morningstar, onneck, piercing, rickshawman, risefall3methods, separatinglines, shootingstar, shortline, spinningtop, stalledpattern, sticksandwich, takuri, tasukigap, thrusting, tristar, unique3river, upsidegap2crows, xsidegap3methods\n"
]
}
],
@@ -926,7 +929,7 @@
"[i] Multiprocessing 5 indicators with 7 chunks and 8/8 cpus.\n",
"[i] Total indicators: 5\n",
"[i] Columns added: 5\n",
"[i] Last Run: Saturday April 10, 2021, NYSE: 5:38:28, Local: 9:38:28 PDT, Day 100/365 (27.0%)\n"
"[i] Last Run: Saturday April 10, 2021, NYSE: 12:37:31, Local: 16:37:31 PDT, Day 100/365 (27.0%)\n"
]
},
{
@@ -954,7 +957,7 @@
{
"data": {
"text/plain": [
"<__main__.Chart at 0x12ffc83d0>"
"<__main__.Chart at 0x132188e20>"
]
},
"execution_count": 11,
@@ -1064,7 +1067,7 @@
{
"data": {
"text/plain": [
"<matplotlib.lines.Line2D at 0x130be2700>"
"<matplotlib.lines.Line2D at 0x132e4c550>"
]
},
"execution_count": 13,
@@ -1103,7 +1106,7 @@
{
"data": {
"text/plain": [
"<matplotlib.lines.Line2D at 0x1308b2cd0>"
"<matplotlib.lines.Line2D at 0x132ebf850>"
]
},
"execution_count": 14,
@@ -1136,7 +1139,7 @@
{
"data": {
"text/plain": [
"<matplotlib.lines.Line2D at 0x130cb4580>"
"<matplotlib.lines.Line2D at 0x132e85dc0>"
]
},
"execution_count": 15,
@@ -1216,7 +1219,7 @@
{
"data": {
"text/plain": [
"<__main__.Chart at 0x130ceb6d0>"
"<__main__.Chart at 0x132f42820>"
]
},
"execution_count": 17,
@@ -1268,7 +1271,7 @@
{
"data": {
"text/plain": [
"<__main__.Chart at 0x130d2f190>"
"<__main__.Chart at 0x132fd0d60>"
]
},
"execution_count": 18,
@@ -1322,7 +1325,7 @@
{
"data": {
"text/plain": [
"<__main__.Chart at 0x13147fd30>"
"<__main__.Chart at 0x132936820>"
]
},
"execution_count": 19,
@@ -1380,7 +1383,7 @@
{
"data": {
"text/plain": [
"<__main__.Chart at 0x130136f70>"
"<__main__.Chart at 0x13247e610>"
]
},
"execution_count": 20,
+1 -1
View File
@@ -40,7 +40,7 @@ Imports = {
Category = {
# Candles
"candles": [
"cdl_pattern", "ha"
"cdl", "cdl_pattern", "ha"
],
# Cycles
"cycles": ["ebsw"],
+1 -1
View File
@@ -2,4 +2,4 @@
from .ha import ha
from .cdl_doji import cdl_doji
from .cdl_inside import cdl_inside
from .cdl_pattern import cdl_pattern, ALL_PATTERNS as CDL_PATTERN_NAMES
from .cdl_pattern import cdl_pattern, cdl, ALL_PATTERNS as CDL_PATTERN_NAMES
+26 -6
View File
@@ -5,8 +5,6 @@ from pandas import Series, DataFrame
from . import cdl_doji, cdl_inside
from pandas_ta.utils import get_offset, verify_series
from pandas_ta import Imports
if Imports["talib"]:
import talib.abstract as tala
ALL_PATTERNS = [
@@ -45,11 +43,15 @@ def cdl_pattern(open_, high, low, close, name: Union[str, Sequence[str]]="all",
if type(name) is str:
name = [name]
if Imports["talib"]:
import talib.abstract as tala
result = {}
for n in name:
if n not in ALL_PATTERNS:
print(f"[X] There is no candle pattern named {n} available!")
continue
if n in pta_patterns:
pattern_result = pta_patterns[n](open_, high, low, close, offset=offset, scalar=scalar, **kwargs)
result[pattern_result.name] = pattern_result
@@ -58,7 +60,7 @@ def cdl_pattern(open_, high, low, close, name: Union[str, Sequence[str]]="all",
print(f"[X] Please install TA-Lib to use {n}. (pip install TA-Lib)")
continue
pattern_func = tala.Function("CDL" + n.upper())
pattern_func = tala.Function(f"CDL{n.upper()}")
pattern_result = Series(pattern_func(open_, high, low, close, **kwargs) / 100 * scalar)
pattern_result.index = close.index
@@ -72,10 +74,9 @@ def cdl_pattern(open_, high, low, close, name: Union[str, Sequence[str]]="all",
if "fill_method" in kwargs:
pattern_result.fillna(method=kwargs["fill_method"], inplace=True)
result["CDL_" + n.upper()] = pattern_result
result[f"CDL_{n.upper()}"] = pattern_result
if len(result) == 0:
return
if len(result) == 0: return
# Prepare DataFrame to return
df = DataFrame(result)
@@ -89,6 +90,23 @@ cdl_pattern.__doc__ = \
A wrapper around all candle patterns.
Examples:
Get all candle patterns (This is the default behaviour)
>>> df = df.ta.cdl_pattern(name="all")
Or
>>> df.ta.cdl("all", append=True) # = df.ta.cdl_pattern("all", append=True)
Get only one pattern
>>> df = df.ta.cdl_pattern(name="doji")
Or
>>> df.ta.cdl("doji", append=True)
Get some patterns
>>> df = df.ta.cdl_pattern(name=["doji", "inside"])
Or
>>> df.ta.cdl(["doji", "inside"], append=True)
Args:
open_ (pd.Series): Series of 'open's
high (pd.Series): Series of 'high's
@@ -105,3 +123,5 @@ Kwargs:
Returns:
pd.DataFrame: one column for each pattern.
"""
cdl = cdl_pattern
+6 -2
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from dataclasses import dataclass, field
from multiprocessing import cpu_count, Pool
from pandas_ta.candles.cdl_pattern import ALL_PATTERNS
from time import perf_counter
from typing import List, Tuple
@@ -597,9 +598,9 @@ class AnalysisIndicators(BasePandasObject):
total_indicators = len(ta_indicators)
header = f"Pandas TA - Technical Analysis Indicators - v{self.version}"
s = f"{header}\nTotal Indicators: {total_indicators}\n"
s = f"{header}\nTotal Indicators: {total_indicators + len(ALL_PATTERNS)}\n"
if total_indicators > 0:
print(f"{s}Abbreviations:\n {', '.join(ta_indicators)}")
print(f"{s}Abbreviations:\n {', '.join(ta_indicators)}\n\nCandle Patterns:\n {', '.join(ALL_PATTERNS)}")
else:
print(s)
@@ -640,6 +641,7 @@ class AnalysisIndicators(BasePandasObject):
"above_value",
"below",
"below_value",
"cdl", # Alias for "cdl_pattern"
"cross",
"cross_value",
# "data", # reserved
@@ -840,6 +842,8 @@ class AnalysisIndicators(BasePandasObject):
result = cdl_pattern(open_=open_, high=high, low=low, close=close, name=name, offset=offset, **kwargs)
return self._post_process(result, **kwargs)
cdl = cdl_pattern
def ha(self, offset=None, **kwargs):
open_ = self._get_column(kwargs.pop("open", "open"))
high = self._get_column(kwargs.pop("high", "high"))
+4 -9
View File
@@ -125,7 +125,7 @@ def yf(ticker: str, **kwargs):
# Ticker Info & Chart History
yfd = yfra.Ticker(ticker)
df = yfd.history(period=period, interval=interval, proxy=proxy, **kwargs)
print(f"[X] df[{type(df)}:{df.empty}]\n{df}\n")
if df.empty: return
df.name = ticker
@@ -134,18 +134,16 @@ def yf(ticker: str, **kwargs):
except KeyError as ke:
print(f"[X] Ticker '{ticker}' not found.")
return
print(f"[X] ticker_info[{type(ticker_info)}:{len(ticker_info.keys())}]\n{ticker_info}\n")
# print(f"[X] ticker_info[{type(ticker_info)}:{len(ticker_info.keys())}]\n{ticker_info}\n")
try:
infodf = DataFrame.from_dict(ticker_info, orient="index")
except TypeError as te:
print(f"[X] TypeError: {te}")
# else:
# infodf = DataFrame(ticker_info)
print(f"[X] infodf.empty: {infodf.empty}")
# print(f"[X] infodf.empty: {infodf.empty}")
if infodf.empty: return
print(f"[X] infodf[{type(infodf)}:{len(infodf.keys())}]\n{infodf}\n")
# print(f"[X] infodf[{type(infodf)}:{len(infodf.keys())}]\n{infodf}\n")
infodf.name, infodf.columns = ticker, [ticker]
# Dividends and Splits
@@ -156,9 +154,6 @@ def yf(ticker: str, **kwargs):
description = kwargs.pop("desc", False)
snd_length = kwargs.pop("snd", 5)
[print(f"{_[0]}: {_[1]}") for _ in sorted(ticker_info.items())]
print()
print("\n==== Company Information " + div)
print(f"{ticker_info['longName']} ({ticker_info['shortName']}) [{ticker_info['symbol']}]")
print(f"[i] {type(ticker_info['longBusinessSummary'])}: {ticker_info['longBusinessSummary']}")
+1 -1
View File
@@ -18,7 +18,7 @@ setup(
"pandas_ta.volatility",
"pandas_ta.volume"
],
version=".".join(("0", "2", "67b")),
version=".".join(("0", "2", "68b")),
description=long_description,
long_description=long_description,
author="Kevin Johnson",
+2 -2
View File
@@ -19,12 +19,12 @@ class TestCandleExtension(TestCase):
def test_cdl_doji_ext(self):
self.data.ta.cdl_doji(append=True)
self.data.ta.cdl_pattern("doji", append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "CDL_DOJI_10_0.1")
def test_cdl_inside_ext(self):
self.data.ta.cdl_inside(append=True)
self.data.ta.cdl_pattern("inside", append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "CDL_INSIDE")
-1
View File
@@ -41,7 +41,6 @@ class TestTrendExtension(TestCase):
def test_cksp_ext(self):
self.data.ta.cksp(tvmode=False, append=True)
self.assertIsInstance(self.data, DataFrame)
print(self.data.columns[-3:])
self.assertEqual(list(self.data.columns[-2:]), ["CKSPl_10_3_20", "CKSPs_10_3_20"])
def test_cksp_tv_ext(self):
+5 -1
View File
@@ -106,15 +106,18 @@ class TestStrategyMethods(TestCase):
# @skip
def test_custom_a(self):
self.category = "Custom A"
print()
print(self.category)
momo_bands_sma_ta = [
{"kind": "cdl_pattern", "name": "tristar"}, # 1
{"kind": "rsi"}, # 1
{"kind": "macd"}, # 3
{"kind": "sma", "length": 50}, # 1
{"kind": "sma", "length": 200 }, # 1
{"kind": "bbands", "length": 20}, # 3
{"kind": "log_return", "cumulative": True}, # 1
{"kind": "ema", "close": "CUMLOGRET_1", "length": 5, "suffix": "CLR"}
{"kind": "ema", "close": "CUMLOGRET_1", "length": 5, "suffix": "CLR"} # 1
]
custom = pandas_ta.Strategy(
@@ -123,6 +126,7 @@ class TestStrategyMethods(TestCase):
"Common indicators with specific lengths and a chained indicator", # description
)
self.data.ta.strategy(custom, verbose=verbose, timed=strategy_timed)
self.assertEqual(len(self.data.columns), 15)
# @skip
def test_custom_args_tuple(self):