3

希望有人可以提供一个给定日期的函数,它将返回纽约证券交易所月份的交易日。

如果考虑到假期,那是一种奖励,如果不是,我也不会太担心。

提前致谢!

4

3 回答 3

6

我在一个名为的个人包中有一个函数,TradingDates它使用timeDate包中的假日日历来返回指定年份中所有交易日的日期。我在这篇文章的末尾包含了该函数的代码以及函数 PrevTradingDateNextTradingDate这是该 TradingDates函数的动机。

获取该代码后,很容易创建一个函数,该函数将返回给定日期所在月份的哪个交易日。目前,输入日期必须是(单个)交易日期,但可以根据您的偏好轻松更改。

TradingDayOfMonth <- function(Date, FUN=holidayNYSE, ...) {
  if (length(Date) > 1) stop('not vectorized; Date should be length 1')
  Date <- as.Date(Date, ...)
  tdy <- TradingDates(format(Date, "%Y"), FUN=FUN) #trading dates in year
  if (!Date %in% tdy) stop("Date is not a Trading Date")
  tdm <- tdy[format(tdy, "%m") %in% format(Date, "%m")] # trading dates in the same month as "Date"
  which(tdm == Date)
}

R> PrevTradingDate()
[1] "2012-11-02"
R> NextTradingDate()
[1] "2012-11-05"
R> TradingDayOfMonth(PrevTradingDate())
[1] 2
R> TradingDayOfMonth(NextTradingDate())
[1] 3
R> TradingDayOfMonth('2012-11-15')
[1] 11

上述工作所需的代码:

#' Get Trading Dates for one or more years
#'
#' Get a vector of dates of non-holiday weekdays.
#' 
#' This uses holiday calendar functions (\code{holidayNYSE} by default)
#' from the \emph{timeDate} package.  If \emph{timeDate} is not loaded, it 
#' will be temporarily loaded, then unloaded \code{on.exit}.
#' 
#' @param year vector of 4 digit years or something that is coercible to 
#'   a vector 4 digit years via \code{as.numeric}
#' @param FUN a function that takes a \code{year} argument and returns a vector
#'   that can be coerced to a \code{Date}.  \code{holidayNYSE} by default. Most
#'   likely, this will be one of:  \sQuote{holidayLONDON}, \sQuote{holidayNERC}, 
#'   \sQuote{holidayNYSE}, \sQuote{holidayTSX}, \sQuote{holidayZURICH}
#' @return a vector of all dates in \code{years} that are weekdays and not 
#'   holidays.
#' @author GSee
#' @examples
#' \dontrun{
#' TradingDates(2012)
#' TradingDates(2010:2011)
#' }
#' @export
TradingDates <- function(year=format(Sys.Date(), "%Y"), FUN=holidayNYSE) {
  # the next few lines should be removed when this code is added to a package
  # that Imports timeDate
  if (!"package:timeDate" %in% search()) {
    suppressPackageStartupMessages({ 
      if (!require(timeDate)) {
        stop("timeDate must be installed to use this function.")
      }
    })
    on.exit(detach(package:timeDate, unload=TRUE))
  }
  ## End of code that should be removed when this is added to a package
  year <- as.numeric(year)
  fun <- match.fun(FUN)
  do.call('c', lapply(year, function(y) {
    holidays <- as.Date(fun(year=y))
    all.days <- seq.Date(as.Date(paste(y, '01-01', sep='-')), 
                         as.Date(paste(y, '12-31', sep='-')), by='days')
    nohol <- all.days[!all.days %in% holidays]
    nohol[!format(nohol, '%w') %in% c("6", "0")] #neither holiday nor weekend
  }))
}


#' Get Date of previous (next) trading day
#' 
#' Get the Date of the previous (next) trading day.
#' 
#' For \code{PrevTradingDate}, \code{n} is the number of days to go back. So,
#' if \code{n} is 2 and today is a a Monday, it would return the date of the
#' prior Thursday because that would be 2 trading days ago.
#' \code{n} works analogously in \code{NextTradingDate}.
#'
#' The maximum value that \code{n} can be is the total number of days in the
#' year prior to \code{Date} plus the total number of years in the current 
#' year of \code{Date}.  So, on the last day of the year, the max value of
#' \code{n} will usually be \code{504} (because most years have 252 trading 
#' days).  One the first day of the year, the max value of \code{n} will usually
#' be \code{252}.
#'
#' @param n number of days to go back. 1 is the previous trading day; 2 is the
#'   trading day before that, etc.  \code{n} should be less than 365, but see
#'   details
#' @param Date a \code{Date} or something that can be coerced to a \code{Date}
#' @return \code{PrevTradingDate} returns the date of the previous trading day 
#' up to, but not including, \code{Date}.  \code{NextTradingDate} returns the 
#' date of the next trading day.
#' @author GSee
#' @seealso \code{\link{TradingDates}}
#' @examples
#' \dontrun{
#' PrevTradingDate()
#' PrevTradingDate('2012-01-03')
#' NextTradingDate()
#' NextTradingDate('2012-12-24')
#' }
#' @export
#' @rdname PrevTradingDate
PrevTradingDate <- function(Date=Sys.Date(), n=1) {
  stopifnot(require(xts)) #remove this line when this is added to a package that Imports xts (needed for first/last)
  D <- as.Date(Date)
  y <- as.numeric(format(D, "%Y"))
  trading.days <- TradingDates(y)
  out <- trading.days[trading.days < Date]
  if (length(out) >= n) {
    first(last(out, n))
  } else { 
    prev.year.td <- TradingDates(y - 1)
    max.n <- length(out) + length(prev.year.td)
    if (n > max.n) stop("'n' is too large. Try something less than 252.")
    new.n <- n - length(out) # we need this many trading days from previous year
    # if it's the 1st trading day of the year, return the last trading date of
    # previous year
    first(last(TradingDates(y - 1), new.n))
  } 
}

#' @export
#' @rdname PrevTradingDate
NextTradingDate <- function(Date=Sys.Date(), n=1) {
  stopifnot(require(xts)) #remove this line when this is added to a package that Imports xts (needed for first/last)
  D <- as.Date(Date)
  y <- as.numeric(format(D, "%Y"))
  trading.days <- TradingDates(y)
  out <- trading.days[trading.days > Date]
  if (length(out) >= n) {
    last(first(out, n))
  } else { 
    next.year.td <- TradingDates(y + 1)
    max.n <- length(out) + length(next.year.td)
    new.n <- n - length(out) # how many trading days we need from next year
    if (n > max.n) stop("'n' is too large. Try something less than 252.")
    # if it's the last trading day of the year, return the first trading date of
    # next year
    last(first(TradingDates(y + 1), new.n))
  }
}
于 2012-11-04T16:17:27.187 回答
4

有一些软件包可以处理繁琐的日历问题,这些包很繁琐。引用自timeDate

“实现工作日、周末和节假日的功能并非易事。在算法意义上并不困难,但实现日历本身的规则可能会变得乏味,例如复活节的日期。”

不过,如果我正确解释了您的问题,那么这样的事情应该可以工作(尽管您可能想考虑一下您想要的结果,如果myDate它本身不是交易日......目前它给出了前一个交易日的交易日)。

library(RQuantLib)

tradingDayOfMonth <- function(myDate, calendar = "UnitedStates/NYSE") {
  FirstOfMonth <- as.Date(paste(year(myDate), month(myDate), "01", sep="/")) 
  businessDaysBetween(calendar, from = FirstOfMonth, to = myDate,
                      includeFirst = 1, includeLast = 1)
}

tradingDayOfMonth(as.Date("2012/11/05"))
# [1] 3
于 2012-11-04T02:58:17.210 回答
0

因为交易只记录在市场开盘的日子里:

TradeDates <- function() {
    # KO is one of the oldest publicly traded companies
    getSymbols("KO", from = as.Date("1973-01-02"), to = Sys.Date())
    TradeDays <- index(KO)
    rm(KO)
    TradeDates
}

TradingDays <- function(TradeDates, year = 2001, month = 5) {
     Date2Month <- function(date)  as.numeric(substring(as.Date(date),6,7))
     Date2Year  <- function(date)  as.numeric(substring(as.Date(date),1,4))
     TradeDates[which(Date2Month(TradeDates) == month & Date2Year(TradeDates) == year)]
}

TradingDays(TradeDates, year = 2001, month = 5) 

# [1] "2001-02-01" "2001-02-02" "2001-02-05" "2001-02-06" "2001-02-07" "2001-02-08"
# [7] "2001-02-09" "2001-02-12" "2001-02-13" "2001-02-14" "2001-02-15" "2001-02-16"
# [13] "2001-02-20" "2001-02-21" "2001-02-22" "2001-02-23" "2001-02-26" "2001-02-27"
# [19] "2001-02-28"
于 2017-05-18T09:10:23.913 回答