Skip to content

Commit e669812

Browse files
dwrpaynebashtage
authored andcommitted
Bank of Canada data source
1 parent f50e5cc commit e669812

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

pandas_datareader/bankofcanada.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from __future__ import unicode_literals
2+
3+
import pandas.compat as compat
4+
from pandas_datareader.base import _BaseReader
5+
6+
class BankOfCanadaReader(_BaseReader):
7+
8+
"""Get data for the given name from Bank of Canada."""
9+
10+
_URL = 'http://www.bankofcanada.ca/valet/observations'
11+
12+
@property
13+
def url(self):
14+
if not isinstance(self.symbols, compat.string_types):
15+
raise ValueError('data name must be string')
16+
17+
return '{0}/{1}/csv'.format(self._URL, self.symbols)
18+
19+
@property
20+
def params(self):
21+
return {'start_date': self.start.strftime('%Y-%m-%d'),
22+
'end_date': self.end.strftime('%Y-%m-%d')}
23+
24+
@staticmethod
25+
def _sanitize_response(response):
26+
"""
27+
Clean up the response string
28+
"""
29+
data = response.text.split('OBSERVATIONS')[1]
30+
return data.split('ERRORS')[0].strip()

pandas_datareader/base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
class _BaseReader(object):
1818

1919
"""
20-
2120
Parameters
2221
----------
2322
sym : string with a single Single stock symbol (ticker).

pandas_datareader/data.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pandas_datareader.yahoo.components import _get_data as get_components_yahoo # noqa
1515
from pandas_datareader.yahoo.options import Options as YahooOptions
1616

17+
from pandas_datareader.bankofcanada import BankOfCanadaReader
1718
from pandas_datareader.eurostat import EurostatReader
1819
from pandas_datareader.fred import FredReader
1920
from pandas_datareader.famafrench import FamaFrenchReader
@@ -69,10 +70,8 @@ def DataReader(name, data_source=None, start=None, end=None,
6970
retry_count=3, pause=0.001, session=None, access_key=None):
7071
"""
7172
Imports data from a number of online sources.
72-
7373
Currently supports Yahoo! Finance, Google Finance, St. Louis FED (FRED),
7474
Kenneth French's data library, and the SEC's EDGAR Index.
75-
7675
Parameters
7776
----------
7877
name : str or list of strs
@@ -92,29 +91,22 @@ def DataReader(name, data_source=None, start=None, end=None,
9291
single value given for symbol, represents the pause between retries.
9392
session : Session, default None
9493
requests.sessions.Session instance to be used
95-
9694
Examples
9795
----------
98-
9996
# Data from Yahoo! Finance
10097
gs = DataReader("GS", "yahoo")
101-
10298
# Corporate Actions (Dividend and Split Data)
10399
# with ex-dates from Yahoo! Finance
104100
gs = DataReader("GS", "yahoo-actions")
105-
106101
# Data from Google Finance
107102
aapl = DataReader("AAPL", "google")
108-
109103
# Data from FRED
110104
vix = DataReader("VIXCLS", "fred")
111-
112105
# Data from Fama/French
113106
ff = DataReader("F-F_Research_Data_Factors", "famafrench")
114107
ff = DataReader("F-F_Research_Data_Factors_weekly", "famafrench")
115108
ff = DataReader("6_Portfolios_2x3", "famafrench")
116109
ff = DataReader("F-F_ST_Reversal_Factor", "famafrench")
117-
118110
# Data from EDGAR index
119111
ed = DataReader("full", "edgar-index")
120112
ed2 = DataReader("daily", "edgar-index")
@@ -140,6 +132,11 @@ def DataReader(name, data_source=None, start=None, end=None,
140132
chunksize=25,
141133
retry_count=retry_count, pause=pause,
142134
session=session).read()
135+
136+
elif data_source == "bankofcanada":
137+
return BankOfCanadaReader(symbols=name, start=start, end=end,
138+
retry_count=retry_count, pause=pause,
139+
session=session).read()
143140

144141
elif data_source == "enigma":
145142
return EnigmaReader(dataset_id=name, api_key=access_key).read()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from datetime import date, timedelta
2+
import pytest
3+
4+
from pandas_datareader._utils import RemoteDataError
5+
import pandas_datareader.data as web
6+
7+
8+
class TestBankOfCanada(object):
9+
10+
@staticmethod
11+
def get_symbol(currency_code, inverted=False):
12+
if inverted:
13+
return 'FXCAD{}'.format(currency_code)
14+
else:
15+
return 'FX{}CAD'.format(currency_code)
16+
17+
def check_bankofcanada_count(self, code):
18+
df = web.DataReader(self.get_symbol(code), 'bankofcanada', date.today() - timedelta(days=30), date.today())
19+
assert df.size > 15
20+
21+
def check_bankofcanada_valid(self, code):
22+
symbol = self.get_symbol(code)
23+
df = web.DataReader(symbol, 'bankofcanada', date.today() - timedelta(days=30), date.today())
24+
assert symbol in df.columns
25+
26+
def check_bankofcanada_inverted(self, code):
27+
symbol = self.get_symbol(code)
28+
symbol_inverted = self.get_symbol(code, inverted=True)
29+
30+
df = web.DataReader(symbol, 'bankofcanada', date.today() - timedelta(days=30), date.today())
31+
df_inv = web.DataReader(symbol_inverted, 'bankofcanada', date.today() - timedelta(days=30), date.today())
32+
33+
pairs = zip((1/df)[symbol].tolist(), df_inv[symbol_inverted].tolist())
34+
assert all(a-b < 0.01 for a, b in pairs)
35+
36+
def test_bankofcanada_usd_count(self):
37+
self.check_bankofcanada_count('USD')
38+
39+
def test_bankofcanada_eur_count(self):
40+
self.check_bankofcanada_count('EUR')
41+
42+
def test_bankofcanada_usd_valid(self):
43+
self.check_bankofcanada_valid('USD')
44+
45+
def test_bankofcanada_eur_valid(self):
46+
self.check_bankofcanada_valid('EUR')
47+
48+
def test_bankofcanada_usd_inverted(self):
49+
self.check_bankofcanada_inverted('USD')
50+
51+
def test_bankofcanada_eur_inverted(self):
52+
self.check_bankofcanada_inverted('EUR')
53+
54+
def test_bankofcanada_bad_range(self):
55+
with pytest.raises(RemoteDataError):
56+
web.DataReader('FXCADUSD', 'bankofcanada', date.today(), date.today() - timedelta(days=30))
57+
58+
def test_bankofcanada_bad_url(self):
59+
with pytest.raises(RemoteDataError):
60+
web.DataReader('abcdefgh', 'bankofcanada', date.today(), date.today() - timedelta(days=30))

0 commit comments

Comments
 (0)