hasquant-0.7.0.0: QuantLib/Time/Calendar.chs
-- CalendarConstructor is declared in QuantLib.Internal.CalendarEnum, but its Read instance
-- needs `calendar` (below), and CalendarEnum -> Calendar -> CalendarEnum would be a cycle if
-- the instance lived there instead -- see deriveReadPlain's comment in Internal/Syntax.hs.
-- Deliberate, not a stray orphan.
{-# OPTIONS_GHC -Wno-orphans #-}
module QuantLib.Time.Calendar
(
-- * Types
Calendar
, CalendarConstructor(..)
, JointCalendarRule(..)
, BusinessDayConvention(..)
-- * Constructors
, calendar
-- * Mutators
, addHoliday
, removeHoliday
-- * Inspectors
, adjust
, advance
, businessDaysBetween
, endOfMonth
, isBusinessDay
, isEndOfMonth
, isHoliday
, isWeekend
, holidays
) where
import QuantLib.Internal
import QuantLib.Internal.Type
{#import QuantLib.Time.Date#}(Weekday)
import QuantLib.Internal.Common
import QuantLib.Internal.CalendarEnum
import System.IO.Unsafe(unsafePerformIO)
#include "qlTypesC2HS.h"
#include "qlEnumC2HS.h"
#include "qlEnumObjects.h"
#include "ql.h"
{#pointer *Calendar foreign -> CCalendar nocode#}
-- |Constructs the calendar for the given country, with an optional market variant.
{#fun qlCalendar{`Int',`Int',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}
calendar :: CalendarConstructor -> IO Calendar
calendar (Bespoke n w) = qlBespokeCalendar n w
calendar (Joint2 c1 c2 r) = qlJointCalendar2 c1 c2 r
calendar (Joint3 c1 c2 c3 r) = qlJointCalendar3 c1 c2 c3 r
calendar (Joint4 c1 c2 c3 c4 r) = qlJointCalendar4 c1 c2 c3 c4 r
calendar x = uncurry qlCalendar $ mapCalendar x
-- |Adjusts a non-business day to the appropriate near business day with respect to the given convention
{#fun qlCalendarAdjust as adjust{withCalendar*`Calendar',withDay*`Day',fromEnumC`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`Day'toDay#}
-- |Advances the given date of the given number of business days and returns the result using business day convention and the EOM flag
{#fun qlCalendarAdvance as advance{withCalendar*`Calendar',withDay*`Day',fromEnumQuantity`(Int,TimeUnit)'&,fromEnumC`BusinessDayConvention',`Bool' -- ^endOfMonth
,preErrorCheck-`String'errorCheck*-}->`Day'toDay#}
-- |Adds a date to the set of holidays for the given calendar.
{#fun qlCalendarAddHoliday as addHoliday{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`()'#}
-- |Calculates the number of business days between two given dates and returns the result.
{#fun qlCalendarBusinessDaysBetween as businessDaysBetween{withCalendar*`Calendar',withDay*`Day',withDay*`Day'
,`Bool' -- ^includeFirst
,`Bool' -- ^includeLast
,preErrorCheck-`String'errorCheck*-}->`Int'#}
-- |last business day of the month to which the given date belongs
{#fun qlCalendarEndOfMonth as endOfMonth{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Day'toDay#}
-- |Returns true iff the date is a business day for the given market.
{#fun qlCalendarIsBusinessDay as isBusinessDay{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Bool'#}
-- |Returns true iff the date is last business day for the month in given market.
{#fun qlCalendarIsEndOfMonth as isEndOfMonth{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Bool'#}
-- |Returns true iff the date is a holiday for the given market.
{#fun qlCalendarIsHoliday as isHoliday{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Bool'#}
-- |Returns true iff the weekday is part of the weekend for the given market.
{#fun qlCalendarIsWeekend as isWeekend{withCalendar*`Calendar',`Weekday',preErrorCheck-`String'errorCheck*-}->`Bool'#}
-- |Removes a date from the set of holidays for the given calendar.
{#fun qlCalendarRemoveHoliday as removeHoliday{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`()'#}
-- |Builds a calendar with no predefined business days; the given weekdays become its weekend.
{#fun qlBespokeCalendar{`String',withEnumArray*`[Weekday]'&,preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}
-- |Combines three calendars into one whose business days are the union or intersection of theirs, per the given rule.
{#fun qlJointCalendar3{withCalendar*`Calendar',withCalendar*`Calendar',withCalendar*`Calendar',fromEnumC`JointCalendarRule',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}
-- |Combines two calendars into one whose business days are the union or intersection of theirs, per the given rule.
{#fun qlJointCalendar2{withCalendar*`Calendar',withCalendar*`Calendar',fromEnumC`JointCalendarRule',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}
-- |Combines four calendars into one whose business days are the union or intersection of theirs, per the given rule.
{#fun qlJointCalendar4{withCalendar*`Calendar',withCalendar*`Calendar',withCalendar*`Calendar',withCalendar*`Calendar',fromEnumC`JointCalendarRule',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}
-- |Returns the holidays between two dates.
{#fun qlCalendarHolidayList as holidays{withCalendar*`Calendar',withDay*`Day' -- ^from
,withDay*`Day' -- ^to
,`Bool' -- ^includeWeekEnds
,preArray-`[Day]'&peekDayArray*,preErrorCheck-`String'errorCheck*-}->`()'#}
-- The name of a QuantLib object is fixed for its lifetime, so materializing one through
-- unsafePerformIO during Read is as safe as showStandalone's own use of it above; NOINLINE
-- keeps GHC from duplicating or floating the C++ call, same reasoning as showStandalone's.
unsafeCalendar :: CalendarConstructor -> Calendar
unsafeCalendar = unsafePerformIO . calendar
{-# NOINLINE unsafeCalendar #-}
-- Hand-written, not `deriving`/TH-spliced: CalendarConstructor's Joint2/3/4 cases carry live
-- Calendar fields, which have no Read instance of their own (see
-- QuantLib.Internal.Syntax.deriveReadPlain's comment for why the generated part -- covering
-- everything except these three -- has to be spliced back in CalendarEnum.chs instead of
-- here). Each alternative below parses a nested CalendarConstructor and materializes it with
-- `calendar`, exactly what a caller passing a literal Joint2/3/4 value would already do.
instance Read CalendarConstructor where
readsPrec d r = readCalendarConstructorPlain d r
++ readParen (d > 10) (\r' ->
[ (Joint2 c1 c2 rule, s3)
| ("Joint2", s0) <- lex r'
, (p1, s1) <- readsPrec 11 s0, let c1 = unsafeCalendar p1
, (p2, s2) <- readsPrec 11 s1, let c2 = unsafeCalendar p2
, (rule, s3) <- readsPrec 11 s2
]) r
++ readParen (d > 10) (\r' ->
[ (Joint3 c1 c2 c3 rule, s4)
| ("Joint3", s0) <- lex r'
, (p1, s1) <- readsPrec 11 s0, let c1 = unsafeCalendar p1
, (p2, s2) <- readsPrec 11 s1, let c2 = unsafeCalendar p2
, (p3, s3) <- readsPrec 11 s2, let c3 = unsafeCalendar p3
, (rule, s4) <- readsPrec 11 s3
]) r
++ readParen (d > 10) (\r' ->
[ (Joint4 c1 c2 c3 c4 rule, s5)
| ("Joint4", s0) <- lex r'
, (p1, s1) <- readsPrec 11 s0, let c1 = unsafeCalendar p1
, (p2, s2) <- readsPrec 11 s1, let c2 = unsafeCalendar p2
, (p3, s3) <- readsPrec 11 s2, let c3 = unsafeCalendar p3
, (p4, s4) <- readsPrec 11 s3, let c4 = unsafeCalendar p4
, (rule, s5) <- readsPrec 11 s4
]) r
-- vim: set ff=unix ts=8 sts=2 sw=2 et: