// Converts an FpML 'NonNegativeAmountSchedule' to a {@code ValueStepSequence}. private ValueStepSequence parseAmountSchedule(XmlElement scheduleEl, double initialValue, FpmlDocument document) { Frequency freq = document.parseFrequency(scheduleEl.getChild("stepFrequency")); LocalDate start = document.parseDate(scheduleEl.getChild("firstNotionalStepDate")); LocalDate end = document.parseDate(scheduleEl.getChild("lastNotionalStepDate")); Optional <XmlElement> amountElOpt = scheduleEl.findChild("notionalStepAmount"); if (amountElOpt.Present) { double amount = document.parseDecimal(amountElOpt.get()); return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount))); } double rate = document.parseDecimal(scheduleEl.getChild("notionalStepRate")); string relativeTo = scheduleEl.findChild("stepRelativeTo").map(el => el.Content).orElse("Previous"); if (relativeTo.Equals("Previous")) { return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaMultiplier(rate))); } else if (relativeTo.Equals("Initial")) { // data model does not support 'relative to initial' but can calculate amount here double amount = initialValue * rate; return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount))); } else { throw new FpmlParseException(Messages.format("Unknown 'stepRelativeTo' value '{}', expected 'Initial' or 'Previous'", relativeTo)); } }
public virtual void test_summarize_knownAmountVarying() { Swap test = Swap.of(KnownAmountSwapLeg.builder().accrualSchedule(PeriodicSchedule.of(date(2018, 2, 12), date(2020, 2, 12), Frequency.P3M, BusinessDayAdjustment.NONE, SHORT_INITIAL, false)).amount(ValueSchedule.builder().initialValue(145_000).stepSequence(ValueStepSequence.of(date(2018, 8, 12), date(2019, 8, 12), Frequency.P6M, ofDeltaAmount(-20_000))).build()).currency(GBP).payReceive(PAY).paymentSchedule(PaymentSchedule.builder().paymentFrequency(Frequency.P3M).paymentDateOffset(DaysAdjustment.NONE).build()).build()); assertEquals(test.summaryDescription(), "2Y Pay GBP 145k variable : 12Feb18-12Feb20"); }
public virtual void test_summarize_irs_weird() { PeriodicSchedule accrual = PeriodicSchedule.of(date(2018, 2, 12), date(2020, 2, 12), Frequency.P3M, BusinessDayAdjustment.NONE, SHORT_INITIAL, false); PaymentSchedule payment = PaymentSchedule.builder().paymentFrequency(Frequency.P3M).paymentDateOffset(DaysAdjustment.NONE).build(); NotionalSchedule notional = NotionalSchedule.of(GBP, ValueSchedule.builder().initialValue(1_000_000).stepSequence(ValueStepSequence.of(date(2018, 8, 12), date(2019, 8, 12), Frequency.P6M, ofDeltaAmount(-50_000))).build()); RateCalculationSwapLeg payLeg = RateCalculationSwapLeg.builder().payReceive(PAY).accrualSchedule(accrual).paymentSchedule(payment).notionalSchedule(notional).calculation(FixedRateCalculation.builder().dayCount(ACT_360).rate(ValueSchedule.builder().initialValue(0.0012).stepSequence(ValueStepSequence.of(date(2018, 8, 12), date(2019, 8, 12), Frequency.P6M, ofDeltaAmount(0.0001))).build()).build()).build(); RateCalculationSwapLeg recLeg = RateCalculationSwapLeg.builder().payReceive(RECEIVE).accrualSchedule(accrual).paymentSchedule(payment).notionalSchedule(notional).calculation(IborRateCalculation.builder().index(IborIndices.GBP_LIBOR_3M).gearing(ValueSchedule.of(1.1)).spread(ValueSchedule.of(0.002)).build()).build(); Swap test = Swap.of(payLeg, recLeg); assertEquals(test.summaryDescription(), "2Y GBP 1mm variable Rec GBP-LIBOR-3M * 1.1 + 0.2% / Pay 0.12% variable : 12Feb18-12Feb20"); }