在R中复制YearFrac()历史日期

时间:2017-12-26 16:37:17

标签: r excel function

我是stackoverflow和R的新用户。可悲的是,我在代码中遇到了一个错误,我似乎无法解决这个错误,我正试图寻求一些帮助。如果我把这个问题放在某个不合适的地方,我会提前原谅自己。

一般的想法是写一个类似于R中Excel的“YearFrac”功能的功能。原因是我需要讨论大学中特定作业的inidivdual债券的年龄,包括小数。我不想在原始数据文件本身上使用Excel,而是想在R中完成它(并且在R中获得更多经验)。此外,为什么我不能依赖RQuantLib包其“yearFraction”功能的原因是我的日期早于1901年。

关于YearFrac()实现的VBA源代码已作为我的示例,您可以找到here

我的代码如下:

IsLeapyear=function(year){
# A year is a leap year if:
# It is evenly divisible by 4
# Not if it is evenly divisible by 100
# But it is if it is evenly divisible by 400
return(
       ((year %% 4 == 0) & (year %% 100 != 0)) | (year %% 400 == 0)
       ) # The %% operator functions like "Mod" in Excel's VBA
}

IsEndOfMonth=function(Day, Month, Year){
# Indicate the number of days that are in a month
# Making the difference between not only 30 & 31
# But also for February in particular when we are dealing with a leap year
if(Month == 1 | Month  == 3 | Month == 5 | Month == 7 | Month == 8 | Month == 10 | Month == 12) # January, March, May, July, August, October, December
  {
    Day == 31
  }
else
  {
    if(Month == 4 | Month == 6 | Month == 9 | Month == 11) # April, June, September, November
      {
        Day == 30
      }
    else
      {
        if(Month == 2) # February case
          {
            if(IsLeapyear(Year) == T)
              {
                Day == 29
              }
            else
              {
                Day == 28
              }
          }
      }
  }
}

# Example
IsEndOfMonth(19,8,1861)

Days360=function(StartYear, EndYear, StartMonth, EndMonth, StartDay, EndDay){
return(
        ((EndYear-StartYear)*360) + ((EndMonth-StartMonth)*30) + (EndDay-StartDay)
      )
}

TmpDays360Nasd=function(StartDate, EndDate, Method, UseEom){
# We set the startdate and enddate inputs as actual dates
require(lubridate)
t0 <- dmy(StartDate)
t1 <- dmy(EndDate)

# Pull the days, months and years apart from the startdate and enddate
StartDay <- day(t0)
StartMonth <- month(t0)
StartYear <- year(t0)
EndDay <- day(t1)
EndMonth <- month(t1)
EndYear <- year(t1)

if(EndMonth == 2 & IsEndOfMonth(EndDay, EndMonth, EndYear) & 
   ((StartMonth == 2 & IsEndOfMonth(StartDay, StartMonth, StartYear) == T) | Method == 3))
  {
    EndDay == 30
  }
if(EndDay == 31 & (StartDay >= 30 | Method == 3))
  {
    EndDay == 30
  }
if(StartDay == 31)
  {
    StartDay == 30
  }
if(UseEom == T & StartMonth == 2 & IsEndOfMonth(StartDay, StartMonth, StartYear) == T)
  {
    StartDay = 30
  }
return(Days360(StartYear, EndYear, StartMonth, EndMonth, StartDay, EndDay))
}

# Random dates chosen to test code snippits
x <- "19-08-1861"
y <- "01-02-1868"

# Example
TmpDays360Nasd(StartDate = x, EndDate = y,Method = 1,UseEom = T)

TmpDays360Euro=function(StartDate, EndDate){
# We set the startdate and enddate inputs as actual dates
require(lubridate)
t0 <- dmy(StartDate)
t1 <- dmy(EndDate)

# Pull the days, months and years apart from the startdate and enddate
StartDay <- day(t0)
StartMonth <- month(t0)
StartYear <- year(t0)
EndDay <- day(t1)
EndMonth <- month(t1)
EndYear <- year(t1)

if(StartDay == 31)
  {
    StartDay == 30
  }
if(EndDay == 31)
  {
    EndDay = 30
  }
return(Days360(StartYear, EndYear, StartMonth, EndMonth, StartDay, EndDay))
}

# Example
TmpDays360Euro(StartDate = x, EndDate = y)

TmpDiffDates=function(StartDate, EndDate, Basis){
  if(Basis == 0) # atpmBasis30360
    {
      DiffDate <- TmpDays360Nasd(StartDate, EndDate, Method = 0, UseEom = T)
    }
  if(Basis == 1 | Basis == 2 | Basis == 3) # atpmBasisActual atpmBasisActual360 atpmBasisActual365 by use of actual count of days
    {
      DiffDate <- as.numeric(dmy(EndDate)-dmy(StartDate)) # The difference between date objects is always in days, which is why we don't need to specify this
    }
  if(Basis == 4)
    {
      DiffDate <- TmpDays360Euro(StartDate, EndDate)
    }
  return(DiffDate)
  }

# Example
TmpDiffDates(StartDate = x, EndDate = y, Basis = 4)

TmpCalcAnnualBasis=function(StartDate, EndDate, Basis){
# We set the startdate and enddate inputs as actual dates
require(lubridate)
t0 <- dmy(StartDate)
t1 <- dmy(EndDate)

# Pull the days, months and years apart from the startdate and enddate
StartDay <- day(t0)
StartMonth <- month(t0)
StartYear <- year(t0)
EndDay <- day(t1)
EndMonth <- month(t1)
EndYear <- year(t1)

if(Basis == 0 | Basis == 2 | Basis == 4) # atpmBasis30360 atpmBasisActual360 atpmBasisE30360
  {
    AnnualBasis <- 360
  }
if(Basis == 3) # atpmBasisActual365
  {
    AnnualBasis <- 365
  }
if(Basis == 1) # atpmBasisActual
  {
    if(StartYear == EndYear)
      {
        if(IsLeapyear(StartYear) == T)
          {
            AnnualBasis <- 366
          }
        else
          {
            AnnualBasis <- 365
          }
      }
    else if((EndYear-1 == StartYear) & ((StartMonth > EndMonth) | ((StartMonth == EndMonth) & StartDay >= EndDay)))
      {
        if(IsLeapyear(StartYear) == T)
          {
            if(StartMonth < 2 | (StartMonth == 2 & StartDay <= 29))
              {
                AnnualBasis <- 366
              }
            else
              {
                AnnualBasis <- 365
              }
          }
        else if(IsLeapyear(EndYear) == T)
          {
            if(EndMonth > 2 | (EndMonth == 2 & EndDay == 29))
              {
                AnnualBasis <- 366
              }
            else
              {
                AnnualBasis <- 365
              }
          }
        else
          {
            AnnualBasis <- 365
          }
      }
    else
      {
        for(z in StartYear:EndYear)
          {
            if(IsLeapyear(z) == T)
              {
                AnnualBasis <- AnnualBasis + 366
              }
            else
              {
                AnnualBasis <- AnnualBasis + 365
              }
          }
        next
          {
            AnnualBasis <- AnnualBasis / (EndYear - StartYear + 1)
          }
      }
  }
return(AnnualBasis)
}

TmpYearFrac=function(StartDate, EndDate, Basis){
nNumerator = TmpDiffDates(StartDate, EndDate, Basis)
nDenom = TmpCalcAnnualBasis(StartDate, EndDate, Basis)

TmpYearFrac = nNumerator/nDenom

return(TmpYearFrac)
}

# Example
nNumerator = TmpDiffDates(StartDate = x, EndDate = y, Basis = 1)
nDenom = TmpCalcAnnualBasis(StartDate = x, EndDate = y, Basis = 1)
TmpYearFrac(StartDate = x, EndDate = y, Basis = 1)

如果我运行代码,我会在第二步到最后一步(即“TmpCalcAnnualBasis”函数)中出现关于“Basis = 1”情况的错误,其中“AnnualBasis”由于某种原因似乎未定义,我可以'似乎抓住了。

关于实际解决方案,我的代码中“x”和“y”给出的两个日期之间的差异应该是实际/实际的6.453114305年。

非常感谢你!

对于我的问题以及发布方法,我期待着你的意见。

0 个答案:

没有答案