double dateUtil::getAccrualFactor(date startDate,date endDate, enums::DayCountEnum dayCount){ double accrualFactor; int numBizDay=0; switch(dayCount){ case enums::thirty_360US: //This day count convention is also called Bond basis. if (endDate.getDay()==31 && (startDate.getDay()==30||31)) endDate.setDay(30); if (startDate.getDay()==31) startDate.setDay(30); accrualFactor = thirty_360(startDate, endDate); break; case enums::thirthE_360: if (startDate.getDay()==31) startDate.setDay(30); if (endDate.getDay()==31) endDate.setDay(30); accrualFactor = thirty_360(startDate, endDate); break; case enums::ACT_360: //This day count is also called Money Market basis or Actual 360 //This is the most used day count convention for money market instruments (maturity below one year). accrualFactor = (endDate.getJudianDayNumber()-startDate.getJudianDayNumber())/360.0; //cout<<"inside ACT_360"<<endl; break; case enums::ACT_365: //Also called English Money Market basis. //The number 365 is used even in a leap year. accrualFactor = (endDate.getJudianDayNumber()-startDate.getJudianDayNumber())/365.0; //cout<<"inside ACT_365"<<endl; break; case enums::ACT_ACT: if (startDate.getYear()==endDate.getYear()){ int numDays = endDate.getJudianDayNumber()-startDate.getJudianDayNumber(); accrualFactor = numDays/(isleapyear(startDate.getYear())?366.0:365.0); }else{ int numStartYearDays = date(startDate.getYear(),12,31).getJudianDayNumber() - startDate.getJudianDayNumber() + 1; double startYearFactor = numStartYearDays/(isleapyear(startDate.getYear())?366.0:365.0); int numEndYearDays = endDate.getJudianDayNumber() - date(endDate.getYear(),1,1).getJudianDayNumber(); double endYearFactor = numEndYearDays/(isleapyear(endDate.getYear())?366.0:365.0); accrualFactor = startYearFactor + endYearFactor +(endDate.getYear()-startDate.getYear()-1); } break; case enums::BUS_252: //Numerator is the number of business days (in a given calendar) from and including the start date up to and excluding the end date. numBizDay=0; for(long i = startDate.getJudianDayNumber();i<endDate.getJudianDayNumber();i++) if (isBizDay(i)) numBizDay++; accrualFactor = numBizDay/252.0; break; case enums::DayCountNull: default: accrualFactor = (endDate.getJudianDayNumber()-startDate.getJudianDayNumber())/numDaysInYear; } return accrualFactor; }
date dateUtil::getEndDateMonthIncrement(date startDate, int numMonth){ if (numMonth==0) return startDate; short startMonth = startDate.getMonth(); short endMonth = (startMonth + numMonth)%12; int yearIncrement = (startMonth + numMonth)/12; yearIncrement = (startMonth + numMonth)<=0?yearIncrement-1:yearIncrement; endMonth = endMonth<=0?endMonth+12:endMonth; short endYear= startDate.getYear()+yearIncrement; date endDate(endYear, endMonth, startDate.getDay()); return endDate; }
date dateUtil::adjustInvalidateDate(date aDate, bool forwardAdjust){ int monthLastDay = getMonthLastDay(aDate.getYear(), aDate.getMonth()); if (aDate.getDay()>monthLastDay){ if (forwardAdjust){ aDate.setMonth(aDate.getMonth()%12+1); aDate.setDay(1); } else{ aDate.setDay(monthLastDay); } } return aDate; }
date dateUtil::adjustInvalidateDate(date aDate, bool forwardAdjust){ unsigned short monthlen[]={31,28,31,30,31,30,31,31,30,31,30,31}; if (isleapyear(aDate.getYear()) && aDate.getMonth()==2) monthlen[1]++; if (aDate.getDay()>monthlen[aDate.getMonth()-1]){ if (forwardAdjust){ aDate.setMonth(aDate.getMonth()%12+1); aDate.setDay(1); } else aDate.setDay(monthlen[aDate.getMonth()-1]); } return aDate; }
date dateUtil::getEndDateMonthIncrement(date startDate, int numMonth){ if (numMonth==0) return startDate; short startMonth = startDate.getMonth(); short endMonth = (startMonth + numMonth); bool isEndMonthPow12 = (startMonth + numMonth)%12==0?true:false; endMonth = isEndMonthPow12 ? 12 : (startMonth + numMonth)%12; int yearIncrement = abs((startMonth + numMonth)/12) - (isEndMonthPow12 ? 1 : 0); if (startMonth + numMonth<0) yearIncrement = -abs((startMonth + numMonth)/12) - 1 - (isEndMonthPow12 ? 1 : 0); endMonth = endMonth<=0 ? endMonth+12 : endMonth; short endYear= startDate.getYear()+ yearIncrement; date endDate(endYear, endMonth, startDate.getDay()); // Adjust the return day to the end of month if the start date is also end of month //if (startDate.getDay() == getMonthLastDay(startDate.getYear(), startDate.getMonth())) //endDate.setDay(getMonthLastDay(endDate.getYear(), endDate.getMonth())); return endDate; }
date date::backDate(date a,int in) { int adays,amonth,ayear; adays=a.getDay(); amonth=a.getMonth(); ayear=a.getYear(); adays=adays+in; if(adays>30) {amonth++; adays+=-30;} if(amonth>12) { ayear++; amonth-=30; } date b(adays,amonth,ayear); return b; }
date dateUtil::getEndDate(date startDate, int increment, enums::DayRollEnum dayRoll, enums::MarketEnum market, DateUnit dateUnit){ date endDate; switch(dateUnit){ case YEAR: endDate = date(startDate.getYear()+increment,startDate.getMonth(), startDate.getDay()); break; case MONTH: endDate = getEndDateMonthIncrement(startDate, increment); break; case WEEK: endDate = date(startDate.getJudianDayNumber()+increment*7); break; case DAY: endDate = date(startDate.getJudianDayNumber()+increment); break; case BIZDAY: endDate = getBizDateOffSet(startDate,increment, market); break; } endDate = dayRollAdjust(adjustInvalidateDate(endDate,false),dayRoll, market); return endDate; }
double dateUtil::thirty_360(date startDate, date endDate){ int yearFactor = 360*(endDate.getYear()-startDate.getYear()); int monthFactor = 30*(endDate.getMonth()-startDate.getMonth()); int dayFactor = endDate.getDay()-startDate.getDay(); return (yearFactor+monthFactor+dayFactor)/360.0; }
//equality checker overload //could have implemented this in the class, but that caused confusion since it didn't match up with the normal usage of the == operator bool operator==(date& a, date& b) { return a.getDay() == b.getDay() && a.getMonth() == b.getMonth() && a.getYear() == b.getYear(); }