(* :Title: Calendar functions *)
(* :Context: QuantLib`Calendar` *)
(* :Author: Niels Elken Sønderby *)
(* :Mathematica Version: 4.0 *)
(* :Copyright: Copyright (C) 2003 Niels Elken Sønderby *)
(* :License:
This file is part of QuantLib for Mathematica, a Mathematica extension for
QuantLib, a free-software/open-source financial C++ library
- http://www.nielses.dk/quantlib/mma/
- http://quantlib.org/
QuantLib for Mathematica is free software: you can redistribute it and/or
modify it under the terms of the QuantLib license. You should have
received a copy of the license along with this program; if not, please
email ferdinando@ametrano.net The license is also available online at
http://quantlib.org/html/license.html
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*)
BeginPackage["QuantLib`Calendar`",
"QuantLib`Common`QuantLibCommon`" (* Needs SymbolToNumber functionality *)
]
(* Usage messages *)
DayOfWeek::usage =
"DayOfWeek[{y, m, d}] gives the day of the week for year y, month m,
and day d."
$DaysOfWeek::usage =
"$DaysOfWeek contains a list of the days of the week."
Sunday::usage = "Sunday is a day of the week."
Monday::usage = "Monday is a day of the week."
Tuesday::usage = "Tuesday is a day of the week."
Wednesday::usage = "Wednesday is a day of the week."
Thursday::usage = "Thursday is a day of the week."
Friday::usage = "Friday is a day of the week."
Saturday::usage = "Saturday is a day of the week."
BusinessDayQ::usage =
"BusinessDayQ[{y, m, d}, HolidayCalendar -> calendar] returns True if the
date is a business day in the given calendar."
HolidayQ::usage =
"HolidayQ[{y, m, d}, HolidayCalendar -> calendar] returns True if the date
is a holiday in the given calendar."
HolidayCalendar::usage =
"HolidayCalendar is an option for several date functions specifying the
dates that are not business days, examples are TokyoCalendar and
MilanCalendar."
$HolidayCalendars::usage =
"$HolidayCalendars is a list of available holiday calendars."
FrankfurtCalendar::usage =
"FrankfurtCalendar is a holiday calendar representing
the Frankfurt calendar."
HelsinkiCalendar::usage =
"HelsinkiCalendar is a holiday calendar representing
the Helsinki calendar."
JohannesburgCalendar::usage =
"JohannesburgCalendar is a holiday calendar representing
the Johannesburg calendar."
LondonCalendar::usage =
"LondonCalendar is a holiday calendar representing the London calendar."
MilanCalendar::usage =
"MilanCalendar is a holiday calendar representing the Milan calendar."
NewYorkCalendar::usage =
"NewYorkCalendar is a holiday calendar representing the New York calendar."
SydneyCalendar::usage =
"SydneyCalendar is a holiday calendar representing
the Sydney (New South Wales, Australia) calendar."
TARGETCalendar::usage =
"TARGETCalendar is a holiday calendar representing
the Trans-European Automated Real-time Gross Express-settlement
Transfer system calendar. http://www.ecb.int/press/00/pr001214_4.htm"
TokyoCalendar::usage =
"TokyoCalendar is a holiday calendar representing the Tokyo calendar."
TorontoCalendar::usage =
"TorontoCalendar is a holiday calendar representing the Toronto calendar."
WellingtonCalendar::usage =
"WellingtonCalendar is a holiday calendar representing
the Wellington calendar."
ZurichCalendar::usage =
"ZurichCalendar is a holiday calendar representing the Zurich calendar."
DaysPlus::usage =
"DaysPlus[{y, m, d}, days, HolidayCalendar -> calendar]
advances the given date with the given number of business days."
RollDate::usage =
"RollDate[{y, m, d}, HolidayCalendar -> calendar, RollingConvention -> roll]"
$RollingConventions::usage =
"$RollingsConventions contains a list of available rolling conventions."
RollingConvention::usage =
"RollingConvention is an option for date functions which specifies how dates
are adjusted if they fall on a holiday."
Preceding::usage =
"Preceding is a rolling convention, which adjust to the first business day
before the given holiday."
ModifiedPreceding::usage =
"ModifiedPreceding is a rolling convention, which adjusts to the first
business day before the given holiday unless it belongs to a different month,
in which case it adjusts to the first business day after the holiday."
Following::usage =
"Following is a rolling convention, which adjust to the first business day
after the given holiday."
ModifiedFollowing::usage =
"ModifiedFollowing is a rolling convention, which adjusts to the first
business day after the given holiday unless it belongs to a different month,
in which case it adjusts to the first business day before the holiday."
Actual365::usage =
"Actual365 represents the Actual/365 day counting convention."
Actual360::usage =
"Actual360 represents the Actual/360 day counting convention."
Thirty360American::usage =
"Thirty360American represents the American (NASD) variant of the 30/360 day
counting convention: if the starting date is the 31st of a month, it becomes
equal to the 30th of the same month. If the ending date is the 31st of a
month and the starting date is earlier than the 30th of a month, the ending
date becomes equal to the 1st of the next month, otherwise the ending date
becomes equal to the 30th of the same month."
Thirty360European::usage =
"Thirty360European represents the European variant of the 30/360 day counting
convention: starting dates or ending dates that occur on the 31st of a month
become equal to the 30th of the same month."
Thirty360Italian::usage =
"Thirty360Italian represents the Italian variant of the 30/360 day counting
convention: starting dates or ending dates that occur on February and are
greater than 27 become equal to 30 for computational sake."
ActualActualISMA::usage =
"ActualActualISMA represents the ISMA Actual/Actual day counting convention.
Also known as Actual/Actual Bond."
ActualActualAFB::usage =
"ActualActualAFB represents the AFB Actual/Actual day counting convention.
Also known as Actual/Actual Euro."
ActualActualISDA::usage =
"ActualActualISDA represents the ISDA Actual/Actual day counting convention.
Also known as Actual/Actual Historical."
DayCountConvention::usage =
"DayCountConvention is an option for date functions that specifies the
length of months and other rules."
$DayCountConventions::usage =
"$DayCountConventions contains a list of available day count conventions."
DaysBetween::usage =
"DaysBetween[{y1_,m1_,d1_},{y2_,m2_,d2}, DayCountConvention-> daycount]
gives the number of days from the first date to the second using the given
day count convention."
YearsBetween::usage =
"YearsBetween[{y1_,m1_,d1_},{y2_,m2_,d2}, DayCountConvention-> daycount]
gives the fraction of years between the two dates using the given day count
convention."
LeapYearQ::usage =
"LeapYearQ[{y, m, d}] or LeapYearQ[year] returns true if the date is in a
leap year."
Begin["`Private`"]
(* Give access to QuantLib`Private` context as LinkPatterns for external
program are there. Does a more elegant solution exist? *)
AppendTo[$ContextPath, "QuantLib`Private`"]
(* Translation table for passing "enum"-values to C++ *)
DayOfWeekNumbers = { {Sunday, 1}, {Monday, 2}, {Tuesday, 3}, {Wednesday, 4},
{Thursday, 5}, {Friday, 6}, {Saturday, 7} }
$DaysOfWeek = Transpose[DayOfWeekNumbers][[1]]
DayOfWeek[{y_,m_,d_}] := NumberToSymbol[qlDayOfWeek[y,m,d],DayOfWeekNumbers]
$HolidayCalendar = TARGETCalendar; (* Default value *)
(* Translation table for passing "enum"-values to C++ *)
HolidayCalendarNumbers = {
{ FrankfurtCalendar, 2 },
{ HelsinkiCalendar, 3 },
{ JohannesburgCalendar, 4 },
{ LondonCalendar, 5 },
{ MilanCalendar, 6 },
{ NewYorkCalendar, 7 },
{ SydneyCalendar, 10 },
{ TARGETCalendar, 11 },
{ TokyoCalendar, 12 },
{ TorontoCalendar, 13 },
{ WellingtonCalendar, 15 },
{ ZurichCalendar, 16 }
}
$HolidayCalendars = Transpose[HolidayCalendarNumbers][[1]]
BusinessDayQ[{y_, m_, d_}, opts___?OptionQ] :=
Module[{holidaycal},
holidaycal = HolidayCalendar /. {opts}
/. Options[BusinessDayQ];
If[holidaycal === None,
True, (* To be consistent with ShiftDate *)
(* DayOfWeek[{y, m, d}] =!= Saturday =!= Sunday, *)
qlBusinessDayQ[y,m,d,
SymbolToNumber[holidaycal, HolidayCalendarNumbers]]]
]
BusinessDayQ[lst : {{_, _, _} ..}, opts___?OptionQ] :=
BusinessDayQ[#, opts]& /@ lst
Options[BusinessDayQ] := { HolidayCalendar -> $HolidayCalendar }
HolidayQ[lst : {{_, _, _} ..}, opts___?OptionQ] :=
(!BusinessDayQ[#, opts])& /@ lst
HolidayQ[args_, opts___?OptionQ] := !BusinessDayQ[args, opts]
DaysPlus[{y_, m_, d_}, days_, opts___?OptionQ] :=
Module[{holidaycal, calnum},
holidaycal = HolidayCalendar /. {opts}
/. Options[DaysPlus];
If[holidaycal === None,
calnum=0,
calnum=SymbolToNumber[holidaycal, HolidayCalendarNumbers]];
qlShiftDate[y,m,d,0,0,days,calnum]
]
Options[DaysPlus] := { HolidayCalendar -> None }
$RollingConvention = Following; (* Default value *)
(* Translation table for passing "enum"-values to C++ *)
RollingConventionNumbers = {
{ Preceding, 1 },
{ ModifiedPreceding, 2 },
{ Following, 3 },
{ ModifiedFollowing, 4 }
}
$RollingConventions = Transpose[RollingConventionNumbers][[1]]
RollDate[{y_, m_, d_}, opts___?OptionQ] :=
Module[{holidaycal, rollconv, calnum, rollnum},
holidaycal = HolidayCalendar /. {opts}
/. Options[RollDate];
rollconv = RollingConvention /. {opts}
/. Options[RollDate];
calnum = SymbolToNumber[holidaycal, HolidayCalendarNumbers];
rollnum = SymbolToNumber[rollconv, RollingConventionNumbers];
qlRollDate[y, m, d, calnum, rollnum]
]
Options[RollDate] := { HolidayCalendar -> $HolidayCalendar,
RollingConvention -> $RollingConvention }
$DayCountConvention = Actual365; (* Default value *)
(* Translation table for passing "enum"-values to C++ *)
DayCountConventionNumbers = {
{ Actual365, 1 },
{ Actual360, 2 },
{ Thirty360American, 3 },
{ Thirty360European, 4 },
{ Thirty360Italian, 5 },
{ ActualActualISMA, 6 },
{ ActualActualAFB, 7 },
{ ActualActualISDA, 8 }
}
$DayCountConventions = Transpose[DayCountConventionNumbers][[1]]
DaysBetween[{y1_,m1_,d1_},{y2_,m2_,d2_}, opts___?OptionQ] :=
Module[{daycount, daycountnum},
daycount = DayCountConvention /. {opts}
/. Options[DaysBetween];
daycountnum = SymbolToNumber[daycount, DayCountConventionNumbers];
qlDaysBetween[y1,m1,d1,y2,m2,d2,daycountnum]
]
Options[DaysBetween] := { DayCountConvention -> $DayCountConvention }
(* Reference period only needed for ActualActualISMA *)
YearsBetween[{y1_, m1_, d1_}, {y2_, m2_, d2_},
{refy1_, refm1_, refd1_}, {refy2_, refm2_, refd2_},
opts___?OptionQ] :=
Module[{daycount, daycountnum},
daycount = DayCountConvention /. {opts}
/. Options[DaysBetween];
daycountnum = SymbolToNumber[daycount, DayCountConventionNumbers];
qlYearsBetween[y1, m1, d1, y2, m2, d2,
refy1, refm1, refd1, refy2, refm2, refd2,
daycountnum]
]
YearsBetween[{y1_, m1_, d1_}, {y2_, m2_, d2_},
opts___?OptionQ] := YearsBetween[{y1,m1,d1}, {y2,m2,d2},
{0,0,0}, {0,0,0}, opts]
Options[YearsBetween] := { DayCountConvention -> $DayCountConvention }
LeapYearQ[y_Integer]:=qlLeapYearQ[y]
Attributes[LeapYearQ] := {Listable}
End[]
EndPackage[]