Как взять взвешенные суммы каждой строки матрицы в R

У меня есть взвешенный портфель акций и история их ежедневной доходности. Я пытаюсь вычислить доходность портфеля в каждый исторический день, предполагая, что веса не меняются, и заменяя отсутствующие данные нулями (я пытаюсь вычислить историческую VaR или < em>Ценность под угрозой).

Вот упрощенная версия:

# portfolio
pfolio = data.frame(ticker = c("stock_a", "stock_b", "stock_noob"), weight = c(0.25, 0.6, 0.15))

# Daily stock returns (with some NA values for one stock):
m = matrix(c(0.0016, 0.0037, -0.0042, -0.0096, -0.0006, -0.0043, -0.0292, -0.0158, 0.0128, 0.0113, 0.0016, 0.0042, NA, NA, 0.0168, -0.0293, 0.0037, -0.0083),
    nrow = 6,
    ncol = 3,
    dimnames = list(c("2017-03-01", "2017-03-02", "2017-03-03", "2017-03-06", "2017-03-07", "2017-03-08"), c("stock_a", "stock_b", "stock_noob"))
)

Я пытаюсь использовать умный метод apply или mapply, но лучшее, что я могу придумать, это сначала очистить данные, а затем применить цикл for (фух):

m_clean = apply(m, c(1, 2), function(x) if (is.na(x)) 0 else x)
answer = numeric(0)
for (i in 1:nrow(m_clean)) {
    answer = c(answer, sum(m_clean[i, pfolio$ticker] * pfolio$weight))
}

Итак, главный вопрос: что такое чистый однострочный способ сделать это?


person lebelinoz    schedule 29.03.2017    source источник


Ответы (1)


Ты можешь сделать:

m_clean <- ifelse(is.na(m), 0, m) # or 
m_clean <- m; m_clean[is.na(m_clean)] <- 0

а потом

answer <- apply(m_clean, 1, weighted.mean, w=pfolio$weight) # or
answer <- colSums(t(m_clean) * pfolio$weight) # or
answer <- tcrossprod(pfolio$weight, m_clean)

Последнее дает матрицу:

#> tcrossprod(pfolio$weight, m_clean)
#     2017-03-01 2017-03-02 2017-03-03 2017-03-06 2017-03-07 2017-03-08
#[1,]   -0.01712  -0.008555    0.00915   -1.5e-05   0.001365      2e-04

другие решения дают именованный вектор.

ориентиры:

library("microbenchmark")
microbenchmark(
  a= apply(m_clean, 1, weighted.mean, w=pfolio$weight),
  c= colSums(t(m_clean) * pfolio$weight),
  p= tcrossprod(pfolio$weight, m_clean),
  m= m_clean %*% pfolio$weight
)
# Unit: microseconds
# expr    min      lq     mean  median      uq    max neval cld
#    a 49.115 51.0590 54.46379 52.3685 53.9815 99.023   100   c
#    c 12.688 13.8385 15.02912 14.8460 15.7560 32.366   100  b 
#    p  5.978  6.8955  7.75998  7.4170  7.8770 30.771   100 a  
#    m  5.438  6.4330  6.95056  6.8615  7.2710 17.109   100 a  
person jogo    schedule 29.03.2017
comment
Спасибо, и спасибо, что рассказали мне о пакете microbenchmark. tcrossprod выдаст вектор вместо матрицы, если вы поменяете местами два параметра: tcrossprod(m_clean, pfolio$weight), как вы сделали в примере с микробенчмарком. - person lebelinoz; 30.03.2017