Files
pandas-ta/examples/PandasTA_Study_Examples.ipynb
T

235 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.54b0
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 = 'Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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 = 'Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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<00:00, 130.05it/s]
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.00%)
[i] Analysis Time: 64.1480 ms (0.0641 s) for 5 columns (avg 12.8315 ms / col)
[+] Downloading[yahoo]: IWM[D]
[+] yf | IWM(5493, 7): 3181.7138 ms (3.1817 s)
[+] Saving: /Users/kj/av_data/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<00:00, 1049.73it/s]
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Friday March 25, 2022, NYSE: 4:36:03, Local: 8:36:03 PDT, Day 84/365 (23.00%)
[i] Analysis Time: 6.5667 ms (0.0066 s) for 5 columns (avg 1.3141 ms / col)
In [12]:
", ".join([f"{t}: {d.shape}" for t,d in watch.data.items()])
Out [12]:
'SPY: (7343, 12), IWM: (5493, 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.566158 25.566158 25.438963 25.547987 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.566152 25.729689 25.566152 25.729689 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.711512 25.802366 25.657000 25.784195 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.820536 26.074926 25.802366 26.056755 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.147597 26.220280 25.856866 26.165768 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 428.742212 429.172800 440.424402 443.089030 123319985.0
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 432.205124 430.240318 440.123272 443.253448 120832915.0
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 433.976492 431.398157 439.717905 443.388472 118175320.0
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 436.609262 432.573979 439.361801 443.560056 110706460.0
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 439.630359 433.203265 438.950176 443.714416 105823648.3

7343 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: 5.2975 ms (0.0053 s) for 5 columns (avg 1.0611 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.566158 25.566158 25.438963 25.547987 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.566152 25.729689 25.566152 25.729689 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.711512 25.802366 25.657000 25.784195 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.820536 26.074926 25.802366 26.056755 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.147597 26.220280 25.856866 26.165768 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 428.742212 429.172800 440.424402 443.089030 123319985.0
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 432.205124 430.240318 440.123272 443.253448 120832915.0
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 433.976492 431.398157 439.717905 443.388472 118175320.0
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 436.609262 432.573979 439.361801 443.560056 110706460.0
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 439.630359 433.203265 438.950176 443.714416 105823648.3

7343 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.00%)')
In [16]:
watch.load("IWM")
Out [16]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 2.0662 ms (0.0021 s) for 2 columns (avg 1.0370 ms / col)
Open High Low Close Volume Dividends Stock Splits SMA_50 SMA_200
Date
2000-05-26 34.265232 34.406338 34.100608 34.406338 74800 0.0 0.0 NaN NaN
2000-05-30 34.900195 35.676277 34.900195 35.676277 57600 0.0 0.0 NaN NaN
2000-05-31 35.793886 36.264239 35.793886 35.805645 36000 0.0 0.0 NaN NaN
2000-06-01 36.540549 36.616982 36.540549 36.616982 7000 0.0 0.0 NaN NaN
2000-06-02 38.274980 38.521915 38.274980 38.521915 29400 0.0 0.0 NaN NaN
... ... ... ... ... ... ... ... ... ...
2022-03-21 206.793514 207.771587 203.539915 205.036972 26747500 0.0 0.0 201.746244 217.737591
2022-03-22 205.905258 208.380389 205.396264 207.092926 24699900 0.0 0.0 201.575179 217.631726
2022-03-23 205.745571 206.793514 203.350285 203.499985 19775000 0.0 0.0 201.347227 217.495812
2022-03-24 204.380005 205.899994 202.729996 205.839996 19731700 0.4 0.0 201.120365 217.379275
2022-03-25 206.089996 206.619995 204.449997 205.070007 6913761 0.0 0.0 200.910439 217.267384

5493 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.00%)')
In [18]:
watch.load("IWM")
Out [18]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 291.3743 ms (0.2914 s) for 8 columns (avg 36.4225 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.265232 34.406338 34.100608 34.406338 74800 0.0 0.0 NaN NaN 0.000000 NaN NaN NaN NaN NaN
2000-05-30 34.900195 35.676277 34.900195 35.676277 57600 0.0 0.0 NaN NaN 0.036245 NaN NaN NaN NaN NaN
2000-05-31 35.793886 36.264239 35.793886 35.805645 36000 0.0 0.0 NaN NaN 0.039865 NaN NaN NaN NaN NaN
2000-06-01 36.540549 36.616982 36.540549 36.616982 7000 0.0 0.0 NaN NaN 0.062271 NaN NaN NaN NaN NaN
2000-06-02 38.274980 38.521915 38.274980 38.521915 29400 0.0 0.0 NaN NaN 0.112987 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-03-21 206.793514 207.771587 203.539915 205.036972 26747500 0.0 0.0 201.810704 200.489627 1.784950 55.186551 209.222114 -1.0 NaN 209.222114
2022-03-22 205.905258 208.380389 205.396264 207.092926 24699900 0.0 0.0 202.984531 201.089927 1.794927 57.336042 209.222114 -1.0 NaN 209.222114
2022-03-23 205.745571 206.793514 203.350285 203.499985 19775000 0.0 0.0 203.099077 201.309023 1.777425 52.588795 209.222114 -1.0 NaN 209.222114
2022-03-24 204.380005 205.899994 202.729996 205.839996 19731700 0.4 0.0 203.708170 201.720930 1.788858 55.190946 209.222114 -1.0 NaN 209.222114
2022-03-25 206.089996 206.619995 204.449997 205.070007 6913761 0.0 0.0 204.010800 202.025391 1.785111 54.138003 209.222114 -1.0 NaN 209.222114

5493 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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.7383 ms (0.0027 s) for 4 columns (avg 0.6859 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.566158 25.566158 25.438963 25.547987 1003200 0.0 0 NaN NaN NaN NaN
1993-02-01 25.566152 25.729689 25.566152 25.729689 480500 0.0 0 NaN NaN NaN NaN
1993-02-02 25.711512 25.802366 25.657000 25.784195 201300 0.0 0 NaN NaN NaN NaN
1993-02-03 25.820536 26.074926 25.802366 26.056755 529400 0.0 0 NaN NaN NaN NaN
1993-02-04 26.147597 26.220280 25.856866 26.165768 531500 0.0 0 NaN NaN 25.856879 NaN
... ... ... ... ... ... ... ... ... ... ... ...
2022-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 1.095882e+08 123319985.0 438.254397 435.509988
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 1.032359e+08 120832915.0 442.032930 440.881722
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 9.890684e+07 118175320.0 442.621949 444.560222
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 9.266299e+07 110706460.0 445.244630 447.088724
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 8.020577e+07 105823648.3 446.489757 448.436489

7343 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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: 6.3230 ms (0.0063 s) for 8 columns (avg 0.7911 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.566158 25.566158 25.438963 25.547987 1003200 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-01 25.566152 25.729689 25.566152 25.729689 480500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-02 25.711512 25.802366 25.657000 25.784195 201300 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-03 25.820536 26.074926 25.802366 26.056755 529400 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-04 26.147597 26.220280 25.856866 26.165768 531500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 -0.963212 3.165579 -4.128790 -8.444926 -5.428754 -2.412583 -111.118362 1.240267
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 0.435860 3.651720 -3.215860 -9.101777 -5.146085 -1.190393 -153.735975 1.205559
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 1.065150 3.424809 -2.359658 -9.517220 -4.773612 -0.030005 -198.742870 1.115435
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 2.079721 3.551503 -1.471782 -9.843831 -4.333591 1.176648 -254.303610 1.081945
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 2.730458 3.361792 -0.631334 -10.125351 -3.889260 2.346830 -320.682608 1.030759

7343 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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: 9.0647 ms (0.0091 s) for 13 columns (avg 0.6977 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-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 440.424402 443.089030 411.721471 ... 0.935990 -0.963212 3.165579 -4.128790 57.318881 2.856144 2.840482 0 30 70
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 440.123272 443.253448 410.665112 ... 0.994239 0.435860 3.651720 -3.215860 60.266397 2.867778 2.851802 0 30 70
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 439.717905 443.388472 411.493926 ... 0.811538 1.065150 3.424809 -2.359658 55.657410 2.854815 2.856143 0 30 70
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 439.361801 443.560056 411.134941 ... 0.917836 2.079721 3.551503 -1.471782 59.510462 2.869777 2.860990 0 30 70
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 438.950176 443.714416 410.643102 ... 0.849659 2.730458 3.361792 -0.631334 58.279543 2.866420 2.862987 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='Friday March 25, 2022, NYSE: 4:36:00, Local: 8:36:00 PDT, Day 84/365 (23.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: 5.4253 ms (0.0054 s) for 5 columns (avg 1.0861 ms / col)
Open High Low Close Volume Dividends Stock Splits EMA_10 MACDh_9_19_10 LB UB LOGRET_5
Date
2022-03-21 444.339996 446.459991 440.679993 444.390015 88349800 0.0 0 433.646674 3.859133 422.794521 452.299498 0.066718
2022-03-22 445.859985 450.579987 445.859985 449.589996 74650400 0.0 0 436.545460 4.296679 432.162252 452.827702 0.056600
2022-03-23 446.910004 448.489990 443.709991 443.799988 79426100 0.0 0 437.864465 3.814877 438.116668 450.684931 0.021706
2022-03-24 445.940002 450.500000 444.760010 450.489990 64565700 0.0 0 440.160015 3.831127 440.822922 452.293069 0.024234
2022-03-25 451.160004 452.980011 448.429993 448.980011 24148266 0.0 0 441.763651 3.454843 441.875188 453.024812 0.009983
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.