-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcurrency.py
93 lines (87 loc) · 4.26 KB
/
currency.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python
#
# This file is part of the pygnclib project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import os.path, re, datetime
import xml.etree.ElementTree as ElemTree
from bs4 import BeautifulSoup
import urllib2, json
# convert Eurofxref xml to dict
def convertEurofxref2ExchangeRates(historic_exchange_rates, xml_string, verbosity):
tree = ElemTree.XML(xml_string)
for dated_entry in tree.find('.//{http://www.ecb.int/vocabulary/2002-08-01/eurofxref}Cube'):
date = datetime.datetime.strptime( dated_entry.attrib['time'], '%Y-%m-%d' )
values = {}
for elem in dated_entry:
values[elem.attrib['currency']] = elem.attrib['rate']
if verbosity > 1: print 'Reading from eurofxref: ', date, ': ', elem.attrib['currency'], ' ', elem.attrib['rate']
historic_exchange_rates[date.date()] = values
# convert historic currencies via eurofxref-hist-90d.xml
def convertHistoricCurrency(historic_exchange_rates, value, from_currency, to_currency, date, verbosity):
if not historic_exchange_rates:
path = os.getenv('HOME',default='')+'/.cache/pygnclib'
filename = path + '/eurofxref-hist-90d.xml'
# file exists, and is current?
content = ""
if not os.path.exists(filename) or datetime.date.fromtimestamp(os.path.getmtime(filename)) != datetime.date.today():
# nope. download/update it.
if verbosity > 0: print 'Downloading eurofxref'
if not os.path.exists(path):
os.mkdir(path)
# if ever 90 days of history is not enough,
# http://www.ecb.int/stats/eurofxref/eurofxref-hist.xml
# has the full history since the 90ties.
content = urllib2.urlopen('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml').read()
# and buffer for the next time
f = open(filename, "wb")
f.write(content)
f.close()
else:
# yes. just read.
if verbosity > 0: print 'Loading cached eurofxref'
f = open(filename)
content = f.read()
if verbosity > 0: print 'Parsing eurofxref'
convertEurofxref2ExchangeRates(historic_exchange_rates, content, verbosity)
if not historic_exchange_rates.has_key(date):
# hmm. seems they spare us the weekends - try one and two days earlier
date1 = datetime.date.fromordinal( date.toordinal()-1 )
date2 = datetime.date.fromordinal( date.toordinal()-2 )
if historic_exchange_rates.has_key(date1):
date = date1
elif historic_exchange_rates.has_key(date2):
date = date2
fromEUR = historic_exchange_rates[date][from_currency]
toEUR = 1.0
if to_currency != 'EUR':
toEUR = historic_exchange_rates[date][to_currency]
return value / float(fromEUR) * float(toEUR)
class CurrencyConverter:
'''Convert currencies, using various online resources.
Keep an instance of this class around to cache once-queried results
'''
def __init__(self, **kwargs):
self.current_exchange_rates = {}
self.historic_exchange_rates = {}
self.verbosity = kwargs.pop('verbosity')
def convert(self, value, from_currency, to_currency, date):
if from_currency == to_currency:
return value
try:
return convertHistoricCurrency(self.historic_exchange_rates, value, from_currency, to_currency, date, self.verbosity)
except:
if self.verbosity > 0: print 'Error in convertHistoricCurrency(%s, %s, %s), falling back to google app' % (value, from_currency, date)
url = 'https://www.google.com/finance/converter?a=1&from=%s&to=%s' % (from_currency, to_currency)
if self.current_exchange_rates.has_key(url):
res = self.current_exchange_rates[url]
else:
tree = BeautifulSoup(urllib2.urlopen(url).read())
span = tree.find(attrs={"class": "bld"})
if span is not None:
res = span.string.split()[0]
self.current_exchange_rates[url] = res
return value * float(res)