diff --git a/src/main/java/org/isda/cdm/functions/CalculationPeriodImpl.java b/src/main/java/org/isda/cdm/functions/CalculationPeriodImpl.java index fa8a449c8a..7d3c897e3d 100644 --- a/src/main/java/org/isda/cdm/functions/CalculationPeriodImpl.java +++ b/src/main/java/org/isda/cdm/functions/CalculationPeriodImpl.java @@ -7,6 +7,7 @@ import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; +import org.isda.cdm.CalculationPeriodData; import org.isda.cdm.CalculationPeriodDates; import com.opengamma.strata.basics.ReferenceData; @@ -18,7 +19,7 @@ import com.rosetta.model.lib.records.Date; import com.rosetta.model.lib.records.DateImpl; -public class CalculationPeriodImpl implements CalculationPeriod { +public class CalculationPeriodImpl extends CalculationPeriod { private final Date referenceDate; @@ -27,11 +28,7 @@ public CalculationPeriodImpl(Date referenceDate) { } @Override - public CalculationResult execute(CalculationPeriodDates calculationPeriodDates) { - return execute(calculationPeriodDates, referenceDate.toLocalDate()); - } - - private CalculationResult execute(CalculationPeriodDates calculationPeriodDates, LocalDate referenceDate) { + protected CalculationPeriodData doEvaluate(CalculationPeriodDates calculationPeriodDates) { PeriodicSchedule periodicSchedule = PeriodicSchedule.of( calculationPeriodDates.getEffectiveDate().getAdjustableDate().getUnadjustedDate().toLocalDate(), calculationPeriodDates.getTerminationDate().getAdjustableDate().getUnadjustedDate().toLocalDate(), @@ -43,7 +40,7 @@ private CalculationResult execute(CalculationPeriodDates calculationPeriodDates, Schedule schedule = periodicSchedule.createSchedule(ReferenceData.minimal()); SchedulePeriod targetPeriod = schedule.getPeriods().stream() - .filter(period -> !(referenceDate.isBefore(period.getStartDate())) && referenceDate.isBefore(period.getEndDate())) + .filter(period -> !(toLocalDate(referenceDate).isBefore(period.getStartDate())) && toLocalDate(referenceDate).isBefore(period.getEndDate())) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Date " + referenceDate.toString() + "not within schedule")); @@ -54,11 +51,16 @@ private CalculationResult execute(CalculationPeriodDates calculationPeriodDates, } } - return new CalculationResult() - .setStartDate(new DateImpl(targetPeriod.getStartDate())) - .setEndDate(new DateImpl(targetPeriod.getEndDate())) - .setDaysInLeapYearPeriod(daysThatAreInLeapYear) - .setDaysInPeriod((int) ChronoUnit.DAYS.between(targetPeriod.getStartDate(), targetPeriod.getEndDate())); + return CalculationPeriodData.builder() + .setStartDate(new DateImpl(targetPeriod.getStartDate())) + .setEndDate(new DateImpl(targetPeriod.getEndDate())) + .setDaysInLeapYearPeriod(daysThatAreInLeapYear) + .setDaysInPeriod((int) ChronoUnit.DAYS.between(targetPeriod.getStartDate(), targetPeriod.getEndDate())) + .build(); + } + + private LocalDate toLocalDate(Date date) { + return LocalDate.of(date.getYear(), date.getMonth(), date.getDay()); } } diff --git a/src/main/java/org/isda/cdm/functions/ResolveNotionalAmountImpl.java b/src/main/java/org/isda/cdm/functions/ResolveNotionalAmountImpl.java deleted file mode 100644 index 1b518a4f90..0000000000 --- a/src/main/java/org/isda/cdm/functions/ResolveNotionalAmountImpl.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.isda.cdm.functions; - -import org.isda.cdm.EquityPayout; - -public class ResolveNotionalAmountImpl implements ResolveNotionalAmount { - - public CalculationResult execute(EquityPayout equityPayout) { - throw new UnsupportedOperationException("TODO: auto-generated method stub"); - } -} diff --git a/src/main/java/org/isda/cdm/functions/ResolveRateOfReturnImpl.java b/src/main/java/org/isda/cdm/functions/ResolveRateOfReturnImpl.java deleted file mode 100644 index 9686e8108d..0000000000 --- a/src/main/java/org/isda/cdm/functions/ResolveRateOfReturnImpl.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.isda.cdm.functions; - -import org.isda.cdm.EquityPayout; - -public class ResolveRateOfReturnImpl implements ResolveRateOfReturn { - - public CalculationResult execute(EquityPayout equityPayout) { - throw new UnsupportedOperationException("TODO: auto-generated method stub"); - } -} diff --git a/src/main/rosetta/model-cdm-calculations.rosetta b/src/main/rosetta/model-cdm-calculations.rosetta index b4b3d31db1..17ecb3d90c 100755 --- a/src/main/rosetta/model-cdm-calculations.rosetta +++ b/src/main/rosetta/model-cdm-calculations.rosetta @@ -4,21 +4,18 @@ version "${project.version}" func EquityCashSettlementAmount: <"Part 1 Section 12 of the 2018 ISDA CDM Equity Confirmation for Security Equity Swap, Para 72. 'Equity Cash Settlement Amount' means, in respect of an Equity Cash Settlement Date, an amount in the Settlement Currency determined by the Calculation Agent as of the Equity Valuation Date to which the Equity Cash Settlement Amount relates, pursuant to the following formula: Equity Cash Settlement Amount = ABS(Rate Of Return) × Equity Notional Amount."> inputs: equityPayout EquityPayout(1..1) output: equityCashSettlementAmount number (1..1) - alias rateOfReturn : Abs( ResolveRateOfReturn( equityPayout ) -> rate ); - alias notionalAmount : ResolveNotionalAmount( equityPayout ) -> notional; + alias rateOfReturn : Abs( RateOfReturn( equityPayout ) ); + alias notionalAmount : EquityNotionalAmount( equityPayout ); assign-output equityCashSettlementAmount : rateOfReturn * notionalAmount func EquityPerformance: <"Part 1 Section 12 of the 2018 ISDA CDM Equity Confirmation for Security Equity Swap, Para 75. 'Equity Performance' means, in respect of an Equity Cash Settlement Date, an amount in the Settlement Currency determined by the Calculation Agent as of the Equity Valuation Date to which the Equity Cash Settlement Amount relates, pursuant to the following formula: Equity Performance = (Rate Of Return) × Equity Notional Amount."> inputs: equityPayout EquityPayout(1..1) output: equityPerformance number (1..1) - - alias rateOfReturn : ResolveRateOfReturn( equityPayout ) -> rate - alias notionalAmount : ResolveNotionalAmount( equityPayout ) -> notional - + alias rateOfReturn : RateOfReturn( equityPayout ) + alias notionalAmount : EquityNotionalAmount( equityPayout ) assign-output equityPerformance : rateOfReturn * notionalAmount - func RateOfReturn: <"Part 1 Section 12 of the 2018 ISDA CDM Equity Confirmation for Security Equity Swap, Para 139. 'Rate Of Return' means, in respect of any Equity Valuation Date, the amount determined pursuant to the following formula: Rate Of Return = (Final Price - Initial Price) / Initial Price."> inputs: equityPayout EquityPayout(1..1) output: rateOfReturn number (1..1) @@ -59,213 +56,178 @@ func ResolvePrice: <"Function specification to return the price on a valuation d date date (1..1) output: price number (1..1) - -calculation FixedAmount <"2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount: The Fixed Amount payable by a party on a Payment Date will be: (a) if an amount is specified for the Swap Transaction as the Fixed Amount payable by that party for that Payment Date or for the related Calculation Period, that amount; or (b) if an amount is not specified for the Swap Transaction as the Fixed Amount payable by that party for that Payment Date or for the related Calculation Period, an amount calculated on a formula basis for that Payment Date or for the related Calculation Period as follows: Fixed Amount = Calculation Amount × Fixed Rate × Day Count Fraction."> -{ - fixedAmount : calculationAmount * fixedRate * dayCountFraction - - where - calculationAmount : InterestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue - fixedRate : InterestRatePayout -> rateSpecification -> fixedRate -> initialValue - dayCountFraction : InterestRatePayout -> dayCountFraction -} - -/* func FixedAmount: <"2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount: The Fixed Amount payable by a party on a Payment Date will be: (a) if an amount is specified for the Swap Transaction as the Fixed Amount payable by that party for that Payment Date or for the related Calculation Period, that amount; or (b) if an amount is not specified for the Swap Transaction as the Fixed Amount payable by that party for that Payment Date or for the related Calculation Period, an amount calculated on a formula basis for that Payment Date or for the related Calculation Period as follows: Fixed Amount = Calculation Amount × Fixed Rate × Day Count Fraction."> inputs: interestRatePayout InterestRatePayout (1..1) output: fixedAmount number (1..1) alias calculationAmount : interestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue; alias fixedRate : interestRatePayout -> rateSpecification -> fixedRate -> initialValue - alias dayCountFraction : interestRatePayout -> dayCountFraction + alias dayCountFraction : DayCountFraction(interestRatePayout, interestRatePayout -> dayCountFraction) assign-output fixedAmount : calculationAmount * fixedRate * dayCountFraction -*/ -calculation FloatingAmount <"2006 ISDA Definition Article 6 Section 6.1. Calculation of a Floating Amount: Subject to the provisions of Section 6.4 (Negative Interest Rates), the Floating Amount payable by a party on a Payment Date will be: (a) if Compounding is not specified for the Swap Transaction or that party, an amount calculated on a formula basis for that Payment Date or for the related Calculation Period as follows: Floating Amount = Calculation Amount × Floating Rate + Spread × Floating Rate Day Count Fraction (b) if “Compounding” is specified to be applicable to the Swap Transaction or that party and 'Flat Compounding' is not specified, an amount equal to the sum of the Compounding Period Amounts for each of the Compounding Periods in the related Calculation Period; or (c) if 'Flat Compounding' is specified to be applicable to the Swap Transaction or that party, an amount equal to the sum of the Basic Compounding Period Amounts for each of the Compounding Periods in the related Calculation Period plus the sum of the Additional Compounding Period Amounts for each such Compounding Period."> -{ + + +func FloatingAmount: <"2006 ISDA Definition Article 6 Section 6.1. Calculation of a Floating Amount: Subject to the provisions of Section 6.4 (Negative Interest Rates), the Floating Amount payable by a party on a Payment Date will be: (a) if Compounding is not specified for the Swap Transaction or that party, an amount calculated on a formula basis for that Payment Date or for the related Calculation Period as follows: Floating Amount = Calculation Amount × Floating Rate + Spread × Floating Rate Day Count Fraction (b) if “Compounding” is specified to be applicable to the Swap Transaction or that party and 'Flat Compounding' is not specified, an amount equal to the sum of the Compounding Period Amounts for each of the Compounding Periods in the related Calculation Period; or (c) if 'Flat Compounding' is specified to be applicable to the Swap Transaction or that party, an amount equal to the sum of the Basic Compounding Period Amounts for each of the Compounding Periods in the related Calculation Period plus the sum of the Additional Compounding Period Amounts for each such Compounding Period."> // TODO - The below calculation needs to be refined for the case of negative interest rate and compounding // TODO - The ISDA 2006 doesn't make reference to the FpML floatingRateMultiplierSchedule. // Discussed resolution path with Jonathan & Harry is for Jonathan to ask the Rates Committee if the rate multiplier is actually used. - - floatingAmount : calculationAmount * ( floatingRate + spread ) * dayCountFraction + inputs: interestRatePayout InterestRatePayout (1..1) + output: floatingAmount number (1..1) - where - calculationAmount : InterestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue - floatingRate : ResolveRateIndex( InterestRatePayout -> rateSpecification -> floatingRate -> floatingRateIndex ) + alias calculationAmount : interestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue + alias floatingRate : ResolveRateIndex( interestRatePayout -> rateSpecification -> floatingRate -> floatingRateIndex ) // TODO: question to group: why can a float rate calculation node in FpML contain multiple rate schedules? - spread : GetRateSchedule( InterestRatePayout -> rateSpecification -> floatingRate ) -> initialValue - dayCountFraction : InterestRatePayout -> dayCountFraction -} + alias spread : GetRateSchedule( interestRatePayout -> rateSpecification -> floatingRate ) -> initialValue + alias dayCountFraction : DayCountFraction(interestRatePayout, interestRatePayout -> dayCountFraction) -calculation DayCountFractionEnum._1_1 <"2006 ISDA Definition Article 4 section 4.16(a): if “1/1” is specified, 1;"> -{ - : 1.0 - - where - payout : InterestRatePayout -} + assign-output floatingAmount : calculationAmount * ( floatingRate + spread ) * dayCountFraction -calculation DayCountFractionEnum.ACT_ACT_ISDA <"2006 ISDA Definition Article 4 section 4.16(b): if “Actual/Actual”, “Actual/Actual (ISDA)”, “Act/Act” or “Act/Act (ISDA)” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 365 (or, if any portion of that Calculation Period or Compounding Period falls in a leap year, the sum of (i) the actual number of days in that portion of the Calculation Period or Compounding Period falling in a leap year divided by 366 and (ii) the actual number of days in that portion of the Calculation Period or Compounding Period falling in a non-leap year divided by 365);"> -{ - : (daysInNonLeapPeriod / 365) + (daysInLeapYearPeriod / 366) - - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) - - daysInLeapYearPeriod <"The number of days of the period that fall in a leap year.">: - calculationPeriod -> daysInLeapYearPeriod - - daysInNonLeapPeriod <"The difference between the total days in the period and the days in leap year period">: - (calculationPeriod -> daysInPeriod) - (calculationPeriod -> daysInLeapYearPeriod) -} +func DayCountFraction: <"A description of inputs and outputs for all day count fraction calculations"> + inputs: + interestRatePayout InterestRatePayout (1..1) + dayCountFractionEnum DayCountFractionEnum (1..1) + output: + result number (1..1) -calculation DayCountFractionEnum.ACT_ACT_ICMA <"2006 ISDA Definition Article 4 section 4.16(c): (c) if “Actual/Actual (ICMA)” or “Act/Act (ICMA)” is specified, a fraction equal to “number of days accrued/number of days in year”, as such terms are used in Rule 251 of the statutes, by-laws, rules and recommendations of the International Capital Market Association (the “ICMA Rule Book”), calculated in accordance with Rule 251 of the ICMA Rule Book as applied to non US dollar denominated straight and convertible bonds issued after December 31, 1998, as though the interest coupon on a bond were being calculated for a coupon period corresponding to the Calculation Period or Compounding Period in respect of which payment is being made;"> -{ - // TODO support the long initial and final stubs - : daysInPeriod / (daysInPeriod * periodsInYear) - - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) - - daysInPeriod <"Number of calendar in the calculation period">: - calculationPeriod -> daysInPeriod - - periodsInYear <"Number of calculation periods in a year">: - PeriodsInYear( InterestRatePayout -> calculationPeriodDates -> calculationPeriodFrequency) -} -calculation DayCountFractionEnum.ACT_365_FIXED <"2006 ISDA Definition Article 4 section 4.16(d): If 'Actual/365 (Fixed)', 'Act/365 (Fixed)', 'A/365 (Fixed)' or 'A/365F' is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 365."> -{ - : daysInPeriod / 365 - - where - daysInPeriod <"Number of calendar in the calculation period">: - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) -> daysInPeriod -} +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> _1_1): <"2006 ISDA Definition Article 4 section 4.16(a): if “1/1” is specified, 1;"> + assign-output result: 1.0 -calculation DayCountFractionEnum.ACT_360 <"'2006 ISDA Definition Article 4 section 4.16(e): if “Actual/360”, “Act/360” or “A/360” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360."> -{ - : daysInPeriod / 360 - - where - daysInPeriod <"Number of calendar in the calculation period">: - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) -> daysInPeriod -} +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> ACT_ACT_ISDA): <"'2006 ISDA Definition Article 4 section 4.16(e): if “Actual/360”, “Act/360” or “A/360” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360."> + alias calculationPeriod: CalculationPeriod(interestRatePayout -> calculationPeriodDates) + alias daysInLeapYearPeriod: <"The number of days of the period that fall in a leap year."> + calculationPeriod -> daysInLeapYearPeriod + alias daysInNonLeapPeriod: <"The difference between the total days in the period and the days in leap year period"> + (calculationPeriod -> daysInPeriod) - (calculationPeriod -> daysInLeapYearPeriod) + assign-output result: + (daysInNonLeapPeriod / 365) + (daysInLeapYearPeriod / 366) -calculation DayCountFractionEnum._30_360 <"2006 ISDA Definition Article 4 section 4.16(f): if “30/360”, “360/360” or “Bond Basis” is specified, the number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360, calculated on a formula basis as follows:[[360 x (Y2 - Y1)] + [30 x (M2 - M1)] + (D2 - D1)]/360."> -{ - : (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 - - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) + +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> ACT_ACT_ICMA): <"2006 ISDA Definition Article 4 section 4.16(c): (c) if “Actual/Actual (ICMA)” or “Act/Act (ICMA)” is specified, a fraction equal to “number of days accrued/number of days in year”, as such terms are used in Rule 251 of the statutes, by-laws, rules and recommendations of the International Capital Market Association (the “ICMA Rule Book”), calculated in accordance with Rule 251 of the ICMA Rule Book as applied to non US dollar denominated straight and convertible bonds issued after December 31, 1998, as though the interest coupon on a bond were being calculated for a coupon period corresponding to the Calculation Period or Compounding Period in respect of which payment is being made;"> + alias calculationPeriod: CalculationPeriod(interestRatePayout -> calculationPeriodDates) + alias daysInPeriod: <"Number of calendar in the calculation period"> + calculationPeriod -> daysInPeriod + alias periodsInYear: <"Number of calculation periods in a year"> + PeriodsInYear(interestRatePayout -> calculationPeriodDates -> calculationPeriodFrequency) + assign-output result: + // TODO support the long initial and final stubs + daysInPeriod / (daysInPeriod * periodsInYear) + +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> ACT_365_FIXED): <"'2006 ISDA Definition Article 4 section 4.16(d): If 'Actual/365 (Fixed)', 'Act/365 (Fixed)', 'A/365 (Fixed)' or 'A/365F' is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 365. ISDA Definition Article 4 section 4.16(e): if “Actual/360”, “Act/360” or “A/360” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360."> + alias daysInPeriod: <"Number of calendar in the calculation period"> + CalculationPeriod(interestRatePayout -> calculationPeriodDates ) -> daysInPeriod + assign-output result: + daysInPeriod / 365 + +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> ACT_360): <"'2006 ISDA Definition Article 4 section 4.16(e): if “Actual/360”, “Act/360” or “A/360” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360."> + alias daysInPeriod: <"Number of calendar in the calculation period"> + CalculationPeriod(interestRatePayout -> calculationPeriodDates ) -> daysInPeriod + assign-output result: + daysInPeriod / 360 + +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> _30_360): <"2006 ISDA Definition Article 4 section 4.16(f): if “30/360”, “360/360” or “Bond Basis” is specified, the number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360, calculated on a formula basis as follows:[[360 x (Y2 - Y1)] + [30 x (M2 - M1)] + (D2 - D1)]/360."> + alias calculationPeriod: + CalculationPeriod(interestRatePayout -> calculationPeriodDates) - startYear <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startYear: <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> year - endYear <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endYear: <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> year - startMonth <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startMonth: <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> month - endMonth <"The calendar month, expressed as number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endMonth: <"The calendar month, expressed as number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> month - endDay <"The calendar day, expressed as a number, immediately following the last day included in the Calculation Period or Compounding Period, unless such number would be 31 and D2, is greater than 29, in which case D2 will be 30">: + alias endDay: <"The calendar day, expressed as a number, immediately following the last day included in the Calculation Period or Compounding Period, unless such number would be 31 and D2, is greater than 29, in which case D2 will be 30"> if calculationPeriod -> startDate -> day > 29 then Min( calculationPeriod -> endDate -> day, 30 ) else calculationPeriod -> endDate -> day - startDay <"The first calendar day, expressed as a number, of the Calculation Period or Compounding Period, unless such number would be 31, in which case, will be 30">: - Min( calculationPeriod -> startDate -> day, 30 ) -} + alias startDay: <"The first calendar day, expressed as a number, of the Calculation Period or Compounding Period, unless such number would be 31, in which case, will be 30"> + Min( calculationPeriod -> startDate -> day, 30 ) + assign-output result: + (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 -calculation DayCountFractionEnum._30E_360 <"2006 ISDA Definition Article 4 section 4.16(g): If '30E/360' or 'Eurobond Basis' is specified, the number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360, calculated on a formula basis as follows:[[360 x (Y2 - Y1)] + [30 x (M2 - M1)] + (D2 - D1)]/360."> -{ - : (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 - - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) + +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> _30E_360): <"'2006 ISDA Definition Article 4 section 4.16(e): if “Actual/360”, “Act/360” or “A/360” is specified, the actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360."> + alias calculationPeriod: + CalculationPeriod(interestRatePayout -> calculationPeriodDates ); - startYear <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startYear: <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> year - endYear <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endYear: <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> year - startMonth <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startMonth: <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> month - endMonth <"The calendar month, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endMonth: <"The calendar month, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> month - endDay <"The first calendar day, expressed as a number, of the Calculation Period or Compounding Period, unless such number would be 31, in which case will be 30">: + alias endDay: <"The first calendar day, expressed as a number, of the Calculation Period or Compounding Period, unless such number would be 31, in which case will be 30"> Min( calculationPeriod -> endDate -> day, 30 ) - startDay <"The calendar day, expressed as a number, immediately following the last day included in the Calculation Period or Compounding Period, unless such number would be 31, in which case will be 30"> : + alias startDay: <"The calendar day, expressed as a number, immediately following the last day included in the Calculation Period or Compounding Period, unless such number would be 31, in which case will be 30"> Min( calculationPeriod -> startDate -> day, 30 ) -} + assign-output result: + (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 -calculation DayCountFractionEnum._30E_360_ISDA <"2006 ISDA Definition Article 4 section 4.16(h): if “30E/360 (ISDA)” is specified, the number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360, calculated on a formula basis as follows: [[360 × (Y2 - Y1)]+[30 × (M2 - M1)] +(D2 - D1)]/360 "> -{ - : (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> _30E_360_ISDA): <"2006 ISDA Definition Article 4 section 4.16(h): if “30E/360 (ISDA)” is specified, the number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 360, calculated on a formula basis as follows: [[360 × (Y2 - Y1)]+[30 × (M2 - M1)] +(D2 - D1)]/360 "> - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) - - alias interestRatePayoutTerminationDate - ToAdjustedDateFunction (InterestRatePayout -> calculationPeriodDates -> terminationDate) - - alias startDateIsInLeapYear + alias calculationPeriod: + CalculationPeriod( interestRatePayout -> calculationPeriodDates ) + + alias interestRatePayoutTerminationDate: + ToAdjustedDateFunction (interestRatePayout -> calculationPeriodDates -> terminationDate) + + alias startDateIsInLeapYear: IsLeapYear(calculationPeriod -> startDate -> year) - - alias endDateIsInLeapYear + + alias endDateIsInLeapYear: IsLeapYear(calculationPeriod -> endDate -> year) - startYear <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startYear: <"The year, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> year - endYear <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endYear: <"The year, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> year - startMonth <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls">: + alias startMonth: <"The calendar month, expressed as a number, in which the first day of the Calculation Period or Compounding Period falls"> calculationPeriod -> startDate -> month - endMonth <"The calendar month, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls">: + alias endMonth: <"The calendar month, expressed as a number, in which the day immediately following the last day included in the Calculation Period or Compounding Period falls"> calculationPeriod -> endDate -> month - startDay: + alias startDay: if startDateIsInLeapYear = False and calculationPeriod -> startDate -> month = 2 and calculationPeriod -> startDate -> day = 28 or startDateIsInLeapYear = True and calculationPeriod -> startDate -> month = 2 and calculationPeriod -> startDate -> day = 29 or calculationPeriod -> startDate -> day = 31 then 30 else calculationPeriod -> endDate -> day - endDay: + alias endDay: if endDateIsInLeapYear = False and calculationPeriod -> endDate -> month = 2 and calculationPeriod -> endDate -> day = 28 or endDateIsInLeapYear = True and calculationPeriod -> endDate -> month = 2 and calculationPeriod -> endDate -> day = 29 or calculationPeriod -> endDate -> day = 31 or calculationPeriod -> endDate = interestRatePayoutTerminationDate then 30 else calculationPeriod -> endDate -> day -} + assign-output result: + (360 * (endYear - startYear) + 30 * (endMonth - startMonth) + (endDay - startDay)) / 360 -calculation DayCountFractionEnum.ACT_365L <"The actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 365 (or, if the later Period End Date of the Calculation Period or Compounding Period falls in a leap year, divided by 366). "> -{ - : daysInPeriod / daysInYear +func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum -> ACT_365L): <"The actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made divided by 365 (or, if the later Period End Date of the Calculation Period or Compounding Period falls in a leap year, divided by 366). "> + alias calculationPeriod: + CalculationPeriod( interestRatePayout -> calculationPeriodDates ) - where - alias calculationPeriod - CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) - - alias endDateIsInLeapYear - IsLeapYear(calculationPeriod -> endDate -> year) - - daysInPeriod <"The actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made ">: - calculationPeriod -> daysInPeriod - - daysInYear <"365 or, if the later Period End Date of the Calculation Period or Compounding Period falls in a leap year, divided by 366. ">: - if (endDateIsInLeapYear = True) then 366 else 365 -} + alias endDateIsInLeapYear: + IsLeapYear(calculationPeriod -> endDate -> year) + + alias daysInPeriod: <"The actual number of days in the Calculation Period or Compounding Period in respect of which payment is being made "> + calculationPeriod -> daysInPeriod + + alias daysInYear: <"365 or, if the later Period End Date of the Calculation Period or Compounding Period falls in a leap year, divided by 366. "> + if (endDateIsInLeapYear = True) then 366 else 365 + + assign-output result: daysInPeriod / daysInYear + func EquityCalculationPeriod: inputs: @@ -286,7 +248,7 @@ func GetRateSchedule: inputs: floatingRateCalculation FloatingRateSpecification (1..1) output: schedule SpreadSchedule (1..1) -func ResolveRateIndex:<"The function to specify that the floating rate index enumeration will be expressed as a number once the rate is observed."> +func ResolveRateIndex: <"The function to specify that the floating rate index enumeration will be expressed as a number once the rate is observed."> inputs:index FloatingRateIndexEnum (1..1) output: rate number(1..1) @@ -297,29 +259,20 @@ func PeriodsInYear: func Abs: inputs: x number (1..1) output: result number (1..1) + +func CalculationPeriod :<"2006 ISDA Definition Section 4.13. 'Calculation Period' means, in respect of a Swap Transaction and a party, each period from, and including, one Period End Date of that party to, but excluding, the next following applicable Period End Date during the Term of the Swap Transaction, except that (a) the initial Calculation Period for the party will commence on, and include, the Effective Date and (b) the final Calculation Period for the party will end on, but exclude, the Termination Date."> + inputs: calculationPeriodDates CalculationPeriodDates (1..1) + output: result CalculationPeriodData (1..1) - - -function ResolveRateOfReturn( equityPayout EquityPayout ) <""> -{ - rate number; - // Body to be copied from "RateOfReturn" specification once new Function Specification module in production -} - -function ResolveNotionalAmount( equityPayout EquityPayout ) <""> -{ - notional number; - // Body to be copied from "EquityNotionalAmount" specification once new Function Specification module in production +class CalculationPeriodData { + startDate date (1..1) + endDate date (1..1) + daysInPeriod int (1..1) + daysInLeapYearPeriod int (1..1) } -// Deprecated - deleted once calculations have moved to Function Spec -function CalculationPeriod( calculationPeriodDates CalculationPeriodDates ) <"2006 ISDA Definition Section 4.13. 'Calculation Period' means, in respect of a Swap Transaction and a party, each period from, and including, one Period End Date of that party to, but excluding, the next following applicable Period End Date during the Term of the Swap Transaction, except that (a) the initial Calculation Period for the party will commence on, and include, the Effective Date and (b) the final Calculation Period for the party will end on, but exclude, the Termination Date."> -{ - startDate date; - endDate date; - daysInPeriod int; - daysInLeapYearPeriod int; - isFirstPeriod boolean; - isLastPeriod boolean; -} - \ No newline at end of file +//data CalculationPeriodData: +// startDate date (1..1) +// endDate date (1..1) +// daysInPeriod int (1..1) +// daysInLeapYearPeriod int (1..1) diff --git a/src/main/rosetta/model-cdm-event-functions.rosetta b/src/main/rosetta/model-cdm-event-functions.rosetta index 6ada9da204..0c7ae73cb0 100755 --- a/src/main/rosetta/model-cdm-event-functions.rosetta +++ b/src/main/rosetta/model-cdm-event-functions.rosetta @@ -240,7 +240,7 @@ func CalculationPeriodSpec: <"A product agnostic approach to extracting the calc result DateRange (1..1) -func GetBusinessDateSpec: <"A function to be implementated by CDM users for systematic implementations to provide a business date"> +func GetBusinessDateSpec: <"A function to be implemented by CDM users for systematic implementations to provide a business date"> output: result date (1..1) diff --git a/src/main/rosetta/model-cdm-product.rosetta b/src/main/rosetta/model-cdm-product.rosetta index 1cafd16952..fe8254e698 100755 --- a/src/main/rosetta/model-cdm-product.rosetta +++ b/src/main/rosetta/model-cdm-product.rosetta @@ -351,13 +351,6 @@ data rule ResolvablePayoutQuantity_quantityMultiplier <"A quantity reference mus when ResolvablePayoutQuantity -> quantityMultiplier exists then ResolvablePayoutQuantity -> quantityReference exists -spec ResolveQuantity <"Function specification to resolve a payout quantity, specified as a resolvable quantity with inputs for the resolution, into a basic quantity with just a number and a unit.">: - inputs: - resolvableQuantity ResolvablePayoutQuantity (1..1) <"The quantity to resolve."> - date date (1..1) - output: - quantity Quantity (1..1) <"The resolved quantity, containing just a number and (optionally) a unit or currency."> - class CrossCurrencyTerms { principalExchanges PrincipalExchanges (0..1); diff --git a/src/main/rosetta/model-no-code-gen.rosetta b/src/main/rosetta/model-no-code-gen.rosetta deleted file mode 100755 index eaf109bd37..0000000000 --- a/src/main/rosetta/model-no-code-gen.rosetta +++ /dev/null @@ -1,222 +0,0 @@ -namespace "org.isda.cdm" -version "${project.version}" - -/* - * Function specification for Portfolio Aggregation - * - * COMMENTED-OUT FOR NOW, THIS WILL NEEDS TO BE ADJUSTED TO REFLECT THE NEW FUNCTION SPEC SYNTAX - * - */ - -/* -spec TransitionPortfolioState( currentState PortfolioState, eventList Event, aggregationParams AggregationParameters ) -> newState PortfolioState -<"Specification to transition the state of a Portfolio based on its current state and a new set of Events. The eventList being passed on is meant to be already filtered on both time and aggregation parameters for the underlying Portfolio."> -{ - pre condition: - MinDatetime( eventList -> timestamp ) >= MaxDatetime( currentState -> lineage -> eventReference -> timestamp ) <"New set of Events must be posterior to the latest Events on the previous PortfolioState."> - IsApplicableEvent( eventList, aggregationParams ) <"Events must be pre-filtered and therefore applicable to the aggregation parameters of the Portfolio."> - - post condition: - newState -> positionList = currentState -> positionList + PositionEffect( eventList ) <"Update the new positions list based on adding the PositionEffect of the new Events to the current positions list, using the further specified + operator"> - newState -> lineage -> eventReference = eventList <"Event lineage of the new state pointing to the latest set of Events."> - newState -> lineage -> portfolioStateReference = currentState <"PortfolioState lineage of the new state pointing to the current, and now previous, state."> -} - -spec MinDatetime: - inputs: - datetimes zonedDateTime (1..*) - output: - result zonedDateTime (1..1) - -spec MaxDatetime: - inputs: - datetimes zonedDateTime (1..*) - output: - result zonedDateTime (1..1) - -spec IsApplicableEvent <"Specification for boolean check whether an Event is applicable to a given Portfolio as defined by its AggregationParameters">: - inputs: - event Event (1..1) - aggregationParams AggregationParameters (1..1) - - output: - isApplicable boolean (1..1) - -spec PositionEffect <"Specification to extract the position effect as a Delta from an Event.">: - inputs: - event Event (1..1) - output: - positionEffect Position (1..1) - - // Refactoring: move as a "method" and the Event class to extract position effects based on primitive - post-condition: - if event -> primitive -> inception exists then - positionEffect = PositionEffect( event -> primitive -> inception ) - else True; - -spec PositionEffect( inception Inception) -> positionEffect Position -<"Specification of PositionEffect for the inception primitive, which corresponds to creating a Position instantiated with the uderlying contractual product and quantity, the status as Formed and a reference to contract now in place.."> -{ - positionEffect -> product = inception -> after -> contract -> contractualProduct - positionEffect -> quantity = inception -> after -> contract -> quantity - positionEffect -> contractReference = -> inception -> after -> contract - positionEffect -> positionStatus = PositionStatusEnum.Formed -} - -spec operator + ( positionA Position, positionB Position ) -> sumPosition Position -<"Operator specification to add 2 positions together."> -{ - // TBD: further define here? -} -*/ - -/* - * Option 2 - A mark to market calculation for an FX Forward as provided by a member firm, but providing more transparency to the inputs of the interpolation function - * - * 1. + explicit in which model elements are being passed into function calls - * 2. - will require lots of product specific logic in a calculation that should be product agnostic - * - * TODO: code generation to support comparison vs. enum values - * TODO: code generation to support variables that reference other variables, under the hood the reference to 'fx' in 'tenor' is broken - * TODO: (non-critical) Change to use alias, so to clearly distinguish between calculation inputs and 'syntactic sugar', enforce non-calc-inputs to be alias' - * TODO: (non-critical) SpotRate( fx ) -> rate is unnecessary, SpotRate( fx ) should be enough, as it returns only 1 value - */ -calculation FxMarkToMarket_2 <"Representation of sample mark to market calculation provided by a member firm, providing more transparency on the parameters used to interpolate the mark to market rate."> -{ - : (quotedQuantity / interpolatedRate - baseQuantity) * interpolatedRate - - where - // variables used in the rate InterpolateFull function call, below. - fx: - ForwardPayout -> underlier -> singleUnderlier -> underlyingProduct -> foreignExchange - - tenor: - fx -> tenorPeriod -> periodMultiplier - - today: - Today() - - tenorRemaining: - ForwardPayout -> settlementTerms -> settlementDate -> adjustableDate -> adjustedDate + today -> time - - spotRate: - SpotRate( fx ) -> rate - - forwardRate: - ForwardRate( fx -> tenorPeriod, fx ) -> rate - - // actual calculation inputs - interpolatedRate <"The interpolated rate.">: - 42.0 // Interpolate( tenor - tenorRemaining, 0, tenor, spotRate, forwardRate ) -> result - - quotedQuantity <"The amount of the quoted currency.">: - if fx -> exchangeRate -> quotedCurrencyPair -> quoteBasis = QuoteBasisEnum.Currency2PerCurrency1 - then fx -> exchangedCurrency2 -> cashflowAmount -> amount - else fx -> exchangedCurrency1 -> cashflowAmount -> amount - - baseQuantity <"The amount of the base currency.">: - if fx -> exchangeRate -> quotedCurrencyPair -> quoteBasis = QuoteBasisEnum.Currency2PerCurrency1 - then fx -> exchangedCurrency1 -> cashflowAmount -> amount - else fx -> exchangedCurrency2 -> cashflowAmount -> amount -} - -function Today() <"Returns the current date of the operating system."> -{ - date date; - time time; -} - -function Interpolate( x number, xStart int, xEnd int, yStart number, yEnd number ) <"Returns the one-dimensional piecewise linear interpolant to a function with given discrete data points ([xStart, xEnd], [yStart, yEnd]), evaluated at x."> -{ - result number; -} - -function SpotRate( fx ForeignExchange ) <"An external market data lookup for the spot fx for the currency pair."> -{ - rate number; -} - -function ForwardRate( tenor Period, fx ForeignExchange ) <"An external market data lookup for the forward fx rate for the currency pair, making use of the period specified on the Foreign Exchange contract."> -{ - rate number; -} - -/* - * Option 3 - reference other calculations, potential to make calculations product agnostic - * - * 1. + Mark to market calculation described in product-agnostic terms - * 2. + Product specific logic (i.e. to extract price and quantity) are abstracted into other 'calculations' or functions - * 3. + Price and quantity abstractions can be reused in Portfolio processing - * 4. - More work involved upgrade syntax and code generators - * - * TODO: requires support for referencing calculations from calculations - * TODO: code generation to support comparison vs. enum values - * TODO: code generation to support variables that reference other variables, under the hood the reference to 'fx' in 'tenor' is broken - */ -/* -calculation MarkToMarket_3 <"Representation of sample mark to market calculation provided by a member firm."> -{ - = tradedQuantity * (tradedPrice - marketPrice) - - where - tradedPrice <"The amount of the quoted currency.">: - TradedPrice( EconomicTerms -> payout ) - - tradedQuantity <"The amount of the base currency.">: - TradedQuantity( EconomicTerms -> payout ) - - marketPrice: - CalculateMarketPrice( ForwardPayout ) -> result -} - -calculation TradedQuantity <"A calculation that takes a Payout and returns the traded quantity."> -{ - = if Payout -> forwardPayout -> foreignExchange exists - then - if ForeignExchange -> exchangeRate -> quotedCurrencyPair -> quoteBasis = QuoteBasisEnum.Currency2PerCurrency1 - then ForeignExchange -> exchangedCurrency1 -> cashflowAmount -> amount - else ForeignExchange -> exchangedCurrency2 -> cashflowAmount -> amount - else if - if Payout -> interestRatePayout -> exists - then Payout -> interestRatePayout -> ... -> notionalAmount - else 0.0 - else if - ... -} - -calculation TradedPrice -{ - = if Payout -> forwardPayout -> foreignExchange exists - then Payout -> forwardPayout -> foreignExchange -> exchangeRate -> rate - else if Payout -> interestRatePayout exists - then - ... -} - -calculation CalculateMarketPrice -{ - = Interpolate(x, xStart, xEnd, yStart, yEnd) - - where - tenorRemaining: - EconomicTerms -> payout -> forwardPayout -> settlementDate - Today() -> date - - tenor: - Tenor( EconomicTerms ) - - x: - tenor - tenorRemaining - - xStart: - 0 - - xEnd: - tenor - - yStart: - ForwardRate( ForwardPayout -> foreignExchange -> tenorPeriod, ForwardPayout -> foreignExchange ) -> rate - - yEnd: - SpotRate( ForwardPayout -> foreignExchange ) -> rate -} -*/ \ No newline at end of file diff --git a/src/test/java/org/isda/cdm/functions/CalculationPeriodImplTest.java b/src/test/java/org/isda/cdm/functions/CalculationPeriodImplTest.java index 6197c401f9..0f3229ab8a 100644 --- a/src/test/java/org/isda/cdm/functions/CalculationPeriodImplTest.java +++ b/src/test/java/org/isda/cdm/functions/CalculationPeriodImplTest.java @@ -10,6 +10,7 @@ import org.isda.cdm.BusinessCenters; import org.isda.cdm.BusinessDayAdjustments; import org.isda.cdm.BusinessDayConventionEnum; +import org.isda.cdm.CalculationPeriodData; import org.isda.cdm.CalculationPeriodDates; import org.isda.cdm.CalculationPeriodFrequency; import org.isda.cdm.PeriodExtendedEnum; @@ -63,16 +64,16 @@ class CalculationPeriodImplTest { @Test void shouldReturnStartAndEndDateOfFirstPeriod() { CalculationPeriod usingStartDatePeriodCalculator = new CalculationPeriodImpl(DateImpl.of(2018, 1, 3)); - CalculationPeriod.CalculationResult usingStartDate = usingStartDatePeriodCalculator.execute(calculationPeriodDates); + CalculationPeriodData usingStartDate = usingStartDatePeriodCalculator.evaluate(calculationPeriodDates); assertThat(usingStartDate.getStartDate(), is(DateImpl.of(2018, 1, 3))); assertThat(usingStartDate.getEndDate(), is(DateImpl.of(2018, 4, 3))); CalculationPeriod usingAnyDatePeriodCalculator = new CalculationPeriodImpl(DateImpl.of(2018, 2, 14)); - CalculationPeriod.CalculationResult usingAnyDate = usingAnyDatePeriodCalculator.execute(calculationPeriodDates); + CalculationPeriodData usingAnyDate = usingAnyDatePeriodCalculator.evaluate(calculationPeriodDates); CalculationPeriod usingEndDatePeriodCalculator = new CalculationPeriodImpl(DateImpl.of(2018, 3, 31)); - CalculationPeriod.CalculationResult usingEndDate = usingEndDatePeriodCalculator.execute(calculationPeriodDates); + CalculationPeriodData usingEndDate = usingEndDatePeriodCalculator.evaluate(calculationPeriodDates); assertThat(usingStartDate, allOf(is(usingAnyDate), is(usingEndDate))); } @@ -89,7 +90,7 @@ void shouldThrowWhenRollConventionNotTerminationDay() { .setCalculationPeriodFrequency(frequency) .build(); - Executable result = () -> unit.execute(calculationPeriodDates); + Executable result = () -> unit.evaluate(calculationPeriodDates); assertThrows(ScheduleException.class, result, "Date '2018-01-03' does not match roll convention 'Day1' when starting to roll forwards"); } diff --git a/src/test/java/org/isda/cdm/functions/DayCountFractionEnumTest.java b/src/test/java/org/isda/cdm/functions/DayCountFractionEnumTest.java index b11d9437a3..3b1b5a36ad 100644 --- a/src/test/java/org/isda/cdm/functions/DayCountFractionEnumTest.java +++ b/src/test/java/org/isda/cdm/functions/DayCountFractionEnumTest.java @@ -1,19 +1,22 @@ package org.isda.cdm.functions; -import com.rosetta.model.lib.records.DateImpl; -import org.isda.cdm.InterestRatePayout; -import org.isda.cdm.calculation.DayCountFractionEnum; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; +import org.isda.cdm.CalculationPeriodData; +import org.isda.cdm.DayCountFractionEnum; +import org.isda.cdm.InterestRatePayout; +import org.isda.cdm.calculation.DayCountFraction; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import com.rosetta.model.lib.records.DateImpl; public class DayCountFractionEnumTest { @@ -61,36 +64,40 @@ void shouldCalculateDcfFor30360BetweenDates30Jan17To30Jan18() { } private BigDecimal calculateAct360(LocalDate startDate, LocalDate endDate, int days, org.isda.cdm.DayCountFractionEnum dcf) { - CalculationPeriod.CalculationResult calculationPeriodResult = Mockito.mock(CalculationPeriod.CalculationResult.class); - when(calculationPeriodResult.getStartDate()).thenReturn(new DateImpl(startDate)); - when(calculationPeriodResult.getEndDate()).thenReturn(new DateImpl(endDate)); - when(calculationPeriodResult.getDaysInPeriod()).thenReturn(days); + CalculationPeriodData calculationPeriodResult = + CalculationPeriodData.builder() + .setStartDate(new DateImpl(startDate)) + .setEndDate(new DateImpl(endDate)) + .setDaysInPeriod(days) + .build(); CalculationPeriod calculationPeriod = Mockito.mock(CalculationPeriod.class); - when(calculationPeriod.execute(any())).thenReturn(calculationPeriodResult); + when(calculationPeriod.evaluate(any())).thenReturn(calculationPeriodResult); InterestRatePayout interestRatePayout = Mockito.mock(InterestRatePayout.class); ToAdjustedDateFunction toAdjustedDate = Mockito.mock(ToAdjustedDateFunction.class); PeriodsInYear periodsInYear = Mockito.mock(PeriodsInYear.class); - DayCountFractionEnum unit = new DayCountFractionEnum(calculationPeriod, periodsInYear, toAdjustedDate); - return unit.calculate(interestRatePayout, dcf).getValue(); + DayCountFraction unit = new DayCountFraction(calculationPeriod, periodsInYear, toAdjustedDate); + return unit.calculate(interestRatePayout, dcf).getResult(); } private BigDecimal calculate30360(LocalDate startDate, LocalDate endDate, org.isda.cdm.DayCountFractionEnum dcf) { - CalculationPeriod.CalculationResult calculationPeriodResult = Mockito.mock(CalculationPeriod.CalculationResult.class); - when(calculationPeriodResult.getStartDate()).thenReturn(new DateImpl(startDate)); - when(calculationPeriodResult.getEndDate()).thenReturn(new DateImpl(endDate)); + CalculationPeriodData calculationPeriodResult = + CalculationPeriodData.builder() + .setStartDate(new DateImpl(startDate)) + .setEndDate(new DateImpl(endDate)) + .build(); CalculationPeriod calculationPeriod = Mockito.mock(CalculationPeriod.class); - when(calculationPeriod.execute(any())).thenReturn(calculationPeriodResult); + when(calculationPeriod.evaluate(any())).thenReturn(calculationPeriodResult); ToAdjustedDateFunction toAdjustedDate = Mockito.mock(ToAdjustedDateFunction.class); PeriodsInYear periodsInYear = Mockito.mock(PeriodsInYear.class); InterestRatePayout interestRatePayout = Mockito.mock(InterestRatePayout.class); - DayCountFractionEnum unit = new DayCountFractionEnum(calculationPeriod, periodsInYear, toAdjustedDate); - return unit.calculate(interestRatePayout, dcf).getValue(); + DayCountFraction unit = new DayCountFraction(calculationPeriod, periodsInYear, toAdjustedDate); + return unit.calculate(interestRatePayout, dcf).getResult(); } } diff --git a/src/test/java/org/isda/cdm/functions/DaysInPeriodImplTest.java b/src/test/java/org/isda/cdm/functions/DaysInPeriodImplTest.java index f5d3deb08d..be6db624de 100644 --- a/src/test/java/org/isda/cdm/functions/DaysInPeriodImplTest.java +++ b/src/test/java/org/isda/cdm/functions/DaysInPeriodImplTest.java @@ -30,7 +30,7 @@ void shouldReturnDaysInPeriodBetweenDates22Mar18To22Jun18() { CalculationPeriodDates calculationPeriodDates = getCalculationPeriodDates(effectiveDate, terminationDate, RollConventionEnum._22); - Integer daysInPeriod = new CalculationPeriodImpl(effectiveDate).execute(calculationPeriodDates).getDaysInPeriod(); + Integer daysInPeriod = new CalculationPeriodImpl(effectiveDate).evaluate(calculationPeriodDates).getDaysInPeriod(); assertNotNull(daysInPeriod); assertThat("Unexpected calculated daysInPeriod", daysInPeriod, is(92)); @@ -43,7 +43,7 @@ void shouldReturnDaysInPeriodBetweenDates29Dec17To29Mar18() { CalculationPeriodDates calculationPeriodDates = getCalculationPeriodDates(effectiveDate, terminationDate, RollConventionEnum._29); - Integer daysInPeriod = new CalculationPeriodImpl(effectiveDate).execute(calculationPeriodDates).getDaysInPeriod(); + Integer daysInPeriod = new CalculationPeriodImpl(effectiveDate).evaluate(calculationPeriodDates).getDaysInPeriod(); assertNotNull(daysInPeriod); assertThat("Unexpected calculated daysInPeriod", daysInPeriod, is(90)); diff --git a/src/test/java/org/isda/cdm/functions/FixedAmountTest.java b/src/test/java/org/isda/cdm/functions/FixedAmountTest.java index 344c288783..1c2cbdf7cc 100644 --- a/src/test/java/org/isda/cdm/functions/FixedAmountTest.java +++ b/src/test/java/org/isda/cdm/functions/FixedAmountTest.java @@ -21,19 +21,24 @@ import org.isda.cdm.RateSpecification; import org.isda.cdm.RollConventionEnum; import org.isda.cdm.Schedule; +import org.isda.cdm.calculation.DayCountFraction; import org.isda.cdm.calculation.FixedAmount; import org.isda.cdm.metafields.FieldWithMetaDayCountFractionEnum; import org.isda.cdm.metafields.FieldWithMetaString; import org.isda.cdm.metafields.ReferenceWithMetaBusinessCenters; import org.junit.jupiter.api.Test; +import com.google.inject.Inject; import com.rosetta.model.lib.records.Date; import com.rosetta.model.lib.records.DateImpl; class FixedAmountTest { private static final Date REFERENCE_DATE = DateImpl.of(2018, 8, 22); - + @Inject private CalculationPeriod calculationPeriod; + @Inject private PeriodsInYear periodsInYear; + @Inject private ToAdjustedDateFunction toAdjustedDateFunction; + @Test void shouldCalculate() { InterestRatePayout interestRatePayout = InterestRatePayout.builder() @@ -89,10 +94,8 @@ void shouldCalculate() { .build()) .build(); - FixedAmount.CalculationResult fixedAmount = new FixedAmount( - new CalculationPeriodImpl(REFERENCE_DATE), null /* TODO - add test param*/, null /* TODO - add test param*/).calculate(interestRatePayout); - - assertThat(fixedAmount.getFixedAmount(), is(new BigDecimal("750000.0000"))); + FixedAmount fixedAmount = new FixedAmount(new CalculationPeriodImpl(REFERENCE_DATE), periodsInYear, toAdjustedDateFunction); + assertThat(fixedAmount.calculate(interestRatePayout).getFixedAmount(), is(new BigDecimal("750000.0000"))); } }