From 11730dad3fd6b72e9d8b57cf1132f66772d1e781 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Sun, 5 Jul 2020 15:30:10 -0700 Subject: [PATCH 01/10] DOC STY --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 87d9c98..6d6b294 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ All the indicators return a named Series or a DataFrame in uppercase underscore * Has 100+ indicators and utility functions. * Option to use __multiprocessing__ when using df.ta.strategy(). See below. -* Example Jupyter Notebook under the examples directory. -* A new 'ta' method called 'strategy' that be default, runs __all__ the indicators. +* Example Jupyter Notebook under the [examples](https://github.com/twopirllc/pandas-ta/tree/master/examples) directory. +* A new 'ta' method called 'strategy'. By default, it runs __all__ the indicators. * Abbreviated Indicator names as listed below. -* __Extended Pandas DataFrame__ as 'ta'. +* __Extended Pandas DataFrame__ as 'ta'. * Easily add prefixes or suffixes or both to columns names. * Categories similar to [TA-lib](https://github.com/mrjbq7/ta-lib/tree/master/docs/func_groups) and tightly correlated with TA Lib in testing. From 334f3648c159d4e0fa67d5d5e631ec691cc50bf9 Mon Sep 17 00:00:00 2001 From: YuvalWein <65113623+YuvalWein@users.noreply.github.com> Date: Tue, 21 Jul 2020 11:30:11 +0300 Subject: [PATCH 02/10] Update cmf.py Confusing documentation: note that in the Arg of doc we have open before volume, and open is not an optional parameter. its different from the real function arguments. --- pandas_ta/volume/cmf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas_ta/volume/cmf.py b/pandas_ta/volume/cmf.py index 03ad4cd..f259a53 100644 --- a/pandas_ta/volume/cmf.py +++ b/pandas_ta/volume/cmf.py @@ -68,8 +68,8 @@ Args: high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's - open (pd.Series): Series of 'open's volume (pd.Series): Series of 'volume's + open (pd.Series): Series of 'open's. Default: None length (int): The short period. Default: 20 offset (int): How many periods to offset the result. Default: 0 @@ -79,4 +79,4 @@ Kwargs: Returns: pd.Series: New feature generated. -""" \ No newline at end of file +""" From b356fca04d537e9ea9530c9dc086b2a1a39c0b44 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Tue, 21 Jul 2020 10:49:33 -0700 Subject: [PATCH 03/10] MAINT BBANDS RMA tests ENH Strategy + Watchlist Class + New Notebook --- .gitignore | 3 + README.md | 133 +- examples/PandasTA_Strategy_Examples.ipynb | 3040 +++++++++++++++++++++ examples/watchlist.py | 202 ++ pandas_ta/core.py | 269 +- pandas_ta/overlap/rma.py | 3 +- pandas_ta/utils.py | 3 +- pandas_ta/volatility/bbands.py | 8 +- tests/config.py | 2 +- tests/context.py | 2 +- tests/test_indicator_candle.py | 12 +- tests/test_indicator_candle_ext.py | 4 +- tests/test_indicator_momentum.py | 86 +- tests/test_indicator_momentum_ext.py | 62 +- tests/test_indicator_overlap.py | 74 +- tests/test_indicator_overlap_ext.py | 50 +- tests/test_indicator_performance.py | 22 +- tests/test_indicator_performance_ext.py | 18 +- tests/test_indicator_statistics.py | 30 +- tests/test_indicator_statistics_ext.py | 16 +- tests/test_indicator_trend.py | 44 +- tests/test_indicator_trend_ext.py | 36 +- tests/test_indicator_volatility.py | 42 +- tests/test_indicator_volatility_ext.py | 26 +- tests/test_indicator_volume.py | 40 +- tests/test_indicator_volume_ext.py | 34 +- 26 files changed, 3827 insertions(+), 434 deletions(-) create mode 100644 examples/PandasTA_Strategy_Examples.ipynb create mode 100644 examples/watchlist.py diff --git a/.gitignore b/.gitignore index 1e31be3..dd90ffa 100644 --- a/.gitignore +++ b/.gitignore @@ -119,10 +119,13 @@ pandas_ta/_wrapper.py data/datas.csv data/SPY_5min.csv data/SPY_1min.csv +data/similang-ch.csv data/tulip.csv examples/taplot.py +examples/charting.ipynb examples/ib_trader.ipynb examples/example2.ipynb +examples/*.csv setup.cfg note.md driver.py diff --git a/README.md b/README.md index 6d6b294..5166135 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ All the indicators return a named Series or a DataFrame in uppercase underscore * Has 100+ indicators and utility functions. * Option to use __multiprocessing__ when using df.ta.strategy(). See below. -* Example Jupyter Notebook under the [examples](https://github.com/twopirllc/pandas-ta/tree/master/examples) directory. +* 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. * Abbreviated Indicator names as listed below. * __Extended Pandas DataFrame__ as 'ta'. @@ -25,50 +25,12 @@ All the indicators return a named Series or a DataFrame in uppercase underscore ## __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. * Improved the calculation performance of indicators: _Exponential Moving Averagage_ and _Weighted Moving Average_. * Removed internal core optimizations when running ```df.ta.strategy('all')``` with multiprocessing. See the ```ta.strategy()``` method for more details. -### __New DataFrame Method:__ - strategy (strategy) - -### __Added indicators:__ - Bias (bias) - Choppiness Index (chop) - Chande Kroll Stop (cksp) - Doji (cdl_doji) - Entropy (entropy) - Heikin-Ashi Candles (ha) - Inertia (inertia) - KDJ (kdj) - Parabolic Stop and Reverse (psar) - Price Distance (pdist) - Psycholigical Line (psl) - Percentage Volume Oscillator (pvo) - Relative Volatility Index (rvi) - Supertrend (supertrend) - Weighted Closing Price (wcp) -### __Added utilities:__ - Above (above) - Above Value (above_value) - Below (below) - Below Value (below_value) - Cross Value (cross_value) -### __User Added Indicators:__ - Aberration (aberration) - BRAR (brar) -### __Corrected Indicators:__ - Absolute Price Oscillator (apo) - Aroon & Aroon Oscillator (aroon) - * Fixed indicator and included oscillator in returned dataframe - Bollinger Bands (bbands) - Commodity Channel Index (cci) - Chande Momentum Oscillator (cmo) - Exponential Moving Average (ema) - Moving Average Convergence Divergence (macd) - Relative Vigor Index (rvgi) - Symmetric Weighted Moving Average (swma) - Weighted Moving Average (wma) ## What is a Pandas DataFrame Extension? @@ -127,9 +89,63 @@ pd.DataFrame().ta.indicators() help(ta.log_return) ``` -## __New DataFrame Method__: _strategy_ with Multiprocessing +## 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__. -Strategy is a new __Pandas (TA)__ method to facilitate bulk indicator processing. By default, running ```df.ta.strategy()``` will append __all +* 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_. + +### Strategy Requirements: +- _name_: Some short memorable string. _Note_: Case-insensitive "All" is reserved. +- _ta_: A list of dicts containing keyword arguments to identify the indicator and the indicator's arguments + +### Optional Requirements: +- _description_: A more detailed description of what the Strategy tries to capture. Default: None +- _created_: At datetime string of when it was created. Default: Automatically generated. + +#### 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 +```python +# Builtin All Default Strategy +AllStrategy = Strategy( + name="All", + description="All the indicators with their default settings. Pandas TA default.", + ta=None +) + +# Builtin Default (Example) Strategy. +CommonStrategy = Strategy( + name="Common Price and Volume SMAs", + description="Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.", + ta=[ + {"kind": "sma", "length": 10}, + {"kind": "sma", "length": 20}, + {"kind": "sma", "length": 50}, + {"kind": "sma", "length": 200}, + {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOL"} + ] +) + +# Your Custom Strategy or whatever your TA composition +CustomStrategy = Strategy( + name="Momo and Volatility", + description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20", + 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"}, + ] +) +``` + +## __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. * The ```ta.strategy()``` method is still __under development__. Future iterations will allow you to load a ```ta.json``` config file with your specific strategy name and parameters to automatically run you bulk indicators. @@ -171,7 +187,32 @@ df.ta.strategy(fast=10, slow=50, verbose=True) df.columns ``` -## __New DataFrame kwargs__: _prefix_ and _suffix_ +### Running a Custom Strategy +While the _Strategy_ Class it has not been fully integrated with the __strategy__ method yet. For now, the following can be done to implement your Custom Strategy. + +```python +# Create a Strategy +CustomStrategy = Strategy( + name="Momo and Volatility", + description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20", + 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"}, + ] +) + +#Running it requires the name and ta properties +df.ta.strategy(name=CustomStrategy.name, ta=CustomStrategy.ta) + +# Sanity check. Make sure all the columns are there +df.columns +``` + +## __DataFrame kwargs__: _prefix_ and _suffix_ ```python prehl2 = df.ta.hl2(prefix="pre") @@ -184,7 +225,7 @@ bothhl2 = df.ta.hl2(prefix="pre", suffix="post") print(bothhl2.name) # "pre_HL2_post" ``` -## __New DataFrame Properties__: _reverse_ & _datetime_ordered_ +## __DataFrame Properties__: _reverse_ & _datetime_ordered_ ```python # The 'reverse' is a helper property that returns the DataFrame @@ -193,7 +234,7 @@ df = df.ta.reverse # The 'datetime_ordered' property returns True if the DataFrame # index is of Pandas datetime64 and df.index[0] < df.index[-1] -# Otherwise it return False +# Otherwise it returns False time_series_in_order = df.ta.datetime_ordered ``` diff --git a/examples/PandasTA_Strategy_Examples.ipynb b/examples/PandasTA_Strategy_Examples.ipynb new file mode 100644 index 0000000..acd857a --- /dev/null +++ b/examples/PandasTA_Strategy_Examples.ipynb @@ -0,0 +1,3040 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas TA ([pandas_ta](https://github.com/twopirllc/pandas-ta)) Strategies for Custom Technical Analysis\n", + "\n", + "## Topics\n", + "- What is a Pandas TA Strategy?\n", + " - Builtin Strategies: __AllStrategy__ and __CommonStrategy__\n", + " - Creating Strategies\n", + "- Watchlist Class\n", + " - Strategy Management and Execution\n", + "- Indicator Composition/Chaining for more Complex Strategies\n", + " - Comprehensive Example: _MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns_" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Populating the interactive namespace from numpy and matplotlib\n" + ] + } + ], + "source": [ + "%matplotlib inline\n", + "import datetime as dt\n", + "\n", + "# import matplotlib.pyplot as plt\n", + "# import mplfinance as mpf\n", + "\n", + "import pandas as pd\n", + "import pandas_ta as ta\n", + "from alphaVantageAPI.alphavantage import AlphaVantage # pip install alphaVantage-api\n", + "\n", + "from watchlist import Watchlist\n", + "%pylab inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# What is a Pandas TA Strategy?\n", + "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__.\n", + "\n", + "## Strategy Requirements:\n", + "- _name_: Some short memorable string. _Note_: Case-insensitive \"All\" is reserved.\n", + "- _ta_: A list of dicts containing keyword arguments to identify the indicator and the indicator's arguments\n", + "\n", + "## Optional Requirements:\n", + "- _description_: A more detailed description of what the Strategy tries to capture. Default: None\n", + "- _created_: At datetime string of when it was created. Default: Automatically generated.\n", + "\n", + "### Things to note:\n", + "- A Strategy will __fail__ when consumed by Pandas TA if there is no {\"kind\": \"indicator name\"} attribute." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# (Builtin) Examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### All" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name = All\n", + "description = All the indicators with their default settings. Pandas TA default.\n", + "created = 07/21/2020, 10:42:07\n", + "ta = None\n" + ] + } + ], + "source": [ + "AllStrategy = ta.AllStrategy\n", + "print(\"name =\", AllStrategy.name)\n", + "print(\"description =\", AllStrategy.description)\n", + "print(\"created =\", AllStrategy.created)\n", + "print(\"ta =\", AllStrategy.ta)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Common" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name = Common Price and Volume SMAs\n", + "description = Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.\n", + "created = 07/21/2020, 10:42:07\n", + "ta = [{'kind': 'sma', 'length': 10}, {'kind': 'sma', 'length': 20}, {'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOL'}]\n" + ] + } + ], + "source": [ + "CommonStrategy = ta.CommonStrategy\n", + "print(\"name =\", CommonStrategy.name)\n", + "print(\"description =\", CommonStrategy.description)\n", + "print(\"created =\", CommonStrategy.created)\n", + "print(\"ta =\", CommonStrategy.ta)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Creating Strategies" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple Strategy A" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "custom_a = ta.Strategy(name=\"A\", ta=[{\"kind\": \"sma\", \"length\": 50}, {\"kind\": \"sma\", \"length\": 200}])\n", + "custom_a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple Strategy B" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "custom_b = ta.Strategy(name=\"B\", ta=[{\"kind\": \"ema\", \"length\": 8}, {\"kind\": \"ema\", \"length\": 21}, {\"kind\": \"log_return\", \"cumulative\": True}, {\"kind\": \"rsi\"}, {\"kind\": \"supertrend\"}])\n", + "custom_b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Bad Strategy. (Misspelled Indicator)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Misspelled indicator, will fail later when ran with Pandas\n", + "custom_run_failure = ta.Strategy(name=\"Runtime Failure\", ta=[{\"kind\": \"percet_return\"}])\n", + "custom_run_failure" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Strategy Management and Execution with _Watchlist_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize AlphaVantage Data Source" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AlphaVantage(\n", + " end_point:str = https://www.alphavantage.co/query,\n", + " api_key:str = YOUR API KEY,\n", + " export:bool = True,\n", + " export_path:str = .,\n", + " output_size:str = full,\n", + " output:str = csv,\n", + " datatype:str = json,\n", + " clean:bool = True,\n", + " proxy:dict = {}\n", + ")" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "AV = AlphaVantage(\n", + " api_key=\"YOUR API KEY\", premium=False,\n", + " output_size='full', clean=True,\n", + " export_path=\".\", export=True\n", + ")\n", + "AV" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create Watchlist and set it's 'ds' to AlphaVantage" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "watch = Watchlist([\"SPY\", \"IWM\"], ds=AV)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Info about the Watchlist. Note, the default Strategy is \"All\"" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Watch(name='Watchlist: SPY, IWM', tickers[2]='SPY, IWM', tf='D', strategy[0]='All')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "watch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Help about Watchlist" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on class Watchlist in module watchlist:\n", + "\n", + "class Watchlist(builtins.object)\n", + " | Watchlist(tickers: list, tf: str = None, name: str = None, strategy: pandas_ta.core.Strategy = None, ds: object = None, **kwargs)\n", + " | \n", + " | Watchlist Class (** This is subject to change! **)\n", + " | ============================================================================\n", + " | A simple Class to load/download financial market data and automatically\n", + " | apply Technical Analysis indicators with a Pandas TA Strategy. Default\n", + " | Strategy: pandas_ta.AllStrategy.\n", + " | \n", + " | Requirements:\n", + " | - Pandas TA (pip install pandas_ta)\n", + " | - AlphaVantage (pip install alphaVantage-api) for the Default Data Source.\n", + " | To use another Data Source, update the load() method after AV.\n", + " | \n", + " | Required Arguments:\n", + " | - tickers: A list of strings containing tickers. Example: ['SPY', 'AAPL']\n", + " | ============================================================================\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(self, tickers: list, tf: str = None, name: str = None, strategy: pandas_ta.core.Strategy = None, ds: object = None, **kwargs)\n", + " | Initialize self. See help(type(self)) for accurate signature.\n", + " | \n", + " | __repr__(self) -> str\n", + " | Return repr(self).\n", + " | \n", + " | indicators(self, *args, **kwargs) -> \n", + " | Returns the list of indicators that are available with Pandas Ta.\n", + " | \n", + " | load(self, ticker: str = None, tf: str = None, index: str = 'date', drop: list = ['dividend', 'split_coefficient'], file_path: str = '.', **kwargs) -> pandas.core.frame.DataFrame\n", + " | Loads or Downloads (if a local csv does not exist) the data from the\n", + " | Data Source. When successful, it returns a Data Frame for the requested\n", + " | ticker. If no tickers are given, it loads all the tickers.\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data descriptors defined here:\n", + " | \n", + " | __dict__\n", + " | dictionary for instance variables (if defined)\n", + " | \n", + " | __weakref__\n", + " | list of weak references to the object (if defined)\n", + " | \n", + " | data\n", + " | When not None, it contains a dictionary of DataFrames keyed by ticker.\n", + " | \n", + " | name\n", + " | The name of the Watchlist. Default: \"Watchlist: {Watchlist.tickers}\".\n", + " | \n", + " | strategy\n", + " | Pandas TA Strategy Class. Default: pandas_ta.AllStrategy\n", + " | \n", + " | tf\n", + " | Alias for timeframe. Default: 'D'\n", + " | \n", + " | tickers\n", + " | tickers\n", + " | \n", + " | If a string, it it converted to a list. Example: 'AAPL' -> ['AAPL']\n", + " | * Does not accept, comma seperated strings.\n", + " | If a list, checks if it is a list of strings.\n", + " | \n", + " | verbose\n", + " | Toggle the verbose property. Default: False\n", + "\n" + ] + } + ], + "source": [ + "help(Watchlist)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Default Strategy is \"All\"" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[!] Loading All: SPY, IWM\n", + "\n", + "[+] Downloading['D']: SPY\n", + "strat.kwargs: {'ta': None, 'verbose': True, 'timed': False}\n", + "[+] Strategy \"All\"\n", + "[i] Indicators with the following arguments: {'append': True}\n", + "[i] Excluded[10]: above, above_value, below, below_value, cross, cross_value, long_run, short_run, trend_return, vp\n", + "[i] Total indicators: 101\n", + "[i] Columns added: 152\n", + "\n", + "[+] Downloading['D']: IWM\n", + "strat.kwargs: {'ta': None, 'verbose': True, 'timed': False}\n", + "[+] Strategy \"All\"\n", + "[i] Indicators with the following arguments: {'append': True}\n", + "[i] Excluded[10]: above, above_value, below, below_value, cross, cross_value, long_run, short_run, trend_return, vp\n", + "[i] Total indicators: 101\n", + "[i] Columns added: 152\n" + ] + } + ], + "source": [ + "# No arguments loads all the tickers and applies the Strategy to each ticker.\n", + "# The result can be accessed with Watchlist's 'data' property which returns a dictionary keyed by ticker and DataFrames as values \n", + "watch.load(verbose=True, timed=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'SPY': open high low close volume ABER_ZG_5_15 \\\n", + " date \n", + " 1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + " 1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + " 1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + " 1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + " 1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.862000 \n", + " 2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 317.127333 \n", + " 2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", + " 2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", + " 2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 320.670000 \n", + " \n", + " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", + " date ... \n", + " 1999-11-01 NaN NaN NaN NaN ... \n", + " 1999-11-02 NaN NaN NaN NaN ... \n", + " 1999-11-03 NaN NaN NaN NaN ... \n", + " 1999-11-04 NaN NaN NaN NaN ... \n", + " 1999-11-05 NaN NaN NaN NaN ... \n", + " ... ... ... ... ... ... \n", + " 2020-07-14 322.137987 309.586013 6.275987 297.831277 ... \n", + " 2020-07-15 323.259587 310.995079 6.132254 298.823299 ... \n", + " 2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", + " 2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", + " 2020-07-20 326.292790 315.047210 5.622790 300.906776 ... \n", + " \n", + " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", + " date \n", + " 1999-11-01 NaN NaN NaN 136.041667 NaN 135.921875 \n", + " 1999-11-02 NaN NaN NaN 135.693303 NaN 135.257775 \n", + " 1999-11-03 NaN NaN NaN 135.682462 NaN 135.625000 \n", + " 1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", + " 1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-14 34.050046 0.942619 0.851435 153.185166 314.416051 317.400000 \n", + " 2020-07-15 36.858968 1.134936 0.764889 153.210321 315.765307 321.502500 \n", + " 2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", + " 2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", + " 2020-07-20 45.052926 1.223611 0.623952 153.259707 318.469407 323.572500 \n", + " \n", + " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", + " date \n", + " 1999-11-01 NaN NaN NaN NaN \n", + " 1999-11-02 NaN NaN NaN NaN \n", + " 1999-11-03 NaN NaN NaN NaN \n", + " 1999-11-04 NaN NaN NaN NaN \n", + " 1999-11-05 NaN NaN NaN NaN \n", + " ... ... ... ... ... \n", + " 2020-07-14 -15.937763 315.716545 317.221127 1.224000 \n", + " 2020-07-15 -4.935711 317.073818 319.420922 1.583443 \n", + " 2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", + " 2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", + " 2020-07-20 -4.035664 320.087455 323.196899 1.674079 \n", + " \n", + " [5212 rows x 157 columns],\n", + " 'IWM': open high low close volume ABER_ZG_5_15 \\\n", + " date \n", + " 2000-05-26 91.06 91.44 90.63 91.44 37400.0 NaN \n", + " 2000-05-30 92.75 94.81 92.75 94.81 28800.0 NaN \n", + " 2000-05-31 95.13 96.38 95.13 95.75 18000.0 NaN \n", + " 2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN \n", + " 2000-06-02 101.70 102.40 101.70 102.40 14700.0 96.091333 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-14 139.43 141.98 138.64 141.83 27919300.0 140.631333 \n", + " 2020-07-15 145.42 147.78 144.79 147.03 40619500.0 141.702000 \n", + " 2020-07-16 146.11 146.67 144.88 146.16 30386200.0 142.972000 \n", + " 2020-07-17 146.68 147.59 145.51 146.59 20632700.0 144.200000 \n", + " 2020-07-20 146.12 146.85 145.15 145.91 18335300.0 145.157333 \n", + " \n", + " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", + " date ... \n", + " 2000-05-26 NaN NaN NaN NaN ... \n", + " 2000-05-30 NaN NaN NaN NaN ... \n", + " 2000-05-31 NaN NaN NaN NaN ... \n", + " 2000-06-01 NaN NaN NaN NaN ... \n", + " 2000-06-02 NaN NaN NaN NaN ... \n", + " ... ... ... ... ... ... \n", + " 2020-07-14 144.933519 136.329148 4.302186 131.931151 ... \n", + " 2020-07-15 146.114040 137.289960 4.412040 132.378072 ... \n", + " 2020-07-16 147.233237 138.710763 4.261237 132.740467 ... \n", + " 2020-07-17 148.315822 140.084178 4.115822 133.164616 ... \n", + " 2020-07-20 149.112100 141.202567 3.954767 133.720436 ... \n", + " \n", + " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", + " date \n", + " 2000-05-26 NaN NaN NaN 91.170000 NaN 91.2375 \n", + " 2000-05-30 NaN NaN NaN 92.454834 NaN 94.2950 \n", + " 2000-05-31 NaN NaN NaN 93.159976 NaN 95.7525 \n", + " 2000-06-01 NaN NaN NaN 93.322938 NaN 97.2600 \n", + " 2000-06-02 NaN NaN NaN 94.592497 NaN 102.2250 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-14 14.580918 0.912088 0.993442 88.330119 141.551704 141.0700 \n", + " 2020-07-15 15.260700 1.069504 0.907148 88.343103 141.954972 146.6575 \n", + " 2020-07-16 15.532794 1.067613 0.898394 88.352707 142.400151 145.9675 \n", + " 2020-07-17 15.940380 1.090399 0.874371 88.359302 142.830341 146.5700 \n", + " 2020-07-20 14.336087 1.085970 0.934221 88.365101 143.084383 145.9550 \n", + " \n", + " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", + " date \n", + " 2000-05-26 NaN NaN NaN NaN \n", + " 2000-05-30 NaN NaN NaN NaN \n", + " 2000-05-31 NaN NaN NaN NaN \n", + " 2000-06-01 NaN NaN NaN NaN \n", + " 2000-06-02 NaN NaN NaN NaN \n", + " ... ... ... ... ... \n", + " 2020-07-14 -41.126461 141.123273 140.481012 -0.140980 \n", + " 2020-07-15 -6.527415 142.121636 143.119010 1.145187 \n", + " 2020-07-16 -14.348981 142.891818 144.553735 0.902863 \n", + " 2020-07-17 -11.142322 143.661273 146.209420 0.982248 \n", + " 2020-07-20 -17.741935 144.230909 146.896798 0.893748 \n", + " \n", + " [5068 rows x 157 columns]}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "watch.data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeABER_ZG_5_15ABER_SG_5_15ABER_XG_5_15ABER_ATR_5_15ACCBL_20...VAR_30VTXP_14VTXM_14VWAPVWMA_10WCPWILLR_14WMA_10ZL_EMA_10Z_30
date
1999-11-01136.5000137.0000135.5625135.56254006500.0NaNNaNNaNNaNNaN...NaNNaNNaN136.041667NaN135.921875NaNNaNNaNNaN
1999-11-02135.9687137.2500134.5937134.59376516900.0NaNNaNNaNNaNNaN...NaNNaNNaN135.693303NaN135.257775NaNNaNNaNNaN
1999-11-03136.0000136.3750135.1250135.50007222300.0NaNNaNNaNNaNNaN...NaNNaNNaN135.682462NaN135.625000NaNNaNNaNNaN
1999-11-04136.7500137.3593135.7656136.53127907500.0NaNNaNNaNNaNNaN...NaNNaNNaN135.950504NaN136.546825NaNNaNNaNNaN
1999-11-05138.6250139.1093136.7812137.87507431500.0136.332267NaNNaNNaNNaN...NaNNaNNaN136.393305NaN137.910125NaNNaNNaNNaN
..................................................................
2020-07-14313.3000319.7600312.0000318.920092791800.0315.862000322.137987309.5860136.275987297.831277...34.0500460.9426190.851435153.185166314.416051317.400000-15.937763315.716545317.2211271.224000
2020-07-15322.4100323.0400319.2700321.850086921500.0317.127333323.259587310.9950796.132254298.823299...36.8589681.1349360.764889153.210321315.765307321.502500-4.935711317.073818319.4209221.583443
2020-07-16319.7900321.2800319.0900320.790054433400.0318.394000324.301437312.4865635.907437299.367555...39.2963901.1421860.731933153.225976316.788363320.487500-9.332227317.993091320.2516631.318671
2020-07-17321.8800322.5700319.7400321.720064421800.0319.447333325.149608313.7450595.702275299.875050...42.0426231.2008110.690749153.244606317.735725321.437500-5.474907318.894727321.7695431.365046
2020-07-20321.4300325.1300320.6200324.270051616200.0320.670000326.292790315.0472105.622790300.906776...45.0529261.2236110.623952153.259707318.469407323.572500-4.035664320.087455323.1968991.674079
\n", + "

5212 rows × 157 columns

\n", + "
" + ], + "text/plain": [ + " open high low close volume ABER_ZG_5_15 \\\n", + "date \n", + "1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + "1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + "1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", + "... ... ... ... ... ... ... \n", + "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.862000 \n", + "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 317.127333 \n", + "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", + "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 320.670000 \n", + "\n", + " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", + "date ... \n", + "1999-11-01 NaN NaN NaN NaN ... \n", + "1999-11-02 NaN NaN NaN NaN ... \n", + "1999-11-03 NaN NaN NaN NaN ... \n", + "1999-11-04 NaN NaN NaN NaN ... \n", + "1999-11-05 NaN NaN NaN NaN ... \n", + "... ... ... ... ... ... \n", + "2020-07-14 322.137987 309.586013 6.275987 297.831277 ... \n", + "2020-07-15 323.259587 310.995079 6.132254 298.823299 ... \n", + "2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", + "2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", + "2020-07-20 326.292790 315.047210 5.622790 300.906776 ... \n", + "\n", + " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", + "date \n", + "1999-11-01 NaN NaN NaN 136.041667 NaN 135.921875 \n", + "1999-11-02 NaN NaN NaN 135.693303 NaN 135.257775 \n", + "1999-11-03 NaN NaN NaN 135.682462 NaN 135.625000 \n", + "1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", + "1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", + "... ... ... ... ... ... ... \n", + "2020-07-14 34.050046 0.942619 0.851435 153.185166 314.416051 317.400000 \n", + "2020-07-15 36.858968 1.134936 0.764889 153.210321 315.765307 321.502500 \n", + "2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", + "2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", + "2020-07-20 45.052926 1.223611 0.623952 153.259707 318.469407 323.572500 \n", + "\n", + " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", + "date \n", + "1999-11-01 NaN NaN NaN NaN \n", + "1999-11-02 NaN NaN NaN NaN \n", + "1999-11-03 NaN NaN NaN NaN \n", + "1999-11-04 NaN NaN NaN NaN \n", + "1999-11-05 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "2020-07-14 -15.937763 315.716545 317.221127 1.224000 \n", + "2020-07-15 -4.935711 317.073818 319.420922 1.583443 \n", + "2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", + "2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", + "2020-07-20 -4.035664 320.087455 323.196899 1.674079 \n", + "\n", + "[5212 rows x 157 columns]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "watch.data['SPY']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Easy to swap Strategies and run them" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Running Simple Strategy A" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load custom_a into Watchlist and verify\n", + "watch.strategy = custom_a\n", + "watch.strategy" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: IWM_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}]}\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeSMA_50SMA_200
date
2000-05-2691.0691.4490.6391.4437400.0NaNNaN
2000-05-3092.7594.8192.7594.8128800.0NaNNaN
2000-05-3195.1396.3895.1395.7518000.0NaNNaN
2000-06-0197.1197.3197.1197.313500.0NaNNaN
2000-06-02101.70102.40101.70102.4014700.0NaNNaN
........................
2020-07-14139.43141.98138.64141.8327919300.0138.1012145.99795
2020-07-15145.42147.78144.79147.0340619500.0138.5282145.97730
2020-07-16146.11146.67144.88146.1630386200.0138.9184145.95140
2020-07-17146.68147.59145.51146.5920632700.0139.3358145.94250
2020-07-20146.12146.85145.15145.9118335300.0139.7052145.93580
\n", + "

5068 rows × 7 columns

\n", + "
" + ], + "text/plain": [ + " open high low close volume SMA_50 SMA_200\n", + "date \n", + "2000-05-26 91.06 91.44 90.63 91.44 37400.0 NaN NaN\n", + "2000-05-30 92.75 94.81 92.75 94.81 28800.0 NaN NaN\n", + "2000-05-31 95.13 96.38 95.13 95.75 18000.0 NaN NaN\n", + "2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN NaN\n", + "2000-06-02 101.70 102.40 101.70 102.40 14700.0 NaN NaN\n", + "... ... ... ... ... ... ... ...\n", + "2020-07-14 139.43 141.98 138.64 141.83 27919300.0 138.1012 145.99795\n", + "2020-07-15 145.42 147.78 144.79 147.03 40619500.0 138.5282 145.97730\n", + "2020-07-16 146.11 146.67 144.88 146.16 30386200.0 138.9184 145.95140\n", + "2020-07-17 146.68 147.59 145.51 146.59 20632700.0 139.3358 145.94250\n", + "2020-07-20 146.12 146.85 145.15 145.91 18335300.0 139.7052 145.93580\n", + "\n", + "[5068 rows x 7 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "watch.load('IWM')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Running Simple Strategy B" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load custom_b into Watchlist and verify\n", + "watch.strategy = custom_b\n", + "watch.strategy" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: SPY_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}]}\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeEMA_8EMA_21CUMLOGRET_1RSI_14SUPERT_7_3.0SUPERTd_7_3.0SUPERTl_7_3.0SUPERTs_7_3.0
date
1999-11-01136.5000137.0000135.5625135.56254006500.0NaNNaNNaNNaN0.0000000NaNNaN
1999-11-02135.9687137.2500134.5937134.59376516900.0NaNNaN-0.0071720.000000NaN0NaNNaN
1999-11-03136.0000136.3750135.1250135.50007222300.0NaNNaN-0.0004616.263520NaN0NaNNaN
1999-11-04136.7500137.3593135.7656136.53127907500.0NaNNaN0.00712012.913259NaN0NaNNaN
1999-11-05138.6250139.1093136.7812137.87507431500.0NaNNaN0.01691520.761745NaN0NaNNaN
..........................................
2020-07-14313.3000319.7600312.0000318.920092791800.0315.153455311.7364180.85550759.173765321.864382-1NaN321.864382
2020-07-15322.4100323.0400319.2700321.850086921500.0316.641576312.6558350.86465361.428658321.864382-1NaN321.864382
2020-07-16319.7900321.2800319.0900320.790054433400.0317.563448313.3953040.86135460.141122321.864382-1NaN321.864382
2020-07-17321.8800322.5700319.7400321.720064421800.0318.487126314.1520950.86424960.911280321.864382-1NaN321.864382
2020-07-20321.4300325.1300320.6200324.270051616200.0319.772209315.0719050.87214463.010941307.8904391307.890439NaN
\n", + "

5212 rows × 13 columns

\n", + "
" + ], + "text/plain": [ + " open high low close volume EMA_8 \\\n", + "date \n", + "1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + "1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + "1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", + "... ... ... ... ... ... ... \n", + "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.153455 \n", + "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 316.641576 \n", + "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 317.563448 \n", + "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 318.487126 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 319.772209 \n", + "\n", + " EMA_21 CUMLOGRET_1 RSI_14 SUPERT_7_3.0 SUPERTd_7_3.0 \\\n", + "date \n", + "1999-11-01 NaN NaN NaN 0.000000 0 \n", + "1999-11-02 NaN -0.007172 0.000000 NaN 0 \n", + "1999-11-03 NaN -0.000461 6.263520 NaN 0 \n", + "1999-11-04 NaN 0.007120 12.913259 NaN 0 \n", + "1999-11-05 NaN 0.016915 20.761745 NaN 0 \n", + "... ... ... ... ... ... \n", + "2020-07-14 311.736418 0.855507 59.173765 321.864382 -1 \n", + "2020-07-15 312.655835 0.864653 61.428658 321.864382 -1 \n", + "2020-07-16 313.395304 0.861354 60.141122 321.864382 -1 \n", + "2020-07-17 314.152095 0.864249 60.911280 321.864382 -1 \n", + "2020-07-20 315.071905 0.872144 63.010941 307.890439 1 \n", + "\n", + " SUPERTl_7_3.0 SUPERTs_7_3.0 \n", + "date \n", + "1999-11-01 NaN NaN \n", + "1999-11-02 NaN NaN \n", + "1999-11-03 NaN NaN \n", + "1999-11-04 NaN NaN \n", + "1999-11-05 NaN NaN \n", + "... ... ... \n", + "2020-07-14 NaN 321.864382 \n", + "2020-07-15 NaN 321.864382 \n", + "2020-07-16 NaN 321.864382 \n", + "2020-07-17 NaN 321.864382 \n", + "2020-07-20 307.890439 NaN \n", + "\n", + "[5212 rows x 13 columns]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "watch.load('SPY')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Running Bad Strategy. (Misspelled indicator)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load custom_run_failure into Watchlist and verify\n", + "watch.strategy = custom_run_failure\n", + "watch.strategy" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: IWM_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'percet_return'}]}\n", + "[X] Oops! 'AnalysisIndicators' object has no attribute 'percet_return'\n" + ] + } + ], + "source": [ + "try:\n", + " iwm = watch.load('IWM')\n", + "except AttributeError as error:\n", + " print(f\"[X] Oops! {error}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Indicator Composition/Chaining\n", + "- When you need an indicator to depend on the value of a prior indicator\n", + "- Utilitze _prefix_ or _suffix_ to help identify unique columns or avoid column name clashes." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Volume MAs and MA chains" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='Volume MAs and Price MA chain', ta=[{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Set EMA's and SMA's 'close' to 'volume' to create Volume MAs, prefix 'volume' MAs with 'VOLUME' so easy to identify the column\n", + "# Take a price EMA and apply LINREG from EMA's output\n", + "volmas_price_ma_chain = [\n", + " {\"kind\":\"ema\", \"close\": \"volume\", \"length\": 10, \"prefix\": \"VOLUME\"},\n", + " {\"kind\":\"sma\", \"close\": \"volume\", \"length\": 20, \"prefix\": \"VOLUME\"},\n", + " {\"kind\":\"ema\", \"length\": 5},\n", + " {\"kind\":\"linreg\", \"close\": \"EMA_5\", \"length\": 8, \"prefix\": \"EMA_5\"},\n", + "]\n", + "vp_ma_chain_ta = ta.Strategy(\"Volume MAs and Price MA chain\", volmas_price_ma_chain)\n", + "vp_ma_chain_ta" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Volume MAs and Price MA chain'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Update the Watchlist\n", + "watch.strategy = vp_ma_chain_ta\n", + "watch.strategy.name" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: SPY_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}]}\n", + "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeVOLUME_EMA_10VOLUME_SMA_20EMA_5EMA_5_LR_8
date
1999-11-01136.5000137.0000135.5625135.56254006500.0NaNNaNNaNNaN
1999-11-02135.9687137.2500134.5937134.59376516900.0NaNNaNNaNNaN
1999-11-03136.0000136.3750135.1250135.50007222300.0NaNNaNNaNNaN
1999-11-04136.7500137.3593135.7656136.53127907500.0NaNNaNNaNNaN
1999-11-05138.6250139.1093136.7812137.87507431500.0NaNNaN136.012480NaN
..............................
2020-07-14313.3000319.7600312.0000318.920092791800.08.361704e+0789676222.80316.336980315.670761
2020-07-15322.4100323.0400319.2700321.850086921500.08.421785e+0787169880.45318.174653316.635348
2020-07-16319.7900321.2800319.0900320.790054433400.07.880249e+0785750820.85319.046435317.729875
2020-07-17321.8800322.5700319.7400321.720064421800.07.618782e+0784954118.65319.937624318.784441
2020-07-20321.4300325.1300320.6200324.270051616200.07.172025e+0780774361.40321.381749320.052445
\n", + "

5212 rows × 9 columns

\n", + "
" + ], + "text/plain": [ + " open high low close volume VOLUME_EMA_10 \\\n", + "date \n", + "1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + "1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + "1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", + "... ... ... ... ... ... ... \n", + "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 8.361704e+07 \n", + "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 8.421785e+07 \n", + "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 7.880249e+07 \n", + "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 7.618782e+07 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 7.172025e+07 \n", + "\n", + " VOLUME_SMA_20 EMA_5 EMA_5_LR_8 \n", + "date \n", + "1999-11-01 NaN NaN NaN \n", + "1999-11-02 NaN NaN NaN \n", + "1999-11-03 NaN NaN NaN \n", + "1999-11-04 NaN NaN NaN \n", + "1999-11-05 NaN 136.012480 NaN \n", + "... ... ... ... \n", + "2020-07-14 89676222.80 316.336980 315.670761 \n", + "2020-07-15 87169880.45 318.174653 316.635348 \n", + "2020-07-16 85750820.85 319.046435 317.729875 \n", + "2020-07-17 84954118.65 319.937624 318.784441 \n", + "2020-07-20 80774361.40 321.381749 320.052445 \n", + "\n", + "[5212 rows x 9 columns]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spy = watch.load('SPY')\n", + "spy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### MACD BBANDS" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}], description='BBANDS_20 applied to MACD', created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# MACD is the initial indicator that BBANDS depends on.\n", + "# Set BBANDS's 'close' to MACD's main signal, in this case 'MACD_12_26_9' and add a prefix (or suffix) so it's easier to identify\n", + "macd_bands_ta = [\n", + " {\"kind\":\"macd\"},\n", + " {\"kind\":\"bbands\", \"close\": \"MACD_12_26_9\", \"length\": 20, \"prefix\": \"MACD\"}\n", + "]\n", + "macd_bands_ta = ta.Strategy(\"MACD BBands\", macd_bands_ta, f\"BBANDS_{macd_bands_ta[1]['length']} applied to MACD\")\n", + "macd_bands_ta" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'MACD BBands'" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Update the Watchlist\n", + "watch.strategy = macd_bands_ta\n", + "watch.strategy.name" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: SPY_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}]}\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeMACD_12_26_9MACDh_12_26_9MACDs_12_26_9MACD_BBL_20_2.0MACD_BBM_20_2.0MACD_BBU_20_2.0
date
1999-11-01136.5000137.0000135.5625135.56254006500.0NaNNaNNaNNaNNaNNaN
1999-11-02135.9687137.2500134.5937134.59376516900.0NaNNaNNaNNaNNaNNaN
1999-11-03136.0000136.3750135.1250135.50007222300.0NaNNaNNaNNaNNaNNaN
1999-11-04136.7500137.3593135.7656136.53127907500.0NaNNaNNaNNaNNaNNaN
1999-11-05138.6250139.1093136.7812137.87507431500.0NaNNaNNaNNaNNaNNaN
....................................
2020-07-14313.3000319.7600312.0000318.920092791800.03.4274210.3410143.0864070.8392133.4240326.008850
2020-07-15322.4100323.0400319.2700321.850086921500.03.8062340.5758623.2303720.9974013.3202925.643184
2020-07-16319.7900321.2800319.0900320.790054433400.03.9750910.5957753.3793161.1555063.2375935.319681
2020-07-17321.8800322.5700319.7400321.720064421800.04.1362740.6055663.5307081.2979953.1755515.053107
2020-07-20321.4300325.1300320.6200324.270051616200.04.4188380.7105043.7083341.3515603.1530964.954633
\n", + "

5212 rows × 11 columns

\n", + "
" + ], + "text/plain": [ + " open high low close volume MACD_12_26_9 \\\n", + "date \n", + "1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + "1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + "1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", + "... ... ... ... ... ... ... \n", + "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 3.427421 \n", + "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 3.806234 \n", + "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 3.975091 \n", + "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 4.136274 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 4.418838 \n", + "\n", + " MACDh_12_26_9 MACDs_12_26_9 MACD_BBL_20_2.0 MACD_BBM_20_2.0 \\\n", + "date \n", + "1999-11-01 NaN NaN NaN NaN \n", + "1999-11-02 NaN NaN NaN NaN \n", + "1999-11-03 NaN NaN NaN NaN \n", + "1999-11-04 NaN NaN NaN NaN \n", + "1999-11-05 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "2020-07-14 0.341014 3.086407 0.839213 3.424032 \n", + "2020-07-15 0.575862 3.230372 0.997401 3.320292 \n", + "2020-07-16 0.595775 3.379316 1.155506 3.237593 \n", + "2020-07-17 0.605566 3.530708 1.297995 3.175551 \n", + "2020-07-20 0.710504 3.708334 1.351560 3.153096 \n", + "\n", + " MACD_BBU_20_2.0 \n", + "date \n", + "1999-11-01 NaN \n", + "1999-11-02 NaN \n", + "1999-11-03 NaN \n", + "1999-11-04 NaN \n", + "1999-11-05 NaN \n", + "... ... \n", + "2020-07-14 6.008850 \n", + "2020-07-15 5.643184 \n", + "2020-07-16 5.319681 \n", + "2020-07-17 5.053107 \n", + "2020-07-20 4.954633 \n", + "\n", + "[5212 rows x 11 columns]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spy = watch.load('SPY')\n", + "spy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Comprehensive Strategy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### MACD and RSI Momentum with BBANDS and SMAs and Cumulative Log Returns" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Strategy(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "momo_bands_sma_ta = [\n", + " {\"kind\":\"sma\", \"length\": 50},\n", + " {\"kind\":\"sma\", \"length\": 200},\n", + " {\"kind\":\"bbands\", \"length\": 20},\n", + " {\"kind\":\"macd\"},\n", + " {\"kind\":\"rsi\"},\n", + " {\"kind\":\"log_return\", \"cumulative\": True},\n", + " {\"kind\":\"sma\", \"close\": \"CUMLOGRET_1\", \"length\": 5, \"suffix\": \"CUMLOGRET\"},\n", + "]\n", + "momo_bands_sma_strategy = ta.Strategy(\n", + " \"Momo, Bands and SMAs and Cumulative Log Returns\", # name\n", + " momo_bands_sma_ta, # ta\n", + " \"MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns\" # description\n", + ")\n", + "momo_bands_sma_strategy" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Momo, Bands and SMAs and Cumulative Log Returns'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Update the Watchlist\n", + "watch.strategy = momo_bands_sma_strategy\n", + "watch.strategy.name" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[i] Loaded['D']: SPY_D.csv\n", + "strat.kwargs: {'ta': [{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], 'timed': True}\n", + "[i] Runtime: 39.0952 ms (0.0391 s)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
openhighlowclosevolumeSMA_50SMA_200BBL_20_2.0BBM_20_2.0BBU_20_2.0MACD_12_26_9MACDh_12_26_9MACDs_12_26_9RSI_14CUMLOGRET_1SMA_5_CUMLOGRET03070
date
1999-11-01136.5000137.0000135.5625135.56254006500.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN03070
1999-11-02135.9687137.2500134.5937134.59376516900.0NaNNaNNaNNaNNaNNaNNaNNaN0.000000-0.007172NaN03070
1999-11-03136.0000136.3750135.1250135.50007222300.0NaNNaNNaNNaNNaNNaNNaNNaN6.263520-0.000461NaN03070
1999-11-04136.7500137.3593135.7656136.53127907500.0NaNNaNNaNNaNNaNNaNNaNNaN12.9132590.007120NaN03070
1999-11-05138.6250139.1093136.7812137.87507431500.0NaNNaNNaNNaNNaNNaNNaNNaN20.7617450.016915NaN03070
1999-11-08137.0000138.3750136.7500138.00004649200.0NaNNaNNaNNaNNaNNaNNaNNaN21.4671260.0178210.00684503070
1999-11-09138.5000138.6875136.2812136.70314533700.0NaNNaNNaNNaNNaNNaNNaNNaN19.5340820.0083790.00995503070
1999-11-10136.2500138.3906136.0781137.71876405600.0NaNNaNNaNNaNNaNNaNNaNNaN25.1864150.0157800.01320303070
1999-11-11138.1875138.5000137.4687138.50004794100.0NaNNaNNaNNaNNaNNaNNaN0.029.2810030.0214380.01606603070
1999-11-12139.2500139.9843137.1250139.750011802900.0NaNNaNNaNNaNNaNNaNNaN0.035.3466370.0304220.01876803070
1999-11-15139.8437140.2500139.4062140.07812187500.0NaNNaNNaNNaNNaNNaNNaN0.036.8694250.0327670.02175703070
1999-11-16140.5625143.0000140.0937141.25007544800.0NaNNaNNaNNaNNaNNaNNaN0.042.0892390.0410990.02830103070
1999-11-17142.2500142.9375141.3125141.62509459000.0NaNNaNNaNNaNNaNNaNNaN0.043.6856270.0437500.03389503070
1999-11-18142.4375143.0000141.6250142.62504491000.0NaNNaNNaNNaNNaNNaNNaN0.047.7971730.0507860.03976503070
1999-11-19142.4062142.9687142.0000142.50004832100.0NaNNaNNaNNaNNaNNaNNaN0.047.3343290.0499090.04366203070
1999-11-22142.4375143.0000141.5000142.46874155400.0NaNNaNNaNNaNNaNNaNNaN0.047.2116750.0496900.04704703070
1999-11-23142.8437142.8437140.3750141.21875918000.0NaNNaNNaNNaNNaNNaNNaN0.042.4995470.0408770.04700203070
1999-11-24140.7500142.4375140.0000141.96874459700.0NaNNaNNaNNaNNaNNaNNaN0.045.9664800.0461740.04748703070
1999-11-26142.4687142.8750141.2500141.43751693900.0NaNNaNNaNNaNNaNNaNNaN0.043.9553240.0424250.04581503070
1999-11-29140.8750141.9218140.4375140.93757348600.0NaNNaN134.086598139.34217144.597742NaNNaN0.042.0977810.0388840.04361003070
\n", + "
" + ], + "text/plain": [ + " open high low close volume SMA_50 \\\n", + "date \n", + "1999-11-01 136.5000 137.0000 135.5625 135.5625 4006500.0 NaN \n", + "1999-11-02 135.9687 137.2500 134.5937 134.5937 6516900.0 NaN \n", + "1999-11-03 136.0000 136.3750 135.1250 135.5000 7222300.0 NaN \n", + "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", + "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", + "1999-11-08 137.0000 138.3750 136.7500 138.0000 4649200.0 NaN \n", + "1999-11-09 138.5000 138.6875 136.2812 136.7031 4533700.0 NaN \n", + "1999-11-10 136.2500 138.3906 136.0781 137.7187 6405600.0 NaN \n", + "1999-11-11 138.1875 138.5000 137.4687 138.5000 4794100.0 NaN \n", + "1999-11-12 139.2500 139.9843 137.1250 139.7500 11802900.0 NaN \n", + "1999-11-15 139.8437 140.2500 139.4062 140.0781 2187500.0 NaN \n", + "1999-11-16 140.5625 143.0000 140.0937 141.2500 7544800.0 NaN \n", + "1999-11-17 142.2500 142.9375 141.3125 141.6250 9459000.0 NaN \n", + "1999-11-18 142.4375 143.0000 141.6250 142.6250 4491000.0 NaN \n", + "1999-11-19 142.4062 142.9687 142.0000 142.5000 4832100.0 NaN \n", + "1999-11-22 142.4375 143.0000 141.5000 142.4687 4155400.0 NaN \n", + "1999-11-23 142.8437 142.8437 140.3750 141.2187 5918000.0 NaN \n", + "1999-11-24 140.7500 142.4375 140.0000 141.9687 4459700.0 NaN \n", + "1999-11-26 142.4687 142.8750 141.2500 141.4375 1693900.0 NaN \n", + "1999-11-29 140.8750 141.9218 140.4375 140.9375 7348600.0 NaN \n", + "\n", + " SMA_200 BBL_20_2.0 BBM_20_2.0 BBU_20_2.0 MACD_12_26_9 \\\n", + "date \n", + "1999-11-01 NaN NaN NaN NaN NaN \n", + "1999-11-02 NaN NaN NaN NaN NaN \n", + "1999-11-03 NaN NaN NaN NaN NaN \n", + "1999-11-04 NaN NaN NaN NaN NaN \n", + "1999-11-05 NaN NaN NaN NaN NaN \n", + "1999-11-08 NaN NaN NaN NaN NaN \n", + "1999-11-09 NaN NaN NaN NaN NaN \n", + "1999-11-10 NaN NaN NaN NaN NaN \n", + "1999-11-11 NaN NaN NaN NaN NaN \n", + "1999-11-12 NaN NaN NaN NaN NaN \n", + "1999-11-15 NaN NaN NaN NaN NaN \n", + "1999-11-16 NaN NaN NaN NaN NaN \n", + "1999-11-17 NaN NaN NaN NaN NaN \n", + "1999-11-18 NaN NaN NaN NaN NaN \n", + "1999-11-19 NaN NaN NaN NaN NaN \n", + "1999-11-22 NaN NaN NaN NaN NaN \n", + "1999-11-23 NaN NaN NaN NaN NaN \n", + "1999-11-24 NaN NaN NaN NaN NaN \n", + "1999-11-26 NaN NaN NaN NaN NaN \n", + "1999-11-29 NaN 134.086598 139.34217 144.597742 NaN \n", + "\n", + " MACDh_12_26_9 MACDs_12_26_9 RSI_14 CUMLOGRET_1 \\\n", + "date \n", + "1999-11-01 NaN NaN NaN NaN \n", + "1999-11-02 NaN NaN 0.000000 -0.007172 \n", + "1999-11-03 NaN NaN 6.263520 -0.000461 \n", + "1999-11-04 NaN NaN 12.913259 0.007120 \n", + "1999-11-05 NaN NaN 20.761745 0.016915 \n", + "1999-11-08 NaN NaN 21.467126 0.017821 \n", + "1999-11-09 NaN NaN 19.534082 0.008379 \n", + "1999-11-10 NaN NaN 25.186415 0.015780 \n", + "1999-11-11 NaN 0.0 29.281003 0.021438 \n", + "1999-11-12 NaN 0.0 35.346637 0.030422 \n", + "1999-11-15 NaN 0.0 36.869425 0.032767 \n", + "1999-11-16 NaN 0.0 42.089239 0.041099 \n", + "1999-11-17 NaN 0.0 43.685627 0.043750 \n", + "1999-11-18 NaN 0.0 47.797173 0.050786 \n", + "1999-11-19 NaN 0.0 47.334329 0.049909 \n", + "1999-11-22 NaN 0.0 47.211675 0.049690 \n", + "1999-11-23 NaN 0.0 42.499547 0.040877 \n", + "1999-11-24 NaN 0.0 45.966480 0.046174 \n", + "1999-11-26 NaN 0.0 43.955324 0.042425 \n", + "1999-11-29 NaN 0.0 42.097781 0.038884 \n", + "\n", + " SMA_5_CUMLOGRET 0 30 70 \n", + "date \n", + "1999-11-01 NaN 0 30 70 \n", + "1999-11-02 NaN 0 30 70 \n", + "1999-11-03 NaN 0 30 70 \n", + "1999-11-04 NaN 0 30 70 \n", + "1999-11-05 NaN 0 30 70 \n", + "1999-11-08 0.006845 0 30 70 \n", + "1999-11-09 0.009955 0 30 70 \n", + "1999-11-10 0.013203 0 30 70 \n", + "1999-11-11 0.016066 0 30 70 \n", + "1999-11-12 0.018768 0 30 70 \n", + "1999-11-15 0.021757 0 30 70 \n", + "1999-11-16 0.028301 0 30 70 \n", + "1999-11-17 0.033895 0 30 70 \n", + "1999-11-18 0.039765 0 30 70 \n", + "1999-11-19 0.043662 0 30 70 \n", + "1999-11-22 0.047047 0 30 70 \n", + "1999-11-23 0.047002 0 30 70 \n", + "1999-11-24 0.047487 0 30 70 \n", + "1999-11-26 0.045815 0 30 70 \n", + "1999-11-29 0.043610 0 30 70 " + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spy = watch.load('SPY', timed=True)\n", + "# Apply constants to the DataFrame for indicators\n", + "spy.ta.constants(True, 0, 0, 1) # 0\n", + "spy.ta.constants(True, 30, 30, 1) # 30\n", + "spy.ta.constants(True, 70, 70, 1) # 70\n", + "spy.head(20)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/watchlist.py b/examples/watchlist.py new file mode 100644 index 0000000..df8cc3c --- /dev/null +++ b/examples/watchlist.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +from functools import lru_cache +from pathlib import Path +from random import random + +import pandas as pd + +from alphaVantageAPI.alphavantage import AlphaVantage # pip install alphaVantage-api +import pandas_ta as ta + + +class Watchlist(object): + """Watchlist Class (** This is subject to change! **) + ============================================================================ + A simple Class to load/download financial market data and automatically + apply Technical Analysis indicators with a Pandas TA Strategy. Default + Strategy: pandas_ta.AllStrategy. + + Requirements: + - Pandas TA (pip install pandas_ta) + - AlphaVantage (pip install alphaVantage-api) for the Default Data Source. + To use another Data Source, update the load() method after AV. + + Required Arguments: + - tickers: A list of strings containing tickers. Example: ['SPY', 'AAPL'] + ============================================================================ + """ + def __init__( + self, + tickers: list, + tf: str = None, + name: str = None, + strategy: ta.Strategy = None, + ds: object = None, + **kwargs + ): + self.tickers = tickers + self.tf = tf + self.verbose = kwargs.pop("verbose", False) + self.name = name + self.data = None + self.kwargs = kwargs + + self.ds = ds if ds is not None else None + self.strategy = strategy + + + def _drop_columns(self, df: pd.DataFrame, cols: list = ['Unnamed: 0', 'date', 'split_coefficient', 'dividend']): + """Helper methods to drop columns silently.""" + df_columns = list(df.columns) + if any(_ in df_columns for _ in cols): + if self.verbose: + print(f"[i] Possible columns dropped: {', '.join(cols)}") + df = df.drop(cols, axis=1, errors='ignore') + return df + + def _load_all(self, **kwargs) -> dict: + """Updates the Watchlist's data property with a dictionary of DataFrames + keyed by ticker.""" + if self.tickers is not None and isinstance(self.tickers, list) and len(self.tickers): + self.data = {ticker: self.load(ticker, **kwargs) for ticker in self.tickers} + return self.data + + def load( + self, + ticker: str = None, + tf: str = None, + index: str = 'date', + drop: list = ['dividend', 'split_coefficient'], + file_path: str = ".", + **kwargs + ) -> pd.DataFrame: + """Loads or Downloads (if a local csv does not exist) the data from the + Data Source. When successful, it returns a Data Frame for the requested + ticker. If no tickers are given, it loads all the tickers.""" + + tf = self.tf if tf is None else tf.upper() + if ticker is not None and isinstance(ticker, str): + ticker = str(ticker).upper() + else: + print(f"[!] Loading All: {', '.join(self.tickers)}") + self._load_all(**kwargs) + return + + filename_ = f"{ticker}_{tf}.csv" + current_file = Path(file_path) / filename_ + + # Load local or from Data Source + if current_file.exists(): + df = pd.read_csv(filename_, index_col=index) + if not df.ta.datetime_ordered: + df = df.set_index(pd.DatetimeIndex(df.index)) + print(f"\n[i] Loaded['{tf}']: {filename_}") + else: + if self.ds is not None and isinstance(self.ds, AlphaVantage): + df = self.ds.data(tf, ticker) + if not df.ta.datetime_ordered: + df = df.set_index(pd.DatetimeIndex(df[index])) + print(f"\n[+] Downloading['{tf}']: {ticker}") + + df = self._drop_columns(df) # Remove select columns + + if kwargs.pop("analyze", True): + df.ta.strategy(name=self.strategy.name, ta=self.strategy.ta, **kwargs) + + df.ticker = ticker # Attach ticker to the DataFrame + return df + + @property + def data(self) -> dict: + """When not None, it contains a dictionary of DataFrames keyed by ticker.""" + return self._data + + @data.setter + def data(self, value: dict) -> None: + # Later check dict has string keys and DataFrame values + if value is not None and isinstance(value, dict): + if self.verbose: print(f"[+] New data") + self._data = value + else: + self._data = None + + @property + def name(self) -> str: + """The name of the Watchlist. Default: "Watchlist: {Watchlist.tickers}".""" + return self._name + + @name.setter + def name(self, value: str) -> None: + if isinstance(value, str): + self._name = str(value) + else: + self._name = f"Watchlist: {', '.join(self.tickers)}" + + @property + def strategy(self) -> ta.Strategy: + """Pandas TA Strategy Class. Default: pandas_ta.AllStrategy""" + return self._strategy + + @strategy.setter + def strategy(self, value: ta.Strategy) -> None: + if value is not None and isinstance(value, ta.Strategy): + self._strategy = value + else: + self._strategy = ta.AllStrategy + + @property + def tf(self) -> str: + """Alias for timeframe. Default: 'D'""" + return self._tf + + @tf.setter + def tf(self, value: str) -> None: + if isinstance(value, str): + value = str(value) + self._tf = value + else: + self._tf = "D" + + @property + def tickers(self) -> list: + """tickers + + If a string, it it converted to a list. Example: 'AAPL' -> ['AAPL'] + * Does not accept, comma seperated strings. + If a list, checks if it is a list of strings. + """ + return self._tickers + + @tickers.setter + def tickers(self, value: (list, str)) -> None: + if value is None: + print(f"[X] {value} is not a valie Watchlist ticker.") + return + elif isinstance(value, list) and [isinstance(_, str) for _ in value]: + self._tickers = list(map(str.upper, value)) + elif isinstance(value, str): + self._tickers = [value.upper()] + self.name = self._tickers + + @property + def verbose(self) -> bool: + """Toggle the verbose property. Default: False""" + return self._verbose + + @verbose.setter + def verbose(self, value: bool) -> None: + if isinstance(value, bool): + self._verbose = bool(value) + else: + self._verbose = False + + def indicators(self, *args, **kwargs) -> any: + """Returns the list of indicators that are available with Pandas Ta.""" + pd.DataFrame().ta.indicators(*args, **kwargs) + + def __repr__(self) -> str: + s = f"Watch(name='{self.name}', tickers[{len(self.tickers)}]='{', '.join(self.tickers)}', tf='{self.tf}', strategy[{self.strategy.total_ta()}]='{self.strategy.name}'" + if self.data is not None: + s += f", data[{len(self.data.keys())}])" + return s + return s + ")" \ No newline at end of file diff --git a/pandas_ta/core.py b/pandas_ta/core.py index f544cba..cd25d04 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- +from dataclasses import dataclass, field +from datetime import datetime from functools import wraps from multiprocessing import cpu_count, Pool from random import random from time import perf_counter +from typing import List import pandas as pd from pandas.core.base import PandasObject @@ -17,7 +20,7 @@ from pandas_ta.volatility import * from pandas_ta.volume import * from pandas_ta.utils import * -version = ".".join(("0", "1", "75b")) +version = ".".join(("0", "1", "76b")) def mp_worker(args): df, method, kwargs = args @@ -40,11 +43,91 @@ def finalize(method): return _wrapper +@dataclass +class Strategy: + """Strategy (Data)Class + A way to name and group your favorite indicators + + Args: + name (str): Some short memorable string. Note: Case-insensitive "All" is reserved. + ta (list of dicts): A list of dicts containing keyword arguments where "kind" is the indicator. + description (str): A more detailed description of what the Strategy tries to capture. Default: None + created (str): At datetime string of when it was created. Default: Automatically generated. *Subject to change* + + Example TA: + ta = [ + {"kind": "sma", "length": 200}, + {"kind": "sma", "close": "volume", "length": 50}, + {"kind": "bbands", "length": 20}, + {"kind": "rsi"}, + {"kind": "macd", "fast": 8, "slow": 21}, + {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOLUME"}, + ] + """ + name: str# = None # Required. + ta: List = field(default_factory=list) # Required. + description: str = None # Helpful. More descriptive version or notes or w/e. + created: str = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") # Optional. May change type later to datetime + last_run: str = None # Auto filled + run_time: str = None # Auto filled + + def __post_init__(self): + has_name = True + is_ta = False + required_args = ["[X] Strategy requires the following argument(s):"] + + name_is_str = isinstance(self.name, str) + ta_is_list = isinstance(self.ta, list) + + if self.name is None or not name_is_str: + required_args.append(" - name. Must be a string. Example: \"My TA\". Note: \"all\" is reserved.") + has_name != has_name + + if self.ta is None: + self.ta = None + elif self.ta is not None and ta_is_list and self.total_ta() > 0: + # Check that all elements of the list are dicts. + # Does not check if the dicts values are valid indicator kwargs + # User must check indicator documentation for all indicators args. + is_ta = all([isinstance(_, dict) and len(_.keys()) > 0 for _ in self.ta]) + else: + s = " - ta. Format is a list of dicts. Example: [{'kind': 'sma', 'length': 10}]" + s += "\n Check the indicator for the correct arguments if you receive this error." + required_args.append(s) + + if len(required_args) > 1: + [print(_) for _ in required_args] + return None + + def total_ta(self): + return len(self.ta) if self.ta is not None else 0 + +# All Default Strategy +AllStrategy = Strategy( + name="All", + description="All the indicators with their default settings. Pandas TA default.", + ta=None +) + +# Default (Example) Strategy. +CommonStrategy = Strategy( + name="Common Price and Volume SMAs", + description="Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.", + ta=[ + {"kind": "sma", "length": 10}, + {"kind": "sma", "length": 20}, + {"kind": "sma", "length": 50}, + {"kind": "sma", "length": 200}, + {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOL"} + ] +) + + class BasePandasObject(PandasObject): """Simple PandasObject Extension - Ensures the DataFrame is not empty and has columns. It would be a - sad Panda otherwise. + Ensures the DataFrame is not empty and has columns. + It would be a sad Panda otherwise. Args: df (pd.DataFrame): Extends Pandas DataFrame @@ -140,30 +223,37 @@ class AnalysisIndicators(BasePandasObject): _adjusted = None _mp = False - def __call__(self, kind=None, alias=None, timed=False, verbose=False, **kwargs): - try: - if isinstance(kind, str): - kind = kind.lower() - fn = getattr(self, kind) + def __call__( + self, + kind: str= None, + alias: str = None, + timed = False, + verbose = False, + **kwargs + ): + try: + if isinstance(kind, str): + kind = kind.lower() + fn = getattr(self, kind) - if timed: stime = perf_counter() + if timed: stime = perf_counter() - # Run the indicator - result = fn(**kwargs) # = getattr(self, kind)(**kwargs) + # Run the indicator + result = fn(**kwargs) # = getattr(self, kind)(**kwargs) - # Add an alias if passed - if alias: result.alias = f"{alias}" + # Add an alias if passed + if alias: result.alias = f"{alias}" - if timed: - result.timed = final_time(stime) - print(f"[+] {kind}:{alias + ':' if alias is not None else ''} {result.timed}") + if timed: + result.timed = final_time(stime) + alias_str = alias + ':' if alias is not None else '' + print(f"[+] {kind}:{alias_str} {result.timed}") - return result - else: - self.help() - - except: pass + return result + else: + self.help() + except: pass @property def adjusted(self) -> str: @@ -257,11 +347,11 @@ class AnalysisIndicators(BasePandasObject): match = [i for i, x in enumerate(matches) if x] # If found, awesome. Return it or return the 'series'. cols = ', '.join(list(df.columns)) - NOT_FOUND = f" [X] Ooops!!!: It's {series not in df.columns}, the series '{series}' not in {cols}" + NOT_FOUND = f"[X] Ooops!!!: It's {series not in df.columns}, the series '{series}' was not found in {cols}" return df.iloc[:,match[0]] if len(match) else print(NOT_FOUND) - def constants(self, append, lower_bound=-100, upper_bound=100, every=1): + def constants(self, append, lower_bound=-100, upper_bound=100, every=10): """Constants Useful for creating indicator levels or if you need some constant value @@ -332,58 +422,7 @@ class AnalysisIndicators(BasePandasObject): s = f"{header}\nTotal Indicators: {total_indicators}\n" print(f"{s}Abbreviations:\n {', '.join(ta_indicators)}") if total_indicators > 0 else print(s) - - # ALL Features - def _all(self, **kwargs): - """Appends by default all non-excluded indicators to the DataFrame. Used by ta.strategy(**kwargs)""" - cpus = cpu_count() - cores = int(kwargs.pop("cores", cpus)) - timed = kwargs.pop("timed", False) - verbose = kwargs.pop("verbose", False) - user_excluded = kwargs.pop("exclude", []) - append = kwargs.setdefault("append", True) - - excluded = ["above", "above_value", "below", "below_value", - "cross", "cross_value", "long_run", "short_run", "trend_return", "vp"] - excluded += user_excluded - - current_columns = len(self._df.columns) - indicators = self.indicators(as_list=True, exclude=excluded) - - print('[+] Strategy "All"') - if verbose: - print(f'[i] Indicators with the following arguments: {kwargs}') - print(f"[i] excluded[{len(excluded)}]: {', '.join(excluded)}") - - if timed: stime = perf_counter() - - if not self.mp: - # Display multiprocessing tip 10% of the time. - if random() < 0.1: - print(f"[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has {cpus} cores. Default: False") - - methods = [getattr(self, kind) for kind in indicators] - [f(**kwargs) for f in methods] - - else: - print(f"[i] multiprocessing: {cores} of {cpu_count()} cores") - pool = Pool(cores) - result = pool.imap_unordered( - mp_worker, ((self._df, ind, kwargs) for ind in indicators), cores - ) - pool.close() - pool.join() - - # Apply prefixes/suffixes and append to the DataFrame - for r in result: - self._add_prefix_suffix(r, **kwargs) - self._append(r, **kwargs) - - print(f"[i] total indicators: {len(indicators)}, columns added: {len(self._df.columns) - current_columns}") - print(f"[i] runtime: {final_time(stime)}\n") if timed else None - - - def strategy(self, **kwargs): + def strategy(self, *args, **kwargs): """Strategy Method An experimental method that by default runs all applicable indicators. @@ -393,17 +432,85 @@ class AnalysisIndicators(BasePandasObject): Args: name (str, optional): Default: 'all' exclude (list, optional): Default: []. List of indicator names to exclude. - verbose (bool): Default: False kwargs: (optional) Default: {}. Any indicator argument you want to modify. For example, length=20 or offset=-1 or high=df['High'] ... - """ - name = kwargs.pop("name", "all") - if name is None or name == "" or not isinstance(name, str): # Extra check - name = "all" - self._all(**kwargs) if name == "all" else None + cpus = cpu_count() + name = kwargs.pop("name", None) + if name is None or name.lower() == "all": + name = "All" + print(f"strat.kwargs: {kwargs}") + # removing before sending the rest of kwargs to the indicators + ta = kwargs.pop("ta", None) + mp = kwargs.pop("mp", False) + cores = int(kwargs.pop("cores", cpus)) + timed = kwargs.pop("timed", False) + verbose = kwargs.pop("verbose", False) + user_excluded = kwargs.pop("exclude", []) + kwargs["append"] = True + + is_all = True if name is None or name.lower() == "all" else False + has_ta = True if ta is not None else False + initial_column_count = len(self._df.columns) + + excluded = [] + excluded += user_excluded # Exclude user excluded ta if listed + + print(f'[+] Strategy "{name}"') if verbose else None + if is_all: + # Exclude utilities special functions + excluded += ["above", "above_value", "below", "below_value", "cross", "cross_value", "long_run", "short_run", "trend_return", "vp"] + ta = self.indicators(as_list=True, exclude=excluded) + else: + for kwds in ta: + kwds["append"] = True + + if verbose: + print(f'[i] Indicators with the following arguments: {kwargs}') + if len(excluded) > 0: + print(f"[i] Excluded[{len(excluded)}]: {', '.join(excluded)}") + + # Enable multiprocessing if user sets: mp=True + if mp: self.mp = not self.mp + + if self.mp: + # TODO: Fix for Custom Strategies + print(f"[i] Multiprocessing: {cores} of {cpu_count()} cores") + pool = Pool(cores) + + if timed: stime = perf_counter() + result = pool.imap_unordered( + mp_worker, ((self._df, ind, kwargs) for ind in ta), cores + ) + pool.close() + pool.join() + + # Apply prefixes/suffixes and appends indicator result to the DataFrame + for r in result: + self._add_prefix_suffix(r, **kwargs) + self._append(r, **kwargs) + if timed: ftime = final_time(stime) + + else: + # Display multiprocessing tip 10% of the time. + if random() < 0.1: + print(f"[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has {cpus} cores. Default: False") + + if timed: stime = perf_counter() + if is_all: + indicators = [getattr(self, kind) for kind in ta] + [f(**kwargs) for f in indicators] + else: + [getattr(self, kwds["kind"])(**kwds) for kwds in ta] + + if timed: ftime = final_time(stime) + + if verbose: + print(f"[i] Total indicators: {len(ta)}") + print(f"[i] Columns added: {len(self._df.columns) - initial_column_count}") + print(f"[i] Runtime: {ftime}") if timed else None # Candles diff --git a/pandas_ta/overlap/rma.py b/pandas_ta/overlap/rma.py index ddbc917..5ed998a 100644 --- a/pandas_ta/overlap/rma.py +++ b/pandas_ta/overlap/rma.py @@ -6,12 +6,11 @@ def rma(close, length=None, offset=None, **kwargs): # Validate Arguments close = verify_series(close) 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 offset = get_offset(offset) alpha = (1.0 / length) if length > 0 else 0.5 # Calculate Result - rma = close.ewm(alpha=alpha, min_periods=min_periods).mean() + rma = close.ewm(alpha=alpha).mean() # Offset if offset != 0: diff --git a/pandas_ta/utils.py b/pandas_ta/utils.py index 77be0e0..256002c 100644 --- a/pandas_ta/utils.py +++ b/pandas_ta/utils.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import math +from pathlib import Path from time import perf_counter import numpy as np @@ -9,7 +10,7 @@ from functools import reduce from operator import mul from sys import float_info as sflt -TRADING_DAYS_PER_YEAR = 250 +TRADING_DAYS_PER_YEAR = 251 TRADING_HOURS_PER_DAY = 6.5 MINUTES_PER_HOUR = 60 diff --git a/pandas_ta/volatility/bbands.py b/pandas_ta/volatility/bbands.py index a9d01c8..83b1005 100644 --- a/pandas_ta/volatility/bbands.py +++ b/pandas_ta/volatility/bbands.py @@ -44,15 +44,15 @@ def bbands(close, length=None, std=None, mamode=None, offset=None, **kwargs): upper.fillna(method=kwargs['fill_method'], inplace=True) # Name and Categorize it - lower.name = f"BBL_{length}" - mid.name = f"BBM_{length}" - upper.name = f"BBU_{length}" + lower.name = f"BBL_{length}_{std}" + mid.name = f"BBM_{length}_{std}" + upper.name = f"BBU_{length}_{std}" mid.category = upper.category = lower.category = 'volatility' # Prepare DataFrame to return data = {lower.name: lower, mid.name: mid, upper.name: upper} bbandsdf = DataFrame(data) - bbandsdf.name = f"BBANDS_{length}" + bbandsdf.name = f"BBANDS_{length}_{std}" bbandsdf.category = 'volatility' return bbandsdf diff --git a/tests/config.py b/tests/config.py index 3c4534f..dde7f77 100644 --- a/tests/config.py +++ b/tests/config.py @@ -6,7 +6,7 @@ VERBOSE = True ALERT = f"[!]" INFO = f"[i]" -CORRELATION = 'corr' #'sem' +CORRELATION = "corr" #"sem" CORRELATION_THRESHOLD = 0.99 # Less than 0.99 is undesirable sample_data = read_csv( diff --git a/tests/context.py b/tests/context.py index a237851..11f5534 100644 --- a/tests/context.py +++ b/tests/context.py @@ -1,5 +1,5 @@ import os import sys -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import pandas_ta \ No newline at end of file diff --git a/tests/test_indicator_candle.py b/tests/test_indicator_candle.py index 1297164..f0a58dc 100644 --- a/tests/test_indicator_candle.py +++ b/tests/test_indicator_candle.py @@ -14,11 +14,11 @@ class TestCandle(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestCandle(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data diff --git a/tests/test_indicator_candle_ext.py b/tests/test_indicator_candle_ext.py index 561a768..ebb3035 100644 --- a/tests/test_indicator_candle_ext.py +++ b/tests/test_indicator_candle_ext.py @@ -26,9 +26,9 @@ class TestCandleExtension(TestCase): def test_ha_ext(self): self.data.ta.ha(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-4:]), ['HA_open', 'HA_high', 'HA_low', 'HA_close']) + self.assertEqual(list(self.data.columns[-4:]), ["HA_open", "HA_high", "HA_low", "HA_close"]) def test_cdl_doji_ext(self): self.data.ta.cdl_doji(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CDL_DOJI_10_0.1') \ No newline at end of file + self.assertEqual(self.data.columns[-1], "CDL_DOJI_10_0.1") \ No newline at end of file diff --git a/tests/test_indicator_momentum.py b/tests/test_indicator_momentum.py index 6a9ad00..32ab89a 100644 --- a/tests/test_indicator_momentum.py +++ b/tests/test_indicator_momentum.py @@ -14,11 +14,11 @@ class TestMomentum(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestMomentum(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data @@ -62,12 +62,12 @@ class TestMomentum(TestCase): def test_ao(self): result = pandas_ta.ao(self.high, self.low) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'AO_5_34') + self.assertEqual(result.name, "AO_5_34") def test_apo(self): result = pandas_ta.apo(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'APO_12_26') + self.assertEqual(result.name, "APO_12_26") try: expected = tal.APO(self.close) @@ -82,12 +82,12 @@ class TestMomentum(TestCase): def test_bias(self): result = pandas_ta.bias(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'BIAS_SMA_26') + self.assertEqual(result.name, "BIAS_SMA_26") def test_bop(self): result = pandas_ta.bop(self.open, self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'BOP') + self.assertEqual(result.name, "BOP") try: expected = tal.BOP(self.open, self.high, self.low, self.close) @@ -102,12 +102,12 @@ class TestMomentum(TestCase): def test_brar(self): result = pandas_ta.brar(self.open, self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'BRAR_26') + self.assertEqual(result.name, "BRAR_26") def test_cci(self): result = pandas_ta.cci(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CCI_14_0.015') + self.assertEqual(result.name, "CCI_14_0.015") try: expected = tal.CCI(self.high, self.low, self.close) @@ -122,12 +122,12 @@ class TestMomentum(TestCase): def test_cg(self): result = pandas_ta.cg(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CG_10') + self.assertEqual(result.name, "CG_10") def test_cmo(self): result = pandas_ta.cmo(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CMO_14') + self.assertEqual(result.name, "CMO_14") try: expected = tal.CMO(self.close) @@ -142,45 +142,45 @@ class TestMomentum(TestCase): def test_coppock(self): result = pandas_ta.coppock(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'COPC_11_14_10') + self.assertEqual(result.name, "COPC_11_14_10") def test_fisher(self): result = pandas_ta.fisher(self.high, self.low) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'FISHERT_5') + self.assertEqual(result.name, "FISHERT_5") def test_inertia(self): result = pandas_ta.inertia(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'INERTIA_20_14') + self.assertEqual(result.name, "INERTIA_20_14") result = pandas_ta.inertia(self.close, self.high, self.low, refined=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'INERTIAr_20_14') + self.assertEqual(result.name, "INERTIAr_20_14") result = pandas_ta.inertia(self.close, self.high, self.low, thirds=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'INERTIAt_20_14') + self.assertEqual(result.name, "INERTIAt_20_14") def test_kdj(self): result = pandas_ta.kdj(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'KDJ_9_3') + self.assertEqual(result.name, "KDJ_9_3") def test_kst(self): result = pandas_ta.kst(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'KST_10_15_20_30_10_10_10_15_9') + self.assertEqual(result.name, "KST_10_15_20_30_10_10_10_15_9") def test_macd(self): result = pandas_ta.macd(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'MACD_12_26_9') + self.assertEqual(result.name, "MACD_12_26_9") try: expected = tal.MACD(self.close) - expecteddf = DataFrame({'MACD_12_26_9': expected[0], 'MACDh_12_26_9': expected[2], 'MACDs_12_26_9': expected[1]}) + expecteddf = DataFrame({"MACD_12_26_9": expected[0], "MACDh_12_26_9": expected[2], "MACDs_12_26_9": expected[1]}) pdt.assert_frame_equal(result, expecteddf) except AssertionError as ae: try: @@ -204,7 +204,7 @@ class TestMomentum(TestCase): def test_mom(self): result = pandas_ta.mom(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MOM_10') + self.assertEqual(result.name, "MOM_10") try: expected = tal.MOM(self.close) @@ -219,32 +219,32 @@ class TestMomentum(TestCase): def test_ppo(self): result = pandas_ta.ppo(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'PPO_12_26_9') + self.assertEqual(result.name, "PPO_12_26_9") try: expected = tal.PPO(self.close) - pdt.assert_series_equal(result['PPO_12_26_9'], expected, check_names=False) + pdt.assert_series_equal(result["PPO_12_26_9"], expected, check_names=False) except AssertionError as ae: try: - corr = pandas_ta.utils.df_error_analysis(result['PPO_12_26_9'], expected, col=CORRELATION) + corr = pandas_ta.utils.df_error_analysis(result["PPO_12_26_9"], expected, col=CORRELATION) self.assertGreater(corr, CORRELATION_THRESHOLD) except Exception as ex: - error_analysis(result['PPO_12_26_9'], CORRELATION, ex) + error_analysis(result["PPO_12_26_9"], CORRELATION, ex) def test_psl(self): result = pandas_ta.psl(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PSL_12') + self.assertEqual(result.name, "PSL_12") def test_pvo(self): result = pandas_ta.pvo(self.volume) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'PVO_12_26_9') + self.assertEqual(result.name, "PVO_12_26_9") def test_roc(self): result = pandas_ta.roc(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ROC_10') + self.assertEqual(result.name, "ROC_10") try: expected = tal.ROC(self.close) @@ -259,7 +259,7 @@ class TestMomentum(TestCase): def test_rsi(self): result = pandas_ta.rsi(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'RSI_14') + self.assertEqual(result.name, "RSI_14") try: expected = tal.RSI(self.close) @@ -274,37 +274,37 @@ class TestMomentum(TestCase): def test_rvgi(self): result = pandas_ta.rvgi(self.open, self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'RVGI_14_4') + self.assertEqual(result.name, "RVGI_14_4") def test_slope(self): result = pandas_ta.slope(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SLOPE_1') + self.assertEqual(result.name, "SLOPE_1") def test_slope_as_angle(self): result = pandas_ta.slope(self.close, as_angle=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ANGLEr_1') + self.assertEqual(result.name, "ANGLEr_1") def test_slope_as_angle_to_degrees(self): result = pandas_ta.slope(self.close, as_angle=True, to_degrees=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ANGLEd_1') + self.assertEqual(result.name, "ANGLEd_1") def test_stoch(self): result = pandas_ta.stoch(self.high, self.low, self.close, fast_k=14, slow_k=14, slow_d=14) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'STOCH_14_14_14') + self.assertEqual(result.name, "STOCH_14_14_14") self.assertEqual(len(result.columns), 4) result = pandas_ta.stoch(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'STOCH_14_5_3') + self.assertEqual(result.name, "STOCH_14_5_3") try: tal_stochf = tal.STOCHF(self.high, self.low, self.close) tal_stoch = tal.STOCH(self.high, self.low, self.close) - tal_stochdf = DataFrame({'STOCHF_14': tal_stochf[0], 'STOCHF_3': tal_stochf[1], 'STOCH_5': tal_stoch[0], 'STOCH_3': tal_stoch[1]}) + tal_stochdf = DataFrame({"STOCHF_14": tal_stochf[0], "STOCHF_3": tal_stochf[1], "STOCH_5": tal_stoch[0], "STOCH_3": tal_stoch[1]}) pdt.assert_frame_equal(result, tal_stochdf) except AssertionError as ae: try: @@ -334,17 +334,17 @@ class TestMomentum(TestCase): def test_trix(self): result = pandas_ta.trix(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'TRIX_30_9') + self.assertEqual(result.name, "TRIX_30_9") def test_tsi(self): result = pandas_ta.tsi(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'TSI_13_25') + self.assertEqual(result.name, "TSI_13_25") def test_uo(self): result = pandas_ta.uo(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'UO_7_14_28') + self.assertEqual(result.name, "UO_7_14_28") try: expected = tal.ULTOSC(self.high, self.low, self.close) @@ -359,7 +359,7 @@ class TestMomentum(TestCase): def test_willr(self): result = pandas_ta.willr(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'WILLR_14') + self.assertEqual(result.name, "WILLR_14") try: expected = tal.WILLR(self.high, self.low, self.close) diff --git a/tests/test_indicator_momentum_ext.py b/tests/test_indicator_momentum_ext.py index deabd83..87ec2db 100644 --- a/tests/test_indicator_momentum_ext.py +++ b/tests/test_indicator_momentum_ext.py @@ -26,152 +26,152 @@ class TestMomentumExtension(TestCase): def test_ao_ext(self): self.data.ta.ao(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'AO_5_34') + self.assertEqual(self.data.columns[-1], "AO_5_34") def test_apo_ext(self): self.data.ta.apo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'APO_12_26') + self.assertEqual(self.data.columns[-1], "APO_12_26") def test_bias_ext(self): self.data.ta.bias(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'BIAS_SMA_26') + self.assertEqual(self.data.columns[-1], "BIAS_SMA_26") def test_bop_ext(self): self.data.ta.bop(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'BOP') + self.assertEqual(self.data.columns[-1], "BOP") def test_brar_ext(self): self.data.ta.brar(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['AR_26', 'BR_26']) + self.assertEqual(list(self.data.columns[-2:]), ["AR_26", "BR_26"]) def test_cci_ext(self): self.data.ta.cci(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CCI_14_0.015') + self.assertEqual(self.data.columns[-1], "CCI_14_0.015") def test_cg_ext(self): self.data.ta.cg(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CG_10') + self.assertEqual(self.data.columns[-1], "CG_10") def test_cmo_ext(self): self.data.ta.cmo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CMO_14') + self.assertEqual(self.data.columns[-1], "CMO_14") def test_coppock_ext(self): self.data.ta.coppock(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'COPC_11_14_10') + self.assertEqual(self.data.columns[-1], "COPC_11_14_10") def test_fisher_ext(self): self.data.ta.fisher(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'FISHERT_5') + self.assertEqual(self.data.columns[-1], "FISHERT_5") def test_inertia_ext(self): self.data.ta.inertia(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'INERTIA_20_14') + self.assertEqual(self.data.columns[-1], "INERTIA_20_14") def test_inertia_refined_ext(self): self.data.ta.inertia(refined=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'INERTIAr_20_14') + self.assertEqual(self.data.columns[-1], "INERTIAr_20_14") def test_inertia_thirds_ext(self): self.data.ta.inertia(thirds=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'INERTIAt_20_14') + self.assertEqual(self.data.columns[-1], "INERTIAt_20_14") def test_kdj_ext(self): self.data.ta.kdj(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['K_9_3', 'D_9_3', 'J_9_3']) + self.assertEqual(list(self.data.columns[-3:]), ["K_9_3", "D_9_3", "J_9_3"]) def test_kst_ext(self): self.data.ta.kst(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['KST_10_15_20_30_10_10_10_15', 'KSTs_9']) + self.assertEqual(list(self.data.columns[-2:]), ["KST_10_15_20_30_10_10_10_15", "KSTs_9"]) def test_macd_ext(self): self.data.ta.macd(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['MACD_12_26_9', 'MACDh_12_26_9', 'MACDs_12_26_9']) + self.assertEqual(list(self.data.columns[-3:]), ["MACD_12_26_9", "MACDh_12_26_9", "MACDs_12_26_9"]) def test_mom_ext(self): self.data.ta.mom(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MOM_10') + self.assertEqual(self.data.columns[-1], "MOM_10") def test_ppo_ext(self): self.data.ta.ppo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['PPO_12_26_9', 'PPOh_12_26_9', 'PPOs_12_26_9']) + self.assertEqual(list(self.data.columns[-3:]), ["PPO_12_26_9", "PPOh_12_26_9", "PPOs_12_26_9"]) def test_psl_ext(self): self.data.ta.psl(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PSL_12') + self.assertEqual(self.data.columns[-1], "PSL_12") def test_pvo_ext(self): self.data.ta.pvo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['PVO_12_26_9', 'PVOh_12_26_9', 'PVOs_12_26_9']) + self.assertEqual(list(self.data.columns[-3:]), ["PVO_12_26_9", "PVOh_12_26_9", "PVOs_12_26_9"]) def test_roc_ext(self): self.data.ta.roc(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ROC_10') + self.assertEqual(self.data.columns[-1], "ROC_10") def test_rsi_ext(self): self.data.ta.rsi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'RSI_14') + self.assertEqual(self.data.columns[-1], "RSI_14") def test_rvgi_ext(self): self.data.ta.rvgi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['RVGI_14_4', 'RVGIs_14_4']) + self.assertEqual(list(self.data.columns[-2:]), ["RVGI_14_4", "RVGIs_14_4"]) def test_slope_ext(self): self.data.ta.slope(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SLOPE_1') + self.assertEqual(self.data.columns[-1], "SLOPE_1") self.data.ta.slope(append=True, as_angle=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ANGLEr_1') + self.assertEqual(self.data.columns[-1], "ANGLEr_1") self.data.ta.slope(append=True, as_angle=True, to_degrees=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ANGLEd_1') + self.assertEqual(self.data.columns[-1], "ANGLEd_1") def test_stoch_ext(self): self.data.ta.stoch(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-4:]), ['STOCHFk_14', 'STOCHFd_3', 'STOCHk_5', 'STOCHd_3']) + self.assertEqual(list(self.data.columns[-4:]), ["STOCHFk_14", "STOCHFd_3", "STOCHk_5", "STOCHd_3"]) def test_trix_ext(self): self.data.ta.trix(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['TRIX_30_9', 'TRIXs_30_9']) + self.assertEqual(list(self.data.columns[-2:]), ["TRIX_30_9", "TRIXs_30_9"]) def test_tsi_ext(self): self.data.ta.tsi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'TSI_13_25') + self.assertEqual(self.data.columns[-1], "TSI_13_25") def test_uo_ext(self): self.data.ta.uo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'UO_7_14_28') + self.assertEqual(self.data.columns[-1], "UO_7_14_28") def test_willr_ext(self): self.data.ta.willr(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'WILLR_14') + self.assertEqual(self.data.columns[-1], "WILLR_14") diff --git a/tests/test_indicator_overlap.py b/tests/test_indicator_overlap.py index 401c816..902b3d0 100644 --- a/tests/test_indicator_overlap.py +++ b/tests/test_indicator_overlap.py @@ -15,11 +15,11 @@ class TestOverlap(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -27,7 +27,7 @@ class TestOverlap(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data @@ -39,7 +39,7 @@ class TestOverlap(TestCase): def test_dema(self): result = pandas_ta.dema(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'DEMA_10') + self.assertEqual(result.name, "DEMA_10") try: expected = tal.DEMA(self.close, 10) @@ -54,7 +54,7 @@ class TestOverlap(TestCase): def test_ema(self): result = pandas_ta.ema(self.close, presma=False) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'EMA_10') + self.assertEqual(result.name, "EMA_10") try: expected = tal.EMA(self.close, 10) @@ -69,17 +69,17 @@ class TestOverlap(TestCase): def test_fwma(self): result = pandas_ta.fwma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'FWMA_10') + self.assertEqual(result.name, "FWMA_10") def test_hl2(self): result = pandas_ta.hl2(self.high, self.low) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'HL2') + self.assertEqual(result.name, "HL2") def test_hlc3(self): result = pandas_ta.hlc3(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'HLC3') + self.assertEqual(result.name, "HLC3") try: expected = tal.TYPPRICE(self.high, self.low, self.close) @@ -94,24 +94,24 @@ class TestOverlap(TestCase): def test_hma(self): result = pandas_ta.hma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'HMA_10') + self.assertEqual(result.name, "HMA_10") def test_kama(self): result = pandas_ta.kama(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'KAMA_10_2_30') + self.assertEqual(result.name, "KAMA_10_2_30") def test_ichimoku(self): ichimoku, span = pandas_ta.ichimoku(self.high, self.low, self.close) self.assertIsInstance(ichimoku, DataFrame) self.assertIsInstance(span, DataFrame) - self.assertEqual(ichimoku.name, 'ICHIMOKU_9_26_52') - self.assertEqual(span.name, 'ICHISPAN_9_26') + self.assertEqual(ichimoku.name, "ICHIMOKU_9_26_52") + self.assertEqual(span.name, "ICHISPAN_9_26") def test_linreg(self): result = pandas_ta.linreg(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LR_14') + self.assertEqual(result.name, "LR_14") try: expected = tal.LINEARREG(self.close) @@ -126,7 +126,7 @@ class TestOverlap(TestCase): def test_linreg_angle(self): result = pandas_ta.linreg(self.close, angle=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LRa_14') + self.assertEqual(result.name, "LRa_14") try: expected = tal.LINEARREG_ANGLE(self.close) @@ -141,7 +141,7 @@ class TestOverlap(TestCase): def test_linreg_intercept(self): result = pandas_ta.linreg(self.close, intercept=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LRb_14') + self.assertEqual(result.name, "LRb_14") try: expected = tal.LINEARREG_INTERCEPT(self.close) @@ -156,12 +156,12 @@ class TestOverlap(TestCase): def test_linreg_r(self): result = pandas_ta.linreg(self.close, r=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LRr_14') + self.assertEqual(result.name, "LRr_14") def test_linreg_slope(self): result = pandas_ta.linreg(self.close, slope=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LRm_14') + self.assertEqual(result.name, "LRm_14") try: expected = tal.LINEARREG_SLOPE(self.close) @@ -176,7 +176,7 @@ class TestOverlap(TestCase): def test_midpoint(self): result = pandas_ta.midpoint(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MIDPOINT_2') + self.assertEqual(result.name, "MIDPOINT_2") try: expected = tal.MIDPOINT(self.close, 2) @@ -191,7 +191,7 @@ class TestOverlap(TestCase): def test_midprice(self): result = pandas_ta.midprice(self.high, self.low) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MIDPRICE_2') + self.assertEqual(result.name, "MIDPRICE_2") try: expected = tal.MIDPRICE(self.high, self.low, 2) @@ -206,27 +206,27 @@ class TestOverlap(TestCase): def test_ohlc4(self): result = pandas_ta.ohlc4(self.open, self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'OHLC4') + self.assertEqual(result.name, "OHLC4") def test_pwma(self): result = pandas_ta.pwma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PWMA_10') + self.assertEqual(result.name, "PWMA_10") def test_rma(self): result = pandas_ta.rma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'RMA_10') + self.assertEqual(result.name, "RMA_10") def test_sinwma(self): result = pandas_ta.sinwma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SINWMA_14') + self.assertEqual(result.name, "SINWMA_14") def test_sma(self): result = pandas_ta.sma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SMA_10') + self.assertEqual(result.name, "SMA_10") try: expected = tal.SMA(self.close, 10) @@ -241,17 +241,17 @@ class TestOverlap(TestCase): def test_swma(self): result = pandas_ta.swma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SWMA_10') + self.assertEqual(result.name, "SWMA_10") def test_supertrend(self): result = pandas_ta.supertrend(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'SUPERT_7_3.0') + self.assertEqual(result.name, "SUPERT_7_3.0") def test_t3(self): result = pandas_ta.t3(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'T3_10_0.7') + self.assertEqual(result.name, "T3_10_0.7") try: expected = tal.T3(self.close, 10) @@ -266,7 +266,7 @@ class TestOverlap(TestCase): def test_tema(self): result = pandas_ta.tema(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'TEMA_10') + self.assertEqual(result.name, "TEMA_10") try: expected = tal.TEMA(self.close, 10) @@ -281,7 +281,7 @@ class TestOverlap(TestCase): def test_trima(self): result = pandas_ta.trima(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'TRIMA_10') + self.assertEqual(result.name, "TRIMA_10") try: expected = tal.TRIMA(self.close, 10) @@ -296,17 +296,17 @@ class TestOverlap(TestCase): def test_vwap(self): result = pandas_ta.vwap(self.high, self.low, self.close, self.volume) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'VWAP') + self.assertEqual(result.name, "VWAP") def test_vwma(self): result = pandas_ta.vwma(self.close, self.volume) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'VWMA_10') + self.assertEqual(result.name, "VWMA_10") def test_wcp(self): result = pandas_ta.wcp(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'WCP') + self.assertEqual(result.name, "WCP") try: expected = tal.WCLPRICE(self.high, self.low, self.close) @@ -321,7 +321,7 @@ class TestOverlap(TestCase): def test_wma(self): result = pandas_ta.wma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'WMA_10') + self.assertEqual(result.name, "WMA_10") try: expected = tal.WMA(self.close, 10) @@ -336,4 +336,4 @@ class TestOverlap(TestCase): def test_zlma(self): result = pandas_ta.zlma(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ZL_EMA_10') + self.assertEqual(result.name, "ZL_EMA_10") diff --git a/tests/test_indicator_overlap_ext.py b/tests/test_indicator_overlap_ext.py index 47ee84e..9ce1967 100644 --- a/tests/test_indicator_overlap_ext.py +++ b/tests/test_indicator_overlap_ext.py @@ -26,87 +26,87 @@ class TestOverlapExtension(TestCase): def test_dema_ext(self): self.data.ta.dema(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'DEMA_10') + self.assertEqual(self.data.columns[-1], "DEMA_10") def test_ema_ext(self): self.data.ta.ema(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'EMA_10') + self.assertEqual(self.data.columns[-1], "EMA_10") def test_fwma_ext(self): self.data.ta.fwma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'FWMA_10') + self.assertEqual(self.data.columns[-1], "FWMA_10") def test_hl2_ext(self): self.data.ta.hl2(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'HL2') + self.assertEqual(self.data.columns[-1], "HL2") def test_hlc3_ext(self): self.data.ta.hlc3(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'HLC3') + self.assertEqual(self.data.columns[-1], "HLC3") def test_hma_ext(self): self.data.ta.hma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'HMA_10') + self.assertEqual(self.data.columns[-1], "HMA_10") def test_kama_ext(self): self.data.ta.kama(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'KAMA_10_2_30') + self.assertEqual(self.data.columns[-1], "KAMA_10_2_30") def test_ichimoku_ext(self): self.data.ta.ichimoku(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-5:]), ['ISA_9', 'ISB_26', 'ITS_9', 'IKS_26', 'ICS_26']) + self.assertEqual(list(self.data.columns[-5:]), ["ISA_9", "ISB_26", "ITS_9", "IKS_26", "ICS_26"]) def test_linreg_ext(self): self.data.ta.linreg(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'LR_14') + self.assertEqual(self.data.columns[-1], "LR_14") def test_midpoint_ext(self): self.data.ta.midpoint(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MIDPOINT_2') + self.assertEqual(self.data.columns[-1], "MIDPOINT_2") def test_midprice_ext(self): self.data.ta.midprice(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MIDPRICE_2') + self.assertEqual(self.data.columns[-1], "MIDPRICE_2") def test_ohlc4_ext(self): self.data.ta.ohlc4(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'OHLC4') + self.assertEqual(self.data.columns[-1], "OHLC4") def test_pwma_ext(self): self.data.ta.pwma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PWMA_10') + self.assertEqual(self.data.columns[-1], "PWMA_10") def test_rma_ext(self): self.data.ta.rma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'RMA_10') + self.assertEqual(self.data.columns[-1], "RMA_10") def test_sinwma_ext(self): self.data.ta.sinwma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SINWMA_14') + self.assertEqual(self.data.columns[-1], "SINWMA_14") def test_sma_ext(self): self.data.ta.sma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SMA_10') + self.assertEqual(self.data.columns[-1], "SMA_10") def test_swma_ext(self): self.data.ta.swma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SWMA_10') + self.assertEqual(self.data.columns[-1], "SWMA_10") def test_supertrend_ext(self): self.data.ta.supertrend(append=True) @@ -116,39 +116,39 @@ class TestOverlapExtension(TestCase): def test_t3_ext(self): self.data.ta.t3(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'T3_10_0.7') + self.assertEqual(self.data.columns[-1], "T3_10_0.7") def test_tema_ext(self): self.data.ta.tema(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'TEMA_10') + self.assertEqual(self.data.columns[-1], "TEMA_10") def test_trima_ext(self): self.data.ta.trima(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'TRIMA_10') + self.assertEqual(self.data.columns[-1], "TRIMA_10") def test_vwap_ext(self): self.data.ta.vwap(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'VWAP') + self.assertEqual(self.data.columns[-1], "VWAP") def test_vwma_ext(self): self.data.ta.vwma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'VWMA_10') + self.assertEqual(self.data.columns[-1], "VWMA_10") def test_wcp_ext(self): self.data.ta.wcp(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'WCP') + self.assertEqual(self.data.columns[-1], "WCP") def test_wma_ext(self): self.data.ta.wma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'WMA_10') + self.assertEqual(self.data.columns[-1], "WMA_10") def test_zlma_ext(self): self.data.ta.zlma(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ZL_EMA_10') \ No newline at end of file + self.assertEqual(self.data.columns[-1], "ZL_EMA_10") \ No newline at end of file diff --git a/tests/test_indicator_performance.py b/tests/test_indicator_performance.py index 0fea777..d25e6ca 100644 --- a/tests/test_indicator_performance.py +++ b/tests/test_indicator_performance.py @@ -10,7 +10,7 @@ class TestPerformace(TestCase): @classmethod def setUpClass(cls): cls.data = sample_data - cls.close = cls.data['close'] + cls.close = cls.data["close"] cls.islong = cls.close > pandas_ta.sma(cls.close, length=50) @classmethod @@ -27,42 +27,42 @@ class TestPerformace(TestCase): def test_log_return(self): result = pandas_ta.log_return(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LOGRET_1') + self.assertEqual(result.name, "LOGRET_1") def test_cum_log_return(self): result = pandas_ta.log_return(self.close, cumulative=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CUMLOGRET_1') + self.assertEqual(result.name, "CUMLOGRET_1") def test_percent_return(self): result = pandas_ta.percent_return(self.close, cumulative=False) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PCTRET_1') + self.assertEqual(result.name, "PCTRET_1") def test_cum_percent_return(self): result = pandas_ta.percent_return(self.close, cumulative=True) - self.assertEqual(result.name, 'CUMPCTRET_1') + self.assertEqual(result.name, "CUMPCTRET_1") def test_log_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=True, cumulative=False) - self.assertEqual(result.name, 'LTR') + self.assertEqual(result.name, "LTR") def test_cum_log_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=True, cumulative=True) - self.assertEqual(result.name, 'CLTR') + self.assertEqual(result.name, "CLTR") def test_variable_cum_log_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=True, cumulative=True, variable=True) - self.assertEqual(result.name, 'CLTR') + self.assertEqual(result.name, "CLTR") def test_pct_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=False, cumulative=False) - self.assertEqual(result.name, 'PTR') + self.assertEqual(result.name, "PTR") def test_cum_pct_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=False, cumulative=True) - self.assertEqual(result.name, 'CPTR') + self.assertEqual(result.name, "CPTR") def test_variable_pct_log_trend_return(self): result = pandas_ta.trend_return(self.close, self.islong, log=False, cumulative=True, variable=True) - self.assertEqual(result.name, 'CPTR') \ No newline at end of file + self.assertEqual(result.name, "CPTR") \ No newline at end of file diff --git a/tests/test_indicator_performance_ext.py b/tests/test_indicator_performance_ext.py index 8ea3e59..af3a0e3 100644 --- a/tests/test_indicator_performance_ext.py +++ b/tests/test_indicator_performance_ext.py @@ -10,7 +10,7 @@ class TestPerformaceExtension(TestCase): @classmethod def setUpClass(cls): cls.data = sample_data - cls.islong = cls.data['close'] > pandas_ta.sma(cls.data['close'], length=50) + cls.islong = cls.data["close"] > pandas_ta.sma(cls.data["close"], length=50) @classmethod def tearDownClass(cls): @@ -25,39 +25,39 @@ class TestPerformaceExtension(TestCase): def test_log_return_ext(self): self.data.ta.log_return(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'LOGRET_1') + self.assertEqual(self.data.columns[-1], "LOGRET_1") def test_cum_log_return_ext(self): self.data.ta.log_return(append=True, cumulative=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CUMLOGRET_1') + self.assertEqual(self.data.columns[-1], "CUMLOGRET_1") def test_percent_return_ext(self): self.data.ta.percent_return(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PCTRET_1') + self.assertEqual(self.data.columns[-1], "PCTRET_1") def test_cum_percent_return_ext(self): self.data.ta.percent_return(append=True, cumulative=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CUMPCTRET_1') + self.assertEqual(self.data.columns[-1], "CUMPCTRET_1") def test_log_trend_return_ext(self): self.data.ta.trend_return(trend=self.islong, log=True, cumulative=False, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'LTR') + self.assertEqual(self.data.columns[-1], "LTR") def test_cum_log_trend_return_ext(self): self.data.ta.trend_return(trend=self.islong, log=True, cumulative=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CLTR') + self.assertEqual(self.data.columns[-1], "CLTR") def test_pct_trend_return_ext(self): self.data.ta.trend_return(trend=self.islong, log=False, cumulative=False, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PTR') + self.assertEqual(self.data.columns[-1], "PTR") def test_cum_pct_trend_return_ext(self): self.data.ta.trend_return(trend=self.islong, log=False, cumulative=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CPTR') \ No newline at end of file + self.assertEqual(self.data.columns[-1], "CPTR") \ No newline at end of file diff --git a/tests/test_indicator_statistics.py b/tests/test_indicator_statistics.py index 57f2adc..5e58dce 100644 --- a/tests/test_indicator_statistics.py +++ b/tests/test_indicator_statistics.py @@ -14,11 +14,11 @@ class TestStatistics(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestStatistics(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data @@ -36,37 +36,37 @@ class TestStatistics(TestCase): def test_entropy(self): result = pandas_ta.entropy(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ENTP_10') + self.assertEqual(result.name, "ENTP_10") def test_kurtosis(self): result = pandas_ta.kurtosis(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'KURT_30') + self.assertEqual(result.name, "KURT_30") def test_mad(self): result = pandas_ta.mad(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MAD_30') + self.assertEqual(result.name, "MAD_30") def test_median(self): result = pandas_ta.median(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MEDIAN_30') + self.assertEqual(result.name, "MEDIAN_30") def test_quantile(self): result = pandas_ta.quantile(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'QTL_30_0.5') + self.assertEqual(result.name, "QTL_30_0.5") def test_skew(self): result = pandas_ta.skew(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SKEW_30') + self.assertEqual(result.name, "SKEW_30") def test_stdev(self): result = pandas_ta.stdev(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'STDEV_30') + self.assertEqual(result.name, "STDEV_30") try: expected = tal.STDDEV(self.close, 30) @@ -81,7 +81,7 @@ class TestStatistics(TestCase): def test_variance(self): result = pandas_ta.variance(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'VAR_30') + self.assertEqual(result.name, "VAR_30") try: expected = tal.VAR(self.close, 30) @@ -96,4 +96,4 @@ class TestStatistics(TestCase): def test_zscore(self): result = pandas_ta.zscore(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'Z_30') \ No newline at end of file + self.assertEqual(result.name, "Z_30") \ No newline at end of file diff --git a/tests/test_indicator_statistics_ext.py b/tests/test_indicator_statistics_ext.py index 4a3727c..33b33ab 100644 --- a/tests/test_indicator_statistics_ext.py +++ b/tests/test_indicator_statistics_ext.py @@ -26,39 +26,39 @@ class TestStatisticsExtension(TestCase): def test_entropy_ext(self): self.data.ta.entropy(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ENTP_10') + self.assertEqual(self.data.columns[-1], "ENTP_10") def test_kurtosis_ext(self): self.data.ta.kurtosis(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'KURT_30') + self.assertEqual(self.data.columns[-1], "KURT_30") def test_mad_ext(self): self.data.ta.mad(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MAD_30') + self.assertEqual(self.data.columns[-1], "MAD_30") def test_median_ext(self): self.data.ta.median(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MEDIAN_30') + self.assertEqual(self.data.columns[-1], "MEDIAN_30") def test_quantile_ext(self): self.data.ta.quantile(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'QTL_30_0.5') + self.assertEqual(self.data.columns[-1], "QTL_30_0.5") def test_skew_ext(self): self.data.ta.skew(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SKEW_30') + self.assertEqual(self.data.columns[-1], "SKEW_30") def test_stdev_ext(self): self.data.ta.stdev(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'STDEV_30') + self.assertEqual(self.data.columns[-1], "STDEV_30") def test_variance_ext(self): self.data.ta.variance(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'VAR_30') + self.assertEqual(self.data.columns[-1], "VAR_30") diff --git a/tests/test_indicator_trend.py b/tests/test_indicator_trend.py index 90d04ff..f6a7152 100644 --- a/tests/test_indicator_trend.py +++ b/tests/test_indicator_trend.py @@ -14,11 +14,11 @@ class TestTrend(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestTrend(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data @@ -37,7 +37,7 @@ class TestTrend(TestCase): def test_adx(self): result = pandas_ta.adx(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'ADX_14') + self.assertEqual(result.name, "ADX_14") try: expected = tal.ADX(self.high, self.low, self.close) @@ -52,16 +52,16 @@ class TestTrend(TestCase): def test_amat(self): result = pandas_ta.amat(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'AMAT_EMA_8_21_2') + self.assertEqual(result.name, "AMAT_EMA_8_21_2") def test_aroon(self): result = pandas_ta.aroon(self.high, self.low) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'AROON_14') + self.assertEqual(result.name, "AROON_14") try: expected = tal.AROON(self.high, self.low) - expecteddf = DataFrame({'AROOND_14': expected[0], 'AROONU_14': expected[1]}) + expecteddf = DataFrame({"AROOND_14": expected[0], "AROONU_14": expected[1]}) pdt.assert_frame_equal(result, expecteddf) except AssertionError as ae: try: @@ -92,44 +92,44 @@ class TestTrend(TestCase): def test_chop(self): result = pandas_ta.chop(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CHOP_14_1_100') + self.assertEqual(result.name, "CHOP_14_1_100") def test_cksp(self): result = pandas_ta.cksp(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'CKSP_10_1_9') + self.assertEqual(result.name, "CKSP_10_1_9") def test_decreasing(self): result = pandas_ta.decreasing(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'DEC_1') + self.assertEqual(result.name, "DEC_1") def test_dpo(self): result = pandas_ta.dpo(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'DPO_20') + self.assertEqual(result.name, "DPO_20") def test_increasing(self): result = pandas_ta.increasing(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'INC_1') + self.assertEqual(result.name, "INC_1") def test_linear_decay(self): result = pandas_ta.linear_decay(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LDECAY_5') + self.assertEqual(result.name, "LDECAY_5") def test_long_run(self): result = pandas_ta.long_run(self.close, self.open) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'LR_2') + self.assertEqual(result.name, "LR_2") def test_psar(self): result = pandas_ta.psar(self.high, self.low) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'PSAR_0.02_0.2') + self.assertEqual(result.name, "PSAR_0.02_0.2") - # Combine Long and Short SAR's into one SAR value + # Combine Long and Short SAR"s into one SAR value psar = result[result.columns[:2]].fillna(0) psar = psar[psar.columns[0]] + psar[psar.columns[1]] psar.name = result.name @@ -147,14 +147,14 @@ class TestTrend(TestCase): def test_qstick(self): result = pandas_ta.qstick(self.open, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'QS_10') + self.assertEqual(result.name, "QS_10") def test_short_run(self): result = pandas_ta.short_run(self.close, self.open) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'SR_2') + self.assertEqual(result.name, "SR_2") def test_vortex(self): result = pandas_ta.vortex(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'VTX_14') \ No newline at end of file + self.assertEqual(result.name, "VTX_14") \ No newline at end of file diff --git a/tests/test_indicator_trend_ext.py b/tests/test_indicator_trend_ext.py index 5f06337..a3df15f 100644 --- a/tests/test_indicator_trend_ext.py +++ b/tests/test_indicator_trend_ext.py @@ -26,79 +26,79 @@ class TestTrendExtension(TestCase): def test_adx_ext(self): self.data.ta.adx(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['ADX_14', 'DMP_14', 'DMN_14']) + self.assertEqual(list(self.data.columns[-3:]), ["ADX_14", "DMP_14", "DMN_14"]) def test_amat_ext(self): self.data.ta.amat(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['AMAT_LR_2', 'AMAT_SR_2']) + self.assertEqual(list(self.data.columns[-2:]), ["AMAT_LR_2", "AMAT_SR_2"]) def test_aroon_ext(self): self.data.ta.aroon(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['AROOND_14', 'AROONU_14', 'AROONOSC_14']) + self.assertEqual(list(self.data.columns[-3:]), ["AROOND_14", "AROONU_14", "AROONOSC_14"]) def test_chop_ext(self): self.data.ta.chop(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CHOP_14_1_100') + self.assertEqual(self.data.columns[-1], "CHOP_14_1_100") def test_cksp_ext(self): self.data.ta.cksp(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CKSPs_10_1_9') + self.assertEqual(self.data.columns[-1], "CKSPs_10_1_9") def test_decreasing_ext(self): self.data.ta.decreasing(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'DEC_1') + self.assertEqual(self.data.columns[-1], "DEC_1") def test_dpo_ext(self): self.data.ta.dpo(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'DPO_20') + self.assertEqual(self.data.columns[-1], "DPO_20") def test_increasing_ext(self): self.data.ta.increasing(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'INC_1') + self.assertEqual(self.data.columns[-1], "INC_1") def test_linear_decay_ext(self): self.data.ta.linear_decay(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'LDECAY_5') + self.assertEqual(self.data.columns[-1], "LDECAY_5") def test_long_run_ext(self): # Nothing passed, return self self.assertEqual(self.data.ta.long_run(append=True).shape, self.data.shape) - fast = self.data.ta.ema('close', 8) - slow = self.data.ta.ema('close', 21) + fast = self.data.ta.ema("close", 8) + slow = self.data.ta.ema("close", 21) self.data.ta.long_run(fast, slow, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'LR_2') + self.assertEqual(self.data.columns[-1], "LR_2") def test_psar_ext(self): self.data.ta.psar(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-4:]), ['PSARl_0.02_0.2', 'PSARs_0.02_0.2', 'PSARaf_0.02_0.2', 'PSARr_0.02_0.2']) + self.assertEqual(list(self.data.columns[-4:]), ["PSARl_0.02_0.2", "PSARs_0.02_0.2", "PSARaf_0.02_0.2", "PSARr_0.02_0.2"]) def test_qstick_ext(self): self.data.ta.qstick(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'QS_10') + self.assertEqual(self.data.columns[-1], "QS_10") def test_short_run_ext(self): # Nothing passed, return self self.assertEqual(self.data.ta.short_run(append=True).shape, self.data.shape) - fast = self.data.ta.ema('close', 8) - slow = self.data.ta.ema('close', 21) + fast = self.data.ta.ema("close", 8) + slow = self.data.ta.ema("close", 21) self.data.ta.short_run(fast, slow, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'SR_2') + self.assertEqual(self.data.columns[-1], "SR_2") def test_vortext_ext(self): self.data.ta.vortex(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-2:]), ['VTXP_14', 'VTXM_14']) + self.assertEqual(list(self.data.columns[-2:]), ["VTXP_14", "VTXM_14"]) diff --git a/tests/test_indicator_volatility.py b/tests/test_indicator_volatility.py index 15585cb..a06296f 100644 --- a/tests/test_indicator_volatility.py +++ b/tests/test_indicator_volatility.py @@ -14,11 +14,11 @@ class TestVolatility(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestVolatility(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume + if hasattr(cls, "volume"): del cls.volume del cls.data @@ -37,17 +37,17 @@ class TestVolatility(TestCase): def test_aberration(self): result = pandas_ta.aberration(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'ABER_5_15') + self.assertEqual(result.name, "ABER_5_15") def test_accbands(self): result = pandas_ta.accbands(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'ACCBANDS_20') + self.assertEqual(result.name, "ACCBANDS_20") def test_atr(self): result = pandas_ta.atr(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ATR_14') + self.assertEqual(result.name, "ATR_14") try: expected = tal.ATR(self.high, self.low, self.close) @@ -62,11 +62,11 @@ class TestVolatility(TestCase): def test_bbands(self): result = pandas_ta.bbands(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'BBANDS_5') + self.assertEqual(result.name, "BBANDS_5_2.0") try: expected = tal.BBANDS(self.close) - expecteddf = DataFrame({'BBL_5': expected[0], 'BBM_5': expected[1], 'BBU_5': expected[2]}) + expecteddf = DataFrame({"BBL_5_2.0": expected[0], "BBM_5_2.0": expected[1], "BBU_5_2.0": expected[2]}) pdt.assert_frame_equal(result, expecteddf) except AssertionError as ae: try: @@ -90,27 +90,27 @@ class TestVolatility(TestCase): def test_donchian(self): result = pandas_ta.donchian(self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'DC_10_20') + self.assertEqual(result.name, "DC_10_20") result = pandas_ta.donchian(self.close, lower_length=20, upper_length=5) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'DC_20_5') + self.assertEqual(result.name, "DC_20_5") def test_kc(self): result = pandas_ta.kc(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'KC_20') + self.assertEqual(result.name, "KC_20") def test_massi(self): result = pandas_ta.massi(self.high, self.low) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MASSI_9_25') + self.assertEqual(result.name, "MASSI_9_25") def test_natr(self): result = pandas_ta.natr(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'NATR_14') + self.assertEqual(result.name, "NATR_14") try: expected = tal.NATR(self.high, self.low, self.close) @@ -125,25 +125,25 @@ class TestVolatility(TestCase): def test_pdist(self): result = pandas_ta.pdist(self.open, self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PDIST') + self.assertEqual(result.name, "PDIST") def test_rvi(self): result = pandas_ta.rvi(self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'RVI_14') + self.assertEqual(result.name, "RVI_14") result = pandas_ta.rvi(self.close, self.high, self.low, refined=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'RVIr_14') + self.assertEqual(result.name, "RVIr_14") result = pandas_ta.rvi(self.close, self.high, self.low, thirds=True) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'RVIt_14') + self.assertEqual(result.name, "RVIt_14") def test_true_range(self): result = pandas_ta.true_range(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'TRUERANGE_1') + self.assertEqual(result.name, "TRUERANGE_1") try: expected = tal.TRANGE(self.high, self.low, self.close) diff --git a/tests/test_indicator_volatility_ext.py b/tests/test_indicator_volatility_ext.py index 14d743f..78d5a94 100644 --- a/tests/test_indicator_volatility_ext.py +++ b/tests/test_indicator_volatility_ext.py @@ -23,64 +23,64 @@ class TestVolatilityExtension(TestCase): def test_aberration_ext(self): self.data.ta.aberration(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-4:]), ['ABER_ZG_5_15', 'ABER_SG_5_15', 'ABER_XG_5_15', 'ABER_ATR_5_15']) + self.assertEqual(list(self.data.columns[-4:]), ["ABER_ZG_5_15", "ABER_SG_5_15", "ABER_XG_5_15", "ABER_ATR_5_15"]) def test_accbands_ext(self): self.data.ta.accbands(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['ACCBL_20', 'ACCBM_20', 'ACCBU_20']) + self.assertEqual(list(self.data.columns[-3:]), ["ACCBL_20", "ACCBM_20", "ACCBU_20"]) def test_atr_ext(self): self.data.ta.atr(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ATR_14') + self.assertEqual(self.data.columns[-1], "ATR_14") def test_bbands_ext(self): self.data.ta.bbands(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['BBL_5', 'BBM_5', 'BBU_5']) + self.assertEqual(list(self.data.columns[-3:]), ["BBL_5_2.0", "BBM_5_2.0", "BBU_5_2.0"]) def test_donchian_ext(self): self.data.ta.donchian(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['DCL_10_20', 'DCM_10_20', 'DCU_10_20']) + self.assertEqual(list(self.data.columns[-3:]), ["DCL_10_20", "DCM_10_20", "DCU_10_20"]) def test_kc_ext(self): self.data.ta.kc(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ['KCL_20', 'KCB_20', 'KCU_20']) + self.assertEqual(list(self.data.columns[-3:]), ["KCL_20", "KCB_20", "KCU_20"]) def test_massi_ext(self): self.data.ta.massi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MASSI_9_25') + self.assertEqual(self.data.columns[-1], "MASSI_9_25") def test_natr_ext(self): self.data.ta.natr(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'NATR_14') + self.assertEqual(self.data.columns[-1], "NATR_14") def test_pdist_ext(self): self.data.ta.pdist(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PDIST') + self.assertEqual(self.data.columns[-1], "PDIST") def test_rvi_ext(self): self.data.ta.rvi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'RVI_14') + self.assertEqual(self.data.columns[-1], "RVI_14") def test_rvi_refined_ext(self): self.data.ta.rvi(refined=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'RVIr_14') + self.assertEqual(self.data.columns[-1], "RVIr_14") def test_rvi_thirds_ext(self): self.data.ta.rvi(thirds=True, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'RVIt_14') + self.assertEqual(self.data.columns[-1], "RVIt_14") def test_true_range_ext(self): self.data.ta.true_range(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'TRUERANGE_1') \ No newline at end of file + self.assertEqual(self.data.columns[-1], "TRUERANGE_1") \ No newline at end of file diff --git a/tests/test_indicator_volume.py b/tests/test_indicator_volume.py index 9e30d6d..7dc1b47 100644 --- a/tests/test_indicator_volume.py +++ b/tests/test_indicator_volume.py @@ -14,11 +14,11 @@ class TestVolume(TestCase): def setUpClass(cls): cls.data = sample_data cls.data.columns = cls.data.columns.str.lower() - cls.open = cls.data['open'] - cls.high = cls.data['high'] - cls.low = cls.data['low'] - cls.close = cls.data['close'] - if 'volume' in cls.data.columns: cls.volume_ = cls.data['volume'] + cls.open = cls.data["open"] + cls.high = cls.data["high"] + cls.low = cls.data["low"] + cls.close = cls.data["close"] + if "volume" in cls.data.columns: cls.volume_ = cls.data["volume"] @classmethod def tearDownClass(cls): @@ -26,7 +26,7 @@ class TestVolume(TestCase): del cls.high del cls.low del cls.close - if hasattr(cls, 'volume'): del cls.volume_ + if hasattr(cls, "volume"): del cls.volume_ del cls.data @@ -37,7 +37,7 @@ class TestVolume(TestCase): def test_ad(self): result = pandas_ta.ad(self.high, self.low, self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'AD') + self.assertEqual(result.name, "AD") try: expected = tal.AD(self.high, self.low, self.close, self.volume_) @@ -52,12 +52,12 @@ class TestVolume(TestCase): def test_ad_open(self): result = pandas_ta.ad(self.high, self.low, self.close, self.volume_, self.open) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ADo') + self.assertEqual(result.name, "ADo") def test_adosc(self): result = pandas_ta.adosc(self.high, self.low, self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'ADOSC_3_10') + self.assertEqual(result.name, "ADOSC_3_10") try: expected = tal.ADOSC(self.high, self.low, self.close, self.volume_) @@ -72,27 +72,27 @@ class TestVolume(TestCase): def test_aobv(self): result = pandas_ta.aobv(self.close, self.volume_) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'AOBV_EMA_2_4_2_2_2') + self.assertEqual(result.name, "AOBV_EMA_2_4_2_2_2") def test_cmf(self): result = pandas_ta.cmf(self.high, self.low, self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CMF_20') + self.assertEqual(result.name, "CMF_20") def test_efi(self): result = pandas_ta.efi(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'EFI_13') + self.assertEqual(result.name, "EFI_13") def test_eom(self): result = pandas_ta.eom(self.high, self.low, self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'EOM_14_100000000') + self.assertEqual(result.name, "EOM_14_100000000") def test_mfi(self): result = pandas_ta.mfi(self.high, self.low, self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'MFI_14') + self.assertEqual(result.name, "MFI_14") try: expected = tal.MFI(self.high, self.low, self.close, self.volume_) @@ -107,12 +107,12 @@ class TestVolume(TestCase): def test_nvi(self): result = pandas_ta.nvi(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'NVI_1') + self.assertEqual(result.name, "NVI_1") def test_obv(self): result = pandas_ta.obv(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'OBV') + self.assertEqual(result.name, "OBV") try: expected = tal.OBV(self.close, self.volume_) @@ -127,19 +127,19 @@ class TestVolume(TestCase): def test_pvi(self): result = pandas_ta.pvi(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PVI_1') + self.assertEqual(result.name, "PVI_1") def test_pvol(self): result = pandas_ta.pvol(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PVOL') + self.assertEqual(result.name, "PVOL") def test_pvt(self): result = pandas_ta.pvt(self.close, self.volume_) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'PVT') + self.assertEqual(result.name, "PVT") def test_vp(self): result = pandas_ta.vp(self.close, self.volume_) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'VP_10') + self.assertEqual(result.name, "VP_10") diff --git a/tests/test_indicator_volume_ext.py b/tests/test_indicator_volume_ext.py index da7efac..2f4e99d 100644 --- a/tests/test_indicator_volume_ext.py +++ b/tests/test_indicator_volume_ext.py @@ -10,7 +10,7 @@ class TestVolumeExtension(TestCase): @classmethod def setUpClass(cls): cls.data = sample_data - cls.open = cls.data['open'] + cls.open = cls.data["open"] @classmethod def tearDownClass(cls): @@ -25,49 +25,49 @@ class TestVolumeExtension(TestCase): def test_ad_ext(self): self.data.ta.ad(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'AD') + self.assertEqual(self.data.columns[-1], "AD") def test_ad_open_ext(self): self.data.ta.ad(open_=self.open, append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ADo') + self.assertEqual(self.data.columns[-1], "ADo") def test_adosc_ext(self): self.data.ta.adosc(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'ADOSC_3_10') + self.assertEqual(self.data.columns[-1], "ADOSC_3_10") def test_aobv_ext(self): self.data.ta.aobv(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-7:]), ['OBV', 'OBV_min_2', 'OBV_max_2', 'OBV_EMA_2', 'OBV_EMA_4', 'AOBV_LR_2', 'AOBV_SR_2']) - # Remove 'OBV' so it does not interfere with test_obv_ext() - self.data.drop('OBV', axis=1, inplace=True) + self.assertEqual(list(self.data.columns[-7:]), ["OBV", "OBV_min_2", "OBV_max_2", "OBV_EMA_2", "OBV_EMA_4", "AOBV_LR_2", "AOBV_SR_2"]) + # Remove "OBV" so it does not interfere with test_obv_ext() + self.data.drop("OBV", axis=1, inplace=True) def test_cmf_ext(self): self.data.ta.cmf(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CMF_20') + self.assertEqual(self.data.columns[-1], "CMF_20") def test_efi_ext(self): self.data.ta.efi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'EFI_13') + self.assertEqual(self.data.columns[-1], "EFI_13") def test_eom_ext(self): self.data.ta.eom(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'EOM_14_100000000') + self.assertEqual(self.data.columns[-1], "EOM_14_100000000") def test_mfi_ext(self): self.data.ta.mfi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'MFI_14') + self.assertEqual(self.data.columns[-1], "MFI_14") def test_nvi_ext(self): self.data.ta.nvi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'NVI_1') + self.assertEqual(self.data.columns[-1], "NVI_1") # print(f"\nNVI: {self.data.columns[-1]}") # print(f"NVI: {self.data.columns}") @@ -76,24 +76,24 @@ class TestVolumeExtension(TestCase): self.assertIsInstance(self.data, DataFrame) # print(f"\nOBV: {self.data.columns[-1]}") # print(f"OBV: {self.data.columns}") - self.assertEqual(self.data.columns[-1], 'OBV') + self.assertEqual(self.data.columns[-1], "OBV") def test_pvi_ext(self): self.data.ta.pvi(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PVI_1') + self.assertEqual(self.data.columns[-1], "PVI_1") def test_pvol_ext(self): self.data.ta.pvol(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PVOL') + self.assertEqual(self.data.columns[-1], "PVOL") def test_pvt_ext(self): self.data.ta.pvt(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'PVT') + self.assertEqual(self.data.columns[-1], "PVT") def test_vp_ext(self): result = self.data.ta.vp() self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, 'VP_10') \ No newline at end of file + self.assertEqual(result.name, "VP_10") \ No newline at end of file From 1d484af53e17745a5b1037e2c993216b8acbd06e Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Tue, 21 Jul 2020 10:57:28 -0700 Subject: [PATCH 04/10] MAINT YuvalWein cmf documentation fix --- pandas_ta/volume/cmf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas_ta/volume/cmf.py b/pandas_ta/volume/cmf.py index f259a53..47e35d2 100644 --- a/pandas_ta/volume/cmf.py +++ b/pandas_ta/volume/cmf.py @@ -69,7 +69,7 @@ Args: low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's - open (pd.Series): Series of 'open's. Default: None + open_ (pd.Series): Series of 'open's. Default: None length (int): The short period. Default: 20 offset (int): How many periods to offset the result. Default: 0 From 7bdd5009a56bfae1a83d2cda9b872b42e6b64097 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Tue, 21 Jul 2020 11:23:28 -0700 Subject: [PATCH 05/10] BUG Donchian input fixed #73 --- pandas_ta/core.py | 7 ++++--- pandas_ta/volatility/donchian.py | 25 ++++++++++++++----------- tests/test_indicator_volatility.py | 6 +++--- tests/test_indicator_volatility_ext.py | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/pandas_ta/core.py b/pandas_ta/core.py index cd25d04..7937af1 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -1280,10 +1280,11 @@ class AnalysisIndicators(BasePandasObject): return result @finalize - def donchian(self, close=None, length=None, offset=None, **kwargs): - close = self._get_column(close, 'close') + def donchian(self, high=None, low=None, lower_length=None, upper_length=None, offset=None, **kwargs): + high = self._get_column(high, 'high') + low = self._get_column(low, 'low') - result = donchian(close=close, length=length, offset=offset, **kwargs) + result = donchian(high=high, low=low, lower_length=lower_length, upper_length=upper_length, offset=offset, **kwargs) return result @finalize diff --git a/pandas_ta/volatility/donchian.py b/pandas_ta/volatility/donchian.py index 7e892a9..cad0777 100644 --- a/pandas_ta/volatility/donchian.py +++ b/pandas_ta/volatility/donchian.py @@ -2,19 +2,20 @@ from pandas import DataFrame from ..utils import get_offset, verify_series -def donchian(close, lower_length=None, upper_length=None, offset=None, **kwargs): +def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwargs): """Indicator: Donchian Channels (DC)""" # Validate arguments - close = verify_series(close) - lower_length = int(lower_length) if lower_length and lower_length > 0 else 10 + high = verify_series(high) + 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 offset = get_offset(offset) # Calculate Result - lower = close.rolling(lower_length, min_periods=lower_min_periods).min() - upper = close.rolling(upper_length, min_periods=upper_min_periods).max() + lower = low.rolling(lower_length, min_periods=lower_min_periods).min() + upper = high.rolling(upper_length, min_periods=upper_min_periods).max() mid = 0.5 * (lower + upper) # Handle fills @@ -60,15 +61,17 @@ Sources: Calculation: Default Inputs: - length=20 - LOWER = close.rolling(length).min() - UPPER = close.rolling(length).max() + lower_length=upper_length=20 + LOWER = low.rolling(lower_length).min() + UPPER = high.rolling(upper_length).max() MID = 0.5 * (LOWER + UPPER) Args: - close (pd.Series): Series of 'close's - length (int): The short period. Default: 20 - offset (int): How many periods to offset the result. Default: 0 + high (pd.Series): Series of 'high's + low (pd.Series): Series of 'low's + lower_length (int): The short period. Default: 20 + upper_length (int): The short period. Default: 20 + offset (int): How many periods to offset the result. Default: 0 Kwargs: fillna (value, optional): pd.DataFrame.fillna(value) diff --git a/tests/test_indicator_volatility.py b/tests/test_indicator_volatility.py index a06296f..a526c44 100644 --- a/tests/test_indicator_volatility.py +++ b/tests/test_indicator_volatility.py @@ -88,11 +88,11 @@ class TestVolatility(TestCase): error_analysis(result.iloc[:,2], CORRELATION, ex, newline=False) def test_donchian(self): - result = pandas_ta.donchian(self.close) + result = pandas_ta.donchian(self.high, self.low) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, "DC_10_20") + self.assertEqual(result.name, "DC_20_20") - result = pandas_ta.donchian(self.close, lower_length=20, upper_length=5) + result = pandas_ta.donchian(self.high, self.low, lower_length=20, upper_length=5) self.assertIsInstance(result, DataFrame) self.assertEqual(result.name, "DC_20_5") diff --git a/tests/test_indicator_volatility_ext.py b/tests/test_indicator_volatility_ext.py index 78d5a94..ae828ee 100644 --- a/tests/test_indicator_volatility_ext.py +++ b/tests/test_indicator_volatility_ext.py @@ -43,7 +43,7 @@ class TestVolatilityExtension(TestCase): def test_donchian_ext(self): self.data.ta.donchian(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-3:]), ["DCL_10_20", "DCM_10_20", "DCU_10_20"]) + self.assertEqual(list(self.data.columns[-3:]), ["DCL_20_20", "DCM_20_20", "DCU_20_20"]) def test_kc_ext(self): self.data.ta.kc(append=True) From 40594c49d1229a1a8d2eab7c534368ed88e329d0 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Wed, 22 Jul 2020 17:08:45 -0700 Subject: [PATCH 06/10] ENH resolved #72 MAINT refactor candles directory --- README.md | 22 +- examples/PandasTA_Strategy_Examples.ipynb | 599 +++++++++++----------- examples/watchlist.py | 2 +- pandas_ta/__init__.py | 2 + pandas_ta/candles/__init__.py | 1 - pandas_ta/candles/candle.py | 14 - pandas_ta/candles/cdl_doji.py | 5 +- pandas_ta/core.py | 60 ++- pandas_ta/utils.py | 32 +- pandas_ta/volume/vp.py | 4 +- 10 files changed, 379 insertions(+), 362 deletions(-) delete mode 100644 pandas_ta/candles/candle.py diff --git a/README.md b/README.md index 5166135..3e87140 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ CommonStrategy = Strategy( ) # Your Custom Strategy or whatever your TA composition -CustomStrategy = Strategy( +CustomStrategy = ta.Strategy( name="Momo and Volatility", description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20", ta=[ @@ -187,12 +187,22 @@ df.ta.strategy(fast=10, slow=50, verbose=True) df.columns ``` -### Running a Custom Strategy +### Running a Builtin, Categorical or Custom Strategy While the _Strategy_ Class it has not been fully integrated with the __strategy__ method yet. For now, the following can be done to implement your Custom Strategy. ```python -# Create a Strategy -CustomStrategy = Strategy( +# Running the builtin CommonStrategy as mentioned above +df.ta.strategy(ta.CommonStrategy) + +# Available categories +ta.categories + +# Running a Categorical Strategy only requires the Category name +df.ta.strategy(name="Momentum") # Default values for all Momentum indicators +df.ta.strategy(name="overlap", length=27) # Override all 'length' attributes + +# Or create your own Custom Strategy +CustomStrategy = ta.Strategy( name="Momo and Volatility", description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20", ta=[ @@ -204,8 +214,10 @@ CustomStrategy = Strategy( {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOLUME"}, ] ) +# To run "Custom Strategy" +df.ta.strategy(CustomStrategy) -#Running it requires the name and ta properties +# Or pass in the name and ta atributes of the "Custom Strategy" df.ta.strategy(name=CustomStrategy.name, ta=CustomStrategy.ta) # Sanity check. Make sure all the columns are there diff --git a/examples/PandasTA_Strategy_Examples.ipynb b/examples/PandasTA_Strategy_Examples.ipynb index acd857a..d327050 100644 --- a/examples/PandasTA_Strategy_Examples.ipynb +++ b/examples/PandasTA_Strategy_Examples.ipynb @@ -67,7 +67,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# (Builtin) Examples" + "# Builtin Examples" ] }, { @@ -88,7 +88,7 @@ "text": [ "name = All\n", "description = All the indicators with their default settings. Pandas TA default.\n", - "created = 07/21/2020, 10:42:07\n", + "created = 07/22/2020, 17:02:37\n", "ta = None\n" ] } @@ -119,7 +119,7 @@ "text": [ "name = Common Price and Volume SMAs\n", "description = Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.\n", - "created = 07/21/2020, 10:42:07\n", + "created = 07/22/2020, 17:02:37\n", "ta = [{'kind': 'sma', 'length': 10}, {'kind': 'sma', 'length': 20}, {'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOL'}]\n" ] } @@ -161,7 +161,7 @@ { "data": { "text/plain": [ - "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 4, @@ -189,7 +189,7 @@ { "data": { "text/plain": [ - "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 5, @@ -217,7 +217,7 @@ { "data": { "text/plain": [ - "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 6, @@ -392,7 +392,7 @@ " | list of weak references to the object (if defined)\n", " | \n", " | data\n", - " | When not None, it contains a dictionary of DataFrames keyed by ticker.\n", + " | When not None, it contains a dictionary of DataFrames keyed by ticker. data = {\"SPY\": pd.DataFrame, ...}\n", " | \n", " | name\n", " | The name of the Watchlist. Default: \"Watchlist: {Watchlist.tickers}\".\n", @@ -439,16 +439,14 @@ "[!] Loading All: SPY, IWM\n", "\n", "[+] Downloading['D']: SPY\n", - "strat.kwargs: {'ta': None, 'verbose': True, 'timed': False}\n", - "[+] Strategy \"All\"\n", + "[+] Strategy: All\n", "[i] Indicators with the following arguments: {'append': True}\n", "[i] Excluded[10]: above, above_value, below, below_value, cross, cross_value, long_run, short_run, trend_return, vp\n", "[i] Total indicators: 101\n", "[i] Columns added: 152\n", "\n", "[+] Downloading['D']: IWM\n", - "strat.kwargs: {'ta': None, 'verbose': True, 'timed': False}\n", - "[+] Strategy \"All\"\n", + "[+] Strategy: All\n", "[i] Indicators with the following arguments: {'append': True}\n", "[i] Excluded[10]: above, above_value, below, below_value, cross, cross_value, long_run, short_run, trend_return, vp\n", "[i] Total indicators: 101\n", @@ -478,11 +476,11 @@ " 1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", " 1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.862000 \n", - " 2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 317.127333 \n", " 2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", " 2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", - " 2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 320.670000 \n", + " 2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 320.673333 \n", + " 2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 322.353333 \n", + " 2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 323.313333 \n", " \n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", " date ... \n", @@ -492,11 +490,11 @@ " 1999-11-04 NaN NaN NaN NaN ... \n", " 1999-11-05 NaN NaN NaN NaN ... \n", " ... ... ... ... ... ... \n", - " 2020-07-14 322.137987 309.586013 6.275987 297.831277 ... \n", - " 2020-07-15 323.259587 310.995079 6.132254 298.823299 ... \n", " 2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", " 2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", - " 2020-07-20 326.292790 315.047210 5.622790 300.906776 ... \n", + " 2020-07-20 326.296123 315.050544 5.622790 300.906776 ... \n", + " 2020-07-21 327.800604 316.906063 5.447270 301.895656 ... \n", + " 2020-07-22 328.577452 318.049214 5.264119 302.558926 ... \n", " \n", " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", " date \n", @@ -506,11 +504,11 @@ " 1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", " 1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-14 34.050046 0.942619 0.851435 153.185166 314.416051 317.400000 \n", - " 2020-07-15 36.858968 1.134936 0.764889 153.210321 315.765307 321.502500 \n", " 2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", " 2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", - " 2020-07-20 45.052926 1.223611 0.623952 153.259707 318.469407 323.572500 \n", + " 2020-07-20 45.091757 1.223611 0.623952 153.261035 318.474591 323.597500 \n", + " 2020-07-21 46.469833 1.211493 0.661493 153.277972 319.600245 325.222500 \n", + " 2020-07-22 50.919143 1.153997 0.689436 153.292643 320.677611 326.355000 \n", " \n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", " date \n", @@ -520,13 +518,13 @@ " 1999-11-04 NaN NaN NaN NaN \n", " 1999-11-05 NaN NaN NaN NaN \n", " ... ... ... ... ... \n", - " 2020-07-14 -15.937763 315.716545 317.221127 1.224000 \n", - " 2020-07-15 -4.935711 317.073818 319.420922 1.583443 \n", " 2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", " 2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", - " 2020-07-20 -4.035664 320.087455 323.196899 1.674079 \n", + " 2020-07-20 -3.801032 320.096545 323.215081 1.680556 \n", + " 2020-07-21 -10.750280 321.291636 324.115975 1.747819 \n", + " 2020-07-22 -2.058111 322.618909 325.718525 1.900614 \n", " \n", - " [5212 rows x 157 columns],\n", + " [5214 rows x 157 columns],\n", " 'IWM': open high low close volume ABER_ZG_5_15 \\\n", " date \n", " 2000-05-26 91.06 91.44 90.63 91.44 37400.0 NaN \n", @@ -535,11 +533,11 @@ " 2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN \n", " 2000-06-02 101.70 102.40 101.70 102.40 14700.0 96.091333 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-14 139.43 141.98 138.64 141.83 27919300.0 140.631333 \n", - " 2020-07-15 145.42 147.78 144.79 147.03 40619500.0 141.702000 \n", " 2020-07-16 146.11 146.67 144.88 146.16 30386200.0 142.972000 \n", " 2020-07-17 146.68 147.59 145.51 146.59 20632700.0 144.200000 \n", - " 2020-07-20 146.12 146.85 145.15 145.91 18335300.0 145.157333 \n", + " 2020-07-20 146.12 146.85 145.15 145.96 19581700.0 145.160667 \n", + " 2020-07-21 147.47 149.16 147.20 148.03 24467100.0 146.623333 \n", + " 2020-07-22 147.09 148.67 147.03 148.11 19080800.0 146.904000 \n", " \n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", " date ... \n", @@ -549,11 +547,11 @@ " 2000-06-01 NaN NaN NaN NaN ... \n", " 2000-06-02 NaN NaN NaN NaN ... \n", " ... ... ... ... ... ... \n", - " 2020-07-14 144.933519 136.329148 4.302186 131.931151 ... \n", - " 2020-07-15 146.114040 137.289960 4.412040 132.378072 ... \n", " 2020-07-16 147.233237 138.710763 4.261237 132.740467 ... \n", " 2020-07-17 148.315822 140.084178 4.115822 133.164616 ... \n", - " 2020-07-20 149.112100 141.202567 3.954767 133.720436 ... \n", + " 2020-07-20 149.115433 141.205900 3.954767 133.720436 ... \n", + " 2020-07-21 150.527782 142.718884 3.904449 134.312288 ... \n", + " 2020-07-22 150.657486 143.150514 3.753486 134.567792 ... \n", " \n", " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", " date \n", @@ -563,11 +561,11 @@ " 2000-06-01 NaN NaN NaN 93.322938 NaN 97.2600 \n", " 2000-06-02 NaN NaN NaN 94.592497 NaN 102.2250 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-14 14.580918 0.912088 0.993442 88.330119 141.551704 141.0700 \n", - " 2020-07-15 15.260700 1.069504 0.907148 88.343103 141.954972 146.6575 \n", " 2020-07-16 15.532794 1.067613 0.898394 88.352707 142.400151 145.9675 \n", " 2020-07-17 15.940380 1.090399 0.874371 88.359302 142.830341 146.5700 \n", - " 2020-07-20 14.336087 1.085970 0.934221 88.365101 143.084383 145.9550 \n", + " 2020-07-20 14.347839 1.085970 0.934221 88.365497 143.089584 145.9800 \n", + " 2020-07-21 11.515402 1.030077 0.909147 88.373523 143.813948 148.1050 \n", + " 2020-07-22 10.497958 1.013525 0.935595 88.379761 144.438962 147.9800 \n", " \n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", " date \n", @@ -577,13 +575,13 @@ " 2000-06-01 NaN NaN NaN NaN \n", " 2000-06-02 NaN NaN NaN NaN \n", " ... ... ... ... ... \n", - " 2020-07-14 -41.126461 141.123273 140.481012 -0.140980 \n", - " 2020-07-15 -6.527415 142.121636 143.119010 1.145187 \n", " 2020-07-16 -14.348981 142.891818 144.553735 0.902863 \n", " 2020-07-17 -11.142322 143.661273 146.209420 0.982248 \n", - " 2020-07-20 -17.741935 144.230909 146.896798 0.893748 \n", + " 2020-07-20 -17.267552 144.240000 146.914980 0.906142 \n", + " 2020-07-21 -9.479866 145.149091 147.299529 1.671168 \n", + " 2020-07-22 -8.808725 145.942909 147.801433 1.797089 \n", " \n", - " [5068 rows x 157 columns]}" + " [5070 rows x 157 columns]}" ] }, "execution_count": 12, @@ -821,54 +819,6 @@ " ...\n", " \n", " \n", - " 2020-07-14\n", - " 313.3000\n", - " 319.7600\n", - " 312.0000\n", - " 318.9200\n", - " 92791800.0\n", - " 315.862000\n", - " 322.137987\n", - " 309.586013\n", - " 6.275987\n", - " 297.831277\n", - " ...\n", - " 34.050046\n", - " 0.942619\n", - " 0.851435\n", - " 153.185166\n", - " 314.416051\n", - " 317.400000\n", - " -15.937763\n", - " 315.716545\n", - " 317.221127\n", - " 1.224000\n", - " \n", - " \n", - " 2020-07-15\n", - " 322.4100\n", - " 323.0400\n", - " 319.2700\n", - " 321.8500\n", - " 86921500.0\n", - " 317.127333\n", - " 323.259587\n", - " 310.995079\n", - " 6.132254\n", - " 298.823299\n", - " ...\n", - " 36.858968\n", - " 1.134936\n", - " 0.764889\n", - " 153.210321\n", - " 315.765307\n", - " 321.502500\n", - " -4.935711\n", - " 317.073818\n", - " 319.420922\n", - " 1.583443\n", - " \n", - " \n", " 2020-07-16\n", " 319.7900\n", " 321.2800\n", @@ -921,28 +871,76 @@ " 321.4300\n", " 325.1300\n", " 320.6200\n", - " 324.2700\n", - " 51616200.0\n", - " 320.670000\n", - " 326.292790\n", - " 315.047210\n", + " 324.3200\n", + " 56150200.0\n", + " 320.673333\n", + " 326.296123\n", + " 315.050544\n", " 5.622790\n", " 300.906776\n", " ...\n", - " 45.052926\n", + " 45.091757\n", " 1.223611\n", " 0.623952\n", - " 153.259707\n", - " 318.469407\n", - " 323.572500\n", - " -4.035664\n", - " 320.087455\n", - " 323.196899\n", - " 1.674079\n", + " 153.261035\n", + " 318.474591\n", + " 323.597500\n", + " -3.801032\n", + " 320.096545\n", + " 323.215081\n", + " 1.680556\n", + " \n", + " \n", + " 2020-07-21\n", + " 326.4500\n", + " 326.9300\n", + " 323.9400\n", + " 325.0100\n", + " 57245300.0\n", + " 322.353333\n", + " 327.800604\n", + " 316.906063\n", + " 5.447270\n", + " 301.895656\n", + " ...\n", + " 46.469833\n", + " 1.211493\n", + " 0.661493\n", + " 153.277972\n", + " 319.600245\n", + " 325.222500\n", + " -10.750280\n", + " 321.291636\n", + " 324.115975\n", + " 1.747819\n", + " \n", + " \n", + " 2020-07-22\n", + " 324.6200\n", + " 327.2000\n", + " 324.5000\n", + " 326.8600\n", + " 49338600.0\n", + " 323.313333\n", + " 328.577452\n", + " 318.049214\n", + " 5.264119\n", + " 302.558926\n", + " ...\n", + " 50.919143\n", + " 1.153997\n", + " 0.689436\n", + " 153.292643\n", + " 320.677611\n", + " 326.355000\n", + " -2.058111\n", + " 322.618909\n", + " 325.718525\n", + " 1.900614\n", " \n", " \n", "\n", - "

5212 rows × 157 columns

\n", + "

5214 rows × 157 columns

\n", "" ], "text/plain": [ @@ -954,11 +952,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", "... ... ... ... ... ... ... \n", - "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.862000 \n", - "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 317.127333 \n", "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 320.670000 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 320.673333 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 322.353333 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 323.313333 \n", "\n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", "date ... \n", @@ -968,11 +966,11 @@ "1999-11-04 NaN NaN NaN NaN ... \n", "1999-11-05 NaN NaN NaN NaN ... \n", "... ... ... ... ... ... \n", - "2020-07-14 322.137987 309.586013 6.275987 297.831277 ... \n", - "2020-07-15 323.259587 310.995079 6.132254 298.823299 ... \n", "2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", "2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", - "2020-07-20 326.292790 315.047210 5.622790 300.906776 ... \n", + "2020-07-20 326.296123 315.050544 5.622790 300.906776 ... \n", + "2020-07-21 327.800604 316.906063 5.447270 301.895656 ... \n", + "2020-07-22 328.577452 318.049214 5.264119 302.558926 ... \n", "\n", " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", "date \n", @@ -982,11 +980,11 @@ "1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", "1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", "... ... ... ... ... ... ... \n", - "2020-07-14 34.050046 0.942619 0.851435 153.185166 314.416051 317.400000 \n", - "2020-07-15 36.858968 1.134936 0.764889 153.210321 315.765307 321.502500 \n", "2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", "2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", - "2020-07-20 45.052926 1.223611 0.623952 153.259707 318.469407 323.572500 \n", + "2020-07-20 45.091757 1.223611 0.623952 153.261035 318.474591 323.597500 \n", + "2020-07-21 46.469833 1.211493 0.661493 153.277972 319.600245 325.222500 \n", + "2020-07-22 50.919143 1.153997 0.689436 153.292643 320.677611 326.355000 \n", "\n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", "date \n", @@ -996,13 +994,13 @@ "1999-11-04 NaN NaN NaN NaN \n", "1999-11-05 NaN NaN NaN NaN \n", "... ... ... ... ... \n", - "2020-07-14 -15.937763 315.716545 317.221127 1.224000 \n", - "2020-07-15 -4.935711 317.073818 319.420922 1.583443 \n", "2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", "2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", - "2020-07-20 -4.035664 320.087455 323.196899 1.674079 \n", + "2020-07-20 -3.801032 320.096545 323.215081 1.680556 \n", + "2020-07-21 -10.750280 321.291636 324.115975 1.747819 \n", + "2020-07-22 -2.058111 322.618909 325.718525 1.900614 \n", "\n", - "[5212 rows x 157 columns]" + "[5214 rows x 157 columns]" ] }, "execution_count": 13, @@ -1043,7 +1041,7 @@ { "data": { "text/plain": [ - "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 14, @@ -1068,7 +1066,7 @@ "text": [ "\n", "[i] Loaded['D']: IWM_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}]}\n" + "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" ] }, { @@ -1173,26 +1171,6 @@ " ...\n", " \n", " \n", - " 2020-07-14\n", - " 139.43\n", - " 141.98\n", - " 138.64\n", - " 141.83\n", - " 27919300.0\n", - " 138.1012\n", - " 145.99795\n", - " \n", - " \n", - " 2020-07-15\n", - " 145.42\n", - " 147.78\n", - " 144.79\n", - " 147.03\n", - " 40619500.0\n", - " 138.5282\n", - " 145.97730\n", - " \n", - " \n", " 2020-07-16\n", " 146.11\n", " 146.67\n", @@ -1217,14 +1195,34 @@ " 146.12\n", " 146.85\n", " 145.15\n", - " 145.91\n", - " 18335300.0\n", - " 139.7052\n", - " 145.93580\n", + " 145.96\n", + " 19581700.0\n", + " 139.7062\n", + " 145.93605\n", + " \n", + " \n", + " 2020-07-21\n", + " 147.47\n", + " 149.16\n", + " 147.20\n", + " 148.03\n", + " 24467100.0\n", + " 140.0196\n", + " 145.93750\n", + " \n", + " \n", + " 2020-07-22\n", + " 147.09\n", + " 148.67\n", + " 147.03\n", + " 148.11\n", + " 19080800.0\n", + " 140.3478\n", + " 145.93235\n", " \n", " \n", "\n", - "

5068 rows × 7 columns

\n", + "

5070 rows × 7 columns

\n", "" ], "text/plain": [ @@ -1236,13 +1234,13 @@ "2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN NaN\n", "2000-06-02 101.70 102.40 101.70 102.40 14700.0 NaN NaN\n", "... ... ... ... ... ... ... ...\n", - "2020-07-14 139.43 141.98 138.64 141.83 27919300.0 138.1012 145.99795\n", - "2020-07-15 145.42 147.78 144.79 147.03 40619500.0 138.5282 145.97730\n", "2020-07-16 146.11 146.67 144.88 146.16 30386200.0 138.9184 145.95140\n", "2020-07-17 146.68 147.59 145.51 146.59 20632700.0 139.3358 145.94250\n", - "2020-07-20 146.12 146.85 145.15 145.91 18335300.0 139.7052 145.93580\n", + "2020-07-20 146.12 146.85 145.15 145.96 19581700.0 139.7062 145.93605\n", + "2020-07-21 147.47 149.16 147.20 148.03 24467100.0 140.0196 145.93750\n", + "2020-07-22 147.09 148.67 147.03 148.11 19080800.0 140.3478 145.93235\n", "\n", - "[5068 rows x 7 columns]" + "[5070 rows x 7 columns]" ] }, "execution_count": 15, @@ -1269,7 +1267,7 @@ { "data": { "text/plain": [ - "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 16, @@ -1294,7 +1292,7 @@ "text": [ "\n", "[i] Loaded['D']: SPY_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}]}\n" + "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" ] }, { @@ -1362,7 +1360,7 @@ " NaN\n", " NaN\n", " 0.000000\n", - " 0\n", + " 1\n", " NaN\n", " NaN\n", " \n", @@ -1378,7 +1376,7 @@ " -0.007172\n", " 0.000000\n", " NaN\n", - " 0\n", + " 1\n", " NaN\n", " NaN\n", " \n", @@ -1394,7 +1392,7 @@ " -0.000461\n", " 6.263520\n", " NaN\n", - " 0\n", + " 1\n", " NaN\n", " NaN\n", " \n", @@ -1410,7 +1408,7 @@ " 0.007120\n", " 12.913259\n", " NaN\n", - " 0\n", + " 1\n", " NaN\n", " NaN\n", " \n", @@ -1426,7 +1424,7 @@ " 0.016915\n", " 20.761745\n", " NaN\n", - " 0\n", + " 1\n", " NaN\n", " NaN\n", " \n", @@ -1447,38 +1445,6 @@ " ...\n", " \n", " \n", - " 2020-07-14\n", - " 313.3000\n", - " 319.7600\n", - " 312.0000\n", - " 318.9200\n", - " 92791800.0\n", - " 315.153455\n", - " 311.736418\n", - " 0.855507\n", - " 59.173765\n", - " 321.864382\n", - " -1\n", - " NaN\n", - " 321.864382\n", - " \n", - " \n", - " 2020-07-15\n", - " 322.4100\n", - " 323.0400\n", - " 319.2700\n", - " 321.8500\n", - " 86921500.0\n", - " 316.641576\n", - " 312.655835\n", - " 0.864653\n", - " 61.428658\n", - " 321.864382\n", - " -1\n", - " NaN\n", - " 321.864382\n", - " \n", - " \n", " 2020-07-16\n", " 319.7900\n", " 321.2800\n", @@ -1515,20 +1481,52 @@ " 321.4300\n", " 325.1300\n", " 320.6200\n", - " 324.2700\n", - " 51616200.0\n", - " 319.772209\n", - " 315.071905\n", - " 0.872144\n", - " 63.010941\n", + " 324.3200\n", + " 56150200.0\n", + " 319.783320\n", + " 315.076450\n", + " 0.872298\n", + " 63.049858\n", " 307.890439\n", " 1\n", " 307.890439\n", " NaN\n", " \n", + " \n", + " 2020-07-21\n", + " 326.4500\n", + " 326.9300\n", + " 323.9400\n", + " 325.0100\n", + " 57245300.0\n", + " 320.944805\n", + " 315.979500\n", + " 0.874423\n", + " 63.615869\n", + " 311.309662\n", + " 1\n", + " 311.309662\n", + " NaN\n", + " \n", + " \n", + " 2020-07-22\n", + " 324.6200\n", + " 327.2000\n", + " 324.5000\n", + " 326.8600\n", + " 49338600.0\n", + " 322.259293\n", + " 316.968636\n", + " 0.880099\n", + " 65.149441\n", + " 312.585425\n", + " 1\n", + " 312.585425\n", + " NaN\n", + " \n", " \n", "\n", - "

5212 rows × 13 columns

\n", + "

5214 rows × 13 columns

\n", "" ], "text/plain": [ @@ -1540,25 +1538,25 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 315.153455 \n", - "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 316.641576 \n", "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 317.563448 \n", "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 318.487126 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 319.772209 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 319.783320 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 320.944805 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 322.259293 \n", "\n", " EMA_21 CUMLOGRET_1 RSI_14 SUPERT_7_3.0 SUPERTd_7_3.0 \\\n", "date \n", - "1999-11-01 NaN NaN NaN 0.000000 0 \n", - "1999-11-02 NaN -0.007172 0.000000 NaN 0 \n", - "1999-11-03 NaN -0.000461 6.263520 NaN 0 \n", - "1999-11-04 NaN 0.007120 12.913259 NaN 0 \n", - "1999-11-05 NaN 0.016915 20.761745 NaN 0 \n", + "1999-11-01 NaN NaN NaN 0.000000 1 \n", + "1999-11-02 NaN -0.007172 0.000000 NaN 1 \n", + "1999-11-03 NaN -0.000461 6.263520 NaN 1 \n", + "1999-11-04 NaN 0.007120 12.913259 NaN 1 \n", + "1999-11-05 NaN 0.016915 20.761745 NaN 1 \n", "... ... ... ... ... ... \n", - "2020-07-14 311.736418 0.855507 59.173765 321.864382 -1 \n", - "2020-07-15 312.655835 0.864653 61.428658 321.864382 -1 \n", "2020-07-16 313.395304 0.861354 60.141122 321.864382 -1 \n", "2020-07-17 314.152095 0.864249 60.911280 321.864382 -1 \n", - "2020-07-20 315.071905 0.872144 63.010941 307.890439 1 \n", + "2020-07-20 315.076450 0.872298 63.049858 307.890439 1 \n", + "2020-07-21 315.979500 0.874423 63.615869 311.309662 1 \n", + "2020-07-22 316.968636 0.880099 65.149441 312.585425 1 \n", "\n", " SUPERTl_7_3.0 SUPERTs_7_3.0 \n", "date \n", @@ -1568,13 +1566,13 @@ "1999-11-04 NaN NaN \n", "1999-11-05 NaN NaN \n", "... ... ... \n", - "2020-07-14 NaN 321.864382 \n", - "2020-07-15 NaN 321.864382 \n", "2020-07-16 NaN 321.864382 \n", "2020-07-17 NaN 321.864382 \n", "2020-07-20 307.890439 NaN \n", + "2020-07-21 311.309662 NaN \n", + "2020-07-22 312.585425 NaN \n", "\n", - "[5212 rows x 13 columns]" + "[5214 rows x 13 columns]" ] }, "execution_count": 17, @@ -1601,7 +1599,7 @@ { "data": { "text/plain": [ - "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 18, @@ -1626,7 +1624,6 @@ "text": [ "\n", "[i] Loaded['D']: IWM_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'percet_return'}]}\n", "[X] Oops! 'AnalysisIndicators' object has no attribute 'percet_return'\n" ] } @@ -1669,7 +1666,7 @@ { "data": { "text/plain": [ - "Strategy(name='Volume MAs and Price MA chain', ta=[{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}], description=None, created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='Volume MAs and Price MA chain', ta=[{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 20, @@ -1722,9 +1719,7 @@ "output_type": "stream", "text": [ "\n", - "[i] Loaded['D']: SPY_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}]}\n", - "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" + "[i] Loaded['D']: SPY_D.csv\n" ] }, { @@ -1845,30 +1840,6 @@ " ...\n", " \n", " \n", - " 2020-07-14\n", - " 313.3000\n", - " 319.7600\n", - " 312.0000\n", - " 318.9200\n", - " 92791800.0\n", - " 8.361704e+07\n", - " 89676222.80\n", - " 316.336980\n", - " 315.670761\n", - " \n", - " \n", - " 2020-07-15\n", - " 322.4100\n", - " 323.0400\n", - " 319.2700\n", - " 321.8500\n", - " 86921500.0\n", - " 8.421785e+07\n", - " 87169880.45\n", - " 318.174653\n", - " 316.635348\n", - " \n", - " \n", " 2020-07-16\n", " 319.7900\n", " 321.2800\n", @@ -1897,16 +1868,40 @@ " 321.4300\n", " 325.1300\n", " 320.6200\n", - " 324.2700\n", - " 51616200.0\n", - " 7.172025e+07\n", - " 80774361.40\n", - " 321.381749\n", - " 320.052445\n", + " 324.3200\n", + " 56150200.0\n", + " 7.254462e+07\n", + " 81001061.40\n", + " 321.398416\n", + " 320.058000\n", + " \n", + " \n", + " 2020-07-21\n", + " 326.4500\n", + " 326.9300\n", + " 323.9400\n", + " 325.0100\n", + " 57245300.0\n", + " 6.976292e+07\n", + " 80162965.80\n", + " 322.602277\n", + " 321.307000\n", + " \n", + " \n", + " 2020-07-22\n", + " 324.6200\n", + " 327.2000\n", + " 324.5000\n", + " 326.8600\n", + " 49338600.0\n", + " 6.604941e+07\n", + " 79226550.80\n", + " 324.021518\n", + " 322.687127\n", " \n", " \n", "\n", - "

5212 rows × 9 columns

\n", + "

5214 rows × 9 columns

\n", "" ], "text/plain": [ @@ -1918,11 +1913,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 8.361704e+07 \n", - "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 8.421785e+07 \n", "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 7.880249e+07 \n", "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 7.618782e+07 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 7.172025e+07 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 7.254462e+07 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 6.976292e+07 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 6.604941e+07 \n", "\n", " VOLUME_SMA_20 EMA_5 EMA_5_LR_8 \n", "date \n", @@ -1932,13 +1927,13 @@ "1999-11-04 NaN NaN NaN \n", "1999-11-05 NaN 136.012480 NaN \n", "... ... ... ... \n", - "2020-07-14 89676222.80 316.336980 315.670761 \n", - "2020-07-15 87169880.45 318.174653 316.635348 \n", "2020-07-16 85750820.85 319.046435 317.729875 \n", "2020-07-17 84954118.65 319.937624 318.784441 \n", - "2020-07-20 80774361.40 321.381749 320.052445 \n", + "2020-07-20 81001061.40 321.398416 320.058000 \n", + "2020-07-21 80162965.80 322.602277 321.307000 \n", + "2020-07-22 79226550.80 324.021518 322.687127 \n", "\n", - "[5212 rows x 9 columns]" + "[5214 rows x 9 columns]" ] }, "execution_count": 22, @@ -1973,7 +1968,7 @@ { "data": { "text/plain": [ - "Strategy(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}], description='BBANDS_20 applied to MACD', created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}], description='BBANDS_20 applied to MACD', created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 23, @@ -2025,7 +2020,7 @@ "text": [ "\n", "[i] Loaded['D']: SPY_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}]}\n" + "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" ] }, { @@ -2162,34 +2157,6 @@ " ...\n", " \n", " \n", - " 2020-07-14\n", - " 313.3000\n", - " 319.7600\n", - " 312.0000\n", - " 318.9200\n", - " 92791800.0\n", - " 3.427421\n", - " 0.341014\n", - " 3.086407\n", - " 0.839213\n", - " 3.424032\n", - " 6.008850\n", - " \n", - " \n", - " 2020-07-15\n", - " 322.4100\n", - " 323.0400\n", - " 319.2700\n", - " 321.8500\n", - " 86921500.0\n", - " 3.806234\n", - " 0.575862\n", - " 3.230372\n", - " 0.997401\n", - " 3.320292\n", - " 5.643184\n", - " \n", - " \n", " 2020-07-16\n", " 319.7900\n", " 321.2800\n", @@ -2222,18 +2189,46 @@ " 321.4300\n", " 325.1300\n", " 320.6200\n", - " 324.2700\n", - " 51616200.0\n", - " 4.418838\n", - " 0.710504\n", - " 3.708334\n", - " 1.351560\n", - " 3.153096\n", - " 4.954633\n", + " 324.3200\n", + " 56150200.0\n", + " 4.422827\n", + " 0.713695\n", + " 3.709131\n", + " 1.351168\n", + " 3.153296\n", + " 4.955423\n", + " \n", + " \n", + " 2020-07-21\n", + " 326.4500\n", + " 326.9300\n", + " 323.9400\n", + " 325.0100\n", + " 57245300.0\n", + " 4.651974\n", + " 0.754274\n", + " 3.897700\n", + " 1.341550\n", + " 3.157320\n", + " 4.973090\n", + " \n", + " \n", + " 2020-07-22\n", + " 324.6200\n", + " 327.2000\n", + " 324.5000\n", + " 326.8600\n", + " 49338600.0\n", + " 4.926070\n", + " 0.822696\n", + " 4.103374\n", + " 1.279092\n", + " 3.183563\n", + " 5.088035\n", " \n", " \n", "\n", - "

5212 rows × 11 columns

\n", + "

5214 rows × 11 columns

\n", "" ], "text/plain": [ @@ -2245,11 +2240,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-14 313.3000 319.7600 312.0000 318.9200 92791800.0 3.427421 \n", - "2020-07-15 322.4100 323.0400 319.2700 321.8500 86921500.0 3.806234 \n", "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 3.975091 \n", "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 4.136274 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.2700 51616200.0 4.418838 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 4.422827 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 4.651974 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 4.926070 \n", "\n", " MACDh_12_26_9 MACDs_12_26_9 MACD_BBL_20_2.0 MACD_BBM_20_2.0 \\\n", "date \n", @@ -2259,11 +2254,11 @@ "1999-11-04 NaN NaN NaN NaN \n", "1999-11-05 NaN NaN NaN NaN \n", "... ... ... ... ... \n", - "2020-07-14 0.341014 3.086407 0.839213 3.424032 \n", - "2020-07-15 0.575862 3.230372 0.997401 3.320292 \n", "2020-07-16 0.595775 3.379316 1.155506 3.237593 \n", "2020-07-17 0.605566 3.530708 1.297995 3.175551 \n", - "2020-07-20 0.710504 3.708334 1.351560 3.153096 \n", + "2020-07-20 0.713695 3.709131 1.351168 3.153296 \n", + "2020-07-21 0.754274 3.897700 1.341550 3.157320 \n", + "2020-07-22 0.822696 4.103374 1.279092 3.183563 \n", "\n", " MACD_BBU_20_2.0 \n", "date \n", @@ -2273,13 +2268,13 @@ "1999-11-04 NaN \n", "1999-11-05 NaN \n", "... ... \n", - "2020-07-14 6.008850 \n", - "2020-07-15 5.643184 \n", "2020-07-16 5.319681 \n", "2020-07-17 5.053107 \n", - "2020-07-20 4.954633 \n", + "2020-07-20 4.955423 \n", + "2020-07-21 4.973090 \n", + "2020-07-22 5.088035 \n", "\n", - "[5212 rows x 11 columns]" + "[5214 rows x 11 columns]" ] }, "execution_count": 25, @@ -2321,7 +2316,7 @@ { "data": { "text/plain": [ - "Strategy(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='07/21/2020, 10:42:07', last_run=None, run_time=None)" + "Strategy(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='07/22/2020, 17:02:37', last_run=None, run_time=None)" ] }, "execution_count": 26, @@ -2380,8 +2375,7 @@ "text": [ "\n", "[i] Loaded['D']: SPY_D.csv\n", - "strat.kwargs: {'ta': [{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], 'timed': True}\n", - "[i] Runtime: 39.0952 ms (0.0391 s)\n" + "[i] Runtime: 31.6960 ms (0.0317 s)\n" ] }, { @@ -3001,13 +2995,6 @@ "spy.head(20)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, diff --git a/examples/watchlist.py b/examples/watchlist.py index df8cc3c..c33aa26 100644 --- a/examples/watchlist.py +++ b/examples/watchlist.py @@ -108,7 +108,7 @@ class Watchlist(object): @property def data(self) -> dict: - """When not None, it contains a dictionary of DataFrames keyed by ticker.""" + """When not None, it contains a dictionary of DataFrames keyed by ticker. data = {"SPY": pd.DataFrame, ...}""" return self._data @data.setter diff --git a/pandas_ta/__init__.py b/pandas_ta/__init__.py index 19aa92e..a47b57e 100644 --- a/pandas_ta/__init__.py +++ b/pandas_ta/__init__.py @@ -18,4 +18,6 @@ except DistributionNotFound: else: __version__ = _dist.version +categories = ["candles", "momentum", "overlap", "performance", "statistics", "trend", "volatility", "volume"] + from pandas_ta.core import * \ No newline at end of file diff --git a/pandas_ta/candles/__init__.py b/pandas_ta/candles/__init__.py index 57e6728..d92eb5e 100644 --- a/pandas_ta/candles/__init__.py +++ b/pandas_ta/candles/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- -from .candle import * from .ha import ha from .cdl_doji import cdl_doji \ No newline at end of file diff --git a/pandas_ta/candles/candle.py b/pandas_ta/candles/candle.py deleted file mode 100644 index bd29f58..0000000 --- a/pandas_ta/candles/candle.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -from pandas_ta.utils import get_offset, non_zero_range, verify_series - -def candle_color(open_, close): - color = close.copy().astype(int) - color[close >= open_] = 1 - color[close < open_] = -1 - return color - -def real_body(open_, close): - return non_zero_range(open_, close) - -def high_low_range(high, low): - return non_zero_range(high, low) \ No newline at end of file diff --git a/pandas_ta/candles/cdl_doji.py b/pandas_ta/candles/cdl_doji.py index 5a3c5ff..8f724ed 100644 --- a/pandas_ta/candles/cdl_doji.py +++ b/pandas_ta/candles/cdl_doji.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- from pandas_ta.overlap import sma -from pandas_ta.utils import get_offset, is_percent, non_zero_range, verify_series -from .candle import * - +from pandas_ta.utils import get_offset, high_low_range, is_percent +from pandas_ta.utils import non_zero_range, real_body, verify_series def cdl_doji(open_, high, low, close, length=None, factor=None, scalar=None, asint=True, offset=None, **kwargs): """Candle Type: Doji""" diff --git a/pandas_ta/core.py b/pandas_ta/core.py index 7937af1..bfe544b 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -8,6 +8,7 @@ from time import perf_counter from typing import List import pandas as pd +from pandas_ta import categories from pandas.core.base import PandasObject from pandas_ta.candles import * @@ -20,7 +21,10 @@ from pandas_ta.volatility import * from pandas_ta.volume import * from pandas_ta.utils import * -version = ".".join(("0", "1", "76b")) +version = ".".join(("0", "1", "77b")) + +# Dictionary of files for each category, used in df.ta.strategy() +Category = {name: category_files(name) for name in categories} def mp_worker(args): df, method, kwargs = args @@ -241,14 +245,14 @@ class AnalysisIndicators(BasePandasObject): # Run the indicator result = fn(**kwargs) # = getattr(self, kind)(**kwargs) - # Add an alias if passed - if alias: result.alias = f"{alias}" - if timed: result.timed = final_time(stime) alias_str = alias + ':' if alias is not None else '' print(f"[+] {kind}:{alias_str} {result.timed}") + # Add an alias if passed + if alias: result.alias = f"{alias}" + return result else: self.help() @@ -438,10 +442,9 @@ class AnalysisIndicators(BasePandasObject): For example, length=20 or offset=-1 or high=df['High'] ... """ cpus = cpu_count() + kwargs["append"] = True # Ensure indicators are appended to the DataFrame + name = kwargs.pop("name", None) - if name is None or name.lower() == "all": - name = "All" - print(f"strat.kwargs: {kwargs}") # removing before sending the rest of kwargs to the indicators ta = kwargs.pop("ta", None) mp = kwargs.pop("mp", False) @@ -449,34 +452,44 @@ class AnalysisIndicators(BasePandasObject): timed = kwargs.pop("timed", False) verbose = kwargs.pop("verbose", False) user_excluded = kwargs.pop("exclude", []) - kwargs["append"] = True + + # Filter if Strategy, Category or by Strategy name and TA + if len(args) and isinstance(args[0], Strategy): + name, ta = args[0].name, args[0].ta + elif name is None or name.lower() == "all": + name = "All" + elif ta is None and name.lower() in categories: + ta = Category[name.lower()] is_all = True if name is None or name.lower() == "all" else False has_ta = True if ta is not None else False initial_column_count = len(self._df.columns) excluded = [] + excluded_functions = ["above", "above_value", "below", "below_value", "cross", "cross_value", "long_run", "short_run", "trend_return", "vp"] excluded += user_excluded # Exclude user excluded ta if listed - print(f'[+] Strategy "{name}"') if verbose else None - if is_all: - # Exclude utilities special functions - excluded += ["above", "above_value", "below", "below_value", "cross", "cross_value", "long_run", "short_run", "trend_return", "vp"] - ta = self.indicators(as_list=True, exclude=excluded) + print(f"[+] Strategy: {name}") if verbose else None + if name.lower() in categories or is_all: + # Exclude special functions + excluded += excluded_functions + if is_all: + ta = self.indicators(as_list=True, exclude=excluded) + else: + ta = Category[name.lower()] else: for kwds in ta: kwds["append"] = True if verbose: print(f'[i] Indicators with the following arguments: {kwargs}') - if len(excluded) > 0: + if is_all and len(excluded) > 0: print(f"[i] Excluded[{len(excluded)}]: {', '.join(excluded)}") # Enable multiprocessing if user sets: mp=True if mp: self.mp = not self.mp if self.mp: - # TODO: Fix for Custom Strategies print(f"[i] Multiprocessing: {cores} of {cpu_count()} cores") pool = Pool(cores) @@ -499,7 +512,7 @@ class AnalysisIndicators(BasePandasObject): print(f"[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has {cpus} cores. Default: False") if timed: stime = perf_counter() - if is_all: + if name.lower() in categories or is_all: indicators = [getattr(self, kind) for kind in ta] [f(**kwargs) for f in indicators] else: @@ -979,11 +992,13 @@ class AnalysisIndicators(BasePandasObject): @finalize def trend_return(self, close=None, trend=None, log=True, cumulative=None, offset=None, trend_reset=None, **kwargs): - close = self._get_column(close, 'close') - trend = self._get_column(trend, f"{trend}") + if trend is None: return self._df + else: + close = self._get_column(close, 'close') + trend = self._get_column(trend, f"{trend}") - result = trend_return(close=close, trend=trend, log=log, cumulative=cumulative, offset=offset, trend_reset=trend_reset, **kwargs) - return result + result = trend_return(close=close, trend=trend, log=log, cumulative=cumulative, offset=offset, trend_reset=trend_reset, **kwargs) + return result # Statistics Indicators @@ -1462,7 +1477,4 @@ class AnalysisIndicators(BasePandasObject): volume = self._get_column(volume, 'volume') result = vp(close=close, volume=volume, width=width, percent=percent, **kwargs) - return result - -# if __name__ == "__main__": -# freeze_support() \ No newline at end of file + return result \ No newline at end of file diff --git a/pandas_ta/utils.py b/pandas_ta/utils.py index 256002c..b9580ed 100644 --- a/pandas_ta/utils.py +++ b/pandas_ta/utils.py @@ -18,9 +18,9 @@ MINUTES_PER_HOUR = 60 def _above_below( series_a: pd.Series, series_b: pd.Series, - above: bool =True, - asint: bool =True, - offset: int =None, + above: bool = True, + asint: bool = True, + offset: int = None, **kwargs ): series_a = verify_series(series_a) @@ -53,8 +53,8 @@ def _above_below( def above( series_a: pd.Series, series_b: pd.Series, - asint: bool =True, - offset: int =None, + asint: bool = True, + offset: int = None, **kwargs ): return _above_below(series_a, series_b, above=True, asint=asint, offset=offset, **kwargs) @@ -98,6 +98,12 @@ def below_value( return _above_below(series_a, series_b, above=False, asint=asint, offset=offset, **kwargs) +def category_files(category: str) -> list: + """Helper function to return all filenames in the category directory.""" + files = [x.stem for x in list(Path(f"pandas_ta/{category}/").glob("*.py")) if x.stem != "__init__"] + return files + + def combination(**kwargs): """https://stackoverflow.com/questions/4941753/is-there-a-math-ncr-function-in-python""" n = int(math.fabs(kwargs.pop('n', 1))) @@ -434,4 +440,18 @@ def weights(w): def zero(x: [int, float]) -> [int, float]: """If the value is close to zero, then return zero. Otherwise return the value.""" - return 0 if -sflt.epsilon < x and x < sflt.epsilon else x \ No newline at end of file + return 0 if -sflt.epsilon < x and x < sflt.epsilon else x + +# Candle Functions + +def candle_color(open_, close): + color = close.copy().astype(int) + color[close >= open_] = 1 + color[close < open_] = -1 + return color + +def real_body(open_, close): + return non_zero_range(open_, close) + +def high_low_range(high, low): + return non_zero_range(high, low) \ No newline at end of file diff --git a/pandas_ta/volume/vp.py b/pandas_ta/volume/vp.py index 770fe6e..8302299 100644 --- a/pandas_ta/volume/vp.py +++ b/pandas_ta/volume/vp.py @@ -83,12 +83,12 @@ Calculation: Args: close (pd.Series): Series of 'close's volume (pd.Series): Series of 'volume's - width (int): How many ranges to distrubute price into. Default: 10 + width (int): How many ranges to distrubute price into. Default: 10 Kwargs: fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): Type of fill method - sort_close (value, optional): Whether to sort by close before splitting into ranges. Default: False + sort_close (value, optional): Whether to sort by close before splitting into ranges. Default: False Returns: pd.DataFrame: New feature generated. From 94696f6120c35cf39ac705dbd414bb379fa0c34d Mon Sep 17 00:00:00 2001 From: YuvalWein <65113623+YuvalWein@users.noreply.github.com> Date: Thu, 23 Jul 2020 10:22:55 +0300 Subject: [PATCH 07/10] Update variance.py When calculation variance we can divide the calculation by N, or by N-1. When calculating sample variance we divide by N-1 (like in the current code).(https://towardsdatascience.com/why-sample-variance-is-divided-by-n-1-89821b83ef6d) Sometimes We want to divide by N like the basis formula, to calculate population variance. (https://en.wikipedia.org/wiki/Variance#Discrete_random_variable) For me its useful to add another parameter that will make it possible to calculate both of then using one function. Is it useful for you? --- pandas_ta/statistics/variance.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pandas_ta/statistics/variance.py b/pandas_ta/statistics/variance.py index 7d5fd26..bb6e2cb 100644 --- a/pandas_ta/statistics/variance.py +++ b/pandas_ta/statistics/variance.py @@ -1,16 +1,18 @@ # -*- coding: utf-8 -*- from ..utils import get_offset, verify_series -def variance(close, length=None, offset=None, **kwargs): +def variance(close, length=None, ddof=1, offset=None, **kwargs): """Indicator: Variance""" # Validate Arguments close = verify_series(close) length = int(length) if length and length > 1 else 30 + ddof = int(ddof) if 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 offset = get_offset(offset) # Calculate Result - variance = close.rolling(length, min_periods=min_periods).var() + variance = close.rolling(length, min_periods=min_periods).var(ddof) # Offset if offset != 0: @@ -37,6 +39,9 @@ Calculation: Args: close (pd.Series): Series of 'close's 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. Default: 1 offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -45,4 +50,4 @@ Kwargs: Returns: pd.Series: New feature generated. -""" \ No newline at end of file +""" From 4cf1d86996afa16d1da522837dcaa1fb586cf910 Mon Sep 17 00:00:00 2001 From: YuvalWein <65113623+YuvalWein@users.noreply.github.com> Date: Thu, 23 Jul 2020 10:26:04 +0300 Subject: [PATCH 08/10] Update stdev.py Same as variance explanation, since std = sqrt(variance): When calculation variance we can divide the calculation by N, or by N-1. When calculating sample variance we divide by N-1 (like in the current code).(https://towardsdatascience.com/why-sample-variance-is-divided-by-n-1-89821b83ef6d) Sometimes We want to divide by N like the basis formula, to calculate population variance. (https://en.wikipedia.org/wiki/Variance#Discrete_random_variable) For me its useful to add another parameter that will make it possible to calculate both of then using one function. Is it useful for you? --- pandas_ta/statistics/stdev.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pandas_ta/statistics/stdev.py b/pandas_ta/statistics/stdev.py index 1f92b3f..74d2fc1 100644 --- a/pandas_ta/statistics/stdev.py +++ b/pandas_ta/statistics/stdev.py @@ -3,15 +3,16 @@ from numpy import sqrt as npsqrt from .variance import variance from ..utils import get_offset, verify_series -def stdev(close, length=None, offset=None, **kwargs): +def stdev(close, length=None, ddof=1, offset=None, **kwargs): """Indicator: Standard Deviation""" # Validate Arguments close = verify_series(close) length = int(length) if length and length > 0 else 30 + ddof = int(ddof) if ddof >= 0 and ddof < length else 1 offset = get_offset(offset) # Calculate Result - stdev = variance(close=close, length=length).apply(npsqrt) + stdev = variance(close=close, length=length, ddof=ddof).apply(npsqrt) # Offset if offset != 0: @@ -39,6 +40,9 @@ Calculation: Args: close (pd.Series): Series of 'close's 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. Default: 1 offset (int): How many periods to offset the result. Default: 0 Kwargs: @@ -47,4 +51,4 @@ Kwargs: Returns: pd.Series: New feature generated. -""" \ No newline at end of file +""" From 93c898a0054ae3aa53f888c7d939cea9dcda2c8b Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Sat, 25 Jul 2020 11:30:00 -0700 Subject: [PATCH 09/10] MAINT rsi refactor --- examples/PandasTA_Strategy_Examples.ipynb | 722 +++++++++++----------- pandas_ta/momentum/rsi.py | 7 +- 2 files changed, 364 insertions(+), 365 deletions(-) diff --git a/examples/PandasTA_Strategy_Examples.ipynb b/examples/PandasTA_Strategy_Examples.ipynb index d327050..00e9b9e 100644 --- a/examples/PandasTA_Strategy_Examples.ipynb +++ b/examples/PandasTA_Strategy_Examples.ipynb @@ -88,7 +88,7 @@ "text": [ "name = All\n", "description = All the indicators with their default settings. Pandas TA default.\n", - "created = 07/22/2020, 17:02:37\n", + "created = 07/25/2020, 11:24:19\n", "ta = None\n" ] } @@ -119,7 +119,7 @@ "text": [ "name = Common Price and Volume SMAs\n", "description = Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.\n", - "created = 07/22/2020, 17:02:37\n", + "created = 07/25/2020, 11:24:19\n", "ta = [{'kind': 'sma', 'length': 10}, {'kind': 'sma', 'length': 20}, {'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOL'}]\n" ] } @@ -161,7 +161,7 @@ { "data": { "text/plain": [ - "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 4, @@ -189,7 +189,7 @@ { "data": { "text/plain": [ - "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 5, @@ -217,7 +217,7 @@ { "data": { "text/plain": [ - "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 6, @@ -476,11 +476,11 @@ " 1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", " 1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", - " 2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", - " 2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 320.673333 \n", - " 2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 322.353333 \n", - " 2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 323.313333 \n", + " 2020-07-20 321.4300 325.1300 320.6200 324.3200 56150230.0 320.673333 \n", + " 2020-07-21 326.4500 326.9300 323.9400 325.0100 57245315.0 322.353333 \n", + " 2020-07-22 324.6200 327.2000 324.5000 326.8600 57792915.0 323.313333 \n", + " 2020-07-23 326.4700 327.2300 321.4800 322.9600 75737989.0 324.014000 \n", + " 2020-07-24 320.9500 321.9900 319.2460 320.8800 73766597.0 323.886400 \n", " \n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", " date ... \n", @@ -490,11 +490,11 @@ " 1999-11-04 NaN NaN NaN NaN ... \n", " 1999-11-05 NaN NaN NaN NaN ... \n", " ... ... ... ... ... ... \n", - " 2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", - " 2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", " 2020-07-20 326.296123 315.050544 5.622790 300.906776 ... \n", " 2020-07-21 327.800604 316.906063 5.447270 301.895656 ... \n", " 2020-07-22 328.577452 318.049214 5.264119 302.558926 ... \n", + " 2020-07-23 329.310511 318.717489 5.296511 303.787477 ... \n", + " 2020-07-24 329.077410 318.695390 5.191010 305.041909 ... \n", " \n", " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", " date \n", @@ -504,11 +504,11 @@ " 1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", " 1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", " ... ... ... ... ... ... ... \n", - " 2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", - " 2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", - " 2020-07-20 45.091757 1.223611 0.623952 153.261035 318.474591 323.597500 \n", - " 2020-07-21 46.469833 1.211493 0.661493 153.277972 319.600245 325.222500 \n", - " 2020-07-22 50.919143 1.153997 0.689436 153.292643 320.677611 326.355000 \n", + " 2020-07-20 45.091757 1.223611 0.623952 153.261128 318.474591 323.597500 \n", + " 2020-07-21 46.469833 1.211493 0.661493 153.278065 319.600245 325.222500 \n", + " 2020-07-22 50.919143 1.153997 0.689436 153.295250 320.677611 326.355000 \n", + " 2020-07-23 52.999190 1.085706 0.763560 153.317466 321.522738 323.657500 \n", + " 2020-07-24 48.773943 1.027629 0.904621 153.338694 321.846761 320.749000 \n", " \n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", " date \n", @@ -518,26 +518,26 @@ " 1999-11-04 NaN NaN NaN NaN \n", " 1999-11-05 NaN NaN NaN NaN \n", " ... ... ... ... ... \n", - " 2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", - " 2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", " 2020-07-20 -3.801032 320.096545 323.215081 1.680556 \n", " 2020-07-21 -10.750280 321.291636 324.115975 1.747819 \n", " 2020-07-22 -2.058111 322.618909 325.718525 1.900614 \n", + " 2020-07-23 -25.800604 323.042909 325.442430 1.309102 \n", + " 2020-07-24 -38.368580 322.932727 323.987442 0.970050 \n", " \n", - " [5214 rows x 157 columns],\n", - " 'IWM': open high low close volume ABER_ZG_5_15 \\\n", - " date \n", - " 2000-05-26 91.06 91.44 90.63 91.44 37400.0 NaN \n", - " 2000-05-30 92.75 94.81 92.75 94.81 28800.0 NaN \n", - " 2000-05-31 95.13 96.38 95.13 95.75 18000.0 NaN \n", - " 2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN \n", - " 2000-06-02 101.70 102.40 101.70 102.40 14700.0 96.091333 \n", - " ... ... ... ... ... ... ... \n", - " 2020-07-16 146.11 146.67 144.88 146.16 30386200.0 142.972000 \n", - " 2020-07-17 146.68 147.59 145.51 146.59 20632700.0 144.200000 \n", - " 2020-07-20 146.12 146.85 145.15 145.96 19581700.0 145.160667 \n", - " 2020-07-21 147.47 149.16 147.20 148.03 24467100.0 146.623333 \n", - " 2020-07-22 147.09 148.67 147.03 148.11 19080800.0 146.904000 \n", + " [5216 rows x 157 columns],\n", + " 'IWM': open high low close volume ABER_ZG_5_15 \\\n", + " date \n", + " 2000-05-26 91.06 91.440 90.63 91.44 37400.0 NaN \n", + " 2000-05-30 92.75 94.810 92.75 94.81 28800.0 NaN \n", + " 2000-05-31 95.13 96.380 95.13 95.75 18000.0 NaN \n", + " 2000-06-01 97.11 97.310 97.11 97.31 3500.0 NaN \n", + " 2000-06-02 101.70 102.400 101.70 102.40 14700.0 96.091333 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-20 146.12 146.850 145.15 145.96 19581689.0 145.160667 \n", + " 2020-07-21 147.47 149.160 147.20 148.03 24467065.0 146.623333 \n", + " 2020-07-22 147.09 148.670 147.03 148.11 24424808.0 146.904000 \n", + " 2020-07-23 147.98 150.200 146.70 148.26 21704889.0 147.400667 \n", + " 2020-07-24 147.29 147.665 145.56 146.08 20015547.0 147.375000 \n", " \n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", " date ... \n", @@ -547,25 +547,25 @@ " 2000-06-01 NaN NaN NaN NaN ... \n", " 2000-06-02 NaN NaN NaN NaN ... \n", " ... ... ... ... ... ... \n", - " 2020-07-16 147.233237 138.710763 4.261237 132.740467 ... \n", - " 2020-07-17 148.315822 140.084178 4.115822 133.164616 ... \n", - " 2020-07-20 149.115433 141.205900 3.954767 133.720436 ... \n", - " 2020-07-21 150.527782 142.718884 3.904449 134.312288 ... \n", - " 2020-07-22 150.657486 143.150514 3.753486 134.567792 ... \n", + " 2020-07-20 149.115307 141.206027 3.954640 133.720919 ... \n", + " 2020-07-21 150.527664 142.719003 3.904331 134.312771 ... \n", + " 2020-07-22 150.657375 143.150625 3.753375 134.568274 ... \n", + " 2020-07-23 151.137150 143.664183 3.736483 135.260831 ... \n", + " 2020-07-24 151.042385 143.707615 3.667385 135.937695 ... \n", " \n", - " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", - " date \n", - " 2000-05-26 NaN NaN NaN 91.170000 NaN 91.2375 \n", - " 2000-05-30 NaN NaN NaN 92.454834 NaN 94.2950 \n", - " 2000-05-31 NaN NaN NaN 93.159976 NaN 95.7525 \n", - " 2000-06-01 NaN NaN NaN 93.322938 NaN 97.2600 \n", - " 2000-06-02 NaN NaN NaN 94.592497 NaN 102.2250 \n", - " ... ... ... ... ... ... ... \n", - " 2020-07-16 15.532794 1.067613 0.898394 88.352707 142.400151 145.9675 \n", - " 2020-07-17 15.940380 1.090399 0.874371 88.359302 142.830341 146.5700 \n", - " 2020-07-20 14.347839 1.085970 0.934221 88.365497 143.089584 145.9800 \n", - " 2020-07-21 11.515402 1.030077 0.909147 88.373523 143.813948 148.1050 \n", - " 2020-07-22 10.497958 1.013525 0.935595 88.379761 144.438962 147.9800 \n", + " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", + " date \n", + " 2000-05-26 NaN NaN NaN 91.170000 NaN 91.23750 \n", + " 2000-05-30 NaN NaN NaN 92.454834 NaN 94.29500 \n", + " 2000-05-31 NaN NaN NaN 93.159976 NaN 95.75250 \n", + " 2000-06-01 NaN NaN NaN 93.322938 NaN 97.26000 \n", + " 2000-06-02 NaN NaN NaN 94.592497 NaN 102.22500 \n", + " ... ... ... ... ... ... ... \n", + " 2020-07-20 14.347839 1.085970 0.934117 88.365517 143.089584 145.98000 \n", + " 2020-07-21 11.515402 1.030077 0.909147 88.373544 143.813948 148.10500 \n", + " 2020-07-22 10.497958 1.013525 0.935595 88.381529 144.438962 147.98000 \n", + " 2020-07-23 11.200568 0.993994 0.920849 88.388676 145.342850 148.35500 \n", + " 2020-07-24 9.687226 0.945133 0.982616 88.395051 145.807709 146.34625 \n", " \n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", " date \n", @@ -575,13 +575,13 @@ " 2000-06-01 NaN NaN NaN NaN \n", " 2000-06-02 NaN NaN NaN NaN \n", " ... ... ... ... ... \n", - " 2020-07-16 -14.348981 142.891818 144.553735 0.902863 \n", - " 2020-07-17 -11.142322 143.661273 146.209420 0.982248 \n", " 2020-07-20 -17.267552 144.240000 146.914980 0.906142 \n", " 2020-07-21 -9.479866 145.149091 147.299529 1.671168 \n", " 2020-07-22 -8.808725 145.942909 147.801433 1.797089 \n", + " 2020-07-23 -14.969136 146.651818 148.188445 1.763914 \n", + " 2020-07-24 -31.790123 146.797273 147.826909 1.077936 \n", " \n", - " [5070 rows x 157 columns]}" + " [5072 rows x 157 columns]}" ] }, "execution_count": 12, @@ -819,60 +819,12 @@ " ...\n", " \n", " \n", - " 2020-07-16\n", - " 319.7900\n", - " 321.2800\n", - " 319.0900\n", - " 320.7900\n", - " 54433400.0\n", - " 318.394000\n", - " 324.301437\n", - " 312.486563\n", - " 5.907437\n", - " 299.367555\n", - " ...\n", - " 39.296390\n", - " 1.142186\n", - " 0.731933\n", - " 153.225976\n", - " 316.788363\n", - " 320.487500\n", - " -9.332227\n", - " 317.993091\n", - " 320.251663\n", - " 1.318671\n", - " \n", - " \n", - " 2020-07-17\n", - " 321.8800\n", - " 322.5700\n", - " 319.7400\n", - " 321.7200\n", - " 64421800.0\n", - " 319.447333\n", - " 325.149608\n", - " 313.745059\n", - " 5.702275\n", - " 299.875050\n", - " ...\n", - " 42.042623\n", - " 1.200811\n", - " 0.690749\n", - " 153.244606\n", - " 317.735725\n", - " 321.437500\n", - " -5.474907\n", - " 318.894727\n", - " 321.769543\n", - " 1.365046\n", - " \n", - " \n", " 2020-07-20\n", " 321.4300\n", " 325.1300\n", " 320.6200\n", " 324.3200\n", - " 56150200.0\n", + " 56150230.0\n", " 320.673333\n", " 326.296123\n", " 315.050544\n", @@ -882,7 +834,7 @@ " 45.091757\n", " 1.223611\n", " 0.623952\n", - " 153.261035\n", + " 153.261128\n", " 318.474591\n", " 323.597500\n", " -3.801032\n", @@ -896,7 +848,7 @@ " 326.9300\n", " 323.9400\n", " 325.0100\n", - " 57245300.0\n", + " 57245315.0\n", " 322.353333\n", " 327.800604\n", " 316.906063\n", @@ -906,7 +858,7 @@ " 46.469833\n", " 1.211493\n", " 0.661493\n", - " 153.277972\n", + " 153.278065\n", " 319.600245\n", " 325.222500\n", " -10.750280\n", @@ -920,7 +872,7 @@ " 327.2000\n", " 324.5000\n", " 326.8600\n", - " 49338600.0\n", + " 57792915.0\n", " 323.313333\n", " 328.577452\n", " 318.049214\n", @@ -930,7 +882,7 @@ " 50.919143\n", " 1.153997\n", " 0.689436\n", - " 153.292643\n", + " 153.295250\n", " 320.677611\n", " 326.355000\n", " -2.058111\n", @@ -938,9 +890,57 @@ " 325.718525\n", " 1.900614\n", " \n", + " \n", + " 2020-07-23\n", + " 326.4700\n", + " 327.2300\n", + " 321.4800\n", + " 322.9600\n", + " 75737989.0\n", + " 324.014000\n", + " 329.310511\n", + " 318.717489\n", + " 5.296511\n", + " 303.787477\n", + " ...\n", + " 52.999190\n", + " 1.085706\n", + " 0.763560\n", + " 153.317466\n", + " 321.522738\n", + " 323.657500\n", + " -25.800604\n", + " 323.042909\n", + " 325.442430\n", + " 1.309102\n", + " \n", + " \n", + " 2020-07-24\n", + " 320.9500\n", + " 321.9900\n", + " 319.2460\n", + " 320.8800\n", + " 73766597.0\n", + " 323.886400\n", + " 329.077410\n", + " 318.695390\n", + " 5.191010\n", + " 305.041909\n", + " ...\n", + " 48.773943\n", + " 1.027629\n", + " 0.904621\n", + " 153.338694\n", + " 321.846761\n", + " 320.749000\n", + " -38.368580\n", + " 322.932727\n", + " 323.987442\n", + " 0.970050\n", + " \n", " \n", "\n", - "

5214 rows × 157 columns

\n", + "

5216 rows × 157 columns

\n", "" ], "text/plain": [ @@ -952,11 +952,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 136.332267 \n", "... ... ... ... ... ... ... \n", - "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 318.394000 \n", - "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 319.447333 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 320.673333 \n", - "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 322.353333 \n", - "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 323.313333 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150230.0 320.673333 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245315.0 322.353333 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 57792915.0 323.313333 \n", + "2020-07-23 326.4700 327.2300 321.4800 322.9600 75737989.0 324.014000 \n", + "2020-07-24 320.9500 321.9900 319.2460 320.8800 73766597.0 323.886400 \n", "\n", " ABER_SG_5_15 ABER_XG_5_15 ABER_ATR_5_15 ACCBL_20 ... \\\n", "date ... \n", @@ -966,11 +966,11 @@ "1999-11-04 NaN NaN NaN NaN ... \n", "1999-11-05 NaN NaN NaN NaN ... \n", "... ... ... ... ... ... \n", - "2020-07-16 324.301437 312.486563 5.907437 299.367555 ... \n", - "2020-07-17 325.149608 313.745059 5.702275 299.875050 ... \n", "2020-07-20 326.296123 315.050544 5.622790 300.906776 ... \n", "2020-07-21 327.800604 316.906063 5.447270 301.895656 ... \n", "2020-07-22 328.577452 318.049214 5.264119 302.558926 ... \n", + "2020-07-23 329.310511 318.717489 5.296511 303.787477 ... \n", + "2020-07-24 329.077410 318.695390 5.191010 305.041909 ... \n", "\n", " VAR_30 VTXP_14 VTXM_14 VWAP VWMA_10 WCP \\\n", "date \n", @@ -980,11 +980,11 @@ "1999-11-04 NaN NaN NaN 135.950504 NaN 136.546825 \n", "1999-11-05 NaN NaN NaN 136.393305 NaN 137.910125 \n", "... ... ... ... ... ... ... \n", - "2020-07-16 39.296390 1.142186 0.731933 153.225976 316.788363 320.487500 \n", - "2020-07-17 42.042623 1.200811 0.690749 153.244606 317.735725 321.437500 \n", - "2020-07-20 45.091757 1.223611 0.623952 153.261035 318.474591 323.597500 \n", - "2020-07-21 46.469833 1.211493 0.661493 153.277972 319.600245 325.222500 \n", - "2020-07-22 50.919143 1.153997 0.689436 153.292643 320.677611 326.355000 \n", + "2020-07-20 45.091757 1.223611 0.623952 153.261128 318.474591 323.597500 \n", + "2020-07-21 46.469833 1.211493 0.661493 153.278065 319.600245 325.222500 \n", + "2020-07-22 50.919143 1.153997 0.689436 153.295250 320.677611 326.355000 \n", + "2020-07-23 52.999190 1.085706 0.763560 153.317466 321.522738 323.657500 \n", + "2020-07-24 48.773943 1.027629 0.904621 153.338694 321.846761 320.749000 \n", "\n", " WILLR_14 WMA_10 ZL_EMA_10 Z_30 \n", "date \n", @@ -994,13 +994,13 @@ "1999-11-04 NaN NaN NaN NaN \n", "1999-11-05 NaN NaN NaN NaN \n", "... ... ... ... ... \n", - "2020-07-16 -9.332227 317.993091 320.251663 1.318671 \n", - "2020-07-17 -5.474907 318.894727 321.769543 1.365046 \n", "2020-07-20 -3.801032 320.096545 323.215081 1.680556 \n", "2020-07-21 -10.750280 321.291636 324.115975 1.747819 \n", "2020-07-22 -2.058111 322.618909 325.718525 1.900614 \n", + "2020-07-23 -25.800604 323.042909 325.442430 1.309102 \n", + "2020-07-24 -38.368580 322.932727 323.987442 0.970050 \n", "\n", - "[5214 rows x 157 columns]" + "[5216 rows x 157 columns]" ] }, "execution_count": 13, @@ -1041,7 +1041,7 @@ { "data": { "text/plain": [ - "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 14, @@ -1065,8 +1065,7 @@ "output_type": "stream", "text": [ "\n", - "[i] Loaded['D']: IWM_D.csv\n", - "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" + "[i] Loaded['D']: IWM_D.csv\n" ] }, { @@ -1113,7 +1112,7 @@ " \n", " 2000-05-26\n", " 91.06\n", - " 91.44\n", + " 91.440\n", " 90.63\n", " 91.44\n", " 37400.0\n", @@ -1123,7 +1122,7 @@ " \n", " 2000-05-30\n", " 92.75\n", - " 94.81\n", + " 94.810\n", " 92.75\n", " 94.81\n", " 28800.0\n", @@ -1133,7 +1132,7 @@ " \n", " 2000-05-31\n", " 95.13\n", - " 96.38\n", + " 96.380\n", " 95.13\n", " 95.75\n", " 18000.0\n", @@ -1143,7 +1142,7 @@ " \n", " 2000-06-01\n", " 97.11\n", - " 97.31\n", + " 97.310\n", " 97.11\n", " 97.31\n", " 3500.0\n", @@ -1153,7 +1152,7 @@ " \n", " 2000-06-02\n", " 101.70\n", - " 102.40\n", + " 102.400\n", " 101.70\n", " 102.40\n", " 14700.0\n", @@ -1171,76 +1170,76 @@ " ...\n", " \n", " \n", - " 2020-07-16\n", - " 146.11\n", - " 146.67\n", - " 144.88\n", - " 146.16\n", - " 30386200.0\n", - " 138.9184\n", - " 145.95140\n", - " \n", - " \n", - " 2020-07-17\n", - " 146.68\n", - " 147.59\n", - " 145.51\n", - " 146.59\n", - " 20632700.0\n", - " 139.3358\n", - " 145.94250\n", - " \n", - " \n", " 2020-07-20\n", " 146.12\n", - " 146.85\n", + " 146.850\n", " 145.15\n", " 145.96\n", - " 19581700.0\n", + " 19581689.0\n", " 139.7062\n", " 145.93605\n", " \n", " \n", " 2020-07-21\n", " 147.47\n", - " 149.16\n", + " 149.160\n", " 147.20\n", " 148.03\n", - " 24467100.0\n", + " 24467065.0\n", " 140.0196\n", " 145.93750\n", " \n", " \n", " 2020-07-22\n", " 147.09\n", - " 148.67\n", + " 148.670\n", " 147.03\n", " 148.11\n", - " 19080800.0\n", + " 24424808.0\n", " 140.3478\n", " 145.93235\n", " \n", + " \n", + " 2020-07-23\n", + " 147.98\n", + " 150.200\n", + " 146.70\n", + " 148.26\n", + " 21704889.0\n", + " 140.7736\n", + " 145.92925\n", + " \n", + " \n", + " 2020-07-24\n", + " 147.29\n", + " 147.665\n", + " 145.56\n", + " 146.08\n", + " 20015547.0\n", + " 141.2408\n", + " 145.92735\n", + " \n", " \n", "\n", - "

5070 rows × 7 columns

\n", + "

5072 rows × 7 columns

\n", "" ], "text/plain": [ - " open high low close volume SMA_50 SMA_200\n", - "date \n", - "2000-05-26 91.06 91.44 90.63 91.44 37400.0 NaN NaN\n", - "2000-05-30 92.75 94.81 92.75 94.81 28800.0 NaN NaN\n", - "2000-05-31 95.13 96.38 95.13 95.75 18000.0 NaN NaN\n", - "2000-06-01 97.11 97.31 97.11 97.31 3500.0 NaN NaN\n", - "2000-06-02 101.70 102.40 101.70 102.40 14700.0 NaN NaN\n", - "... ... ... ... ... ... ... ...\n", - "2020-07-16 146.11 146.67 144.88 146.16 30386200.0 138.9184 145.95140\n", - "2020-07-17 146.68 147.59 145.51 146.59 20632700.0 139.3358 145.94250\n", - "2020-07-20 146.12 146.85 145.15 145.96 19581700.0 139.7062 145.93605\n", - "2020-07-21 147.47 149.16 147.20 148.03 24467100.0 140.0196 145.93750\n", - "2020-07-22 147.09 148.67 147.03 148.11 19080800.0 140.3478 145.93235\n", + " open high low close volume SMA_50 SMA_200\n", + "date \n", + "2000-05-26 91.06 91.440 90.63 91.44 37400.0 NaN NaN\n", + "2000-05-30 92.75 94.810 92.75 94.81 28800.0 NaN NaN\n", + "2000-05-31 95.13 96.380 95.13 95.75 18000.0 NaN NaN\n", + "2000-06-01 97.11 97.310 97.11 97.31 3500.0 NaN NaN\n", + "2000-06-02 101.70 102.400 101.70 102.40 14700.0 NaN NaN\n", + "... ... ... ... ... ... ... ...\n", + "2020-07-20 146.12 146.850 145.15 145.96 19581689.0 139.7062 145.93605\n", + "2020-07-21 147.47 149.160 147.20 148.03 24467065.0 140.0196 145.93750\n", + "2020-07-22 147.09 148.670 147.03 148.11 24424808.0 140.3478 145.93235\n", + "2020-07-23 147.98 150.200 146.70 148.26 21704889.0 140.7736 145.92925\n", + "2020-07-24 147.29 147.665 145.56 146.08 20015547.0 141.2408 145.92735\n", "\n", - "[5070 rows x 7 columns]" + "[5072 rows x 7 columns]" ] }, "execution_count": 15, @@ -1267,7 +1266,7 @@ { "data": { "text/plain": [ - "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 16, @@ -1291,8 +1290,7 @@ "output_type": "stream", "text": [ "\n", - "[i] Loaded['D']: SPY_D.csv\n", - "[i] Set 'df.ta.mp = True' to enable multiprocessing. This computer has 4 cores. Default: False\n" + "[i] Loaded['D']: SPY_D.csv\n" ] }, { @@ -1390,7 +1388,7 @@ " NaN\n", " NaN\n", " -0.000461\n", - " 6.263520\n", + " 50.185503\n", " NaN\n", " 1\n", " NaN\n", @@ -1406,7 +1404,7 @@ " NaN\n", " NaN\n", " 0.007120\n", - " 12.913259\n", + " 69.153995\n", " NaN\n", " 1\n", " NaN\n", @@ -1422,7 +1420,7 @@ " NaN\n", " NaN\n", " 0.016915\n", - " 20.761745\n", + " 79.896816\n", " NaN\n", " 1\n", " NaN\n", @@ -1445,48 +1443,16 @@ " ...\n", " \n", " \n", - " 2020-07-16\n", - " 319.7900\n", - " 321.2800\n", - " 319.0900\n", - " 320.7900\n", - " 54433400.0\n", - " 317.563448\n", - " 313.395304\n", - " 0.861354\n", - " 60.141122\n", - " 321.864382\n", - " -1\n", - " NaN\n", - " 321.864382\n", - " \n", - " \n", - " 2020-07-17\n", - " 321.8800\n", - " 322.5700\n", - " 319.7400\n", - " 321.7200\n", - " 64421800.0\n", - " 318.487126\n", - " 314.152095\n", - " 0.864249\n", - " 60.911280\n", - " 321.864382\n", - " -1\n", - " NaN\n", - " 321.864382\n", - " \n", - " \n", " 2020-07-20\n", " 321.4300\n", " 325.1300\n", " 320.6200\n", " 324.3200\n", - " 56150200.0\n", + " 56150230.0\n", " 319.783320\n", " 315.076450\n", " 0.872298\n", - " 63.049858\n", + " 63.569724\n", " 307.890439\n", " 1\n", " 307.890439\n", @@ -1498,11 +1464,11 @@ " 326.9300\n", " 323.9400\n", " 325.0100\n", - " 57245300.0\n", + " 57245315.0\n", " 320.944805\n", " 315.979500\n", " 0.874423\n", - " 63.615869\n", + " 64.179426\n", " 311.309662\n", " 1\n", " 311.309662\n", @@ -1514,11 +1480,43 @@ " 327.2000\n", " 324.5000\n", " 326.8600\n", - " 49338600.0\n", + " 57792915.0\n", " 322.259293\n", " 316.968636\n", " 0.880099\n", - " 65.149441\n", + " 65.830627\n", + " 312.585425\n", + " 1\n", + " 312.585425\n", + " NaN\n", + " \n", + " \n", + " 2020-07-23\n", + " 326.4700\n", + " 327.2300\n", + " 321.4800\n", + " 322.9600\n", + " 75737989.0\n", + " 322.415005\n", + " 317.513306\n", + " 0.868096\n", + " 59.594031\n", + " 312.585425\n", + " 1\n", + " 312.585425\n", + " NaN\n", + " \n", + " \n", + " 2020-07-24\n", + " 320.9500\n", + " 321.9900\n", + " 319.2460\n", + " 320.8800\n", + " 73766597.0\n", + " 322.073893\n", + " 317.819369\n", + " 0.861634\n", + " 56.518677\n", " 312.585425\n", " 1\n", " 312.585425\n", @@ -1526,7 +1524,7 @@ " \n", " \n", "\n", - "

5214 rows × 13 columns

\n", + "

5216 rows × 13 columns

\n", "" ], "text/plain": [ @@ -1538,25 +1536,25 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 317.563448 \n", - "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 318.487126 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 319.783320 \n", - "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 320.944805 \n", - "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 322.259293 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150230.0 319.783320 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245315.0 320.944805 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 57792915.0 322.259293 \n", + "2020-07-23 326.4700 327.2300 321.4800 322.9600 75737989.0 322.415005 \n", + "2020-07-24 320.9500 321.9900 319.2460 320.8800 73766597.0 322.073893 \n", "\n", " EMA_21 CUMLOGRET_1 RSI_14 SUPERT_7_3.0 SUPERTd_7_3.0 \\\n", "date \n", "1999-11-01 NaN NaN NaN 0.000000 1 \n", "1999-11-02 NaN -0.007172 0.000000 NaN 1 \n", - "1999-11-03 NaN -0.000461 6.263520 NaN 1 \n", - "1999-11-04 NaN 0.007120 12.913259 NaN 1 \n", - "1999-11-05 NaN 0.016915 20.761745 NaN 1 \n", + "1999-11-03 NaN -0.000461 50.185503 NaN 1 \n", + "1999-11-04 NaN 0.007120 69.153995 NaN 1 \n", + "1999-11-05 NaN 0.016915 79.896816 NaN 1 \n", "... ... ... ... ... ... \n", - "2020-07-16 313.395304 0.861354 60.141122 321.864382 -1 \n", - "2020-07-17 314.152095 0.864249 60.911280 321.864382 -1 \n", - "2020-07-20 315.076450 0.872298 63.049858 307.890439 1 \n", - "2020-07-21 315.979500 0.874423 63.615869 311.309662 1 \n", - "2020-07-22 316.968636 0.880099 65.149441 312.585425 1 \n", + "2020-07-20 315.076450 0.872298 63.569724 307.890439 1 \n", + "2020-07-21 315.979500 0.874423 64.179426 311.309662 1 \n", + "2020-07-22 316.968636 0.880099 65.830627 312.585425 1 \n", + "2020-07-23 317.513306 0.868096 59.594031 312.585425 1 \n", + "2020-07-24 317.819369 0.861634 56.518677 312.585425 1 \n", "\n", " SUPERTl_7_3.0 SUPERTs_7_3.0 \n", "date \n", @@ -1566,13 +1564,13 @@ "1999-11-04 NaN NaN \n", "1999-11-05 NaN NaN \n", "... ... ... \n", - "2020-07-16 NaN 321.864382 \n", - "2020-07-17 NaN 321.864382 \n", "2020-07-20 307.890439 NaN \n", "2020-07-21 311.309662 NaN \n", "2020-07-22 312.585425 NaN \n", + "2020-07-23 312.585425 NaN \n", + "2020-07-24 312.585425 NaN \n", "\n", - "[5214 rows x 13 columns]" + "[5216 rows x 13 columns]" ] }, "execution_count": 17, @@ -1599,7 +1597,7 @@ { "data": { "text/plain": [ - "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='Runtime Failure', ta=[{'kind': 'percet_return'}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 18, @@ -1666,7 +1664,7 @@ { "data": { "text/plain": [ - "Strategy(name='Volume MAs and Price MA chain', ta=[{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}], description=None, created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='Volume MAs and Price MA chain', ta=[{'kind': 'ema', 'close': 'volume', 'length': 10, 'prefix': 'VOLUME'}, {'kind': 'sma', 'close': 'volume', 'length': 20, 'prefix': 'VOLUME'}, {'kind': 'ema', 'length': 5}, {'kind': 'linreg', 'close': 'EMA_5', 'length': 8, 'prefix': 'EMA_5'}], description=None, created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 20, @@ -1840,38 +1838,14 @@ " ...\n", " \n", " \n", - " 2020-07-16\n", - " 319.7900\n", - " 321.2800\n", - " 319.0900\n", - " 320.7900\n", - " 54433400.0\n", - " 7.880249e+07\n", - " 85750820.85\n", - " 319.046435\n", - " 317.729875\n", - " \n", - " \n", - " 2020-07-17\n", - " 321.8800\n", - " 322.5700\n", - " 319.7400\n", - " 321.7200\n", - " 64421800.0\n", - " 7.618782e+07\n", - " 84954118.65\n", - " 319.937624\n", - " 318.784441\n", - " \n", - " \n", " 2020-07-20\n", " 321.4300\n", " 325.1300\n", " 320.6200\n", " 324.3200\n", - " 56150200.0\n", - " 7.254462e+07\n", - " 81001061.40\n", + " 56150230.0\n", + " 7.254859e+07\n", + " 81019145.80\n", " 321.398416\n", " 320.058000\n", " \n", @@ -1881,9 +1855,9 @@ " 326.9300\n", " 323.9400\n", " 325.0100\n", - " 57245300.0\n", - " 6.976292e+07\n", - " 80162965.80\n", + " 57245315.0\n", + " 6.976618e+07\n", + " 80181050.95\n", " 322.602277\n", " 321.307000\n", " \n", @@ -1893,15 +1867,39 @@ " 327.2000\n", " 324.5000\n", " 326.8600\n", - " 49338600.0\n", - " 6.604941e+07\n", - " 79226550.80\n", + " 57792915.0\n", + " 6.758922e+07\n", + " 79667351.70\n", " 324.021518\n", " 322.687127\n", " \n", + " \n", + " 2020-07-23\n", + " 326.4700\n", + " 327.2300\n", + " 321.4800\n", + " 322.9600\n", + " 75737989.0\n", + " 6.907082e+07\n", + " 76850881.55\n", + " 323.667679\n", + " 323.406458\n", + " \n", + " \n", + " 2020-07-24\n", + " 320.9500\n", + " 321.9900\n", + " 319.2460\n", + " 320.8800\n", + " 73766597.0\n", + " 6.992459e+07\n", + " 76090907.45\n", + " 322.738452\n", + " 323.487321\n", + " \n", " \n", "\n", - "

5214 rows × 9 columns

\n", + "

5216 rows × 9 columns

\n", "" ], "text/plain": [ @@ -1913,11 +1911,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 7.880249e+07 \n", - "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 7.618782e+07 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 7.254462e+07 \n", - "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 6.976292e+07 \n", - "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 6.604941e+07 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150230.0 7.254859e+07 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245315.0 6.976618e+07 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 57792915.0 6.758922e+07 \n", + "2020-07-23 326.4700 327.2300 321.4800 322.9600 75737989.0 6.907082e+07 \n", + "2020-07-24 320.9500 321.9900 319.2460 320.8800 73766597.0 6.992459e+07 \n", "\n", " VOLUME_SMA_20 EMA_5 EMA_5_LR_8 \n", "date \n", @@ -1927,13 +1925,13 @@ "1999-11-04 NaN NaN NaN \n", "1999-11-05 NaN 136.012480 NaN \n", "... ... ... ... \n", - "2020-07-16 85750820.85 319.046435 317.729875 \n", - "2020-07-17 84954118.65 319.937624 318.784441 \n", - "2020-07-20 81001061.40 321.398416 320.058000 \n", - "2020-07-21 80162965.80 322.602277 321.307000 \n", - "2020-07-22 79226550.80 324.021518 322.687127 \n", + "2020-07-20 81019145.80 321.398416 320.058000 \n", + "2020-07-21 80181050.95 322.602277 321.307000 \n", + "2020-07-22 79667351.70 324.021518 322.687127 \n", + "2020-07-23 76850881.55 323.667679 323.406458 \n", + "2020-07-24 76090907.45 322.738452 323.487321 \n", "\n", - "[5214 rows x 9 columns]" + "[5216 rows x 9 columns]" ] }, "execution_count": 22, @@ -1968,7 +1966,7 @@ { "data": { "text/plain": [ - "Strategy(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}], description='BBANDS_20 applied to MACD', created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'prefix': 'MACD'}], description='BBANDS_20 applied to MACD', created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 23, @@ -2157,40 +2155,12 @@ " ...\n", " \n", " \n", - " 2020-07-16\n", - " 319.7900\n", - " 321.2800\n", - " 319.0900\n", - " 320.7900\n", - " 54433400.0\n", - " 3.975091\n", - " 0.595775\n", - " 3.379316\n", - " 1.155506\n", - " 3.237593\n", - " 5.319681\n", - " \n", - " \n", - " 2020-07-17\n", - " 321.8800\n", - " 322.5700\n", - " 319.7400\n", - " 321.7200\n", - " 64421800.0\n", - " 4.136274\n", - " 0.605566\n", - " 3.530708\n", - " 1.297995\n", - " 3.175551\n", - " 5.053107\n", - " \n", - " \n", " 2020-07-20\n", " 321.4300\n", " 325.1300\n", " 320.6200\n", " 324.3200\n", - " 56150200.0\n", + " 56150230.0\n", " 4.422827\n", " 0.713695\n", " 3.709131\n", @@ -2204,7 +2174,7 @@ " 326.9300\n", " 323.9400\n", " 325.0100\n", - " 57245300.0\n", + " 57245315.0\n", " 4.651974\n", " 0.754274\n", " 3.897700\n", @@ -2218,7 +2188,7 @@ " 327.2000\n", " 324.5000\n", " 326.8600\n", - " 49338600.0\n", + " 57792915.0\n", " 4.926070\n", " 0.822696\n", " 4.103374\n", @@ -2226,9 +2196,37 @@ " 3.183563\n", " 5.088035\n", " \n", + " \n", + " 2020-07-23\n", + " 326.4700\n", + " 327.2300\n", + " 321.4800\n", + " 322.9600\n", + " 75737989.0\n", + " 4.773569\n", + " 0.536156\n", + " 4.237413\n", + " 1.215602\n", + " 3.243110\n", + " 5.270617\n", + " \n", + " \n", + " 2020-07-24\n", + " 320.9500\n", + " 321.9900\n", + " 319.2460\n", + " 320.8800\n", + " 73766597.0\n", + " 4.433763\n", + " 0.157080\n", + " 4.276683\n", + " 1.211360\n", + " 3.306770\n", + " 5.402179\n", + " \n", " \n", "\n", - "

5214 rows × 11 columns

\n", + "

5216 rows × 11 columns

\n", "" ], "text/plain": [ @@ -2240,11 +2238,11 @@ "1999-11-04 136.7500 137.3593 135.7656 136.5312 7907500.0 NaN \n", "1999-11-05 138.6250 139.1093 136.7812 137.8750 7431500.0 NaN \n", "... ... ... ... ... ... ... \n", - "2020-07-16 319.7900 321.2800 319.0900 320.7900 54433400.0 3.975091 \n", - "2020-07-17 321.8800 322.5700 319.7400 321.7200 64421800.0 4.136274 \n", - "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150200.0 4.422827 \n", - "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245300.0 4.651974 \n", - "2020-07-22 324.6200 327.2000 324.5000 326.8600 49338600.0 4.926070 \n", + "2020-07-20 321.4300 325.1300 320.6200 324.3200 56150230.0 4.422827 \n", + "2020-07-21 326.4500 326.9300 323.9400 325.0100 57245315.0 4.651974 \n", + "2020-07-22 324.6200 327.2000 324.5000 326.8600 57792915.0 4.926070 \n", + "2020-07-23 326.4700 327.2300 321.4800 322.9600 75737989.0 4.773569 \n", + "2020-07-24 320.9500 321.9900 319.2460 320.8800 73766597.0 4.433763 \n", "\n", " MACDh_12_26_9 MACDs_12_26_9 MACD_BBL_20_2.0 MACD_BBM_20_2.0 \\\n", "date \n", @@ -2254,11 +2252,11 @@ "1999-11-04 NaN NaN NaN NaN \n", "1999-11-05 NaN NaN NaN NaN \n", "... ... ... ... ... \n", - "2020-07-16 0.595775 3.379316 1.155506 3.237593 \n", - "2020-07-17 0.605566 3.530708 1.297995 3.175551 \n", "2020-07-20 0.713695 3.709131 1.351168 3.153296 \n", "2020-07-21 0.754274 3.897700 1.341550 3.157320 \n", "2020-07-22 0.822696 4.103374 1.279092 3.183563 \n", + "2020-07-23 0.536156 4.237413 1.215602 3.243110 \n", + "2020-07-24 0.157080 4.276683 1.211360 3.306770 \n", "\n", " MACD_BBU_20_2.0 \n", "date \n", @@ -2268,13 +2266,13 @@ "1999-11-04 NaN \n", "1999-11-05 NaN \n", "... ... \n", - "2020-07-16 5.319681 \n", - "2020-07-17 5.053107 \n", "2020-07-20 4.955423 \n", "2020-07-21 4.973090 \n", "2020-07-22 5.088035 \n", + "2020-07-23 5.270617 \n", + "2020-07-24 5.402179 \n", "\n", - "[5214 rows x 11 columns]" + "[5216 rows x 11 columns]" ] }, "execution_count": 25, @@ -2316,7 +2314,7 @@ { "data": { "text/plain": [ - "Strategy(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='07/22/2020, 17:02:37', last_run=None, run_time=None)" + "Strategy(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='07/25/2020, 11:24:19', last_run=None, run_time=None)" ] }, "execution_count": 26, @@ -2375,7 +2373,7 @@ "text": [ "\n", "[i] Loaded['D']: SPY_D.csv\n", - "[i] Runtime: 31.6960 ms (0.0317 s)\n" + "[i] Runtime: 34.4336 ms (0.0344 s)\n" ] }, { @@ -2502,7 +2500,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 6.263520\n", + " 50.185503\n", " -0.000461\n", " NaN\n", " 0\n", @@ -2524,7 +2522,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 12.913259\n", + " 69.153995\n", " 0.007120\n", " NaN\n", " 0\n", @@ -2546,7 +2544,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 20.761745\n", + " 79.896816\n", " 0.016915\n", " NaN\n", " 0\n", @@ -2568,7 +2566,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 21.467126\n", + " 80.574537\n", " 0.017821\n", " 0.006845\n", " 0\n", @@ -2590,7 +2588,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 19.534082\n", + " 58.528352\n", " 0.008379\n", " 0.009955\n", " 0\n", @@ -2612,7 +2610,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 25.186415\n", + " 66.303684\n", " 0.015780\n", " 0.013203\n", " 0\n", @@ -2634,7 +2632,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 29.281003\n", + " 70.833962\n", " 0.021438\n", " 0.016066\n", " 0\n", @@ -2656,7 +2654,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 35.346637\n", + " 76.319408\n", " 0.030422\n", " 0.018768\n", " 0\n", @@ -2678,7 +2676,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 36.869425\n", + " 77.514804\n", " 0.032767\n", " 0.021757\n", " 0\n", @@ -2700,7 +2698,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 42.089239\n", + " 81.170904\n", " 0.041099\n", " 0.028301\n", " 0\n", @@ -2722,7 +2720,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 43.685627\n", + " 82.169980\n", " 0.043750\n", " 0.033895\n", " 0\n", @@ -2744,7 +2742,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 47.797173\n", + " 84.527630\n", " 0.050786\n", " 0.039765\n", " 0\n", @@ -2766,7 +2764,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 47.334329\n", + " 83.049344\n", " 0.049909\n", " 0.043662\n", " 0\n", @@ -2788,7 +2786,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 47.211675\n", + " 82.659517\n", " 0.049690\n", " 0.047047\n", " 0\n", @@ -2810,7 +2808,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 42.499547\n", + " 68.775385\n", " 0.040877\n", " 0.047002\n", " 0\n", @@ -2832,7 +2830,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 45.966480\n", + " 71.832489\n", " 0.046174\n", " 0.047487\n", " 0\n", @@ -2854,7 +2852,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 43.955324\n", + " 66.840920\n", " 0.042425\n", " 0.045815\n", " 0\n", @@ -2876,7 +2874,7 @@ " NaN\n", " NaN\n", " 0.0\n", - " 42.097781\n", + " 62.442534\n", " 0.038884\n", " 0.043610\n", " 0\n", @@ -2938,24 +2936,24 @@ "date \n", "1999-11-01 NaN NaN NaN NaN \n", "1999-11-02 NaN NaN 0.000000 -0.007172 \n", - "1999-11-03 NaN NaN 6.263520 -0.000461 \n", - "1999-11-04 NaN NaN 12.913259 0.007120 \n", - "1999-11-05 NaN NaN 20.761745 0.016915 \n", - "1999-11-08 NaN NaN 21.467126 0.017821 \n", - "1999-11-09 NaN NaN 19.534082 0.008379 \n", - "1999-11-10 NaN NaN 25.186415 0.015780 \n", - "1999-11-11 NaN 0.0 29.281003 0.021438 \n", - "1999-11-12 NaN 0.0 35.346637 0.030422 \n", - "1999-11-15 NaN 0.0 36.869425 0.032767 \n", - "1999-11-16 NaN 0.0 42.089239 0.041099 \n", - "1999-11-17 NaN 0.0 43.685627 0.043750 \n", - "1999-11-18 NaN 0.0 47.797173 0.050786 \n", - "1999-11-19 NaN 0.0 47.334329 0.049909 \n", - "1999-11-22 NaN 0.0 47.211675 0.049690 \n", - "1999-11-23 NaN 0.0 42.499547 0.040877 \n", - "1999-11-24 NaN 0.0 45.966480 0.046174 \n", - "1999-11-26 NaN 0.0 43.955324 0.042425 \n", - "1999-11-29 NaN 0.0 42.097781 0.038884 \n", + "1999-11-03 NaN NaN 50.185503 -0.000461 \n", + "1999-11-04 NaN NaN 69.153995 0.007120 \n", + "1999-11-05 NaN NaN 79.896816 0.016915 \n", + "1999-11-08 NaN NaN 80.574537 0.017821 \n", + "1999-11-09 NaN NaN 58.528352 0.008379 \n", + "1999-11-10 NaN NaN 66.303684 0.015780 \n", + "1999-11-11 NaN 0.0 70.833962 0.021438 \n", + "1999-11-12 NaN 0.0 76.319408 0.030422 \n", + "1999-11-15 NaN 0.0 77.514804 0.032767 \n", + "1999-11-16 NaN 0.0 81.170904 0.041099 \n", + "1999-11-17 NaN 0.0 82.169980 0.043750 \n", + "1999-11-18 NaN 0.0 84.527630 0.050786 \n", + "1999-11-19 NaN 0.0 83.049344 0.049909 \n", + "1999-11-22 NaN 0.0 82.659517 0.049690 \n", + "1999-11-23 NaN 0.0 68.775385 0.040877 \n", + "1999-11-24 NaN 0.0 71.832489 0.046174 \n", + "1999-11-26 NaN 0.0 66.840920 0.042425 \n", + "1999-11-29 NaN 0.0 62.442534 0.038884 \n", "\n", " SMA_5_CUMLOGRET 0 30 70 \n", "date \n", diff --git a/pandas_ta/momentum/rsi.py b/pandas_ta/momentum/rsi.py index 87cbea1..777b128 100644 --- a/pandas_ta/momentum/rsi.py +++ b/pandas_ta/momentum/rsi.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from pandas import DataFrame, concat +from pandas_ta.overlap import rma from pandas_ta.utils import get_drift, get_offset, verify_series, signals def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs): @@ -18,10 +19,10 @@ def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs): positive[positive < 0] = 0 # Make negatives 0 for the postive series negative[negative > 0] = 0 # Make postives 0 for the negative series - positive_avg = positive.ewm(com=length, adjust=False).mean() - negative_avg = negative.ewm(com=length, adjust=False).mean().abs() + positive_avg = rma(positive, length=length) + negative_avg = rma(negative, length=length) - rsi = scalar * positive_avg / (positive_avg + negative_avg) + rsi = scalar * positive_avg / (positive_avg + negative_avg.abs()) # Offset if offset != 0: From e643a9847d36a0e546a7b7307723f6b1dacf1bb7 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Sat, 25 Jul 2020 11:51:21 -0700 Subject: [PATCH 10/10] ENH var and stdev ddof addition MAINT refactoring --- pandas_ta/core.py | 2 +- pandas_ta/statistics/entropy.py | 2 +- pandas_ta/statistics/kurtosis.py | 2 +- pandas_ta/statistics/mad.py | 2 +- pandas_ta/statistics/median.py | 2 +- pandas_ta/statistics/quantile.py | 2 +- pandas_ta/statistics/skew.py | 2 +- pandas_ta/statistics/stdev.py | 2 +- pandas_ta/statistics/variance.py | 2 +- pandas_ta/statistics/zscore.py | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pandas_ta/core.py b/pandas_ta/core.py index bfe544b..68140c9 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -21,7 +21,7 @@ from pandas_ta.volatility import * from pandas_ta.volume import * from pandas_ta.utils import * -version = ".".join(("0", "1", "77b")) +version = ".".join(("0", "1", "78b")) # Dictionary of files for each category, used in df.ta.strategy() Category = {name: category_files(name) for name in categories} diff --git a/pandas_ta/statistics/entropy.py b/pandas_ta/statistics/entropy.py index 9b383af..216833d 100644 --- a/pandas_ta/statistics/entropy.py +++ b/pandas_ta/statistics/entropy.py @@ -20,7 +20,7 @@ def entropy(close, length=None, base=None, offset=None, **kwargs): # Name & Category entropy.name = f"ENTP_{length}" - entropy.category = 'statistics' + entropy.category = "statistics" return entropy diff --git a/pandas_ta/statistics/kurtosis.py b/pandas_ta/statistics/kurtosis.py index 261e748..4b6fa82 100644 --- a/pandas_ta/statistics/kurtosis.py +++ b/pandas_ta/statistics/kurtosis.py @@ -18,7 +18,7 @@ def kurtosis(close, length=None, offset=None, **kwargs): # Name & Category kurtosis.name = f"KURT_{length}" - kurtosis.category = 'statistics' + kurtosis.category = "statistics" return kurtosis diff --git a/pandas_ta/statistics/mad.py b/pandas_ta/statistics/mad.py index 1b9fc7a..a355717 100644 --- a/pandas_ta/statistics/mad.py +++ b/pandas_ta/statistics/mad.py @@ -23,7 +23,7 @@ def mad(close, length=None, offset=None, **kwargs): # Name & Category mad.name = f"MAD_{length}" - mad.category = 'statistics' + mad.category = "statistics" return mad diff --git a/pandas_ta/statistics/median.py b/pandas_ta/statistics/median.py index 61503db..dcf43c6 100644 --- a/pandas_ta/statistics/median.py +++ b/pandas_ta/statistics/median.py @@ -18,7 +18,7 @@ def median(close, length=None, offset=None, **kwargs): # Name & Category median.name = f"MEDIAN_{length}" - median.category = 'statistics' + median.category = "statistics" return median diff --git a/pandas_ta/statistics/quantile.py b/pandas_ta/statistics/quantile.py index 515af6e..30a81b0 100644 --- a/pandas_ta/statistics/quantile.py +++ b/pandas_ta/statistics/quantile.py @@ -19,7 +19,7 @@ def quantile(close, length=None, q=None, offset=None, **kwargs): # Name & Category quantile.name = f"QTL_{length}_{q}" - quantile.category = 'statistics' + quantile.category = "statistics" return quantile diff --git a/pandas_ta/statistics/skew.py b/pandas_ta/statistics/skew.py index 8705589..dbed0d4 100644 --- a/pandas_ta/statistics/skew.py +++ b/pandas_ta/statistics/skew.py @@ -24,7 +24,7 @@ def skew(close, length=None, offset=None, **kwargs): # Name & Category skew.name = f"SKEW_{length}" - skew.category = 'statistics' + skew.category = "statistics" return skew diff --git a/pandas_ta/statistics/stdev.py b/pandas_ta/statistics/stdev.py index 74d2fc1..d89561d 100644 --- a/pandas_ta/statistics/stdev.py +++ b/pandas_ta/statistics/stdev.py @@ -20,7 +20,7 @@ def stdev(close, length=None, ddof=1, offset=None, **kwargs): # Name & Category stdev.name = f"STDEV_{length}" - stdev.category = 'statistics' + stdev.category = "statistics" return stdev diff --git a/pandas_ta/statistics/variance.py b/pandas_ta/statistics/variance.py index bb6e2cb..5dc182d 100644 --- a/pandas_ta/statistics/variance.py +++ b/pandas_ta/statistics/variance.py @@ -20,7 +20,7 @@ def variance(close, length=None, ddof=1, offset=None, **kwargs): # Name & Category variance.name = f"VAR_{length}" - variance.category = 'statistics' + variance.category = "statistics" return variance diff --git a/pandas_ta/statistics/zscore.py b/pandas_ta/statistics/zscore.py index 848e49b..09165ed 100644 --- a/pandas_ta/statistics/zscore.py +++ b/pandas_ta/statistics/zscore.py @@ -22,7 +22,7 @@ def zscore(close, length=None, std=None, offset=None, **kwargs): # Name & Category zscore.name = f"Z_{length}" - zscore.category = 'statistics' + zscore.category = "statistics" return zscore