2016-04-24 4 views
1

J'ai un problème pour me demander de calculer le produit de laminage d'une série de retours de 1 période. La longueur de la fenêtre mobile est variable. Le but est d'obtenir le produit roulant des déclarations de 1 période qui couvre le plus possible une fenêtre de 12 mois.Calculer le produit cumulatif sur des fenêtres de temps de 1 an dans R

J'ai été en mesure de produire une solution de travail en utilisant la force brute à travers for boucles et if déclarations, mais je me demande s'il existe une solution élégante. J'ai passé beaucoup de temps à essayer avec rollapply et d'autres fonctions similaires, mais je n'ai pas été en mesure d'obtenir une solution.

Les données ci-dessous illustrent le problème.

date  rt_1_period rt_12_mth_window 
1 04-04-13 NA   NA 
2 10-04-13 0.729096362 NA 
3 24-05-13 1.002535647 NA 
4 30-05-13 0.993675716 NA 
5 21-07-13 1.002662843 NA 
6 03-08-13 1.009516582 NA 
7 01-09-13 0.963099395 NA 
8 20-10-13 1.012470278 NA 
9 25-10-13 1.01308502 NA 
10 03-11-13 1.005440704 NA 
11 01-01-14 1.024208021 NA 
12 11-01-14 0.996613924 NA 
13 17-02-14 1.009811368 NA 
14 24-02-14 1.008139557 NA 
15 30-03-14 1.002794709 NA 
16 30-04-14 0.998745849 1.042345473 
17 02-05-14 1.002324076 1.044767963 
18 27-06-14 0.997741026 1.046389027 
19 24-08-14 1.015767546 1.050072129 
20 05-09-14 1.014405005 1.106010894 
21 02-11-14 1.013830296 1.09319212 
22 09-11-14 1.013127219 1.101549487 
23 16-11-14 1.012614177 1.115444628 
24 18-01-15 0.986893629 1.078458006 
25 24-01-15 1.028120919 1.108785236 
26 10-04-15 0.912452762 0.991025615 
27 09-08-15 1.004676152 0.981376513 
28 07-01-16 1.004236123 0.934086003 
29 01-04-16 1.02341302 0.94215696 

Dans l'exemple des 12 mois de retour pour la ligne 29 est calculé comme le produit d'une période de retour de ligne 26 à 29 parce 04/02/15 (365 jours à partir de 04/01/16) est compris entre De l'autre côté, la déclaration de 12 mois pour la ligne 15 est NA parce que 30-03-13 (365 jours du 30-03-14) est en dehors de la fenêtre temporelle pour laquelle j'ai des retours de période observables.

Je serais heureux si quelqu'un pourrait suggérer une façon d'aborder ce problème. Pour plus de clarté, si les données fournies n'ont pas beaucoup de sens, c'est parce qu'il s'agit d'une version réduite d'une base de données plus grande que j'ai créée à des fins d'illustration.

Répondre

0

Vous pouvez utiliser xts et lubridate pour simplyfying manipulations de date

données:

require(xts) 
require(lubridate) 


DF = read.csv(text=" 
date,rt_1_period,rt_12_mth_window 
04-04-13,   , 
10-04-13,0.729096362, 
24-05-13,1.002535647, 
30-05-13,0.993675716, 
21-07-13,1.002662843, 
03-08-13,1.009516582, 
01-09-13,0.963099395, 
20-10-13,1.012470278, 
25-10-13,1.01308502 , 
03-11-13,1.005440704, 
01-01-14,1.024208021, 
11-01-14,0.996613924, 
17-02-14,1.009811368, 
24-02-14,1.008139557, 
30-03-14,1.002794709, 
30-04-14,0.998745849,1.042345473 
02-05-14,1.002324076,1.044767963 
27-06-14,0.997741026,1.046389027 
24-08-14,1.015767546,1.050072129 
05-09-14,1.014405005,1.106010894 
02-11-14,1.013830296,1.09319212 
09-11-14,1.013127219,1.101549487 
16-11-14,1.012614177,1.115444628 
18-01-15,0.986893629,1.078458006 
24-01-15,1.028120919,1.108785236 
10-04-15,0.912452762,0.991025615 
09-08-15,1.004676152,0.981376513 
07-01-16,1.004236123,0.934086003 
01-04-16,1.02341302 ,0.94215696",header=TRUE,stringsAsFactors=FALSE,na.strings="") 


#Convert to xts time series for ease in date manipulation 

DF_xts = xts(DF[,-1],order.by = as.Date(DF[,1],format="%d-%m-%y")) 
head(DF_xts) 
# 
#    rt_1_period rt_12_mth_window 
#2013-04-04   NA    NA 
#2013-04-10 0.729096362    NA 
#2013-05-24 1.002535647    NA 
#2013-05-30 0.993675716    NA 
#2013-07-21 1.002662843    NA 
#2013-08-03 1.009516582    NA 




#set lag period as 1 year 
lagPeriod = 1 

cumulatif 12m produit:

Pour chaque date construire une fenêtre [prevYearDate, date] , le sous-ensemble 1m revient dans cette fenêtre, calculez le produit cumulatif et sélectionnez le dernier produit

rt_12_mth_window_Calc = do.call(rbind,lapply(as.Date(index(DF_xts)),function(x) { 

prevYearDate = x-years(lagPeriod) 

rt_12_mth_window_Calc = last(cumprod(DF_xts[paste0(prevYearDate,"/",x),"rt_1_period"])) 
colnames(rt_12_mth_window_Calc) = "rt_12_mth_window_Calc" 

return(rt_12_mth_window_Calc) 

})) 

Dataset final:

#Merge with original time series for final dataset 

new_DF = merge.xts(DF_xts,rt_12_mth_window_Calc) 

#Calculate difference in original and calculated 12 month returns 
new_DF$delta = new_DF$rt_12_mth_window_Calc - new_DF$rt_12_mth_window 
new_DF 

#   rt_1_period rt_12_mth_window rt_12_mth_window_Calc   delta 
#2013-04-04   NA    NA     NA    NA 
#2013-04-10 0.729096362    NA     NA    NA 
#2013-05-24 1.002535647    NA     NA    NA 
#2013-05-30 0.993675716    NA     NA    NA 
#2013-07-21 1.002662843    NA     NA    NA 
#2013-08-03 1.009516582    NA     NA    NA 
#2013-09-01 0.963099395    NA     NA    NA 
#2013-10-20 1.012470278    NA     NA    NA 
#2013-10-25 1.013085020    NA     NA    NA 
#2013-11-03 1.005440704    NA     NA    NA 
#2014-01-01 1.024208021    NA     NA    NA 
#2014-01-11 0.996613924    NA     NA    NA 
#2014-02-17 1.009811368    NA     NA    NA 
#2014-02-24 1.008139557    NA     NA    NA 
#2014-03-30 1.002794709    NA     NA    NA 
#2014-04-30 0.998745849  1.042345473   1.042345470 -2.64001643e-09 
#2014-05-02 1.002324076  1.044767963   1.044767960 -2.54864396e-09 
#2014-06-27 0.997741026  1.046389027   1.046389025 -1.97754613e-09 
#2014-08-24 1.015767546  1.050072129   1.050072127 -1.66086833e-09 
#2014-09-05 1.014405005  1.106010894   1.106010893 -1.34046041e-09 
#2014-11-02 1.013830296  1.093192120   1.093192120 -6.47777387e-11 
#2014-11-09 1.013127219  1.101549487   1.101549488 5.99306826e-10 
#2014-11-16 1.012614177  1.115444628   1.115444628 -1.89856353e-10 
#2015-01-18 0.986893629  1.078458006   1.078458005 -1.15637744e-09 
#2015-01-24 1.028120919  1.108785236   1.108785235 -9.57268265e-10 
#2015-04-10 0.912452762  0.991025615   0.991025613 -1.54581248e-09 
#2015-08-09 1.004676152  0.981376513   0.996850412 1.54738992e-02 
#2016-01-07 1.004236123  0.934086003   0.934086002 -9.15302278e-10 
#2016-04-01 1.023413020  0.942156960   0.942156960 -1.82048598e-10 

Les valeurs calculées et sont très proches orignal pour toutes les observations, sauf pour 09/08/2015, l'écart des valeurs est de 1,55%, pourriez-vous confirmer vos calculs pour cette période

+0

Merci beaucoup pour la réponse! Très appréciée! Vous avez raison le 2015-08-09. Les données que j'ai utilisées étaient un copier coller à partir d'une feuille de calcul Excel maquette et votre version est correcte. J'ai commencé à utiliser votre code et semble bien fonctionner. Merci! – Abdd

+0

Juste essayé d'exécuter le code sur le jeu de données réel qui est une version expnded de ce que j'ai posté et a obtenu l'erreur suivante 'Erreur dans appliquer (coredata (x), 2, fonction (y) cumprod (y)): dim (X) doit avoir une longueur positive. Savez-vous quelle pourrait être l'origine?Merci d'avance – Abdd

+0

pourriez-vous mettre à jour votre question et inclure l'appel de fonction que vous faites avec 'dput (head (data))' wherre 'data' est vos données d'entrée. Seulement alors nous pouvons répliquer l'erreur – OdeToMyFiddle

0

Voici une solution qui ne dépend que de xts, et peut-être plus simple pour certains.

library(xts) 
x <- as.xts(read.zoo(text="date,rt_1_period,rt_12_mth_window 
04-04-13,   , 
10-04-13,0.729096362, 
24-05-13,1.002535647, 
30-05-13,0.993675716, 
21-07-13,1.002662843, 
03-08-13,1.009516582, 
01-09-13,0.963099395, 
20-10-13,1.012470278, 
25-10-13,1.013085020, 
03-11-13,1.005440704, 
01-01-14,1.024208021, 
11-01-14,0.996613924, 
17-02-14,1.009811368, 
24-02-14,1.008139557, 
30-03-14,1.002794709, 
30-04-14,0.998745849,1.042345473 
02-05-14,1.002324076,1.044767963 
27-06-14,0.997741026,1.046389027 
24-08-14,1.015767546,1.050072129 
05-09-14,1.014405005,1.106010894 
02-11-14,1.013830296,1.09319212 
09-11-14,1.013127219,1.101549487 
16-11-14,1.012614177,1.115444628 
18-01-15,0.986893629,1.078458006 
24-01-15,1.028120919,1.108785236 
10-04-15,0.912452762,0.991025615 
09-08-15,1.004676152,0.981376513 
07-01-16,1.004236123,0.934086003 
01-04-16,1.023413020,0.94215696", header=TRUE, sep=",", format="%d-%m-%y")) 
ix <- index(x)  # index values 
ixlag <- ix-365  # 1-year lag index values 
x$rt_12 <- NA_real_ # initialize result column 
for(i in which(ixlag > ix[1])) { 
    # 1-year subset 
    xyear <- window(x, start=ixlag[i], end=ix[i]) 
    # calculate product and update result column 
    x[i,"rt_12"] <- prod(xyear[,"rt_1_period"]) 
} 
+0

Merci pour la solution alternative! – Abdd