Backtrader: Alpha Vantage Data – Direct Ingest

As noted back in April last year, many of the good quality, free equity data sources from the likes of Yahoo and Quandl are disappearing. This is why companies such as Alpha Vantage are an absolute godsend for the tinkerer and cash-challenged retail trader! In that first post last year, we created a simple script to download and save EOD (End Of Day) data to a CSV File. Now, as a follow up to that script, we will take things a step further. Rather than saving the data to a CSV file, the example code in this post will download the data and directly ingest it into backtrader as a Pandas data feed. This will be useful for those who do not wish to store and manage a large library of CSV files or just want to test some random tickers from time to time.

Getting an API Key

Before we dive into the code. In order to download the data from Alpha Vantage, you must register for an API key. It is free and will grant you lifetime access. If you don’t have one already, head over to the following link and sign up before continuing. Source: https://www.alphavantage.co/support/#api-key

Installation

Once we have an API key, we also need to install a python package to interact with the API. Romel Torres has created an excellent python wrapper for the API. To install it simply type: pip install alpha_vantage Remember to replace pipwithpip3if you already have python2 installed. alpha_vantagerequires a number of dependencies such as pandas. However, Pip should handle it, download and install all required packages for you.

The Code

'''
Author: www.backtest-rookies.com

MIT License

Copyright (c) 2019 backtest-rookies.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'''

from alpha_vantage.timeseries import TimeSeries
import pandas as pd
import numpy as np
import backtrader as bt
from datetime import datetime

# IMPORTANT!
# ----------
# Register for an API at:
# https://www.alphavantage.co/support/#api-key
# Then insert it here.
Apikey = 'INSERT YOUR API KEY'


def alpha_vantage_eod(symbol_list, compact=False, debug=False, *args, **kwargs):
    '''
    Helper function to download Alpha Vantage Data.

    This will return a nested list with each entry containing:
        [0] pandas dataframe
        [1] the name of the feed.
    '''
    data_list = list()

    size = 'compact' if compact else 'full'

    for symbol in symbol_list:

        if debug:
            print('Downloading: {}, Size: {}'.format(symbol, size))

        # Submit our API and create a session
        alpha_ts = TimeSeries(key=Apikey, output_format='pandas')

        data, meta_data = alpha_ts.get_daily(symbol=symbol, outputsize=size)

        #Convert the index to datetime.
        data.index = pd.to_datetime(data.index)
        data.columns = ['Open', 'High', 'Low', 'Close','Volume']

        if debug:
            print(data)

        data_list.append((data, symbol))

    return data_list

class TestStrategy(bt.Strategy):

    def __init__(self):

        pass

    def next(self):

        for i, d in enumerate(self.datas):

            bar = len(d)
            dt = d.datetime.datetime()
            dn = d._name
            o = d.open[0]
            h = d.high[0]
            l = d.low[0]
            c = d.close[0]
            v = d.volume[0]


            print('{} Bar: {} | {} | O: {} H: {} L: {} C: {} V:{}'.format(dt, bar,dn,o,h,l,c,v))


# Create an instance of cerebro
cerebro = bt.Cerebro()

# Add our strategy
cerebro.addstrategy(TestStrategy)

# Download our data from Alpha Vantage.
symbol_list = ['LGEN.L','LLOY.L']
data_list = alpha_vantage_eod(
                symbol_list,
                compact=False,
                debug=False)

for i in range(len(data_list)):

    data = bt.feeds.PandasData(
                dataname=data_list[i][0], # This is the Pandas DataFrame
                name=data_list[i][1], # This is the symbol
                timeframe=bt.TimeFrame.Days,
                compression=1,
                fromdate=datetime(2018,1,1),
                todate=datetime(2019,1,1)
                )

    #Add the data to Cerebro
    cerebro.adddata(data)

print('Starting to run')
# Run the strategy
cerebro.run()

Code Commentary

Before trying to run the code, be sure to update the API key:
# IMPORTANT!
# ----------
# Register for an API at:
# https://www.alphavantage.co/support/#api-key
# Then insert it here.
Apikey = 'INSERT YOUR API KEY'
Most of the magic in this script happens within the alpha_vantage_eod()function. It is here that we download the data and massage it into a format that we can easily pass to Backtrader.  As such, it makes sense to go over the function parameters:
  • symbol_list: Is a simple list of symbols/tickers that we will download. If you just want to download a single instrument then simply place a single ticker inside a list like so: symbol_list = ['AAPL']
  • compact: This is useful for testing. It will download only the last 100 data points and as such data download speeds are much quicker. Set this parameter to Trueif you wish to speed things up.
  • debug: Will just provide some extra prints to the terminal in case you are getting some weird results. Using this option may allow you to see which symbol/ticker is giving you pain.
The alpha_vantage_eod()function will return a nested list of data feeds. In other words, each entry in the returned list is another list. The nested (second) lists contain two items. The first item (at index position [0]) is the pandas dataframe and the second item (at index position [1]) is the symbol string for that dataframe. Having  easy access to the symbol allows us to add it as the name of the datafeed in backtrader. Regarding the strategy, it was only designed for testing / checking the feeds are added correctly. However, one thing that can be noted is that the next()method (function) has been coded in a way to support multiple data feeds.  As such, the strategy can support one or more data feeds and handle them appropriately to print out their OHLCVvalues. For more information on how to create a more complete strategy that supports multiple data feeds, see this tutorial. For those interested, further API information can be found here: Reference: https://www.alphavantage.co/documentation/

Output

Running the script you should see some output that looks like this: Image showing the terminal output from the code example

Notes and Further Improvements:

  1. Alpha Vantage has API call limits. When using their free API, you are limited to 5 API calls per minute and a total of 500 a day. Therefore, if you have a large symbol list (over 5) then you will need to add a sleep function to wait 12 seconds between downloads. This is obviously slow down the initialization of the backtest too. So if you plan on making a large number of API calls, you may want to consider saving the output to CSV as shown in the previous post.
  2. The example code above downloads unadjusted data. If you require adjusted data, Alpha Vantage does provide this. However, they only provide an adjusted close value. Therefore, some extra work is required to massage the open, high and low values if you still want to work with OHLCdata. A future post may cover this!
  3. Alpha Vantage also provide Intra-day Equity, FX and Crypto data! Readers may want to use this code example as a base to access these other feeds.

Find This Post Useful?

If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny. 

Backtest Rookies is a registered with Brave publisher!

Brave users can drop us a tip.

Alternatively, support us by switching to Brave using this referral link and we will receive some BAT! 


https://brave.com/bac691

Referral Link

Enjoying the content and thinking of subscribing to Tradingview? Support this site by clicking the referral link before you sign up! 

https://tradingview.go2cloud.org/SHpB


Donate with PayPal using any payment method you are comfortable with! 


3HxNVyh5729ieTfPnTybrtK7J7QxJD9gjD

0x9a2f88198224d59e5749bacfc23d79507da3d431

M8iUBnb8KamHR18gpgi2sSG7jopddFJi8S