16

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"))
Max Ghenis
  • 14,783
  • 16
  • 84
  • 132

3 Answers3

29

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.
GSee
  • 48,880
  • 13
  • 125
  • 145
  • 2
    You can actually get by without a TrueFX username: `qt <- QueryTrueFX(); qt[qt$Symbol %in% paste(to, from, sep="/"),]`, but you'd still need to either know whether you need the pair quoted in reverse, or have some logic to see which exists. – GSee Nov 02 '14 at 01:19
  • is this quant mod function now defunct? quant mod::getFX("USD/JPY") returns: Error in download.file(oanda.URL, destfile = tmp, quiet = !verbose) : cannot open URL 'http://www.oanda.com/currency/historical-rates/download?quote_currency=USD&end_date=2016-04-27&start_date=2014-12-15&period=daily&display=absolute&rate=0&data_range=y2&price=mid&view=table&base_currency_0=JPY&base_currency_1=&base_currency_2=&base_currency_3=&base_currency_4=&download=csv' – tim Apr 27 '16 at 18:02
  • 1
    @tim it has been fixed in the development version. Alternatively, you can work around like this: `options(download.file.method="wget"); getFX("USD/JPY")` – GSee Apr 28 '16 at 12:15
  • 2
    this is why r is the best – Paul Apr 12 '17 at 06:40
  • 3
    One question: How to use 'quantmod' to get yahoo quotes for a specific date, say 2019-12-31? – vicky Feb 27 '20 at 14:48
7

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")

enter image description here

Some more examples can be found here, and here.

stevec
  • 41,291
  • 27
  • 223
  • 311
  • Hello @stevec, I really like priceR but can I ask where the data for priceR originates? The reason I ask is that, if I do an inflation adjustment (say 50 from Jan 2000 to Jan 2019) for US dollars and compare it to an online calculator - then I get really similar results. But for EUR priceR significantly underestimates the correction (~65 vs ~69). For GBP it's ~73 vs ~85 suggested by the Bank of England. I guess because the UK moved to RPI from CPI, but is there a way to get priceR to use (say) RPI instead? – Mooks Sep 01 '20 at 15:45
  • @Mooks thanks for letting me know! All inflation data comes directly from the World Bank API. All currency exchange data comes from the European Central Bank (via https://exchangerate.host/). If you confirm there is a bug, please let me know here: https://github.com/stevecondylios/priceR/issues and I will follow up – stevec Sep 01 '20 at 15:48
  • @Mooks [here](https://data.worldbank.org/indicator/FP.CPI.TOTL.ZG) is the documentation for the World Bank inflation measure `adjust_for_inflation()` uses – stevec Sep 01 '20 at 15:54
  • @Mooks Unfortunately there's no easy way to use the RPI. The best I could suggest is you could view the [code that calculates real prices](https://github.com/stevecondylios/priceR/blob/master/R/adjust_for_inflation.R#L573-L592) and try to incorporate RPI instead of CPI. Hope that's some help – stevec Sep 01 '20 at 16:01
  • 2
    Awesome package! Thanks – Frederick Feb 26 '21 at 11:37
6

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, to, dt=Sys.Date()) {
  require(quantmod)
  obj.names <- getFX(paste0(from, "/", to), from=dt, to=dt)
  result <- numeric(length(obj.names))
  names(result) <- obj.names
  for (obj.name in obj.names) {
    result[obj.name] <- as.numeric(get(obj.name))[1]
    # Clean up    
    rm(obj.name)
  }
  return(result)
}

TestExchangeRates <- function() {
  from <- c("CAD", "JPY", "USD")
  to <- c("USD", "USD", "EUR")
  GetExchangeRates(from, to)
}
Max Ghenis
  • 14,783
  • 16
  • 84
  • 132
  • 2
    `getFX` is nice for historic requests, but it only updates daily. – GSee Nov 02 '14 at 00:47
  • 1
    However, historical data in only available for the past 180 days. Is there any way to also get older data? – Frederick May 03 '19 at 13:16
  • Beware that **quantmod::getFX** returns mid prices from OANDA (I found this by comparing rates to other sources and using OANDA online feed). The mid prices are something like intraday average... I found really strange effects on these data. Really strange... – Alexey Burnakov May 17 '19 at 12:03