knitr::opts_chunk$set(echo = TRUE)

Setup

Make a data.frame with to and from currencies, and amounts

library(priceR)
library(dplyr)
library(tidyr)
library(purrr)
library(lubridate)

sim_count <- 10000
set.seed(123)
transactions_complex <- tibble(
  sales_date = sample(
    seq(as.Date('2021/01/01'), 
        as.Date('2022/01/01'), 
        by = "day"), 
    replace = TRUE, sim_count) %>% 
    sort(),
  from_currency = sample(
    c("CAD", "EUR", "JPY", "USD"), 
    replace = TRUE, sim_count),
  to_currency = sample(
    c("CAD", "EUR", "JPY", "USD"), 
    replace = TRUE, sim_count),
  list_price_start = abs(rnorm(sim_count, 1000, 1000))
) %>% 
  filter(from_currency != to_currency)

transactions_complex
# Define unexported functions

pminmax <- function(x, y) {
  paste(pmin.int(x, y), pmax.int(x, y), sep = ".")
}

from_to_dates_rates <- function(from, to, dates){
  priceR::historical_exchange_rates(
    from = from,
    to = to,
    start_date = dates[[1]],
    end_date = dates[[2]]
  ) %>%
    set_names("date", "rate")
}

# Define convert_currencies

convert_currencies <- function(price_from,
                               from,
                               to,
                               date = lubridate::today(),
                               floor_unit = "day") {


  rates_start <- tibble(
    from = from,
    to = to,
    date = date %>% 
      as.Date() %>% 
      floor_date(floor_unit)
  ) %>% 
    mutate(from_to = pminmax(from, to)) %>%
    distinct(from_to, date, .keep_all = TRUE)

  # When passing things to the priceR API it is MUCH faster to send over a range
  # of dates rather than doing this individually for each date. Doing such
  # reduces API calls.

  rates_end <- rates_start %>% 
    group_by(from_to) %>% 
    summarise(date_range = list(range(date)),
              from = from[[1]],
              to = to[[1]],
              rates_lookup = pmap(
                .l = list(from, to, date_range),
                .f = from_to_dates_rates
              )
    ) %>% 
    select(-date_range) %>% 
    unnest(rates_lookup)

  rates_lookup <- rates_end %>% 
    semi_join(rates_start, "date")

  # this step makes it so could convert either "from" or "to" currency
  rates_lookup <- bind_rows(rates_lookup,
            rates_lookup %>%
              rename(from = to, to = from) %>%
              mutate(rate = 1 / rate)) %>% 
    distinct()

  tibble(price = price_from, 
         from = from, 
         to = to, 
         date = date) %>% 
    left_join(rates_lookup, c("from", "to", "date")) %>% 
    mutate(output = price * rate) %>% 
    pull(output)
}

Usage

Use convert_currencies() to convert

transactions_complex %>%
  mutate(
    list_price_converted = convert_currencies(
      price_from = list_price_start,
      from = from_currency,
      to = to_currency,
      date = sales_date
    )
  )


stevecondylios/priceR documentation built on Aug. 21, 2024, 8:21 a.m.