Support Bank of Canada daily exchange rates.
This commit is contained in:
parent
039d7fb809
commit
947eaacd29
10 changed files with 818 additions and 32 deletions
|
@ -80,6 +80,18 @@ date,base,quote,amount,source,type
|
|||
END
|
||||
run_test "$name" "$cmd" "$expected"
|
||||
|
||||
name="Bank of Canada"
|
||||
cmd="pricehist fetch bankofcanada CAD/USD -s 2021-01-04 -e 2021-01-08"
|
||||
read -r -d '' expected <<END
|
||||
date,base,quote,amount,source,type
|
||||
2021-01-04,CAD,USD,0.7843,bankofcanada,default
|
||||
2021-01-05,CAD,USD,0.7870,bankofcanada,default
|
||||
2021-01-06,CAD,USD,0.7883,bankofcanada,default
|
||||
2021-01-07,CAD,USD,0.7870,bankofcanada,default
|
||||
2021-01-08,CAD,USD,0.7871,bankofcanada,default
|
||||
END
|
||||
run_test "$name" "$cmd" "$expected"
|
||||
|
||||
name="Coinbase Pro"
|
||||
cmd="pricehist fetch coinbasepro BTC/EUR -s 2021-01-04 -e 2021-01-08"
|
||||
read -r -d '' expected <<END
|
||||
|
|
246
tests/pricehist/sources/test_bankofcanada.py
Normal file
246
tests/pricehist/sources/test_bankofcanada.py
Normal file
|
@ -0,0 +1,246 @@
|
|||
import logging
|
||||
import os
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
import responses
|
||||
|
||||
from pricehist import exceptions
|
||||
from pricehist.price import Price
|
||||
from pricehist.series import Series
|
||||
from pricehist.sources.bankofcanada import BankOfCanada
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def src():
|
||||
return BankOfCanada()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def type(src):
|
||||
return src.types()[0]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def requests_mock():
|
||||
with responses.RequestsMock() as mock:
|
||||
yield mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def series_list_url():
|
||||
return "https://www.bankofcanada.ca/valet/lists/series/json"
|
||||
|
||||
|
||||
def fetch_url(series_name):
|
||||
return f"https://www.bankofcanada.ca/valet/observations/{series_name}/json"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def series_list_json():
|
||||
dir = Path(os.path.splitext(__file__)[0])
|
||||
return (dir / "series-partial.json").read_text()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def series_list_response_ok(requests_mock, series_list_url, series_list_json):
|
||||
requests_mock.add(responses.GET, series_list_url, body=series_list_json, status=200)
|
||||
yield requests_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def recent_response_ok(requests_mock):
|
||||
json = (Path(os.path.splitext(__file__)[0]) / "recent.json").read_text()
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), body=json, status=200)
|
||||
yield requests_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def all_response_ok(requests_mock):
|
||||
json = (Path(os.path.splitext(__file__)[0]) / "all-partial.json").read_text()
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), body=json, status=200)
|
||||
yield requests_mock
|
||||
|
||||
|
||||
def test_normalizesymbol(src):
|
||||
assert src.normalizesymbol("cad") == "CAD"
|
||||
assert src.normalizesymbol("usd") == "USD"
|
||||
|
||||
|
||||
def test_metadata(src):
|
||||
assert isinstance(src.id(), str)
|
||||
assert len(src.id()) > 0
|
||||
|
||||
assert isinstance(src.name(), str)
|
||||
assert len(src.name()) > 0
|
||||
|
||||
assert isinstance(src.description(), str)
|
||||
assert len(src.description()) > 0
|
||||
|
||||
assert isinstance(src.source_url(), str)
|
||||
assert src.source_url().startswith("http")
|
||||
|
||||
assert datetime.strptime(src.start(), "%Y-%m-%d")
|
||||
|
||||
assert isinstance(src.types(), list)
|
||||
assert len(src.types()) > 0
|
||||
assert isinstance(src.types()[0], str)
|
||||
assert len(src.types()[0]) > 0
|
||||
|
||||
assert isinstance(src.notes(), str)
|
||||
|
||||
|
||||
def test_symbols(src, series_list_response_ok):
|
||||
syms = src.symbols()
|
||||
assert ("CAD/USD", "Canadian dollar to US dollar daily exchange rate") in syms
|
||||
assert len(syms) > 3
|
||||
|
||||
|
||||
def test_symbols_requests_logged(src, series_list_response_ok, caplog):
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
src.symbols()
|
||||
assert any(
|
||||
["DEBUG" == r.levelname and "curl " in r.message for r in caplog.records]
|
||||
)
|
||||
|
||||
|
||||
def test_symbols_not_found(src, requests_mock, series_list_url):
|
||||
requests_mock.add(responses.GET, series_list_url, body='{"series":{}}', status=200)
|
||||
with pytest.raises(exceptions.ResponseParsingError) as e:
|
||||
src.symbols()
|
||||
assert "data not found" in str(e.value)
|
||||
|
||||
|
||||
def test_symbols_network_issue(src, requests_mock, series_list_url):
|
||||
requests_mock.add(
|
||||
responses.GET,
|
||||
series_list_url,
|
||||
body=requests.exceptions.ConnectionError("Network issue"),
|
||||
)
|
||||
with pytest.raises(exceptions.RequestError) as e:
|
||||
src.symbols()
|
||||
assert "Network issue" in str(e.value)
|
||||
|
||||
|
||||
def test_symbols_bad_status(src, requests_mock, series_list_url):
|
||||
requests_mock.add(responses.GET, series_list_url, status=500)
|
||||
with pytest.raises(exceptions.BadResponse) as e:
|
||||
src.symbols()
|
||||
assert "Server Error" in str(e.value)
|
||||
|
||||
|
||||
def test_symbols_parsing_error(src, requests_mock, series_list_url):
|
||||
requests_mock.add(responses.GET, series_list_url, body="NOT JSON")
|
||||
with pytest.raises(exceptions.ResponseParsingError) as e:
|
||||
src.symbols()
|
||||
assert "while parsing data" in str(e.value)
|
||||
|
||||
|
||||
def test_fetch_known_pair(src, type, recent_response_ok):
|
||||
series = src.fetch(Series("CAD", "USD", type, "2021-01-01", "2021-01-07"))
|
||||
req = recent_response_ok.calls[0].request
|
||||
assert req.params["order_dir"] == "asc"
|
||||
assert req.params["start_date"] == "2021-01-01"
|
||||
assert req.params["end_date"] == "2021-01-07"
|
||||
assert series.prices[0] == Price("2021-01-04", Decimal("0.7843"))
|
||||
assert series.prices[-1] == Price("2021-01-07", Decimal("0.7870"))
|
||||
assert len(series.prices) == 4
|
||||
|
||||
|
||||
def test_fetch_requests_logged(src, type, recent_response_ok, caplog):
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
src.fetch(Series("CAD", "USD", type, "2021-01-01", "2021-01-07"))
|
||||
assert any(
|
||||
["DEBUG" == r.levelname and "curl " in r.message for r in caplog.records]
|
||||
)
|
||||
|
||||
|
||||
def test_fetch_long_hist_from_start(src, type, all_response_ok):
|
||||
series = src.fetch(Series("CAD", "USD", type, src.start(), "2021-01-07"))
|
||||
assert series.prices[0] == Price("2017-01-03", Decimal("0.7443"))
|
||||
assert series.prices[-1] == Price("2021-01-07", Decimal("0.7870"))
|
||||
assert len(series.prices) > 13
|
||||
|
||||
|
||||
def test_fetch_from_before_start(src, type, requests_mock):
|
||||
body = """{ "observations": [] }"""
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), status=200, body=body)
|
||||
series = src.fetch(Series("CAD", "USD", type, "2000-01-01", "2017-01-01"))
|
||||
assert len(series.prices) == 0
|
||||
|
||||
|
||||
def test_fetch_to_future(src, type, all_response_ok):
|
||||
series = src.fetch(Series("CAD", "USD", type, "2021-01-01", "2100-01-01"))
|
||||
assert len(series.prices) > 0
|
||||
|
||||
|
||||
def test_wrong_dates_order(src, type, requests_mock):
|
||||
body = """{ "message": "The End date must be greater than the Start date." }"""
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), status=400, body=body)
|
||||
with pytest.raises(exceptions.BadResponse) as e:
|
||||
src.fetch(Series("CAD", "USD", type, "2021-01-07", "2021-01-01"))
|
||||
assert "End date must be greater" in str(e.value)
|
||||
|
||||
|
||||
def test_fetch_in_future(src, type, requests_mock):
|
||||
body = """{ "observations": [] }"""
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), status=200, body=body)
|
||||
series = src.fetch(Series("CAD", "USD", type, "2030-01-01", "2030-01-07"))
|
||||
assert len(series.prices) == 0
|
||||
|
||||
|
||||
def test_fetch_empty(src, type, requests_mock):
|
||||
requests_mock.add(
|
||||
responses.GET, fetch_url("FXCADUSD"), body="""{"observations":{}}"""
|
||||
)
|
||||
series = src.fetch(Series("CAD", "USD", type, "2021-01-03", "2021-01-03"))
|
||||
assert len(series.prices) == 0
|
||||
|
||||
|
||||
def test_fetch_no_quote(src, type):
|
||||
with pytest.raises(exceptions.InvalidPair):
|
||||
src.fetch(Series("CAD", "", type, "2021-01-01", "2021-01-07"))
|
||||
|
||||
|
||||
def test_fetch_unknown_pair(src, type, requests_mock):
|
||||
requests_mock.add(
|
||||
responses.GET,
|
||||
fetch_url("FXCADAFN"),
|
||||
status=404,
|
||||
body="""{
|
||||
"message": "Series FXCADAFN not found.",
|
||||
"docs": "https://www.bankofcanada.ca/valet/docs"
|
||||
}""",
|
||||
)
|
||||
with pytest.raises(exceptions.InvalidPair):
|
||||
src.fetch(Series("CAD", "AFN", type, "2021-01-01", "2021-01-07"))
|
||||
|
||||
|
||||
def test_fetch_network_issue(src, type, requests_mock):
|
||||
body = requests.exceptions.ConnectionError("Network issue")
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), body=body)
|
||||
with pytest.raises(exceptions.RequestError) as e:
|
||||
src.fetch(Series("CAD", "USD", type, "2021-01-01", "2021-01-07"))
|
||||
assert "Network issue" in str(e.value)
|
||||
|
||||
|
||||
def test_fetch_bad_status(src, type, requests_mock):
|
||||
requests_mock.add(
|
||||
responses.GET,
|
||||
fetch_url("FXCADUSD"),
|
||||
status=500,
|
||||
body="""{"message": "Some other reason"}""",
|
||||
)
|
||||
with pytest.raises(exceptions.BadResponse) as e:
|
||||
src.fetch(Series("CAD", "USD", type, "2021-01-01", "2021-01-07"))
|
||||
assert "Internal Server Error" in str(e.value)
|
||||
|
||||
|
||||
def test_fetch_parsing_error(src, type, requests_mock):
|
||||
requests_mock.add(responses.GET, fetch_url("FXCADUSD"), body="NOT JSON")
|
||||
with pytest.raises(exceptions.ResponseParsingError) as e:
|
||||
src.fetch(Series("CAD", "USD", type, "2021-01-01", "2021-01-07"))
|
||||
assert "while parsing data" in str(e.value)
|
101
tests/pricehist/sources/test_bankofcanada/all-partial.json
Normal file
101
tests/pricehist/sources/test_bankofcanada/all-partial.json
Normal file
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"terms": {
|
||||
"url": "https://www.bankofcanada.ca/terms/"
|
||||
},
|
||||
"seriesDetail": {
|
||||
"FXCADUSD": {
|
||||
"label": "CAD/USD",
|
||||
"description": "Canadian dollar to US dollar daily exchange rate",
|
||||
"dimension": {
|
||||
"key": "d",
|
||||
"name": "date"
|
||||
}
|
||||
}
|
||||
},
|
||||
"observations": [
|
||||
{
|
||||
"d": "2017-01-03",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7443"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-04",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7510"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-05",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7551"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-06",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7568"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-09",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7553"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-10",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7568"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2017-01-11",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7547"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2020-12-29",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7809"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2020-12-30",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7831"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2020-12-31",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7854"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-04",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7843"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-05",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7870"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-06",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7883"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-07",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7870"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
41
tests/pricehist/sources/test_bankofcanada/recent.json
Normal file
41
tests/pricehist/sources/test_bankofcanada/recent.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"terms": {
|
||||
"url": "https://www.bankofcanada.ca/terms/"
|
||||
},
|
||||
"seriesDetail": {
|
||||
"FXCADUSD": {
|
||||
"label": "CAD/USD",
|
||||
"description": "Canadian dollar to US dollar daily exchange rate",
|
||||
"dimension": {
|
||||
"key": "d",
|
||||
"name": "date"
|
||||
}
|
||||
}
|
||||
},
|
||||
"observations": [
|
||||
{
|
||||
"d": "2021-01-04",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7843"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-05",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7870"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-06",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7883"
|
||||
}
|
||||
},
|
||||
{
|
||||
"d": "2021-01-07",
|
||||
"FXCADUSD": {
|
||||
"v": "0.7870"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
272
tests/pricehist/sources/test_bankofcanada/series-partial.json
Normal file
272
tests/pricehist/sources/test_bankofcanada/series-partial.json
Normal file
|
@ -0,0 +1,272 @@
|
|||
{
|
||||
"terms": {
|
||||
"url": "https://www.bankofcanada.ca/terms/"
|
||||
},
|
||||
"series": {
|
||||
"FXAUDCAD": {
|
||||
"label": "AUD/CAD",
|
||||
"description": "Australian dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXAUDCAD"
|
||||
},
|
||||
"FXBRLCAD": {
|
||||
"label": "BRL/CAD",
|
||||
"description": "Brazilian real to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXBRLCAD"
|
||||
},
|
||||
"FXCNYCAD": {
|
||||
"label": "CNY/CAD",
|
||||
"description": "Chinese renminbi to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCNYCAD"
|
||||
},
|
||||
"FXEURCAD": {
|
||||
"label": "EUR/CAD",
|
||||
"description": "European euro to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXEURCAD"
|
||||
},
|
||||
"FXHKDCAD": {
|
||||
"label": "HKD/CAD",
|
||||
"description": "Hong Kong dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXHKDCAD"
|
||||
},
|
||||
"FXINRCAD": {
|
||||
"label": "INR/CAD",
|
||||
"description": "Indian rupee to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXINRCAD"
|
||||
},
|
||||
"FXIDRCAD": {
|
||||
"label": "IDR/CAD",
|
||||
"description": "Indonesian rupiah to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXIDRCAD"
|
||||
},
|
||||
"FXJPYCAD": {
|
||||
"label": "JPY/CAD",
|
||||
"description": "Japanese yen to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXJPYCAD"
|
||||
},
|
||||
"FXMYRCAD": {
|
||||
"label": "MYR/CAD",
|
||||
"description": "Malaysian ringgit to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXMYRCAD"
|
||||
},
|
||||
"FXMXNCAD": {
|
||||
"label": "MXN/CAD",
|
||||
"description": "Mexican peso to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXMXNCAD"
|
||||
},
|
||||
"FXNZDCAD": {
|
||||
"label": "NZD/CAD",
|
||||
"description": "New Zealand dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXNZDCAD"
|
||||
},
|
||||
"FXNOKCAD": {
|
||||
"label": "NOK/CAD",
|
||||
"description": "Norwegian krone to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXNOKCAD"
|
||||
},
|
||||
"FXPENCAD": {
|
||||
"label": "PEN/CAD",
|
||||
"description": "Peruvian new sol to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXPENCAD"
|
||||
},
|
||||
"FXRUBCAD": {
|
||||
"label": "RUB/CAD",
|
||||
"description": "Russian ruble to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXRUBCAD"
|
||||
},
|
||||
"FXSARCAD": {
|
||||
"label": "SAR/CAD",
|
||||
"description": "Saudi riyal to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXSARCAD"
|
||||
},
|
||||
"FXSGDCAD": {
|
||||
"label": "SGD/CAD",
|
||||
"description": "Singapore dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXSGDCAD"
|
||||
},
|
||||
"FXZARCAD": {
|
||||
"label": "ZAR/CAD",
|
||||
"description": "South African rand to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXZARCAD"
|
||||
},
|
||||
"FXKRWCAD": {
|
||||
"label": "KRW/CAD",
|
||||
"description": "South Korean won to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXKRWCAD"
|
||||
},
|
||||
"FXSEKCAD": {
|
||||
"label": "SEK/CAD",
|
||||
"description": "Swedish krona to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXSEKCAD"
|
||||
},
|
||||
"FXCHFCAD": {
|
||||
"label": "CHF/CAD",
|
||||
"description": "Swiss franc to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCHFCAD"
|
||||
},
|
||||
"FXTWDCAD": {
|
||||
"label": "TWD/CAD",
|
||||
"description": "Taiwanese dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXTWDCAD"
|
||||
},
|
||||
"FXTHBCAD": {
|
||||
"label": "THB/CAD",
|
||||
"description": "Thai baht to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXTHBCAD"
|
||||
},
|
||||
"FXTRYCAD": {
|
||||
"label": "TRY/CAD",
|
||||
"description": "Turkish lira to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXTRYCAD"
|
||||
},
|
||||
"FXGBPCAD": {
|
||||
"label": "GBP/CAD",
|
||||
"description": "UK pound sterling to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXGBPCAD"
|
||||
},
|
||||
"FXUSDCAD": {
|
||||
"label": "USD/CAD",
|
||||
"description": "US dollar to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXUSDCAD"
|
||||
},
|
||||
"FXVNDCAD": {
|
||||
"label": "VND/CAD",
|
||||
"description": "Vietnamese dong to Canadian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXVNDCAD"
|
||||
},
|
||||
"FXCADAUD": {
|
||||
"label": "CAD/AUD",
|
||||
"description": "Canadian dollar to Australian dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADAUD"
|
||||
},
|
||||
"FXCADBRL": {
|
||||
"label": "CAD/BRL",
|
||||
"description": "Canadian dollar to Brazilian real daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADBRL"
|
||||
},
|
||||
"FXCADCNY": {
|
||||
"label": "CAD/CNY",
|
||||
"description": "Canadian dollar to Chinese renminbi daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADCNY"
|
||||
},
|
||||
"FXCADEUR": {
|
||||
"label": "CAD/EUR",
|
||||
"description": "Canadian dollar to European euro daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADEUR"
|
||||
},
|
||||
"FXCADHKD": {
|
||||
"label": "CAD/HKD",
|
||||
"description": "Canadian dollar to Hong Kong dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADHKD"
|
||||
},
|
||||
"FXCADINR": {
|
||||
"label": "CAD/INR",
|
||||
"description": "Canadian dollar to Indian rupee daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADINR"
|
||||
},
|
||||
"FXCADIDR": {
|
||||
"label": "CAD/IDR",
|
||||
"description": "Canadian dollar to Indonesian rupiah daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADIDR"
|
||||
},
|
||||
"FXCADJPY": {
|
||||
"label": "CAD/JPY",
|
||||
"description": "Canadian dollar to Japanese yen daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADJPY"
|
||||
},
|
||||
"FXCADMYR": {
|
||||
"label": "CAD/MYR",
|
||||
"description": "Canadian dollar to Malaysian ringgit daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADMYR"
|
||||
},
|
||||
"FXCADMXN": {
|
||||
"label": "CAD/MXN",
|
||||
"description": "Canadian dollar to Mexican peso daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADMXN"
|
||||
},
|
||||
"FXCADNZD": {
|
||||
"label": "CAD/NZD",
|
||||
"description": "Canadian dollar to New Zealand dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADNZD"
|
||||
},
|
||||
"FXCADNOK": {
|
||||
"label": "CAD/NOK",
|
||||
"description": "Canadian dollar to Norwegian krone daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADNOK"
|
||||
},
|
||||
"FXCADPEN": {
|
||||
"label": "CAD/PEN",
|
||||
"description": "Canadian dollar to Peruvian new sol daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADPEN"
|
||||
},
|
||||
"FXCADRUB": {
|
||||
"label": "CAD/RUB",
|
||||
"description": "Canadian dollar to Russian ruble daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADRUB"
|
||||
},
|
||||
"FXCADSAR": {
|
||||
"label": "CAD/SAR",
|
||||
"description": "Canadian dollar to Saudi riyal daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADSAR"
|
||||
},
|
||||
"FXCADSGD": {
|
||||
"label": "CAD/SGD",
|
||||
"description": "Canadian dollar to Singapore dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADSGD"
|
||||
},
|
||||
"FXCADZAR": {
|
||||
"label": "CAD/ZAR",
|
||||
"description": "Canadian dollar to South African rand daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADZAR"
|
||||
},
|
||||
"FXCADKRW": {
|
||||
"label": "CAD/KRW",
|
||||
"description": "Canadian dollar to South Korean won daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADKRW"
|
||||
},
|
||||
"FXCADSEK": {
|
||||
"label": "CAD/SEK",
|
||||
"description": "Canadian dollar to Swedish krona daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADSEK"
|
||||
},
|
||||
"FXCADCHF": {
|
||||
"label": "CAD/CHF",
|
||||
"description": "Canadian dollar to Swiss franc daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADCHF"
|
||||
},
|
||||
"FXCADTWD": {
|
||||
"label": "CAD/TWD",
|
||||
"description": "Canadian dollar to Taiwanese dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADTWD"
|
||||
},
|
||||
"FXCADTHB": {
|
||||
"label": "CAD/THB",
|
||||
"description": "Canadian dollar to Thai baht daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADTHB"
|
||||
},
|
||||
"FXCADTRY": {
|
||||
"label": "CAD/TRY",
|
||||
"description": "Canadian dollar to Turkish lira daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADTRY"
|
||||
},
|
||||
"FXCADGBP": {
|
||||
"label": "CAD/GBP",
|
||||
"description": "Canadian dollar to UK pound sterling daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADGBP"
|
||||
},
|
||||
"FXCADUSD": {
|
||||
"label": "CAD/USD",
|
||||
"description": "Canadian dollar to US dollar daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADUSD"
|
||||
},
|
||||
"FXCADVND": {
|
||||
"label": "CAD/VND",
|
||||
"description": "Canadian dollar to Vietnamese dong daily exchange rate",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/FXCADVND"
|
||||
},
|
||||
"INDINF_GRACE_Q": {
|
||||
"label": "Foreign demand for Canadian non-commodity exports (GRACE) (2007=100)",
|
||||
"description": "Foreign demand for Canadian non-commodity exports (GRACE) (2007=100)",
|
||||
"link": "https://www.bankofcanada.ca/valet/series/INDINF_GRACE_Q"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue