2026-03-16 13:13:15 +00:00

129 lines
4.1 KiB
R

GetECBHistoricalExchangeRateData <- function() {
# 1. Setup temporary files and download the data
temp_zip <- tempfile(fileext = ".zip")
url <- "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.zip"
message("Downloading data from ECB...")
download.file(url, temp_zip, quiet = TRUE)
# 2. Unzip and identify the CSV file
unzipped_files <- unzip(temp_zip, exdir = tempdir())
csv_file <- unzipped_files[grep("\\.csv$", unzipped_files)]
# 3. Load the data into R
message("Loading data...")
df <- read.csv(csv_file, na.strings = c("N/A", "NA", ""), stringsAsFactors = FALSE)
# Clean up temp files
unlink(temp_zip)
unlink(csv_file)
return(df)
}
PreProcessData <- function(df, target_currencies, last_n_days = NULL) {
# Preprocess Dates and Time
df$Date <- as.Date(df$Date)
df <- df[order(df$Date), ]
# Filter by the last N days if specified
if (!is.null(last_n_days)) {
cutoff_date <- max(df$Date, na.rm = TRUE) - last_n_days
df <- df[df$Date >= cutoff_date, ]
message(sprintf("Filtered data to the last %d days (since %s).", last_n_days, cutoff_date))
}
# Create a Time Index for the regression
df$TimeIndex <- as.numeric(df$Date - min(df$Date))
# Ensure targets actually exist in the dataframe to prevent errors
valid_targets <- intersect(target_currencies, names(df))
# Filter the data frame down to Date, TimeIndex, and those specific targets
df <- df[, c("Date", "TimeIndex", valid_targets)]
# Create the new cross pairs dynamically
# combn(valid_targets, 2) creates all unique 2-pair combinations
if (length(valid_targets) >= 2) {
pair_combos <- combn(valid_targets, 2)
for (i in 1:ncol(pair_combos)) {
base_curr <- pair_combos[1, i]
quote_curr <- pair_combos[2, i]
# Create column name, e.g., "USD_JPY"
pair_name <- paste0(base_curr, "_", quote_curr)
# Math: To get Base/Quote, divide the ECB Quote column by the ECB Base column
df[[pair_name]] <- df[[quote_curr]] / df[[base_curr]]
}
}
# Update the 'currencies' vector so the loop analyzes original and new columns
currencies <- setdiff(names(df), c("Date", "TimeIndex"))
return(list(currencies = currencies, df = df))
}
CalculateMetrics <- function(df,currencies) {
# 5. Loop through each currency, run regression, and calculate metrics
results_list <- list()
message("Running regressions...")
for (curr in currencies) {
valid_data <- df[!is.na(df[[curr]]), ]
if (nrow(valid_data) > 2) {
# Simple linear regression: Exchange Rate ~ Time
model <- lm(valid_data[[curr]] ~ valid_data$TimeIndex)
# Extract Beta (slope) and Residual Standard Error (RSE)
beta <- coef(model)[2]
rse <- summary(model)$sigma
# Calculate Signal-to-Noise Ratio: |Beta| / RSE
if (!is.na(rse) && rse > 0) {
signal_to_noise <- abs(beta) / rse
} else {
signal_to_noise <- NA
}
# Store results
results_list[[curr]] <- data.frame(
Currency = curr,
Beta = beta,
AbsBeta = abs(beta),
RSE = rse,
SignalToNoise = signal_to_noise,
stringsAsFactors = FALSE,
row.names = NULL
)
}
}
# Combine all results
results_df <- do.call(rbind, results_list)
return (results_df)
}
OrderBySignalToNoiseRatio <- function(results_df) {
# 6. Order by the Signal-to-Noise ratio and get the top 3
top_3_currencies <- results_df[order(results_df$SignalToNoise, decreasing = TRUE), ]
top_3_currencies <- head(top_3_currencies, 3)
return (top_3_currencies)
}
#
# 10. RUNTIME
#
df <- GetECBHistoricalExchangeRateData()
res <- PreProcessData(df,c("USD", "JPY", "GBP","CAD","NOK"),720)
results_df <- CalculateMetrics(res$df,res$currencies)
top_3_currencies <- OrderBySignalToNoiseRatio(results_df)
# Print the final output
message("\nTop 3 currencies by Trend Predictability (|Beta| / RSE):")
print(top_3_currencies)