A utility package for calling NBP (Polish National Bank) Web API.
Project description
A utility package for calling NBP (Polish National Bank) Web API and converting various currencies to Polish zloty using its exchange rates.
NBPy requires Python 3.3 or newer
Installation
From PyPI:
$ pip3 install nbpy
From source code:
$ git clone https://github.com/kuszaj/nbpy
$ cd nbpy
$ python3 setup.py install
Usage
NBPy provides a NBPClient class for generating API callers, given available currency code:
>>> import nbpy
>>> #: Available currencies
>>> nbpy.currencies
{'EUR': NBPCurrency(Euro, code=EUR, tables={'A', 'C'}), 'USD': NBPCurrency(United States dollar, code=USD, tables={'A', 'C'}), ...}
>>> nbp = nbpy.NBPClient('eur')
>>> nbp
NBPClient(USD, as_float=False, suppress_errors=False, cache_size=128)
>>> nbp.currency_code = 'EUR'
>>> nbp
NBPClient(EUR, as_float=False, suppress_errors=False, cache_size=128)
currency_code has to be one of the available codes from nbpy.currencies otherwise NBPClient raises UnknownCurrencyCode.
>>> from nbpy.errors import UnknownCurrencyCode
>>> 'XYZ' in nbpy.currencies
False
>>> try:
... nbp.currency_code = 'XYZ'
... except UnknownCurrencyCode:
... print('XYZ is unknown')
...
XYZ is unknown
API calls
All API calls defined in NBPClient returns either a NBPExchangeRate object or a list its instances.
.current() returns current exchange rate for currency. Note that it doesn’t necessarily mean current day: for weekends, holidays and before official announcements by Polish National Bank method returns last available value.
>>> nbp.current()
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)
>>> #: Calling NBPClient object is synonymous with current()
>>> nbp()
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)
.today() returns exchange rate for current day, if available. Otherwise, raises APIError.
>>> nbp.today()
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)
...
>>> #: A day later, during national holiday
>>> from nbpy.errors import APIError
>>> try:
... nbp.today()
... except APIError:
... print("No data available")
...
No data available
.date(date) returns exchange rate for given day, if available. Otherwise, raises APIError. Argument date has to be either datetime.datetime or a properly formatted date string (YYYY-MM-DD), otherwise method raises DateFormattingError.
>>> from nbpy.errors import APIError, DateFormattingError
>>> nbp.date('2017-10-02')
NBPExchangeRate(EUR->PLN, 2017-10-02, mid=4.3137)
>>> try:
... nbp.date('2017-10-01')
... except APIError:
... print("No data available for date")
...
No data available for date
>>> try:
... nbp.date('01/10/17')
... except DateFormattingError:
... print("Improperly formatted date string")
...
Improperly formatted date string
.last(n) returns last n available exchange rates, ordered by date in ascending order.
>>> nbp.last(3)
[NBPExchangeRate(EUR->PLN, 2017-10-27, mid=4.2520),
NBPExchangeRate(EUR->PLN, 2017-10-30, mid=4.2403),
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)]
.date_range(start_date, end_date) returns exchange rates for given date range [start_date, end_date], ordered by date in ascending order. Both arguments are restricted in the same way as date for date() method.
If range covers more than 93 days, method raises APIError.
>>> from nbp.errors import APIError
>>> nbp.date_range('2017-10-01', '2017-10-14')
[NBPExchangeRate(EUR->PLN, 2017-10-02, mid=4.3137),
NBPExchangeRate(EUR->PLN, 2017-10-03, mid=4.3105),
NBPExchangeRate(EUR->PLN, 2017-10-04, mid=4.3025), ...]
>>> try:
... nbp.date_range('2017-01-01', '2017-06-01')
... except APIError:
... print('Invalid date range')
...
Invalid date range
Bid/ask rates
By default all API call methods return average exchange rate (mid). However, by passing bid_ask=True you can additionally get bid/ask values. Not that not every currency has them available: for such case bid_ask is ignored.
>>> nbp()
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)
>>> nbp(bid_ask=True)
NBPExchangeRate(EUR->PLN, 2017-11-02, bid=4.2036, ask=4.2886)
>>> #: No bid/ask values for CUP
>>> nbp.currency_code = 'CUP'
>>> nbp()
NBPExchangeRate(CUP->PLN, 2017-10-31, mid=3.6529)
>>> from nbpy.errors import BidAskUnavailable
>>> try:
... nbp(bid_ask=True)
... except BidAskUnavailable:
... print('Bid/ask unavailable')
...
Bid/ask unavailable
Suppressing errors
If you want API calls to always return something, despite possible issues with API, you can pass suppress_errors=True to NBPClient. With this flag turned on API calls instead of raising BidAskUnavailable and APIError exceptions will return None.
>>> from nbp.errors import APIError
>>> try:
... nbp.date_range('2017-01-01', '2017-06-01')
... except APIError:
... print('Invalid date range')
...
Invalid date range
>>> nbp.suppress_errors = True
>>> print(nbp.date_range('2017-01-01', '2017-06-01'))
None
Cache size
For efficiency, NBPClient utilizes LRU cache for by saving last 128 calls. You can change this value by passing cache_size to NBPClient. This value can be set only during object initialization.
>>> nbp = NBPClient('eur', cache_size=64)
>>> nbp
NBPClient(EUR, as_float=False, suppress_errors=False, cache_size=64)
>>> try:
... nbp.cache_size = 128
... except AttributeError:
... print("Can't overwrite cache_size")
...
Can't overwrite cache_size
Rates as floats
By default all exchange rates are parsed as decimal.Decimal objects. You can change this behaviour by passing as_float=True, which will force all exchange rates to be parsed as float.
>>> nbp = NBPClient('eur')
>>> type(nbp().mid)
<class 'decimal.Decimal'>
>>> nbp = NBPClient('eur', as_float=True)
>>> type(nbp().mid)
<class 'float'>
Exchange rates
NBPClient calls returns an NBPExchangeRate object (their list), which can be used as a converter for calculating given amount in foreign currency to Polish zlotys.
>>> exchange_rate = nbp()
>>> exchange_rate
NBPExchangeRate(EUR->PLN, 2017-10-31, mid=4.2498)
>>> amount = 1000
>>> exchange_rate(amount)
{'mid': Decimal('4249.8000')}
>>> exchange_rate * amount
{'mid': Decimal('4249.8000')}
>>> amount * exchange_rate
{'mid': Decimal('4249.8000')}
>>>
>>> exchange_rate = nbp(all_values=True)
>>> exchange_rate
NBPExchangeRate(EUR->PLN, 2017-11-02, bid=4.2036, ask=4.2886)
>>> exchange_rate(amount)
{'bid': Decimal('4204.3000'), 'ask': Decimal('4289.3000')}
Example
Below script prints and summarises a list of invoices in foreign currencies.
from datetime import datetime, timedelta
from decimal import Decimal
from nbpy import NBPClient
from nbpy.errors import APIError
class Invoice(object):
"""Invoice class with builtin currency converter."""
def __init__(self, currency_code, date, amount):
self.currency_code = currency_code
self.date = date
self.amount = Decimal("{:.2f}".format(amount))
self._nbp = NBPClient(currency_code)
@property
def amount_in_pln(self):
exchange_rate = None
date = datetime.strptime(self.date, '%Y-%m-%d')
while exchange_rate is None:
# Get exchange rates until valid is found
try:
exchange_rate = self._nbp.date(date.strftime('%Y-%m-%d'))
break
except APIError:
date -= timedelta(days=1)
amount = (exchange_rate * self.amount)['mid']
return round(amount, 2)
# List of invoices in foreign currencies
invoices = [
Invoice('EUR', '2017-10-03', 650.0),
Invoice('EUR', '2017-10-06', 890.0),
Invoice('USD', '2017-10-11', 1230.0),
]
# Print all amounts in their currencies and PLN
template = "{currency} {amount:7.2f} {amount_in_pln:7.2f}"
for invoice in invoices:
print(template.format(
currency=invoice.currency_code,
amount=invoice.amount,
amount_in_pln=invoice.amount_in_pln,
))
# Sum all values in PLN
# Since amount_in_pln were already called, script will use cached values
# instead of calling NBP Web API
sum_amount_in_pln = sum([invoice.amount_in_pln for invoice in invoices])
print("-" * 23)
print(" total: {sum:8.2f}".format(sum=sum_amount_in_pln))
# EUR 650.00 2801.82
# EUR 890.00 3830.74
# USD 1230.00 4454.94
# -----------------------
# total: 11087.50
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file NBPy-0.1.1.tar.gz
.
File metadata
- Download URL: NBPy-0.1.1.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6004d076c64406aef4ce06c01e8b0c760e71bf909c4df92872aa1b22a96ab5b2 |
|
MD5 | d72126378fa80e405e54976b4ce10003 |
|
BLAKE2b-256 | cd35e914bdd37160437a82145f95581a444021d8afe6b99f76d88b0acd31ad60 |
File details
Details for the file NBPy-0.1.1-py3-none-any.whl
.
File metadata
- Download URL: NBPy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 43166515b09f96ead854baf1915a737d2bd6122330d3a3568668f4c0da8bd10c |
|
MD5 | fc17696d5f35183e079b159cc823631f |
|
BLAKE2b-256 | a24d30022d111139aec35de977dc758f6bb1dca8325418e258a756050f67f9e9 |