Search code examples
rdataframeblockmaxima

Extract minima returns


I am trying to apply the block maxima (in my case minima) approach of Extreme Value Theory to financial returns. I have daily returns for 30 financial indices stored in a csv file called 'Returns'. I start by loading the data

Returns<-read.csv("Returns.csv", header=TRUE)               

I then extract the minimum returns over consecutive non-overlapping blocks of equal length (i.e., 5 days) for each index I have in my 'Returns.csv' file. For that, I do the following

    for (xx in Returns)                             #Obtain the minima. 
    {
    rows<-length(xx)                                #This is the number of returns
    m<-5                                            #When m<-5 we obtain weekly minima. Change accordingly (e.g., 20)
    k<-rows/m                                       #This is the number of blocks (i.e., number of returns/size of block),
    bm<-rep(0,k)                                    #which is also the number of extremes
    for(i in 1:k){bm[i]<-min(xx[((i-1)*m+1):(i*m)])}
                                        #Store the minima in a file 'minima.csv' 
    write.table(bm,file="minima.csv", append=TRUE, row.names=FALSE, col.names=FALSE)

The code extracts the minima returns for all indices correctly but when the minima are stored in the file 'minima.csv' they all appear in the same column (appended). What I want the code to do is to read the financial returns contained in the first column of the file 'Returns.csv', extract the minima returns over consecutive non-overlapping blocks of equal length (i.e., 5 days) and store them in the first column of the file 'minima.csv'. Then do exactly the same for the financial returns contained in the second column of the file 'Returns.csv' and store the minima returns in the second column of the file 'minima.csv', and so on, until I reach column 30.


Solution

  • I think your data looks similar to this:

    > m <- matrix(1:40, ncol=4)
    > m
          [,1] [,2] [,3] [,4]
     [1,]    1   11   21   31
     [2,]    2   12   22   32
     [3,]    3   13   23   33
     [4,]    4   14   24   34
     [5,]    5   15   25   35
     [6,]    6   16   26   36
     [7,]    7   17   27   37
     [8,]    8   18   28   38
     [9,]    9   19   29   39
    [10,]   10   20   30   40
    

    Obviously you have more rows and columns and your data is not just the sequence of 1 to 40. To chunk each column with a size of 5 and find the minimum for each column run:

    > apply(m, 2, function(x) sapply(split(x, ceiling(seq_along(x)/5)),  min))
      [,1] [,2] [,3] [,4]
    1    1   11   21   31
    2    6   16   26   36
    

    Basically the apply is splitting m by the columns and applying the function to each column. The inner function takes each column, chunks the columns and then returns the minimum of each chunk. Your data is in a dataframe not a matrix so you need to do this before you run the command above.

    m <- as.matrix(Returns)
    

    To write this to a csv

    > mins <- apply(m, 2, function(x) sapply(split(x, ceiling(seq_along(x)/5)),  min))
    > write.table(mins, file="test.min.csv", sep=',', row.names=F, col.names=F, quote=F)