Comparing functions getSymbols
and getFX
:
- only the first one changes the date input to -1 day, see below. EDIT: since 2023-10-30 not anymore
- getSymbols returns several values per day, however, Open, Close, etc are the same
- The second one has the 180 days limitation.
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
}
TFX
– Boeschen