Files
pandas-ta/examples/PandasTA_Study_Examples.ipynb
T

222 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.32b0
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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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
[+] Downloading[yahoo]: SPY[D]
[+] yf | SPY(7310, 7): 4522.0008 ms (4.5220 s)
[+] Saving: /Users/kj/av_data/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, 122.64it/s]
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Monday February 7, 2022, NYSE: 5:46:21, Local: 9:46:21 PST, Day 38/365 (10.00%)
[i] Analysis Time: 55.7978 ms (0.0558 s)
[+] Downloading[yahoo]: IWM[D]
[+] yf | IWM(5460, 7): 3960.7030 ms (3.9607 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, 1266.47it/s]
[i] Total indicators: 5
[i] Columns added: 5
[i] Last Run: Monday February 7, 2022, NYSE: 5:46:25, Local: 9:46:25 PST, Day 38/365 (10.00%)
[i] Analysis Time: 5.0981 ms (0.0051 s)
In [12]:
", ".join([f"{t}: {d.shape}" for t,d in watch.data.items()])
Out [12]:
'SPY: (7310, 12), IWM: (5460, 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.645573 25.645573 25.517983 25.627346 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.645579 25.809624 25.645579 25.809624 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.791393 25.882529 25.736712 25.864302 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.900767 26.155947 25.882540 26.137720 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.228843 26.301752 25.937209 26.247070 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 442.022003 454.610001 461.063572 440.467170 126778345.0
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 442.582004 453.600002 460.865603 440.713518 129087460.0
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 442.567004 452.511002 460.478942 440.886810 129761735.0
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 443.639005 451.549002 460.121924 441.089413 131335570.0
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 444.420245 450.627122 459.719042 441.264651 129058021.6

7310 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.2129 ms (0.0042 s)
Open High Low Close Volume Dividends Stock Splits SMA_10 SMA_20 SMA_50 SMA_200 VOL_SMA_20
Date
1993-01-29 25.645573 25.645573 25.517983 25.627346 1003200 0.0 0 NaN NaN NaN NaN NaN
1993-02-01 25.645579 25.809624 25.645579 25.809624 480500 0.0 0 NaN NaN NaN NaN NaN
1993-02-02 25.791393 25.882529 25.736712 25.864302 201300 0.0 0 NaN NaN NaN NaN NaN
1993-02-03 25.900767 26.155947 25.882540 26.137720 529400 0.0 0 NaN NaN NaN NaN NaN
1993-02-04 26.228843 26.301752 25.937209 26.247070 531500 0.0 0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 442.022003 454.610001 461.063572 440.467170 126778345.0
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 442.582004 453.600002 460.865603 440.713518 129087460.0
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 442.567004 452.511002 460.478942 440.886810 129761735.0
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 443.639005 451.549002 460.121924 441.089413 131335570.0
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 444.420245 450.627122 459.719042 441.264651 129058021.6

7310 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.00%)')
In [16]:
watch.load("IWM")
Out [16]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 2.1510 ms (0.0022 s)
Open High Low Close Volume Dividends Stock Splits SMA_50 SMA_200
Date
2000-05-26 34.332574 34.473957 34.167627 34.473957 74800 0.0 0.0 NaN NaN
2000-05-30 34.968806 35.746414 34.968806 35.746414 57600 0.0 0.0 NaN NaN
2000-05-31 35.864248 36.335526 35.864248 35.876030 36000 0.0 0.0 NaN NaN
2000-06-01 36.612394 36.688976 36.612394 36.688976 7000 0.0 0.0 NaN NaN
2000-06-02 38.350235 38.597656 38.350235 38.597656 29400 0.0 0.0 NaN NaN
... ... ... ... ... ... ... ... ... ...
2022-02-01 201.660004 203.570007 197.970001 203.360001 43429400 0.0 0.0 215.571844 221.587410
2022-02-02 203.619995 203.899994 199.289993 201.339996 42777800 0.0 0.0 214.958340 221.516338
2022-02-03 198.839996 201.240005 197.050003 197.529999 39629400 0.0 0.0 214.288376 221.399866
2022-02-04 197.039993 200.100006 194.919998 198.380005 34238900 0.0 0.0 213.643388 221.292209
2022-02-07 198.429993 200.699997 197.990005 199.100006 14568016 0.0 0.0 213.007815 221.167410

5460 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.00%)')
In [18]:
watch.load("IWM")
Out [18]:
[i] Loaded IWM[D]: IWM_D.csv
[i] Analysis Time: 256.9024 ms (0.2569 s)
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.332574 34.473957 34.167627 34.473957 74800 0.0 0.0 NaN NaN 0.000000 NaN 0.000000 1 NaN NaN
2000-05-30 34.968806 35.746414 34.968806 35.746414 57600 0.0 0.0 NaN NaN 0.036246 NaN NaN 1 NaN NaN
2000-05-31 35.864248 36.335526 35.864248 35.876030 36000 0.0 0.0 NaN NaN 0.039865 NaN NaN 1 NaN NaN
2000-06-01 36.612394 36.688976 36.612394 36.688976 7000 0.0 0.0 NaN NaN 0.062272 NaN NaN 1 NaN NaN
2000-06-02 38.350235 38.597656 38.350235 38.597656 29400 0.0 0.0 NaN NaN 0.112987 NaN NaN 1 NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-01 201.660004 203.570007 197.970001 203.360001 43429400 0.0 0.0 200.301436 206.124694 1.774774 43.961827 213.373369 -1 NaN 213.373369
2022-02-02 203.619995 203.899994 199.289993 201.339996 42777800 0.0 0.0 200.532228 205.689722 1.764791 41.878172 213.373369 -1 NaN 213.373369
2022-02-03 198.839996 201.240005 197.050003 197.529999 39629400 0.0 0.0 199.865066 204.947929 1.745686 38.200475 213.373369 -1 NaN 213.373369
2022-02-04 197.039993 200.100006 194.919998 198.380005 34238900 0.0 0.0 199.535052 204.350845 1.749980 39.477464 213.373369 -1 NaN 213.373369
2022-02-07 198.429993 200.699997 197.990005 199.100006 14568016 0.0 0.0 199.438375 203.873496 1.753603 40.597174 213.373369 -1 NaN 213.373369

5460 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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: 3.1504 ms (0.0032 s)
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.645573 25.645573 25.517983 25.627346 1003200 0.0 0 NaN NaN NaN NaN
1993-02-01 25.645579 25.809624 25.645579 25.809624 480500 0.0 0 NaN NaN NaN NaN
1993-02-02 25.791393 25.882529 25.736712 25.864302 201300 0.0 0 NaN NaN NaN NaN
1993-02-03 25.900767 26.155947 25.882540 26.137720 529400 0.0 0 NaN NaN NaN NaN
1993-02-04 26.228843 26.301752 25.937209 26.247070 531500 0.0 0 NaN NaN 25.937212 NaN
... ... ... ... ... ... ... ... ... ... ... ...
2022-02-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 1.489213e+08 126778345.0 445.815160 440.058132
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 1.431831e+08 129087460.0 449.660109 444.740702
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 1.386088e+08 129761735.0 448.640075 448.179915
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 1.349227e+08 131335570.0 448.660054 450.446614
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 1.175757e+08 129058021.6 448.324171 451.300024

7310 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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: 5.8750 ms (0.0059 s)
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.645573 25.645573 25.517983 25.627346 1003200 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-01 25.645579 25.809624 25.645579 25.809624 480500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-02 25.791393 25.882529 25.736712 25.864302 201300 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-03 25.900767 26.155947 25.882540 26.137720 529400 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
1993-02-04 26.228843 26.301752 25.937209 26.247070 531500 0.0 0 NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2022-02-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 -6.355974 -0.385707 -5.970267 -10.847819 -1.971159 6.905502 -900.654085 0.253014
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 -5.089661 0.704485 -5.794146 -10.909064 -2.448053 6.012958 -691.244083 0.343895
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 -4.897084 0.717650 -5.614733 -10.902124 -2.880662 5.140800 -556.917940 0.374311
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 -4.522875 0.873487 -5.396362 -10.817408 -3.263513 4.290382 -462.930241 0.416642
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 -4.261719 0.907714 -5.169433 -10.688294 -3.599817 3.488660 -393.824272 0.453311

7310 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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.8356 ms (0.0078 s)
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-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 461.063572 440.467170 426.328965 ... 0.470652 -6.355974 -0.385707 -5.970267 49.051706 2.872122 2.847201 0 30 70
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 460.865603 440.713518 427.294308 ... 0.571277 -5.089661 0.704485 -5.794146 52.739652 2.881789 2.857968 0 30 70
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 460.478942 440.886810 426.950170 ... 0.384374 -4.897084 0.717650 -5.614733 44.302038 2.858003 2.864968 0 30 70
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 460.121924 441.089413 426.953306 ... 0.442084 -4.522875 0.873487 -5.396362 46.115639 2.862695 2.867999 0 30 70
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 459.719042 441.264651 426.914311 ... 0.437276 -4.261719 0.907714 -5.169433 45.322806 2.860357 2.866993 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 7, 2022, NYSE: 5:46:16, Local: 9:46:16 PST, Day 38/365 (10.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: 6.0854 ms (0.0061 s)
Open High Low Close Volume Dividends Stock Splits EMA_10 MACDh_9_19_10 LB UB LOGRET_5
Date
2022-02-01 450.679993 453.630005 446.940002 452.950012 123155400 0.0 0 446.298610 0.683990 424.623547 459.148463 0.041655
2022-02-02 455.500000 458.119995 453.049988 457.350006 117361000 0.0 0 448.307954 1.932347 428.254768 465.105242 0.053834
2022-02-03 450.950012 452.970001 445.709991 446.600006 118024400 0.0 0 447.997418 1.748571 439.214911 460.289105 0.034999
2022-02-04 446.350006 452.779999 443.829987 448.700012 118335600 0.0 0 448.125163 1.778507 443.623448 458.580568 0.015158
2022-02-07 449.510010 450.859985 446.769989 447.652405 39513832 0.0 0 448.039207 1.668326 442.682020 458.618957 -0.005031
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 [ ]: