Given a matrix, which represents a multivariate time series, wherein some observations are missing, I want to calculate the most likely observation, given a covariance matrix.
Notation: \$x_{-i}\$ represents some vector with the \$i\$th elements removed.
Let \$m\$ be an index of missing observations, \$X\$ is a vector of observations, \$\Omega\$ is a covariance matrix, then \$X_m=X_{-m} \Omega_{-m,-m}^{-1}\Omega_{-m,m}\$
This calculation is repeated for every row.
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat runLinearModelOverTimeInPlace(arma::mat returnsMat, arma::mat covMat) {
int nrow = returnsMat.n_rows;
for (int iRow = 0; iRow < nrow; iRow++){
arma::mat rowMat = returnsMat.row(iRow);
arma::uvec missingIndex = find_nonfinite(rowMat);
if (missingIndex.n_elem > 0) {
arma::uvec notMissingIndex = find_finite(rowMat);
arma::mat A = covMat.submat(notMissingIndex, notMissingIndex);
arma::mat B = covMat.submat(notMissingIndex, missingIndex);
arma::mat beta = arma::solve(A,B);
arma::uvec rowIndexVec = arma::linspace<arma::uvec>(iRow, iRow, 1);
arma::mat res = returnsMat.submat(rowIndexVec, notMissingIndex) * beta;
returnsMat.submat(rowIndexVec, missingIndex) = res;
}
}
return returnsMat;
}
Here is a test case that runs in R:
runLinearModelOverTime = function(returns_with_holes, cov_returns) {
N_sample = nrow(returns_with_holes)
sapply(seq(1, N_sample), \(i){
res = returns_with_holes[i,]
missingIndex = which(is.na(returns_with_holes[i,]))
if(length(missingIndex)>0){
beta = solve(cov_returns[-missingIndex, -missingIndex], cov_returns[-missingIndex, missingIndex])
res[missingIndex] <- returns_with_holes[i,-missingIndex] %*% beta
res
} else {
res
}
}) |> t()
}
set.seed(123)
x = matrix(runif(60), nrow = 10)
# x_ = x + 1
# x_ = x_ - 1
# all.equal(x, x_)
y = cov(x)
x[sample(60, 10)] <- NA
expectedOutput = runLinearModelOverTime(x,y)
actualOutput = runLinearModelOverTimeInPlace(x,y)
all.equal(expectedOutput, actualOutput)