2

Let's say I have the following data frame of series.

library(zoo)
n=10
date = as.Date(1:n);date
y = rnorm(10);y
dat = data.frame(date,y)
dat

         date           y
1  1970-01-02 -0.02052313
2  1970-01-03  0.28255304
3  1970-01-04 -0.10718621
4  1970-01-05 -1.19299366
5  1970-01-06  1.17072468
6  1970-01-07  0.55849119
7  1970-01-08  0.30474050
8  1970-01-09 -0.30777180
9  1970-01-10 -0.01874367
10 1970-01-11 -0.74233556

Calculating the rolling standard deviation with width (rolling window) of 3 days,i do:

a = zoo::rollapply(dat$y,3,sd)

With results:

       2         3         4         5         6 
1.7924102 0.4189522 0.4599979 0.4164408 0.3786601 
        7         8         9 
0.9481849 0.7048868 0.2494578 

And finding the maximum standard deviation

max(a)
1.79241

Now I want to find out in which time 3-day interval this maximum refers to.How can I do that? Imagine that my series is 20 years, so I want to find the maximum standard deviation of this 20 years and extract the specific 3 day time interval.

Homer Jay Simpson
  • 1,043
  • 6
  • 19

2 Answers2

1

Updated in response to OPs clarification of working days to include a date vector which misses out weekends, in a nominal manner (I've not checked if these dates are real weekends, the purpose is to miss out dates for weekends).

set.seed(123)

n = 10

date = as.Date(c(1, 4:8, 11:14), origin = "1970-01-01")

y = rnorm(10)

dat = data.frame(date ,y)

roll_win <- 3

dat$a = c(rep(NA_real_, roll_win - 1), zoo::rollapply(dat$y, roll_win ,sd))

dat <- subset(dat, !is.na(a))

dat_max <- dat[dat$a == max(dat$a, na.rm = TRUE), ]

dat_max$date_start <- dat$date[which(dat$a == max(dat$a, na.rm = TRUE)) - (roll_win - 1)]

dat_max
#>         date         y        a date_start
#> 8 1970-01-13 -1.265061 1.496275 1970-01-09

Created on 2022-02-22 by the reprex package (v2.0.1)

Peter
  • 11,500
  • 5
  • 21
  • 31
  • Thank you for your answer.It is very clear and helpful.But I wonder is there a way to identify the interval? I mean it started at 1970/1/9 until 1970/1/12 ? I want R to report the 3 day time interval – Homer Jay Simpson Feb 18 '22 at 10:27
  • updated answer, of course you can adjust the appearance of the output, the information is there, I hope. – Peter Feb 18 '22 at 10:32
  • I like your updated answer but think that the actual days are not the working financial days. – Homer Jay Simpson Feb 18 '22 at 11:20
  • I'm not sure I fully understand what you mean by the "working financial days": should the date values only represent working days, ie exclude weekends and public holidays? Should the date interval refer to the lagged start date rather than max date - two days? – Peter Feb 18 '22 at 11:23
  • no no is ok. thank you.it dependents on the dates on the data frame – Homer Jay Simpson Feb 18 '22 at 11:25
  • I mean if the dataset contains only trading days the Rollapply will roll calculate the usual days including weekends etc. – Homer Jay Simpson Feb 22 '22 at 13:46
  • See revised data and code which, I think, does now only include working days. – Peter Feb 22 '22 at 14:30
  • Is right but I will post a new question with a proper data set – Homer Jay Simpson Feb 22 '22 at 15:01
  • Sorry I thought the question asked for "(rolling window) of 3 days", 10 days seems to be a new criterion; the dummy example assumes that the 9th is a Friday, 10-11 are the weekend (Sat and Sun), 12 and 13 are Mon and Tues so three working days in all: Fri 9th, Mon 12th and Tues 13th – Peter Feb 22 '22 at 15:07
  • Check the real problem [here](https://stackoverflow.com/questions/71226192/obtaining-trading-days-from-rollapply-in-r) – Homer Jay Simpson Feb 22 '22 at 18:19
1

In the case of a centered window, you can do:

step = (3-1)/2
wmax = which.max(a)
int = (wmax - step):(wmax + step)
dat[int[int > 0],] #Avoids error when wmax < step.

#         date          y
# 1 1970-01-02 -0.6264538
# 2 1970-01-03  0.1836433
# 3 1970-01-04 -0.8356286
#Data
library(zoo)
set.seed(1)
n=10
date = as.Date(1:n)
y = rnorm(10)
dat = data.frame(date,y)
dat

a = rollapply(dat$y,3,sd)
Maël
  • 45,206
  • 3
  • 29
  • 67