Files
pandas-ta/examples/PandasTA_Study_Examples.ipynb
T

231 KiB
Raw Blame History

Pandas TA (pandas_ta) Studies for Custom Technical Analysis

Topics

  • What is a Pandas TA Study?
    • Builtin Studies: AllStudy and CommonStudy
    • Creating Studies
  • Watchlist Class
    • Study Management and Execution
    • NOTE: The watchlist module is independent of Pandas TA. To easily use it, copy it from your local pandas_ta installation directory into your project directory.
  • Indicator Composition/Chaining for more Complex Studies
    • Comprehensive Example: MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns
In [1]:
%matplotlib inline
import datetime as dt

from tqdm import tqdm

import pandas as pd
import pandas_ta as ta
from alphaVantageAPI.alphavantage import AlphaVantage  # pip install alphaVantage-api

from watchlist import Watchlist # Is this failing? If so, copy it locally. See above.

print(f"\nPandas TA v{ta.version}\nTo install the Latest Version:\n$ pip install -U git+https://github.com/twopirllc/pandas-ta\n")
%pylab inline
Pandas TA v0.3.48b0
To install the Latest Version:
$ pip install -U git+https://github.com/twopirllc/pandas-ta

Populating the interactive namespace from numpy and matplotlib

What is a Pandas TA Study?

A Study is a simple way to name and group TA indicators. Technically, a Study is a simple Data Class to contain list of indicators and their parameters. Note: Study is experimental and subject to change. Pandas TA comes with two basic Studies: AllStudy and CommonStudy.

Study 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 Study tries to capture. Default: None
  • created: At datetime string of when it was created. Default: Automatically generated.

Things to note:

  • A Study will fail when consumed by Pandas TA if there is no {"kind": "indicator name"} attribute.

Builtin Examples

All

Default Values

In [2]:
AllStudy = ta.AllStudy
print(f"{AllStudy.name = }")
print(f"{AllStudy.description = }")
print(f"{AllStudy.created = }")
print(f"{AllStudy.ta = }")
print(f"{AllStudy.cores = }")
AllStudy.name = 'All'
AllStudy.description = 'All the indicators with their default settings. Pandas TA default.'
AllStudy.created = 'Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)'
AllStudy.ta = None
AllStudy.cores = 8

Common

Default Values

In [3]:
CommonStudy = ta.CommonStudy
print(f"{CommonStudy.name = }")
print(f"{CommonStudy.description = }")
print(f"{CommonStudy.created = }")
print(f"{CommonStudy.ta = }")
print(f"{CommonStudy.cores = }")
CommonStudy.name = 'Common Price and Volume SMAs'
CommonStudy.description = 'Common Price SMAs: 10, 20, 50, 200 and Volume SMA: 20.'
CommonStudy.created = 'Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)'
CommonStudy.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'}]
CommonStudy.cores = 0
In [ ]:

Creating Studies

Studies require a name and an array of dicts containing the "kind" of indicator ("sma") and other potential parameters for ta.

Simple Study A

In [4]:
custom_a = ta.Study(name="A", cores=0, ta=[{"kind": "sma", "length": 50}, {"kind": "sma", "length": 200}])
custom_a
Out [4]:
Study(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')

Simple Study B

In [5]:
custom_b = ta.Study(name="B", cores=0, ta=[{"kind": "ema", "length": 8}, {"kind": "ema", "length": 21}, {"kind": "log_return", "cumulative": True}, {"kind": "rsi"}, {"kind": "supertrend"}])
custom_b
Out [5]:
Study(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')

Bad Study. (Misspelled Indicator)

In [6]:
# Misspelled indicator, will fail later when ran with Pandas TA
custom_run_failure = ta.Study(name="Runtime Failure", cores=0, ta=[{"kind": "peret_return"}])
custom_run_failure
Out [6]:
Study(name='Runtime Failure', ta=[{'kind': 'peret_return'}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [ ]:

Study Management and Execution with Watchlist

Initialize AlphaVantage Data Source

In [7]:
AV = AlphaVantage(
    api_key="YOUR API KEY", premium=False,
    output_size='full', clean=True,
    export_path=".", export=True
)
AV
Out [7]:
AlphaVantage(
  end_point:str = https://www.alphavantage.co/query,
  api_key:str = YOUR API KEY,
  export:bool = True,
  export_path:str = .,
  output_size:str = full,
  output:str = csv,
  datatype:str = json,
  clean:bool = True,
  proxy:dict = {}
)

Create Watchlist and set it's 'ds' to AlphaVantage

In [8]:
data_source = "av" # Default
data_source = "yahoo"
watch = Watchlist(["SPY", "IWM"], ds_name=data_source, timed=True)

Info about the Watchlist. Note, the default Study is "All"

In [9]:
watch
Out [9]:
Watch(name='Watch: SPY, IWM', ds_name='yahoo', tickers[2]='SPY, IWM', tf='D', study[5]='Common Price and Volume SMAs')

Help about Watchlist

In [10]:
help(Watchlist)
Help on class Watchlist in module watchlist:

class Watchlist(builtins.object)
 |  Watchlist(tickers: list, tf: str = None, name: str = None, study: pandas_ta.utils._study.Study = None, ds_name: str = 'av', **kwargs)
 |  
 |  # 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 Study.
 |  
 |  Default Study: pandas_ta.CommonStudy
 |  
 |  ## Package Support:
 |  ### Data Source (Default: AlphaVantage)
 |  - AlphaVantage (pip install alphaVantage-api).
 |  - Python Binance (pip install python-binance). # Future Support
 |  - Yahoo Finance (pip install yfinance). # Almost Supported
 |  
 |  # Technical Analysis:
 |  - Pandas TA (pip install pandas_ta)
 |  
 |  ## Required Arguments:
 |  - tickers: A list of strings containing tickers. Example: ["SPY", "AAPL"]
 |  
 |  Methods defined here:
 |  
 |  __init__(self, tickers: list, tf: str = None, name: str = None, study: pandas_ta.utils._study.Study = None, ds_name: str = 'av', **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __repr__(self) -> str
 |      Return repr(self).
 |  
 |  indicators(self, *args, **kwargs) -> <built-in function any>
 |      Returns the list of indicators that are available with Pandas Ta.
 |  
 |  load(self, ticker: str = None, tf: str = None, index: str = 'date', drop: list = [], plot: bool = False, **kwargs) -> pandas.core.frame.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.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  data
 |      When not None, it contains a dictionary of DataFrames keyed by ticker. data = {"SPY": pd.DataFrame, ...}
 |  
 |  name
 |      The name of the Watchlist. Default: "Watchlist: {Watchlist.tickers}".
 |  
 |  strategy
 |      Sets a valid Strategy. Default: pandas_ta.CommonStrategy
 |  
 |  study
 |      Sets a valid Study. Default: pandas_ta.CommonStudy
 |  
 |  tf
 |      Alias for timeframe. Default: 'D'
 |  
 |  tickers
 |      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.
 |  
 |  verbose
 |      Toggle the verbose property. Default: False

Default Study is "Common"

In [11]:
# No arguments loads all the tickers and applies the Study to each ticker.
# The result can be accessed with Watchlist's 'data' property which returns a 
# dictionary keyed by ticker and DataFrames as values 
watch.load(verbose=True)
[!] Loading All: SPY, IWM
[i] Loaded SPY[D]: SPY_D.csv
[+] Study: Common Price and Volume SMAs
[i] Indicator arguments: {'timed': True, 'append': True}
[i] No mulitproccessing (cores = 0).
[i] Progress: 100%|█| 5/5 [00:00<
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Monday February 28, 2022, NYSE: 7:02:33, Local: 11:02:33 PST, Day 59/365 (16.00%)
[i] Analysis Time: 57.8152 ms (0.0578 s) for 5 columns (avg 11.5647 ms / col).
[i] Loaded IWM[D]: IWM_D.csv
[+] Study: Common Price and Volume SMAs
[i] Indicator arguments: {'timed': True, 'append': True}
[i] No mulitproccessing (cores = 0).
[i] Progress: 100%|█| 5/5 [00:00<
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Monday February 28, 2022, NYSE: 7:02:33, Local: 11:02:33 PST, Day 59/365 (16.00%)
[i] Analysis Time: 5.0522 ms (0.0051 s) for 5 columns (avg 1.0112 ms / col).
In [12]:
", ".join([f"{t}: {d.shape}" for t,d in watch.data.items()])
Out [12]:
'SPY: (7324, 12), IWM: (5474, 12)'
In [13]:
watch.data["SPY"]
Out [13]:
Open High Low Close Volume Dividends Stock Splits SMA_10 SMA_20 SMA_50 SMA_200 VOL_SMA_20
Date
1993-01-29 25.645567 25.645567 25.517978 25.627340 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.645570 25.809614 25.645570 25.809614 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.791378 25.882514 25.736697 25.864286 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.900760 26.155940 25.882533 26.137712 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.228853 26.301761 25.937218 26.247080 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 443.084003 443.732504 456.582517 442.721047 1.252365e+08
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 440.185004 443.106505 455.639678 442.761832 1.234655e+08
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 437.261002 442.852504 454.906946 442.852832 1.248431e+08
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 436.104001 443.178004 454.427191 443.034645 1.234349e+08
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 435.430002 442.766504 453.722542 443.172199 1.192668e+08

7324 rows × 12 columns

In [ ]:
In [14]:
watch.load("SPY", plot=True, mas=True)
Out [14]:
[i] Loaded SPY[D]: SPY_D.csv
[i] Analysis Time: 4.1666 ms (0.0042 s) for 5 columns (avg 0.8351 ms / col).
Open High Low Close Volume Dividends Stock Splits SMA_10 SMA_20 SMA_50 SMA_200 VOL_SMA_20
Date
1993-01-29 25.645567 25.645567 25.517978 25.627340 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.645570 25.809614 25.645570 25.809614 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.791378 25.882514 25.736697 25.864286 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.900760 26.155940 25.882533 26.137712 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.228853 26.301761 25.937218 26.247080 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 443.084003 443.732504 456.582517 442.721047 1.252365e+08
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 440.185004 443.106505 455.639678 442.761832 1.234655e+08
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 437.261002 442.852504 454.906946 442.852832 1.248431e+08
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 436.104001 443.178004 454.427191 443.034645 1.234349e+08
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 435.430002 442.766504 453.722542 443.172199 1.192668e+08

7324 rows × 12 columns

In [ ]:

Easy to swap Studies and run them

Running Simple Study A

In [15]:
# Load custom_a into Watchlist and verify
watch.study = custom_a
watch.study
Out [15]:
Study(name='A', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [16]:
watch.load("IWM")
Out [16]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 1.7527 ms (0.0018 s) for 2 columns (avg 0.8802 ms / col).
Open High Low Close Volume Dividends Stock Splits SMA_50 SMA_200
Date
2000-05-26 34.332581 34.473965 34.167634 34.473965 74800 0.0 0.0 NaN NaN
2000-05-30 34.968825 35.746433 34.968825 35.746433 57600 0.0 0.0 NaN NaN
2000-05-31 35.864218 36.335495 35.864218 35.875999 36000 0.0 0.0 NaN NaN
2000-06-01 36.612378 36.688961 36.612378 36.688961 7000 0.0 0.0 NaN NaN
2000-06-02 38.350228 38.597649 38.350228 38.597649 29400 0.0 0.0 NaN NaN
... ... ... ... ... ... ... ... ... ...
2022-02-22 198.479996 200.449997 195.350006 196.660004 31847100 0.0 0.0 209.63768 220.087778
2022-02-23 198.240005 198.899994 192.550003 192.979996 31491500 0.0 0.0 209.11240 219.962649
2022-02-24 188.320007 198.479996 187.919998 198.039993 52221100 0.0 0.0 208.75240 219.866293
2022-02-25 198.690002 202.619995 197.000000 202.500000 33631400 0.0 0.0 208.51880 219.827520
2022-02-28 200.470001 204.600006 200.479904 202.509995 20468009 0.0 0.0 208.21740 219.769443

5474 rows × 9 columns

Running Simple Study B

In [17]:
# Load custom_b into Watchlist and verify
watch.study = custom_b
watch.study
Out [17]:
Study(name='B', ta=[{'kind': 'ema', 'length': 8}, {'kind': 'ema', 'length': 21}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'rsi'}, {'kind': 'supertrend'}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [18]:
watch.load("IWM")
Out [18]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 247.7720 ms (0.2478 s) for 8 columns (avg 30.9721 ms / col).
Open High Low Close Volume Dividends Stock Splits EMA_8 EMA_21 CUMLOGRET_1 RSI_14 SUPERT_7_3.0 SUPERTd_7_3.0 SUPERTl_7_3.0 SUPERTs_7_3.0
Date
2000-05-26 34.332581 34.473965 34.167634 34.473965 74800 0.0 0.0 NaN NaN 0.000000 NaN 0.000000 1 NaN NaN
2000-05-30 34.968825 35.746433 34.968825 35.746433 57600 0.0 0.0 NaN NaN 0.036246 NaN NaN 1 NaN NaN
2000-05-31 35.864218 36.335495 35.864218 35.875999 36000 0.0 0.0 NaN NaN 0.039864 NaN NaN 1 NaN NaN
2000-06-01 36.612378 36.688961 36.612378 36.688961 7000 0.0 0.0 NaN NaN 0.062272 NaN NaN 1 NaN NaN
2000-06-02 38.350228 38.597649 38.350228 38.597649 29400 0.0 0.0 NaN NaN 0.112987 NaN NaN 1 NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-22 198.479996 200.449997 195.350006 196.660004 31847100 0.0 0.0 200.961183 202.721204 1.741272 40.121546 213.017055 -1 NaN 213.017055
2022-02-23 198.240005 198.899994 192.550003 192.979996 31491500 0.0 0.0 199.187586 201.835640 1.722382 36.468006 211.403898 -1 NaN 211.403898
2022-02-24 188.320007 198.479996 187.919998 198.039993 52221100 0.0 0.0 198.932565 201.490581 1.748265 44.016839 211.164767 -1 NaN 211.164767
2022-02-25 198.690002 202.619995 197.000000 202.500000 33631400 0.0 0.0 199.725328 201.582346 1.770535 49.691015 211.164767 -1 NaN 211.164767
2022-02-28 200.470001 204.600006 200.479904 202.509995 20468009 0.0 0.0 200.344143 201.666678 1.770585 49.703318 211.164767 -1 NaN 211.164767

5474 rows × 15 columns

Running Bad Study. (Misspelled indicator)

In [19]:
# Load custom_run_failure into Watchlist and verify
watch.study = custom_run_failure
watch.study
Out [19]:
Study(name='Runtime Failure', ta=[{'kind': 'peret_return'}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [20]:
try:
    iwm = watch.load("IWM")
except AttributeError as error:
    print(f"[X] Oops! {error}")
[i] Loaded IWM[D]: IWM_D.csv
[X] Oops! 'AnalysisIndicators' object has no attribute 'peret_return'
In [ ]:

Indicator Composition/Chaining

  • When you need an indicator to depend on the value of a prior indicator
  • Utilitze prefix or suffix to help identify unique columns or avoid column name clashes.
  • Set cores=0 for better performance when few indicators

Volume MAs and MA chains

In [21]:
# Set EMA's and SMA's 'close' to 'volume' to create Volume MAs, prefix 'volume' MAs with 'VOLUME' so easy to identify the column
# Take a price EMA and apply LINREG from EMA's output
volmas_price_ma_chain = [
    {"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"},
]
vp_ma_chain_ta = ta.Study("Volume MAs and Price MA chain", cores=0, ta=volmas_price_ma_chain)
vp_ma_chain_ta
Out [21]:
Study(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'}], cores=0, description='', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [22]:
# Update the Watchlist
watch.study = vp_ma_chain_ta
watch.study.name
Out [22]:
'Volume MAs and Price MA chain'
In [23]:
spy = watch.load("SPY")
spy
Out [23]:
[i] Loaded SPY[D]: SPY_D.csv
[i] Analysis Time: 2.6769 ms (0.0027 s) for 4 columns (avg 0.6714 ms / col).
Open High Low Close Volume Dividends Stock Splits VOLUME_EMA_10 VOLUME_SMA_20 EMA_5 EMA_5_LR_8
Date
1993-01-29 25.645567 25.645567 25.517978 25.627340 1003200 0.0 0 NaN NaN NaN NaN
1993-02-01 25.645570 25.809614 25.645570 25.809614 480500 0.0 0 NaN NaN NaN NaN
1993-02-02 25.791378 25.882514 25.736697 25.864286 201300 0.0 0 NaN NaN NaN NaN
1993-02-03 25.900760 26.155940 25.882533 26.137712 529400 0.0 0 NaN NaN NaN NaN
1993-02-04 26.228853 26.301761 25.937218 26.247080 531500 0.0 0 NaN NaN 25.937207 NaN
... ... ... ... ... ... ... ... ... ... ... ...
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 1.159478e+08 1.252365e+08 436.476400 438.103977
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 1.189715e+08 1.234655e+08 431.634270 434.610989
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 1.362390e+08 1.248431e+08 430.522843 431.390383
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 1.335984e+08 1.234349e+08 432.931895 429.881644
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 1.240521e+08 1.192668e+08 433.194597 429.579707

7324 rows × 11 columns

In [ ]:

MACD BBANDS

In [24]:
# MACD is the initial indicator that BBANDS depends on.
# 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
macd_bands_ta = [
    {"kind":"macd"},
    {"kind":"bbands", "close": "MACD_12_26_9", "length": 20, "ddof": 0, "prefix": "MACD"}
]
macd_bands_ta = ta.Study("MACD BBands", cores=0, ta=macd_bands_ta, description=f"BBANDS_{macd_bands_ta[1]['length']} applied to MACD")
macd_bands_ta
Out [24]:
Study(name='MACD BBands', ta=[{'kind': 'macd'}, {'kind': 'bbands', 'close': 'MACD_12_26_9', 'length': 20, 'ddof': 0, 'prefix': 'MACD'}], cores=0, description='BBANDS_20 applied to MACD', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [25]:
# Update the Watchlist
watch.study = macd_bands_ta
watch.study.name
Out [25]:
'MACD BBands'
In [26]:
spy = watch.load("SPY")
spy
Out [26]:
[i] Loaded SPY[D]: SPY_D.csv
[i] Analysis Time: 4.4833 ms (0.0045 s) for 8 columns (avg 0.5609 ms / col).
Open High Low Close Volume Dividends Stock Splits MACD_12_26_9 MACDh_12_26_9 MACDs_12_26_9 MACD_BBL_20_2.0 MACD_BBM_20_2.0 MACD_BBU_20_2.0 MACD_BBB_20_2.0 MACD_BBP_20_2.0
Date
1993-01-29 25.645567 25.645567 25.517978 25.627340 1003200 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-01 25.645570 25.809614 25.645570 25.809614 480500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-02 25.791378 25.882514 25.736697 25.864286 201300 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-03 25.900760 26.155940 25.882533 26.137712 529400 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-04 26.228853 26.301761 25.937218 26.247080 531500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 -5.233734 -1.083594 -4.150140 -8.736828 -5.040904 -1.344981 -146.637319 0.473913
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 -6.404132 -1.803194 -4.600938 -8.676812 -5.018951 -1.361090 -145.761973 0.310657
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 -6.741579 -1.712512 -5.029066 -8.484443 -4.964817 -1.445191 -141.782713 0.247592
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 -6.175286 -0.916976 -5.258310 -7.980895 -4.839860 -1.698824 -129.798625 0.287423
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 -5.982717 -0.579525 -5.403192 -7.467832 -4.719630 -1.971427 -116.458406 0.270198

7324 rows × 15 columns

In [ ]:

Comprehensive Study

MACD and RSI Momentum with BBANDS and SMAs and Cumulative Log Returns

In [27]:
momo_bands_sma_ta = [
    {"kind":"sma", "length": 50},
    {"kind":"sma", "length": 200},
    {"kind":"bbands", "length": 20, "ddof": 0},
    {"kind":"macd"},
    {"kind":"rsi"},
    {"kind":"log_return", "cumulative": True},
    {"kind":"sma", "close": "CUMLOGRET_1", "length": 5, "suffix": "CUMLOGRET"},
]
momo_bands_sma_Study = ta.Study(
    name="Momo, Bands and SMAs and Cumulative Log Returns", # name
    ta=momo_bands_sma_ta, # ta
    description="MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns", # description
    cores=0
)
momo_bands_sma_Study
Out [27]:
Study(name='Momo, Bands and SMAs and Cumulative Log Returns', ta=[{'kind': 'sma', 'length': 50}, {'kind': 'sma', 'length': 200}, {'kind': 'bbands', 'length': 20, 'ddof': 0}, {'kind': 'macd'}, {'kind': 'rsi'}, {'kind': 'log_return', 'cumulative': True}, {'kind': 'sma', 'close': 'CUMLOGRET_1', 'length': 5, 'suffix': 'CUMLOGRET'}], cores=0, description='MACD and RSI Momo with BBANDS and SMAs 50 & 200 and Cumulative Log Returns', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [28]:
# Update the Watchlist
watch.study = momo_bands_sma_Study
watch.study.name
Out [28]:
'Momo, Bands and SMAs and Cumulative Log Returns'
In [29]:
spy = watch.load("SPY")
# Apply constants to the DataFrame for indicators
spy.ta.constants(True, [0, 30, 70])
spy.tail()
Out [29]:
[i] Loaded SPY[D]: SPY_D.csv
[i] Analysis Time: 7.0055 ms (0.0070 s) for 13 columns (avg 0.5394 ms / col).
Open High Low Close Volume Dividends Stock Splits SMA_50 SMA_200 BBL_20_2.0 ... BBP_20_2.0 MACD_12_26_9 MACDh_12_26_9 MACDs_12_26_9 RSI_14 CUMLOGRET_1 SMA_5_CUMLOGRET 0 30 70
Date
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 456.582517 442.721047 427.227554 ... 0.070962 -5.233734 -1.083594 -4.150140 36.088546 2.819125 2.840067 0 30 70
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 455.639678 442.761832 424.436141 ... -0.066580 -6.404132 -1.803194 -4.600938 32.177252 2.801227 2.828936 0 30 70
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 454.906946 442.852832 423.532824 ... 0.123376 -6.741579 -1.712512 -5.029066 38.189228 2.816164 2.820568 0 30 70
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 454.427191 443.034645 424.441322 ... 0.355150 -6.175286 -0.916976 -5.258310 45.878058 2.837988 2.820884 0 30 70
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 453.722542 443.172199 423.583827 ... 0.264201 -5.982717 -0.579525 -5.403192 43.398750 2.828739 2.820649 0 30 70

5 rows × 23 columns

In [ ]:

Additional Study Options

The params keyword takes a tuple as a shorthand to the parameter arguments in order.

  • Note: If the indicator arguments change, so will results. Breaking Changes will always be posted on the README.

The col_numbers keyword takes a tuple specifying which column to return if the result is a DataFrame.

In [30]:
params_ta = [
    {"kind":"ema", "params": (10,)},
    # params sets MACD's keyword arguments: fast=9, slow=19, signal=10
    # and returning the 2nd column: histogram
    {"kind":"macd", "params": (9, 19, 10), "col_numbers": (1,)},
    # Selects the Lower and Upper Bands and renames them LB and UB, ignoring the MB
    {"kind":"bbands", "col_numbers": (0,2), "col_names": ("LB", "UB")},
    {"kind":"log_return", "params": (5, False)},
]
params_ta_Study = ta.Study(
    name="EMA, MACD History, Outter BBands, Log Returns", # name
    ta=params_ta, # ta
    description="EMA, MACD History, BBands(LB, UB), and Log Returns Study", # description
    cores=0
)
params_ta_Study
Out [30]:
Study(name='EMA, MACD History, Outter BBands, Log Returns', ta=[{'kind': 'ema', 'params': (10,)}, {'kind': 'macd', 'params': (9, 19, 10), 'col_numbers': (1,)}, {'kind': 'bbands', 'col_numbers': (0, 2), 'col_names': ('LB', 'UB')}, {'kind': 'log_return', 'params': (5, False)}], cores=0, description='EMA, MACD History, BBands(LB, UB), and Log Returns Study', created='Monday February 28, 2022, NYSE: 7:02:32, Local: 11:02:32 PST, Day 59/365 (16.00%)')
In [31]:
# Update the Watchlist
watch.study = params_ta_Study
watch.study.name
Out [31]:
'EMA, MACD History, Outter BBands, Log Returns'
In [32]:
spy = watch.load("SPY")
spy.tail()
Out [32]:
[i] Loaded SPY[D]: SPY_D.csv
[i] Analysis Time: 4.8132 ms (0.0048 s) for 5 columns (avg 0.9637 ms / col).
Open High Low Close Volume Dividends Stock Splits EMA_10 MACDh_9_19_10 LB UB LOGRET_5
Date
2022-02-22 431.890015 435.500000 425.859985 429.570007 124391800 0.0 0 440.455752 -1.389834 425.349472 452.074540 -0.021760
2022-02-23 432.660004 433.260010 421.350006 421.950012 132578000 0.0 0 437.091072 -2.234858 417.561858 450.202156 -0.055656
2022-02-24 411.019989 428.760010 410.640015 428.299988 213942900 0.0 0 435.492693 -2.003742 419.815568 440.628438 -0.041839
2022-02-25 429.609985 437.839996 427.859985 437.750000 121715600 0.0 0 435.903112 -0.893305 419.582816 441.137191 0.001577
2022-02-28 432.029999 438.200012 431.859985 433.720001 81093943 0.0 0 435.506183 -0.439231 419.620509 440.895495 -0.001175
In [ ]:

Disclaimer

  • All investments involve risk, and the past performance of a security, industry, sector, market, financial product, trading Study, or individuals trading does not guarantee future results or returns. Investors are fully responsible for any investment decisions they make. Such decisions should be based solely on an evaluation of their financial circumstances, investment objectives, risk tolerance, and liquidity needs.

  • Any opinions, news, research, analyses, prices, or other information offered is provided as general market commentary, and does not constitute investment advice. I will not accept liability for any loss or damage, including without limitation any loss of profit, which may arise directly or indirectly from use of or reliance on such information.

In [ ]: