Back to Community
How to use talib.ATR with history()?

Does anyone know how to use the new history(20,'1d',...) functionality with talib.ATR? (not ta.ATR) ATR needs high, low, and close data so somehow the panels from history() need to be merged?

Any help much appreciated!

James

8 responses

James,

You can use history to get the fields in separate DataFrames, then pass a column from each one to talib.ATR, see the example

Clone Algorithm
38
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month

import talib


STOCK = sid(8554)

def initialize(context):
    pass

# Will be called on every trade event for the securities you specify. 
def handle_data(context, data):
    highs = history(20, '1d', 'high')[STOCK]
    lows = history(20, '1d', 'low')[STOCK]
    closes = history(20, '1d', 'close_price')[STOCK]
    
    ATR = talib.ATR(highs, lows, closes)
    # ATR returns an array, you want the last value
    ATR = ATR[-1]
    record(ATR=ATR)
There was a runtime error.

HI David,

Thanks for that, will it also work for multiple stocks (at once)?

James

Hello James,

Here's an example for ROC:

https://www.quantopian.com/posts/roc-in-quantopian

I expect it'll work for ATR, as well.

[EDIT:] Oops...missed your comment about the merging business...if you can't get it to work, I should have time later today to fiddle with it.

Grant

James,

Here's what I pulled together:

import talib  
import pandas as pd

def initialize(context):  
    context.stocks = [ sid(19662),  # XLY Consumer Discrectionary SPDR Fund  
                       sid(19656),  # XLF Financial SPDR Fund  
                       sid(19658),  # XLK Technology SPDR Fund  
                       sid(19655),  # XLE Energy SPDR Fund  
                       sid(19661),  # XLV Health Care SPRD Fund  
                       sid(19657),  # XLI Industrial SPDR Fund  
                       sid(19659),  # XLP Consumer Staples SPDR Fund  
                       sid(19654),  # XLB Materials SPDR Fund  
                       sid(19660) ] # XLU Utilities SPRD Fund

def handle_data(context, data):  
    highs = history(20, '1d', 'high')  
    lows = history(20, '1d', 'low')  
    closes = history(20, '1d', 'close_price')  
    ATR = pd.DataFrame(index=closes.index,columns=closes.columns)  
    for stock in list(closes.columns.values):  
        ATR[stock] = talib.ATR(highs[stock],lows[stock],closes[stock])  
    print ATR.tail(1)  

The for-loop is not elegant, but it does the job. Does the algo spit out the correct ATR values?

Grant

Clone Algorithm
15
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
import pandas as pd

def initialize(context):
    
    context.stocks = [ sid(19662),  # XLY Consumer Discrectionary SPDR Fund
                       sid(19656),  # XLF Financial SPDR Fund
                       sid(19658),  # XLK Technology SPDR Fund
                       sid(19655),  # XLE Energy SPDR Fund
                       sid(19661),  # XLV Health Care SPRD Fund
                       sid(19657),  # XLI Industrial SPDR Fund
                       sid(19659),  # XLP Consumer Staples SPDR Fund
                       sid(19654),  # XLB Materials SPDR Fund
                       sid(19660) ] # XLU Utilities SPRD Fund

def handle_data(context, data):
    
    highs = history(20, '1d', 'high')
    lows = history(20, '1d', 'low')
    closes = history(20, '1d', 'close_price')
    
    ATR = pd.DataFrame(index=closes.index,columns=closes.columns)
    for stock in list(closes.columns.values):
        ATR[stock] = talib.ATR(highs[stock],lows[stock],closes[stock])
    
    print ATR.tail(1)
There was a runtime error.

Thanks Grant!

Is there a way to make it work with history dataframes shorter than two weeks? I get NaN values with daily dataframes shorter than 15. I have read two weeks is the typical period but it seems like a strange limitation.

Thanks for any help

Clone Algorithm
2
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
import pandas as pd

def initialize(context):
    
    context.stocks = [ sid(19662),  # XLY Consumer Discrectionary SPDR Fund
                       sid(19656),  # XLF Financial SPDR Fund
                       sid(19658),  # XLK Technology SPDR Fund
                       sid(19655),  # XLE Energy SPDR Fund
                       sid(19661),  # XLV Health Care SPRD Fund
                       sid(19657),  # XLI Industrial SPDR Fund
                       sid(19659),  # XLP Consumer Staples SPDR Fund
                       sid(19654),  # XLB Materials SPDR Fund
                       sid(19660) ] # XLU Utilities SPRD Fund

def handle_data(context, data):
    
    highs = history(14, '1d', 'high')
    lows = history(14, '1d', 'low')
    closes = history(14, '1d', 'close_price')
    
    ATR = pd.DataFrame(index=closes.index,columns=closes.columns)
    for stock in list(closes.columns.values):
        ATR[stock] = talib.ATR(highs[stock],lows[stock],closes[stock])
    
    print ATR.tail(1)
There was a runtime error.

Robby, you will have to change the 'timeperiod' parameter in the talib.ATR function. The default is 14, so you will need to use 15 bars before you stop getting NaN values. I added a context variable to set the window used in the ATR calculations. In general, for talib functions with a timeperiod parameter, you need either the same number of bars or one more bar than the timeperiod used.

Clone Algorithm
11
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
import pandas as pd

def initialize(context):
    
    context.stocks = [ sid(19662),  # XLY Consumer Discrectionary SPDR Fund
                       sid(19656),  # XLF Financial SPDR Fund
                       sid(19658),  # XLK Technology SPDR Fund
                       sid(19655),  # XLE Energy SPDR Fund
                       sid(19661),  # XLV Health Care SPRD Fund
                       sid(19657),  # XLI Industrial SPDR Fund
                       sid(19659),  # XLP Consumer Staples SPDR Fund
                       sid(19654),  # XLB Materials SPDR Fund
                       sid(19660) ] # XLU Utilities SPRD Fund
    context.atr_window = 5

def handle_data(context, data):
    
    highs = history(14, '1d', 'high')
    lows = history(14, '1d', 'low')
    closes = history(14, '1d', 'close_price')
    
    ATR = pd.DataFrame(index=closes.index,columns=closes.columns)
    for stock in list(closes.columns.values):
        ATR[stock] = talib.ATR(highs[stock],lows[stock],closes[stock],
                               timeperiod=context.atr_window)
    
    print ATR.tail(1)
There was a runtime error.

thanks David. i assumed it autoset to the length of the history frames because it gave me an error when trying to use frames of different lengths, and when trying use slices. next time i will rtfm.