Viaticos a dolar

Los montos de los viáticos pueden estar en pesos, dolares y/o euros y es imposible poder compararlos. Por suerte, el Banco Nación Argentino tiene las cotizaciones historicas. Utilizamos eso para combertir todos los viaticos a dolar.


In [1]:
import json
import datetime

import requests
import pandas as pd

In [2]:
def historical_price(coin, search_dates, date_format='%d/%m/%Y'):
    """
    Get the historical price of the dolar or euro from the Argentina National Bank
    
    Parameters
    ----------
    coin: str
      'dolar' or 'euro'
    search_dates: list
      list with all the date (in string) to search
    date_format: str, optinal
      Format of the dates
      
    Return
    ------
    prices: list
    
    """
    # Check if the coint type is correct
    coin = coin.capitalize()
    if coin not in ['Dolar', 'Euro']:
        return {'error': 'Coin bust be "dolar" or "euro"'}
    
    # Get the cookies
    session = requests.session()
    response = session.get("http://www.bna.com.ar/")
    
    # To datetime.datetime object
    search_dates = [datetime.datetime.strptime(date, date_format) 
                    for date in search_dates]
    
    prices = []
    for cnt, search in enumerate(search_dates):
        original_date = search
        
        # Progress text
        print("\rDescargando fecha {0}/{1}: ....".format(cnt + 1, len(search_dates)), end='')
        
        # Si no encuentro para esa fecha exacta, avanzo un dia
        while True:
            # Parameters
            params = {'id': 'billetes',
                      'fecha': datetime.datetime.strftime(search, '%d/%m/%Y'),
                      'filtroEuro': '1',
                      'filtroDolar': '1'}

            # Get the data
            url_historic = "http://www.bna.com.ar/Cotizador/HistoricoPrincipales"
            response  = session.get(url_historic, params=params)

            # Utilizan ',' en los numeros. Lo reemplazo por un '.'
            html = response.text.replace(',', '.')

            try:
                # Parse table to DataFrame
                df = pd.read_html(html, match=coin, header=0)[0]
                break
            except:
                search = search + datetime.timedelta(1)

        # Str to datetime
        df['Fecha'] = df['Fecha'].apply(lambda ele: datetime.datetime.strptime(ele, '%d/%m/%Y'))

        # Find the most closest day
        index = (df['Fecha'] - search).abs().argmin()

        # Datetime to str
        df['Fecha'] = df['Fecha'].apply(lambda ele: datetime.datetime.strftime(ele, '%d-%m-%Y'))
        
        # Result
        data = json.loads(df.iloc[index].to_json())
        data['Fecha consulta'] = datetime.datetime.strftime(original_date, '%d-%m-%Y')
        prices.append(data)
        
        # Progress text
        print("\rDescargando fecha {0}/{1}: Done".format(cnt, len(search_dates)), end='')
        
    return prices

In [3]:
def dolar2pesos(row):
    "Viaticos en dolares a pesos"
    if row['Viaticos_dolar'] != 0:
        
        # Busco el cambio correcto
        for price in prices_dolar:
            if row['Fecha_salida'] == price['Fecha']:
                break
   
        # Calculo el cambio
        return row['Viaticos_dolar'] * price['Venta']
    else:
        return 0

def euro2pesos(row):
    "Viaticos en euro a pesos"
    if row['Viaticos_euro'] != 0:
        
        # Busco el cambio correcto
        for price in prices_euro:
            if row['Fecha_salida'] == price['Fecha']:
                break
   
        # Calculo el cambio
        return row['Viaticos_euro'] * price['Venta']
    else:
        return 0
    
def total2dolar(row):
    "Viatico total en pesos a dolares"
    if row['Viaticos_Total_Pesos'] != 0:
        
        # Busco el cambio correcto
        for price in prices_dolar:
            if row['Fecha_salida'] == price['Fecha']:
                break
   
        # Calculo el cambio
        return row['Viaticos_Total_Pesos'] / price['Venta']
    else:
        return 0


csvs = ['../viajes_{0}.csv'.format(i) for i in range(2012, 2018)]

for csv in csvs:
    df = pd.read_csv(csv)

    # Los años 2016 y 2017 no tienen la columna 'Viaticos_pesos'. Se la agrego
    if csv in ['../viajes_2016.csv', '../viajes_2017.csv']:
        df['Viaticos_pesos'] = [0 for _ in range(df.shape[0])]
    
    # Calculo de la convercion del dolar a peso
    df_dolar = df[df['Viaticos_dolar'] != 0]
    dates = df_dolar['Fecha_salida'].tolist()
    # Get the coint price
    prices_dolar = historical_price('dolar', dates, '%d-%m-%Y')
    #
    dolar_a_pesos = df.apply(dolar2pesos, axis=1)

    # Calculo de la convercion del euro a peso
    df_euro = df[df['Viaticos_euro'] != 0]
    dates = df_euro['Fecha_salida'].tolist()
    # Get the coint price
    prices_euro = historical_price('euro', dates, '%d-%m-%Y')
    #
    euro_a_pesos = df.apply(euro2pesos, axis=1)

    df['Viaticos_Total_Pesos'] = df['Viaticos_pesos'] + dolar_a_pesos + euro_a_pesos
    
    # Calculo del viatico total en pesos a dolares
    df_total = df[df['Viaticos_Total_Pesos'] != 0]
    dates = df_total['Fecha_salida'].tolist()
    # Get the coint price
    prices_dolar = historical_price('dolar', dates, '%d-%m-%Y')
    #
    total_dolar = df.apply(total2dolar, axis=1)

    df['Viaticos_Total_Dolar'] = total_dolar

    df.to_csv(csv, index=False)


Descargando fecha 18/19: Donene

In [4]:
df.head()


Out[4]:
Autoridad Expediente Destino Viaticos_euro Viaticos_dolar Motivo Bloque Fecha_salida Fecha_llegada Viaticos_pesos Viaticos_Total_Pesos Viaticos_Total_Dolar
0 PINEDO, Federico 5420/2016 Alemania/Suiza/Reino Unido de Gran Bretaña 2100.0 0.0 "International Democrat Union Executive Meetin... Frente PRO 14-01-2017 05-02-2017 0 37800.0 2423.076923
1 CREXELL, Carmen Lucila 5534/2016 Gran Bretaña/ Irlanda del Norte 2100.0 0.0 Grupo Parlamentario de Amistad Gran Bretaña - ... Movimiento Popular Neuquino 27-01-2017 07-02-2017 0 37800.0 2347.826087
2 URTUBEY, Rodolfo Julio 5534/2016 Gran Bretaña/ Irlanda del Norte 2100.0 0.0 Grupo Parlamentario de Amistad Gran Bretaña - ... Frente para la Victoria 28-01-2017 05-02-2017 0 37800.0 2423.076923
3 PEREYRA, Guillermo 333/2017 España 1200.0 0.0 Comitiva oficial del Ministerio de Trabajo Movimiento Popular Neuquino 18-02-2017 28-02-2017 0 21600.0 1384.615385
4 PETCOFF NAIDENOFF, Luis Carlos 333/2017 España 1200.0 0.0 Comitiva oficial del Ministerio de Trabajo Unión Cívica Radical 20-02-2017 26-02-2017 0 21600.0 1358.490566

In [ ]: