5.4 Realized measures of co-volatility
Commands, such as
rCov()
,rThresholdCov()
,rBPCov()
,rTSCov()
andrRTSCov()
, also support calculating realized covariance (co-volatility) when usingxts
objects of multiple assets nAbove commands compute covariance matrix of dimensions n×n for each trading day, which can be standardized for obtaining a correlation matrix by setting the argument
cor=TRUE
For instance, in the bivariate case (assets x and y), the realized covariance (RCOV) for each trading day t is calculated as the sum of the products of synchronized and equally spaced m intraday returns at the K-th sampling frequency
RCOVKt=m∑j=1r(x)t,jr(y)t,j
If the intraday returns of two assets are combined into a single matrix of dimensions m×2, the inner product of this matrix will result in a 2×2 symetric matrix with realized variances on the diagonal and the off–diagonal realized covariances
In addition to the issues of microstructure noise and price jumps, two additional problems emerge when computing realized covariance: high–frequency prices are not synchronized over multiple assets and the covariance matrix is not guaranteed to be positive semi–definite
As the sampling frequency increases (i.e., the sampling interval shortens), RCOV converges to the integrated covariance (ICOV), assuming no microstructure noise in synchronized returns. However, in practice, microstructure noise causes the diagonal elements to be biased upwards and the off–diagonal elements to be biased downwards as sampling frequency increases
Moreover, in the case of non-synchronous returns, an additional bias in realized correlation arises due to so–called Epps effect, further reducing the absolute value of off-diagonal elements
Synchronization schemes and selection of optimal sampling frequency K (neither too low nor too high) are crucial for obtaining an unbiased ICOV estimate, effectively mitigating two primary sources of bias: (a) microstructure noise and (b) the Epps effect
Estimator | Jump robust | Microstructure noise robust | Asynchronized data | Positive semidefinite |
---|---|---|---|---|
RCOV | ✓ | |||
RTHRESCOV | ✓ | ✓ | ||
RBPCOV | ✓ | |||
RTTSCOV | ✓ | ✓ | ✓ | |
RRTTSCOV | ✓ | ✓ | ✓ | ✓ |
The majority of estimators are robust to the price jumps, although they are sensitive to microstructure noise (but can become robust if a sufficiently low optimal sampling frequency is chosen) and time sychronization
RRTTSCOV is the only one that does not lose data with sparse sampling, it is robust not only to microstructure noise and price jumps but also to asynchronous trading, as it employs the refresh time synchronization scheme (previous tick method), and finally the negative eigenvalues of the covariance matrix are replaced with zeros to deal with non positive semidefiniteness (argument
makePsd=TRUE
)The first refresh time corresponds to the first time at which both stocks have traded, the subsequent refresh time is defined as the first time when both stocks have again traded, etc.
covariance_matrices
). Within rRTSCov()
command use input as a list of prices tesla
and
nasdaq
, and set the slow time scale to 8 minutes, while keeping the fast time
scale at the highest possible sampling frequency of 1 minute. Extract the covariance matrix
for the last observed date 2025-03-28
. Again employ the
same command b
to produce correlation_matrices
object by setting argument cor=TRUE
(default is FALSE).
Solution
Copy the code lines below to the clipboard, paste them into an R Script file, and run them.# Loading R data file (.R) from Google Drive using tweaked URL
load(url("https://drive.google.com/uc?export=download&id=1X0uwaGECIsrz9uZZXvfZjLcYCiTF98mi"))
# Making sure that both objects are structured as xts
tesla <- as.xts(tesla) # structured as xts object
nasdaq <- as.xts(nasdaq) # structured as xts object
# Loading highfrequency package from the library
library(highfrequency)
# Make sure that both equities have been traded for same dates
unique_dates1=unique(as.Date(index(tesla))) # 245 days
unique_dates2=unique(as.Date(index(nasdaq))) # 250 days
matching_dates=as.Date(intersect(unique_dates1,unique_dates2))
covariance_matrices <- list()
for (i in seq_along(matching_dates)) {
pData_list <- list(tesla[paste0(matching_dates[i])], nasdaq[paste0(matching_dates[i])])
RTTSRCOV <- rRTSCov(pData_list,
cor = FALSE,
K = 8,
J = 1,
eta=9,
makePsd=TRUE)
covariance_matrices[[as.character(matching_dates[i])]] <- RTTSRCOV}
covariance_matrices["2025-03-28"] # extracts covariance matrix for specific date
covariance_matrices[245] # alternative when day is 245
correlation_matrices <- list()
for (i in seq_along(matching_dates)) {
pData_list <- list(tesla[paste0(matching_dates[i])], nasdaq[paste0(matching_dates[i])])
RTTSRCOV <- rRTSCov(pData_list,
cor = TRUE,
K = 8,
J = 1,
eta=9,
makePsd=TRUE)
correlation_matrices[[as.character(matching_dates[i])]] <- RTTSRCOV}
realized_correlations <- sapply(correlation_matrices, function(x) x[1, 2])
realized_correlations <- xts(realized_correlations,order.by = as.Date(matching_dates))
colnames(realized_correlations) <- c("RTTSRCOV")
library(ggplot2)
ggplot(realized_correlations, aes(x = Index)) +
geom_line(aes(y = RTTSRCOV, color = "RTTSRCOV")) +
geom_smooth(aes(y = RTTSRCOV, color = "RTTSRCOV (smoothed)"), method = "loess", span = 0.07, se = FALSE, linewidth = 1) +
labs(x = "", y = "", title = "Realized correlations") +
scale_color_manual(
values = c("RTTSRCOV" = "steelblue", "RTTSRCOV (smoothed)" = "orchid")
) +
theme_minimal() +
theme(
panel.background = element_rect(fill = "white", color = NA),
legend.position = c(0.85, 0.1),
legend.background = element_blank(),
legend.key = element_blank(),
legend.title = element_blank(),
axis.line = element_line(color = "black"))
covariance_matrices
). Within rRTSCov()
command use input as a list of prices tesla
and
nasdaq
, and set the slow time scale to 8 minutes, while keeping the fast time
scale at the highest possible sampling frequency of 1 minute. Extract the covariance matrix
for the last observed date 2025-03-28
. Again employ the
same command b
to produce correlation_matrices
object by setting argument cor=TRUE
(default is FALSE).
Solution
Copy the code lines below to the clipboard, paste them into an R Script file, and run them.sampling <- c(2:20)
correlation_list <- list()
for (k in sampling) {
for (i in seq_along(matching_dates)) {
pData_list <- list(tesla[paste0(matching_dates[i])], nasdaq[paste0(matching_dates[i])])
RTTSRCOV <- rRTSCov(pData_list,
cor = TRUE,
K = k,
J = 1,
eta=9,
makePsd=TRUE)
correlation_matrices[[as.character(matching_dates[i])]] <- RTTSRCOV
correlations <- xts(sapply(correlation_matrices, function(x) x[1, 2]),order.by = as.Date(matching_dates))
correlation_list[[paste0("K", k)]] <- correlations
}}
all_correlations <- do.call(merge, correlation_list)
colnames(all_correlations) <- names(correlation_list)
# Averaging out realized correlations across days against sampling frequency
correlation_average <- data.frame("AvgCor"=colMeans(all_correlations))
correlation_average$frequency <- sampling
# Plotting the Epps effect
ggplot(correlation_average, aes(x = frequency, y = AvgCor)) +
geom_line(color = "coral") +
geom_point(color = "coral", size = 2) +
labs(x = "Sampling frequency (minutes)", y = "Average realized correlation",title="Epps effect") +
theme_minimal()