My RcppBDT package has a function for this.
RcppBDT wraps parts of the Boost Date_Time library, and Boost Date_Time happens to have a number of functions like that. So here is a quick loop for years 2008 to 2011, getting each year's fourth Wednesday in November:
R> library(RcppBDT)
Loading required package: Rcpp
Creating a generic function for ‘print’ from package ‘base’ in package ‘RcppBDT’
Creating a generic function for ‘format’ from package ‘base’ in package ‘RcppBDT’
R> for (y in 2008:2011) print(getNthDayOfWeek(fourth, Wed, Nov, y))
[1] "2008-11-26"
[1] "2009-11-25"
[1] "2010-11-24"
[1] "2011-11-23"
R>
Here fourth
, Wed
and Nov
are constants in the package namespace, modeled after corresponding enum
types in the underlying C++ library. Makes for pretty easy use.
Edit: Here is a complete example for all 4th-Wed-in-Nov since 2000. I ensure that both the GSPC
and the vector Wed
of Wednesdays agree on the same Date
type. Then it is just a matter of sticking Wed
into GSPC
:
R> library(quantmod)
Loading required package: Defaults
Loading required package: TTR
R> getSymbols("^GSPC", from="1900-01-01")
R> Wed <- sapply(2000:2011, function(y) getNthDayOfWeek(fourth, Wed, Nov, y))
R> index(GSPC) <- as.Date(index(GSPC))
R> GSPC[as.Date(Wed)]
GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
2000-11-22 1347.35 1347.35 1321.89 1322.36 963200000 1322.36
2001-11-28 1149.50 1149.50 1128.29 1128.52 1423700000 1128.52
2002-11-27 913.31 940.41 913.31 938.87 1350300000 938.87
2003-11-26 1053.89 1058.45 1048.28 1058.45 1097700000 1058.45
2004-11-24 1176.94 1182.46 1176.94 1181.76 1149600000 1181.76
2005-11-23 1261.23 1270.64 1259.51 1265.61 1985400000 1265.61
2006-11-22 1402.69 1407.89 1402.26 1406.09 2237710000 1406.09
2007-11-28 1432.95 1471.62 1432.95 1469.02 4508020000 1469.02
2008-11-26 852.90 887.68 841.37 887.68 5793260000 887.68
2009-11-25 1106.49 1111.18 1104.75 1110.63 3036350000 1110.63
2010-11-24 1183.70 1198.62 1183.70 1198.35 3384250000 1198.35
2011-11-23 1187.48 1187.48 1161.79 1161.79 3798940000 1161.79
R>
Edit 2 As a Public Servive Announcement, here is where Jeff's answer fails:
R> ind <- .indexmon(GSPC)==10 & .indexmday(GSPC) > 22 & .indexmday(GSPC) < 29
+ & .indexwday(GSPC) == 3
R> index(GSPC)[ind]
[1] "1951-11-28" "1952-11-26" "1953-11-25" "1954-11-24" "1955-11-23"
[6] "1956-11-28" "1957-11-27" "1958-11-26" "1959-11-25" "1960-11-23"
[11] "1962-11-28" "1963-11-27" "1964-11-25" "1965-11-24" "1966-11-23"
[16] "1968-11-27" "1969-11-26" "1970-11-25" "1971-11-24" "1973-11-28"
[21] "1974-11-27" "1975-11-26" "1976-11-24" "1977-11-23" "1979-11-28"
[26] "1980-11-26" "1981-11-25" "1982-11-24" "1983-11-23" "1984-11-28"
[31] "1985-11-27" "1986-11-26" "1987-11-25" "1988-11-23" "1990-11-28"
[36] "1991-11-27" "1992-11-25" "1993-11-24" "1994-11-23" "1996-11-27"
[41] "1997-11-26" "1998-11-25" "1999-11-24" "2001-11-28" "2002-11-27"
[46] "2003-11-26" "2004-11-24" "2005-11-23" "2007-11-28" "2008-11-26"
[51] "2009-11-25" "2010-11-24" "2011-11-23"
and
R> S <- 1951:2011
R> S[!S %in% as.numeric(format(index(GSPC)[ind], "%Y")) ]
[1] 1961 1967 1972 1978 1989 1995 2000 2006
R>
So there are eight years missing in the sample of sixty when you use his approach.