joshuaulrich / xts

Extensible time series class that provides uniform handling of many R time series classes by extending zoo.
http://joshuaulrich.github.io/xts/
GNU General Public License v2.0
220 stars 71 forks source link

Error in lag.xts(x, n, na.pad = na.pad) : abs(k) must be less than nrow(x) #343

Closed interzonez closed 1 year ago

interzonez commented 3 years ago

Description

Encountering an error running RMD script: Error in lag.xts(x, n, na.pad = na.pad) : abs(k) must be less than nrow(x)

In the get_unlevered_target_weights() function below

Expected behavior

Script is calculating weights. Below is the current codeblock and the traceback.

Minimal, reproducible example

#subsetprices <- na.locf(prices['2010::20200410'])
subsetprices <- na.locf(prices['2010::'])
etf_returns <- na.omit(Return.calculate(subsetprices, method='discrete')) 

# Get weights
unl_etf_weights <- get_unlevered_target_weights(etf_returns, rebal = 22, vol_lookback = 90, cor_lookback = 120, cor_shrinkage = 1, adjust_momo = TRUE, momo_multiplier = 0.1)**

# Restrict IEMB exposures to 15%, due to concerns over potential credit risk negative skews which won't appear in the data
EMB_weight_cap <- 0.15

# Subset unl_etf_weights data to pick those which we need to modify
unl_etf_weights_EMB_more_then_cap <- unl_etf_weights[unl_etf_weights$IEMB.LSE > EMB_weight_cap]

# Modify EMB weights
EMB_modded_weights <- replace(unl_etf_weights$IEMB.LSE, unl_etf_weights$IEMB.LSE > EMB_weight_cap, EMB_weight_cap)

# Rescale weights back to 1 on subset
weights_ex_EMB <- subset(unl_etf_weights_EMB_more_then_cap, select = -IEMB.LSE)
weights_ex_EMB <- (1-EMB_weight_cap) * weights_ex_EMB / rowSums(weights_ex_EMB)
unl_etf_weights_EMB_more_then_cap <- cbind(weights_ex_EMB, EMB_modded_weights)

# Ensure we have a right order before we bind back our modified subset
unl_etf_weights_EMB_more_then_cap <- unl_etf_weights_EMB_more_then_cap[,symbols_RP]
unl_etf_weights <- unl_etf_weights[,symbols_RP]

# combine two subset into one
unl_etf_weights <- rbind(unl_etf_weights_EMB_more_then_cap, unl_etf_weights[unl_etf_weights$IEMB.LSE <= EMB_weight_cap])
unl_etf_weights <- unl_etf_weights[c(!duplicated(time(unl_etf_weights))[-1], TRUE)]

# Ensure returns matrix in xts object is in the same order as in the backtest
etf_backtest_returns <- etf_returns[,symbols_RP]
etf_backtest_weights <- unl_etf_weights[,symbols_RP]

# Subset so we're only reporting on the live trading record
etf_backtest_returns <- etf_backtest_returns['2019-9::']
etf_backtest_weights <- etf_backtest_weights['2019-9::']

# Generate performance charts
riskperformance(etf_backtest_returns, weights=etf_backtest_weights)

Error in lag.xts(x, n, na.pad = na.pad) : abs(k) must be less than nrow(x)
6. lag.xts(x, n, na.pad = na.pad)
5. TTR::ROC(synthetic_prices, n = formation_period, type = "discrete")
4. xts::lag.xts(TTR::ROC(synthetic_prices, n = formation_period, type = "discrete"), 1)
3. na.omit(xts::lag.xts(TTR::ROC(synthetic_prices, n = formation_period, type = "discrete"), 1))
2. get_momo_adjustments(ret, formation_period = 12 * 22, vol_weights = volw)
1. get_unlevered_target_weights(etf_returns, rebal = 22, vol_lookback = 90, cor_lookback = 120, cor_shrinkage = 1, adjust_momo = TRUE, momo_multiplier = 0.1)

Session Info

R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] shiny_1.5.0                forcats_0.5.0              stringr_1.4.0              dplyr_1.0.2               
 [5] purrr_0.3.4                readr_1.3.1                tidyr_1.1.2                tibble_3.0.3              
 [9] ggplot2_3.3.2              tidyverse_1.3.0            PerformanceAnalytics_2.0.4 quantmod_0.4.17           
[13] TTR_0.24.2                 xts_0.12.1                 zoo_1.8-8                  here_0.1                  
[17] pacman_0.5.1              

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.5       lubridate_1.7.9  lattice_0.20-41  assertthat_0.2.1 rprojroot_1.3-2  digest_0.6.25    mime_0.9        
 [8] R6_2.4.1         cellranger_1.1.0 backports_1.1.10 reprex_0.3.0     evaluate_0.14    httr_1.4.2       pillar_1.4.6    
[15] rlang_0.4.7      curl_4.3         readxl_1.3.1     rstudioapi_0.11  blob_1.2.1       rmarkdown_2.4    munsell_0.5.0   
[22] tinytex_0.26     broom_0.7.1      httpuv_1.5.4     compiler_4.0.2   modelr_0.1.8     xfun_0.17        pkgconfig_2.0.3 
[29] htmltools_0.5.0  tidyselect_1.1.0 quadprog_1.5-8   fansi_0.4.1      later_1.1.0.1    crayon_1.3.4     dbplyr_1.4.4    
[36] withr_2.3.0      grid_4.0.2       xtable_1.8-4     jsonlite_1.7.1   gtable_0.3.0     lifecycle_0.2.0  DBI_1.1.0       
[43] magrittr_1.5     scales_1.1.1     cli_2.0.2        stringi_1.5.3    promises_1.1.1   fs_1.5.0         xml2_1.3.2      
[50] ellipsis_0.3.1   generics_0.0.2   vctrs_0.3.4      tools_4.0.2      glue_1.4.2       hms_0.5.3        fastmap_1.0.1   
[57] yaml_2.2.1       colorspace_1.4-1 rvest_0.3.6      knitr_1.30       haven_2.3.1     
joshuaulrich commented 3 years ago

Thanks for the report. Unfortunately, this isn't a reproducible example. You need to provide the data and the necessary functions for me to be able to run this code. I can't investigate unless you do that.

In case you can't share your code/data, here are some thoughts to help you investigate:

  1. The error isn't in get_unlevered_target_weights(). It's in get_momo_adjustments().
  2. Look at the output of TTR::ROC(synthetic_prices, n = formation_period, type = "discrete") in the call that fails. My guess is that the result does not have any observations... for some reason.

You can use options(error=recover) to make R start the debugger as soon as there's an error. It will give you a chance to step into any function call in the call stack.

Also, you can email me the data and code, if you do not want to share it publicly. Use maintainer('xts') to get my address.

ghost commented 3 years ago
Error in lag.xts(x, n, na.pad = na.pad) : abs(k) must be less than nrow(x)

This doesn't appear to be a bug in xts. The message is correct: abs(k) must be less than the number of available rows. If the user specifies k greater than nrow(x), then maybe xts should return a vector with NA, not an error - this is a bug in user's code, not in xts.

joshuaulrich commented 1 year ago

Closing, since this isn't something that can be fixed by changes in xts' code.