Question

I want to cumulate the returns of >4000 individual securities over 3 months i.e. a quarter. I want the results in a new dataframe showing what the cumulative returns are per quarter. How can I do this in a loop or using the apply function/plyr package?

Example:

returns<-c(rnorm(96,1,0.1))
    names<-c(rep("a",24),rep("b",24),rep("c",24), rep("d",24))
    years<-c(rep(2003,12),rep(2004,12))
    year<-rep(years,4)
    month<-rep(1:12,8)
    funds<-data.frame(names,year,month,returns)

EDIT:

I have written the following code previously (for my real dataset)

for (k in 1:length(uniquefundnames)){                               

  id<-funds$id[k]                                   

  quart1<-period.1$factor.perf[period.1$fund_id==id]*           
    period.2$factor.perf[period.2$fund_id==id]*
    period.3$factor.perf[period.3$fund_id==id]

 funds$return.1[k]<-quart1                          

}
Was it helpful?

Solution

How about this with plyr:

require(plyr)
funds$q<-ceiling(funds$month/3)
ddply(funds,.(year,q),summarize,ret=prod(returns))

  year q      ret
1 2003 1 1.349575
2 2003 2 1.156997
3 2003 3 1.094396
4 2003 4 1.114892
5 2004 1 1.205335
6 2004 2 1.086034
7 2004 3 1.468498
8 2004 4 1.833158

EDIT - sorry - cumulative by name

require(plyr)
funds$q<-ceiling(funds$month/3)
qrets<-ddply(funds,.(names,year,q),summarize,ret=prod(returns))
qrets$cum<-cumprod(qrets$ret)



names year q       ret      cum
1      a 2003 1 1.0561211 1.056121
2      a 2003 2 1.0953151 1.156785
3      a 2003 3 1.0216484 1.181828
4      a 2003 4 0.9917425 1.172069
5      a 2004 1 1.0119346 1.186057
6      a 2004 2 1.2291385 1.457829
7      a 2004 3 1.1856941 1.728539
8      a 2004 4 1.1645479 2.012966
9      b 2003 1 0.9441853 1.900613
10     b 2003 2 1.0018355 1.904102
11     b 2003 3 1.0503731 2.000017
12     b 2003 4 0.9353941 1.870804
13     b 2004 1 1.0605124 1.984011
14     b 2004 2 0.9882635 1.960726
15     b 2004 3 0.9051943 1.774838
16     b 2004 4 0.9547135 1.694462
17     c 2003 1 1.1991934 2.031987
18     c 2003 2 1.2028025 2.444079
19     c 2003 3 1.2238102 2.991089
20     c 2003 4 0.9579562 2.865332
21     c 2004 1 1.0398172 2.979422
22     c 2004 2 0.9187201 2.737255
23     c 2004 3 1.1507847 3.149991
24     c 2004 4 1.2836914 4.043617
25     d 2003 1 1.1285913 4.563591
26     d 2003 2 0.8766021 4.000453
27     d 2003 3 0.8333271 3.333686
28     d 2003 4 1.2545656 4.182328
29     d 2004 1 1.0801464 4.517526
30     d 2004 2 0.9731656 4.396301
31     d 2004 3 1.1889534 5.226997
32     d 2004 4 1.2844251 6.713686

EDIT updated with treatment of partial quarter data and filtering for subsets of names

require(plyr)
funds$q<-ceiling(funds$month/3)
qrets<-ddply(funds,.(names,year,q),summarize,ret=prod(returns),no_months=length(names))

# options for quarters with missing months (only pick one)
qrets$cum<-cumprod(qrets[qrets$no_months==3,]$ret)  # ignores entire quarter
qrets$cum<-cumprod(qrets$ret*3/qrets$no_months)     # factor the existing performanc
                                                    # to the entire quarter


qrets                                      # returns all results
qrets[qrets$names %in% c("a","b"),]        # filters for a subset of names

names year q       ret no_months      cum
1      a 2003 1 1.1791380         3 1.179138
2      a 2003 2 1.0300797         3 1.214606
3      a 2003 3 0.9737514         3 1.182724
4      a 2003 4 0.9431317         3 1.115465
5      a 2004 1 0.9750367         3 1.087619
6      a 2004 2 1.2181052         3 1.324835
7      a 2004 3 0.9239893         3 1.224133
8      a 2004 4 0.9864147         3 1.207503
9      b 2003 1 1.2407158         3 1.498168
10     b 2003 2 0.9369874         3 1.403765
11     b 2003 3 0.7991036         3 1.121753
12     b 2003 4 1.1315174         3 1.269283
13     b 2004 1 0.9563123         3 1.213831
14     b 2004 2 0.9895436         3 1.201139
15     b 2004 3 1.2702817         3 1.525785
16     b 2004 4 0.8010484         3 1.222228
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top