Reputation: 15793
Are there are any R packages/functions to get exchange rates in real time, e.g. from Google Finance? Would prefer to avoid RCurl or other parsers if something's already out there.
Specifically, given vectors of "from" and "to" currency symbols, I'd like to know the rates. Something like:
IdealFunction(c("CAD", "JPY", "USD"), c("USD", "USD", "EUR"))
Upvotes: 18
Views: 29239
Reputation: 3043
Comparing functions getSymbols
and getFX
:
Regarding Alexey Burkanov comment
"Beware that quantmod::getFX returns mid prices from OANDA"
it seems true, because the average
built here is closer to FX than the "Adjusted column" of getSymbol
(other tests show same trend, not shown).
from_curr <- c("CAD", "JPY", "USD")
to_curr <- c("USD", "USD", "EUR")
library(quantmod)
# this dates will not work currently see above
res <- GetExchangeRates(from_curr = from_curr, to_curr = to_curr, "2023-05-03", "2023-05-09")
# artificial avg_low_high_this_fun column vs FX:
sum(abs(res$FX - res$avg), na.rm = T)
0.005812667
# Adjusted_Sy == Close == Open ? vs FX:
sum(abs(res$FX - res$Adjusted_Sy), na.rm = T)
0.01492536
# inspired in other answer:
require(quantmod)
require(dplyr)
require(stringr)
require(rlang)
require(tibble)
GetExchangeRates <- function(from_curr, to_curr, from_date, to_date = from_date) {
exchanges <- paste0(from_curr, "/", to_curr)
result_getFX <- mapply(
function(from_curr, to_curr) {
ready_name <- paste0(from_curr, ".", to_curr)
getFX(paste0(from_curr, "/", to_curr),
from = from_date,
to = to_date,
src = "yahoo",
auto.assign = FALSE
) |>
as.list() |>
as.data.frame() |>
rownames_to_column(var = "date") |>
set_names(~ (.) |> paste0("FX")) |>
set_names(~ (.) |> str_replace_all(ready_name, ""))
},
from_curr, to_curr,
SIMPLIFY = F
)
names(result_getFX) <- exchanges
result_getFX <- result_getFX |> bind_rows(.id = "exchange")
result_getSymbols <- try(get_exchange_rates_symbol(from_curr, to_curr, from_date, to_date), silent = TRUE)
if (inherits(result_getSymbols, "try-error")) {
warning("getSymbol unavailable for weekends or between two non-dollar currencies")
return(result_getFX)
}
merge(result_getFX, result_getSymbols,
by.y = c("exchange", "date_input"), by.x = c("exchange", "dateFX"),
all = TRUE
)
}
get_exchange_rates_symbol <- function(from_curr, to_curr, from_date, to_date = from_date) {
exchanges <- paste0(from_curr, "/", to_curr)
result_getSymbols <- mapply(
function(from_curr, to_curr) {
ready_name <- paste0(from_curr, to_curr)
getSymbols(paste0(ready_name, "=X"),
src = "yahoo", auto.assign = FALSE,
from = as.Date(from_date), to = as.Date(to_date)
) |>
as.list() |>
as.data.frame() |>
rownames_to_column(var = "date") |>
set_names(~ (.) |> str_replace_all(".X", "")) |>
rowwise() |>
mutate("{ready_name}.avg_low_high_this_fun" := mean(c(
.data[[paste0(ready_name, ".Low")]],
.data[[paste0(ready_name, ".High")]]
), na.rm = TRUE)) |>
set_names(~ (.) |> str_replace_all(paste0(ready_name, "."), "")) |>
set_names(~ (.) |> paste0("_Sy")) |>
mutate(date_input = ifelse(
as.Date(date_Sy) < as.Date("2023-10-30"),
as.character(as.Date(date_Sy) + 1),
date_Sy
)) |>
relocate(date_input, .before = date_Sy) |>
relocate(avg_low_high_this_fun_Sy, .after = date_input)
},
from_curr, to_curr,
SIMPLIFY = FALSE
)
names(result_getSymbols) <- exchanges
result_getSymbols <- result_getSymbols |>
bind_rows(.id = "exchange") |>
as.data.frame()
result_getSymbols
}
Upvotes: 0
Reputation: 15793
Looks like TFX
and quantmod
have functions for this (thanks to @RStudent and @KFB for the tips). I preferred quantmod
since it didn't require setting up an account, but AFAICT there's no vectorized current-snapshot function like what I'm seeking. This function GetExchangeRates
does this:
GetExchangeRates <- function(from_curr, to_curr, dt) {
require(quantmod)
exchanges <- paste0(from_curr, "/", to_curr)
result <- mapply(
function(from_curr, to_curr) {
getFX(paste0(from_curr, "/", to_curr),
from = dt,
to = dt,
src = "yahoo",
auto.assign = FALSE
)
},
from_curr, to_curr
)
names(result) <- exchanges
return(result)
}
TestExchangeRates <- function() {
from_curr <- c("CAD", "JPY", "USD")
to_curr <- c("USD", "USD", "EUR")
dt <- Sys.Date() -1
GetExchangeRates(from_curr, to_curr, dt)
}
TestExchangeRates()
# CAD/USD JPY/USD USD/EUR
# 0.72915600 0.00667232 0.94388600
Upvotes: 6
Reputation: 52268
You could use historical_exchange_rates()
from the priceR
library.
E.g. to get the daily AUD to USD exchange rate from 2010 to 2020:
# install.packages("priceR")
library(priceR)
cur <- historical_exchange_rates("AUD", to = "USD",
start_date = "2010-01-01", end_date = "2020-06-30")
tail(cur)
date one_AUD_equivalent_to_x_USD
2020-06-25 0.688899
2020-06-26 0.686340
2020-06-27 0.686340
2020-06-28 0.685910
2020-06-29 0.687335
2020-06-30 0.690166
dim(cur)
[1] 3834 2
# Plot USD vs AUD last 10 years
library(ggplot2)
library(tidyverse)
cur %>%
tail(365 * 10) %>%
rename(aud_to_usd = one_AUD_equivalent_to_x_USD) %>%
mutate(date = as.Date(date)) %>%
ggplot(aes(x = date, y = aud_to_usd, group = 1)) +
geom_line() +
geom_smooth(method = 'loess') +
theme(axis.title.x=element_blank(),
axis.ticks.x=element_blank()) +
scale_x_date(date_labels = "%Y", date_breaks = "1 year")
Some more examples can be found here, and here.
Upvotes: 7
Reputation: 49810
You can use quantmod to get yahoo quotes. (I'm not sure how delayed yahoo FX quotes are, or how often they're updated.)
library(quantmod)
from <- c("CAD", "JPY", "USD")
to <- c("USD", "USD", "EUR")
getQuote(paste0(from, to, "=X"))
# Trade Time Last Change % Change Open High Low Volume
#CADUSD=X 2014-11-01 08:23:00 0.8875 N/A N/A N/A N/A N/A N/A
#JPYUSD=X 2014-11-01 08:23:00 0.0089 N/A N/A N/A N/A N/A N/A
#USDEUR=X 2014-11-01 08:23:00 0.7985 N/A N/A N/A N/A N/A N/A
Or TFX for real-time, millisecond timestamped quotes if you sign up for a free account. (note you have to use market convention; i.e. USD/JPY instead of JPY/USD)
library(TFX)
pairs <- paste(to, from, sep="/")
QueryTrueFX(ConnectTrueFX(pairs, "validUser", "anytext"))
# Symbol Bid.Price Ask.Price High Low TimeStamp
#1 USD/CAD 1.12651 1.12665 1.12665 1.12651 2014-10-31 20:45:00.559
#2 USD/JPY 112.34600 112.35900 112.35900 112.34600 2014-10-31 20:45:00.134
#3 EUR/USD 1.25234 1.25253 1.25253 1.25234 2014-10-31 20:45:00.598
Or if you have an Interactive Brokers account, you can use the IBrokers package, or my twsInstrument package (which is basically just wrappers for IBrokers functions)
library(twsInstrument)
getQuote(paste0(to, from), src="IB") # only works when market is open.
Upvotes: 30