This class generates payment details:
generatePaymentCalculationPeriods : (Fetch f) => CalculationPeriodDates -> Optional ResetDates -> Optional OtherDates -> Optional PaymentDates -> f [PaymentCalculationPeriod]
generatePaymentCalculationPeriods cpds rds ods (fmap (checkPaymentDates cpds) -> pds) = do
-- Roll out calculation periods
cps <-
case (rds, ods) of
(Some r, None) -> generateResetPeriods cpds rds
(None, Some o) -> generateOtherPeriods cpds ads
(Some r, Some o) -> do
r <- generateResetPeriods cpds rds
o <- generateOtherPeriods cpds ods
return (r ++ o)
(None, None) -> error "expecting calculation period"
-- Define payment calculation period
let adj = optional noAdj (\x -> get "paymentDatesAdjustments" x.paymentDatesAdjustments) pds
let payRelativeTo = optional PayRelativeToEnumCalculationPeriodEndDate (\x -> get "payRelativeTo" x.payRelativeTo) pds
let offset = (\x -> x.paymentDaysOffset) =<< pds
mapA (generateSinglePeriod payRelativeTo offset adj . replicate 1) cps
where
noAdj = BusinessDayAdjustments
{ id = None
, businessCenters = None
, businessDayConvention = BusinessDayConventionEnumNONE
}
generateSinglePeriod :
(Fetch f)
=> PayRelativeToEnum
-> Optional Offset
-> BusinessDayAdjustments
-> [CalculationPeriod]
-> f PaymentCalculationPeriod
generateSinglePeriod _ _ _ [] = error "expecting at least one calculation period"
generateSinglePeriod payRelativeTo offset adj cps = do
let baseDate = case payRelativeTo of
PayRelativeToEnumCalculationPeriodStartDate ->
(get "adjustedStartDate" . (\cp -> cp.adjustedStartDate) . head) cps
PayRelativeToEnumCalculationPeriodEndDate ->
(get "adjustedEndDate" . (\cp -> cp.adjustedEndDate) . last) $ cps
otherwise -> throwNotSupportedError (show payRelativeTo)
uPayDate <- optional (pure baseDate) (\o -> applyOffset o adj.businessCenters baseDate) offset
aPayDate <- adjustDate adj uPayDate
return PaymentCalculationPeriod
{ id = None
, adjustedPaymentDate = Some aPayDate
, calculationPeriod = cps
, discountFactor = None
, fixedPaymentAmount = None
, forecastPaymentAmount = None
, presentValueAmount = None
, unadjustedPaymentDate = Some uPayDate
}
The PaymentCalculationPeriod details for the floatingRateDefinition:
populatePCP : [(Optional Text, ResetPrimitive)] -> [(Optional Text, EventPrimitive)] -> InterestRatePayout -> PaymentCalculationPeriod -> (PaymentCalculationPeriod, Lineage)
populatePCP existingResets existingEvents irp pcp =
let (resetReferences, eventReferences, cpsFull) = unzip3 $ map (setInterestRate . setDayCountFraction . setQuantity) pcp.calculationPeriod
lineage = emptyLineage
{ interestRatePayoutReference = [referenceWithEmptyMeta irp.primeKey]
, eventReference = map referenceWithEmptyMeta $ concat resetReferences
, eventReference = map referenceWithEmptyMeta $ concat eventReferences
}
pcpFull = pcp { calculationPeriod = cpsFull }
in (pcpFull, lineage)
where
...
setInterestRate : CalculationPeriod -> ([Text], [Text], CalculationPeriod)
setInterestRate cp
...
| Some floatingRate <- irp.rateSpecification.floatingRate
, Some otherValue <- irp.rateSpecification.otherValue
= let frDef = get "floatingRateDefinition" cp.floatingRateDefinition
frdNew = FR.calcFloatingRate existingResets floatingRate frDef
ovDef = get "otherValueDefinition" cp.otherValueDefinition
ovdNew = OV.calcOtherValue existingEvents otherValue ovDef
in (fst frdNew, fst ovdNew, cp { floatingRateDefinition = Some (snd frdNew)
; otherValueDefinition = Some (snd ovdNew) })
| otherwise = error "expecting exactly two 'rateSpecification'"