Reporting de ventas con R (Multidivisa)

En empresas internacionales es comun operar con diferentes divisas y consolidar los resultados en una moneda unica.

El objetivo de este proyecto es la elaboración de un reporte de ventas, automatizado, en Euros, de una empresa que se dedica al transporte de pasajaeros urbanos y que opera en diferentes ciudades del mundo: con euros, pesos mexicanos, pesos argentinos, chilenos…

Para ello dispongo de un ejemplo con 52.646 transacciones.

Para obtener los tipos de cambio tenemos que tener acceso a datos economicos y las librerias de R: quantmod y Quandl permiten hacerlo.

library(quantmod)
library(Quandl)
library(tidyverse)
library(dplyr)
library(kableExtra)
library(reshape)
library(lubridate)
library(ggplot2)
library(scales)
library(tidyquant)

Existen distintas fuentes y cada una de ella tiene sus particularidades: Oanda.com por ejemplo, proporciona datos historicos de 180 días, ¡aunque siempre se puede modificar el argumento de la función (from - to)!

https://finance.yahoo.com/?guccounter=1

https://www.alphavantage.co/

https://fred.stlouisfed.org/

https://www.oanda.com/rw-en/

Como ejemplo sencillo hacemos una llamada a la API del Banco Central Europeo (BCE), en este caso a traves del paquete de R quandl(), para extraer la cotización del dollar con respecto al euro:

# Import EURUSD data from BCE
eurusd<-Quandl(code="ECB/EURUSD")

El resultado que proporciona es el siguiente:

DateValue
2020-12-091.2109
2020-12-081.2114
2020-12-071.2128
2020-12-041.2159
2020-12-031.2151
2020-12-021.2066

Volviendo al ejemplo empresarial con el que estsmos trabajando, las divisas con las que la compañia opera son las siguientes…

## [1] "EUR" "MXN" "BRL" "PEN" "ARS" "CLP" "USD"

…volviendo al dataset, las variables que necesito para medir las ventas son:

journey_idcreated_atcurrencyprice_basecost_baseciudad
3b5ecd53ea384e6dabc8f3861636e9ff2017-12-17 00:20:33EUR1254991Madrid
78456c6023f14e629a116e1764e938a82017-11-24 06:39:45EUR1179955Madrid
aad8fe7a29774e0eb03c93e7271d47a72017-11-29 20:57:36EUR15001215Madrid
64bc20e94aa444e4844551cc83605c212017-11-10 20:43:56EUR600486Madrid
249c56c03bef4c4cb988406f7314bb8c2017-12-14 22:02:20EUR550434Madrid
360569767bf24d9bb84495760959eec72017-12-22 05:54:54EUR1078852Madrid

Agrupamos las ventas de la compañia por mes…

monthsales
12,147,525.0
28,296,543.0
312,540,979.0
48,920,553.0
512,063,367.0
613,269,868.0

…pero esto no es lo correcto en estos momentos por que estamos agregando las ventas en diferentes divisas…

Lo importante del proyecto viene a continuación… y lo detallo paso por paso:

  1. Preparamos una tabla de fechas

currDF  <- data.frame(
  date = seq.Date(from = as.Date('2017-01-03 13:20:24'), to = as.Date('2017-12-30 09:54:08'), length = 52645),
  variable = datos$currency,
  amount = datos$price_base,stringsAsFactors=FALSE)


currDF = currDF %>% mutate(aniomes = paste(year(date),month(date)))

currDF$divisaaniomes<-paste(currDF$variable,currDF$aniomes)
  1. Los datos que tenemos son del 2017, marcamos los limites y el formato de los datos
#tipos de cambio historicos de 2017
startDt = as.Date("2017-01-03 13:20:24")
endDt = as.Date("2017-12-30 09:54:08")
currCombinations = paste(setdiff(unique(currDF$variable),"EUR"),"EUR=X",sep="")
  1. Extraemos la cotiación de las divisas desde yahoo con la función getSymbols(). Y alimentamos la tabla.

Asegurarse de tener Internet al ejecutar este codigo.

fxData = do.call(merge.xts,lapply(currCombinations,function(x)
  getSymbols.yahoo(x, src="yahoo", from=startDt,to=endDt,auto.assign=FALSE)[,4])) #make sure you have internet
colnames(fxData) = gsub("EUR.X.Close","",colnames(fxData))
fxData$EUR = 1
  1. Calculamos la media de la cotización de cada divisa durante cada mez: tipo de cambio medio de cada mes y de cada divisa. (¡ojo! si el reporting es anual, podemos modificar la formula)
fxData_DF = data.frame(date=index(fxData),coredata(fxData),stringsAsFactors=FALSE)
fxMolten = melt(fxData_DF,id="date",variable.name="currency",value.name="conversionFactor")

#creamos la columna aniomes para poder calcular el tipo de cambio medio de cada mes
fxMolten = fxMolten %>% mutate(aniomes = paste(year(date),month(date)))

fxMolten %>% group_by(aniomes, variable) %>% summarise(amountmedia = mean(value))
## # A tibble: 84 x 3
## # Groups:   aniomes [12]
##    aniomes variable amountmedia
##    <chr>   <fct>          <dbl>
##  1 2017 1  MXN          0.0439 
##  2 2017 1  BRL          0.294  
##  3 2017 1  PEN         NA      
##  4 2017 1  ARS          0.0591 
##  5 2017 1  CLP          0.00144
##  6 2017 1  USD          0.941  
##  7 2017 1  EUR          1      
##  8 2017 10 MXN          0.0452 
##  9 2017 10 BRL          0.266  
## 10 2017 10 PEN          0.266  
## # ... with 74 more rows
#eliminamos NAs
fxMolten<-fxMolten[complete.cases(fxMolten), ] #desaparecen algunas lineas
fxMolten %>% group_by(aniomes, variable) %>% summarise(amountmedia = mean(value))
## # A tibble: 79 x 3
## # Groups:   aniomes [12]
##    aniomes variable amountmedia
##    <chr>   <fct>          <dbl>
##  1 2017 1  MXN          0.0439 
##  2 2017 1  BRL          0.294  
##  3 2017 1  ARS          0.0591 
##  4 2017 1  CLP          0.00144
##  5 2017 1  USD          0.941  
##  6 2017 1  EUR          1      
##  7 2017 10 MXN          0.0452 
##  8 2017 10 BRL          0.266  
##  9 2017 10 PEN          0.266  
## 10 2017 10 ARS          0.0487 
## # ... with 69 more rows
#creamos la columna divisaaniomes para poder calcular el tipo de cambio medio de cada mes
fxMolten$divisaaniomes<-paste(fxMolten$variable,fxMolten$aniomes)
tipocamiomedio= fxMolten %>% group_by(divisaaniomes, variable) %>% summarise(amountmedia = mean(value))
#mergeamos con datoscabify
datos = datos %>% mutate(aniomes = paste(year(created_at),month(created_at)))
datos$divisaaniomes<-paste(datos$currency,datos$aniomes)
datosdivisa = merge(datos,tipocamiomedio, by= "divisaaniomes")
#hacemos la conversion de nuestras variables economicas
datosdivisa$price_base_EUR<-datosdivisa$price_base*datosdivisa$amountmedia
datosdivisa$cost_base_EUR<-datosdivisa$cost_base*datosdivisa$amountmedia

datos1 <- inner_join(datos,datosdivisa, by= "journey_id")
  1. Incorporamos las columnas de coste y facturación en euros
journey_idcreated_at.xcurrency.xprice_base.xcost_base.xprice_base_EURcost_base_EURciudad.x
3b5ecd53ea384e6dabc8f3861636e9ff2017-12-17 00:20:33EUR12549911254991Madrid
78456c6023f14e629a116e1764e938a82017-11-24 06:39:45EUR11799551179955Madrid
aad8fe7a29774e0eb03c93e7271d47a72017-11-29 20:57:36EUR1500121515001215Madrid
64bc20e94aa444e4844551cc83605c212017-11-10 20:43:56EUR600486600486Madrid
249c56c03bef4c4cb988406f7314bb8c2017-12-14 22:02:20EUR550434550434Madrid
360569767bf24d9bb84495760959eec72017-12-22 05:54:54EUR10788521078852Madrid

Ahora que tenemos los datos en euros, vuelvo agrupar los resultados de las ventas por mes

#str(datosdivisa$created_at)

datos1$price_base_EUR[is.na(datos1$price_base_EUR)] <- 0

datos1$month <- month(datos1$created_at.x)


datos2 <- datos1 %>%
    # group by year and summarizing sales
    group_by(month) %>%
    summarize(sales = sum(price_base_EUR)) %>%
    ungroup()

datos2$sales <- format(round(as.numeric(datos2$sales), 1), nsmall=1, big.mark=",")

datos2%>%
    knitr::kable()%>%
    kable_styling(bootstrap_options = "striped", font_size = 14)
monthsales
11,996,251.7
26,946,050.0
39,241,637.4
46,656,708.0
59,011,863.8
610,326,851.0
710,132,739.2
84,160,307.1
99,956,338.7
1011,966,307.2
1111,838,035.0
129,258,994.3

Estan facturando alrededor de 91 millones de euros anuales. Quiero ver las cifras por ciudades…

Parece que Madrid es una ciudad muy importante para la compañia…

Quiero ver como vende la empresa en Madrid semana a semana…

Karlos Garcia
Karlos Garcia
Analista de Datos independiente

Analisis de datos economicos y financieros en el País Vasco, España y Europa