Get a list of ASX stocks that have a market capitlisation greater than $100 million from Eoddata.com, then use this list to download as much daily data as possible for each stock in the list from Yahoo Finance.
Next, run a backtest for a momentum trading strategy with trading signals generated by Doncian Channels, which is one of the signals that Richard Dennis' Turtle Traders used.
Note: This analysis of the momentum strategy assumes/suffers from the following:
1.1 Mathjax Basic Tutorial and Quick Reference
1.2 Github Markdown Cheatsheet
2.1 Plotly Offline 2.2 Eoddata.com Web Service 2.3 Pandas Time Series Offset Aliases
In [1]:
# %matplotlib inline
from getpass import getpass
from pandas_datareader import data
from datetime import datetime, timedelta
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import requests as r
import pandas as pd
import xml.etree.cElementTree as etree
# allow plotly to embed plots in notebook
init_notebook_mode(connected=True)
# constants
web_service = 'http://ws.eoddata.com/data.asmx'
name_space ='http://ws.eoddata.com/Data'
exchange = 'ASX'
# ivars
min_mcap = 100000000
min_days_traded = 250
start = '1999-01-01'
end = str(datetime.now())[:10]
In [2]:
eoddata_username = getpass()
In [3]:
eoddata_password = getpass()
In [8]:
# set params to make the login call
call = 'Login'
url = '/'.join((web_service, call))
params = {'Username': eoddata_username, 'Password': eoddata_password}
# make login call
s = r.Session()
response = s.get(url, params=params, stream=True)
# set token if login was successful
if response.status_code == 200:
xml_doc_root = etree.parse(response.raw).getroot()
if xml_doc_root.get('Message') == 'Login Successful':
token = xml_doc_root.get('Token')
Here we are going to make a call to get a list of fundamentals for each stock from the ASX. This uses a web service call named FundamentalList.
In [9]:
# set params to make the fundamental list call
call = 'FundamentalList'
url = '/'.join((web_service, call))
params = {'Token': token, 'Exchange': exchange}
# make fundamental list call
response = s.get(url, params=params, stream=True)
xml_doc_root = etree.parse(response.raw).getroot()
# get a list of ticker symbols for all stocks that have a market cap greater than
# the threshold established by min_mcap
symbol_list = []
for fundamental in xml_doc_root.findall(".//{%s}FUNDAMENTAL" % (name_space)):
if int(fundamental.get('MarketCap')) >= min_mcap:
symbol_list.append([
fundamental.get('Symbol'),
fundamental.get('Name'),
int(fundamental.get('MarketCap')),])
# create a dataframe from the data returned to use as a reference/lookup table later
df = pd.DataFrame(symbol_list, columns=['yahoo_ticker', 'name', 'mcap'])
df = df.sort_values(by='mcap', ascending=False).reset_index(drop=True)
symbol_list = None
# create a column that will hold the ticker symbols Yahoo Finance expects
df['yahoo_ticker'] = df['yahoo_ticker'] + '.AX'
# place the ticker symbols into a separate list to keep our later code tidier,
# and determine how many stocks we have in the list
stocks = df['yahoo_ticker'].values.tolist()
len(stocks)
In [13]:
%%time
prices = data.DataReader(stocks, 'yahoo', start, end)['Adj Close']
In [14]:
stats = prices.describe().transpose()
cols_to_drop = list(stats[stats['count'] < min_days_traded].index)
len(cols_to_drop)
Out[14]:
In [15]:
prices.drop(cols_to_drop, axis=1, inplace=True)
prices.iloc[:, 0:10].head()
Out[15]:
In [16]:
prices.fillna(method='ffill', inplace=True)
prices.iloc[:, 0:10].head()
Out[16]:
In [19]:
iplot([{'x': prices.index, 'y': prices['CBA.AX']}])