En Venezuela una de las pocas formas de saber la paridad entre el dolar “paralelo” y el Bolivar fuerte es utilizando el portal “DolarToday”. El sitio web (https://dolartoday.com/historico-dolar/) ofrece datos que van desde el 2010 hasta el presente, en los cuales puede ver la paridad entre las dos monedas.
En un arranque de ociosidad, decidí bajarme el archivo de Excel con las tasas de conversión, lo exporte a CSV y de allí escribí un programa en Python 3 que hace lo siguiente:
- Extendiende la clase ‘dict’ en Python para mantener un diccionario con claves ordenadas, el cual se pueda guardar y recuperar a si mismo desde el disco duro
- Usar struct.Struct para guardar y leer data binaria (también muestro como leer un archivo comprimido con gzip).
El código a continuación:
#!/usr/bin/env python3
# Simple program to save the 'Dolartoday' extra official dollar rates from CSV to a custom format
# @author Jose Vicente Nunez, josevnz@kodegeek.com
import os, sys, datetime, re, gzip, struct
from optparse import OptionParser, OptionValueError
from datetime import datetime
class DollarToday:
def __init__(self, ddate, value):
if isinstance(ddate, datetime):
self.__date = ddate
else:
self.__date = datetime.strptime(ddate, "%m-%d-%Y")
self.__value = float(value)
assert self.__value > 0.0, "¡{} para la fecha {} es invalida!".format(value, self.__date)
@property
def date(self):
return self.__date
@date.setter
def date(self, date):
assert isinstance(date, datetime), "Invalid date {}".format(date)
self.__date = date
@property
def value(self):
return self.__value
def __str__(self):
return "DollarToday[date={}, value={}]".format(self.__date, self.__value)
def __hash__(self):
return str(id(self))
class DollarCollection(dict):
__FILE_MAGIC = b"DLR\x00" # Me invente este numero mágico...
__FILE_VERSION = b"\x00\x01"
__dollarStruct = struct.Struct(" self.__FILE_VERSION:
raise "Unsupported file version: {}, expected {}".format(version, self.__FILE_VERSION)
self.clear()
while True:
data = fh.read(self.__dollarStruct.size)
if len(data) == 0:
break
numbers = self.__dollarStruct.unpack(data)
#if verbose:
# print("{}".format(",".join([str(x) for x in numbers])))
dolar = DollarToday(
datetime.fromordinal(numbers[0]),
numbers[1]
)
self[dolar.date] = dolar
except (Exception) as err:
raise
finally:
if (fh is not None):
fh.close()
def readCsv(self, file):
fh = None
tempMap = {}
try:
fh = open(file, "r", encoding="UTF-8")
for line in fh.readlines():
# 6-23-2010 9.92
(date, value) = line.strip().split("\t")
if re.match("Fecha", date):
continue
try:
dolVsBol = DollarToday(date, value)
tempMap[dolVsBol.date] = dolVsBol
except (Exception) as err:
print(err)
self.clear()
self.update(tempMap)
except (Exception) as err:
raise
finally:
if (fh is not None):
fh.close()
def __str__(self):
return "Records={},\n{}".format(len(self), ",\n".join([str(date) for date in self.values()]))
def main(options):
verbose = options.verbose
dc = DollarCollection()
if options.report == None:
dc.readCsv(options.read)
dc.save(options.write)
else:
dc.readBinary(options.report, verbose)
if verbose:
print("{}".format(dc))
if __name__ == "__main__":
usagetext = """
%prog --read csv.file --write binary.file
Or:
%prog --report binary.file
"""
op = OptionParser(usage=usagetext)
op.add_option(
"-r", "--read",
action="store",
dest="read",
help="Ruta completa del archivo CSV fuente, cada linea tiene una clave=valor")
op.add_option(
"-w", "--write",
action="store",
dest="write",
help="Ruta completa para guardar el archivo en nuevo formato binario")
op.add_option(
"-p", "--report",
action="store",
dest="report",
help="Lee el archivo binario en memoria. No es compatible con --read y --write")
op.add_option(
"-v", "--verbose",
action="store_true",
default=False,
dest="verbose",
help="Activar impresión de valores por pantalla")
(options, values) = op.parse_args()
main(options)
Un ejemplo de como correrlo:
DolarToday.py --read /Users/josevnz/Documents/dolartoday.csv --write /Users/josevnz/Documents/dolartoday.jose --verbose
DolarToday.py --report /Users/josevnz/Documents/dolartoday.jose --verbose
Y la salida luce como esto:
Records=1917,
DollarToday[date=2010-06-23 00:00:00, value=9.92],
DollarToday[date=2010-06-25 00:00:00, value=8.05],
DollarToday[date=2010-06-26 00:00:00, value=8.05],
DollarToday[date=2010-06-27 00:00:00, value=7.91],
DollarToday[date=2010-06-28 00:00:00, value=7.91],
DollarToday[date=2010-06-29 00:00:00, value=7.92],
DollarToday[date=2010-06-30 00:00:00, value=7.97],
DollarToday[date=2010-07-01 00:00:00, value=7.97],
DollarToday[date=2010-07-02 00:00:00, value=7.98],
Si tan sólo el gobierno de Nicolás Maduro fuera tan transparente como mis programas 🙂