//------------------------------------------------------------------------- // fixed rate calculation private static RateCalculation parseFixedRateCalculation(CsvRow row, string leg, Currency currency, DayCount defaultFixedLegDayCount) { FixedRateCalculation.Builder builder = FixedRateCalculation.builder(); // basics double fixedRate = LoaderUtils.parseDoublePercent(getValue(row, leg, FIXED_RATE_FIELD)); DayCount dayCount = findValue(row, leg, DAY_COUNT_FIELD).map(s => LoaderUtils.parseDayCount(s)).orElse(defaultFixedLegDayCount); if (dayCount == null) { throw new System.ArgumentException("Swap leg must define day count using '" + leg + DAY_COUNT_FIELD + "'"); } builder.dayCount(dayCount); builder.rate(ValueSchedule.of(fixedRate)); // initial stub double?initialStubRateOpt = findValue(row, leg, INITIAL_STUB_RATE_FIELD).map(s => LoaderUtils.parseDoublePercent(s)); double?initialStubAmountOpt = findValue(row, leg, INITIAL_STUB_AMOUNT_FIELD).map(s => LoaderUtils.parseDouble(s)); if (initialStubRateOpt.HasValue && initialStubAmountOpt.HasValue) { throw new System.ArgumentException("Swap leg must not define both '" + leg + INITIAL_STUB_RATE_FIELD + "' and '" + leg + INITIAL_STUB_AMOUNT_FIELD + "'"); } initialStubRateOpt.ifPresent(v => builder.initialStub(FixedRateStubCalculation.ofFixedRate(v))); initialStubAmountOpt.ifPresent(v => builder.initialStub(FixedRateStubCalculation.ofKnownAmount(CurrencyAmount.of(currency, v)))); // final stub double?finalStubRateOpt = findValue(row, leg, FINAL_STUB_RATE_FIELD).map(s => LoaderUtils.parseDoublePercent(s)); double?finalStubAmountOpt = findValue(row, leg, FINAL_STUB_AMOUNT_FIELD).map(s => LoaderUtils.parseDouble(s)); if (finalStubRateOpt.HasValue && finalStubAmountOpt.HasValue) { throw new System.ArgumentException("Swap leg must not define both '" + leg + FINAL_STUB_RATE_FIELD + "' and '" + leg + FINAL_STUB_AMOUNT_FIELD + "'"); } finalStubRateOpt.ifPresent(v => builder.finalStub(FixedRateStubCalculation.ofFixedRate(v))); finalStubAmountOpt.ifPresent(v => builder.finalStub(FixedRateStubCalculation.ofKnownAmount(CurrencyAmount.of(currency, v)))); return(builder.build()); }
// Converts an FpML 'fixedRateSchedule' to a {@code RateCalculation}. private RateCalculation parseFixed(XmlElement legEl, XmlElement calcEl, XmlElement fixedEl, FpmlDocument document) { // supported elements: // 'calculationPeriodAmount/calculation/fixedRateSchedule' // 'calculationPeriodAmount/calculation/dayCountFraction' // 'stubCalculationPeriodAmount' // rejected elements: // 'resetDates' // 'stubCalculationPeriodAmount/initialStub/floatingRate' // 'stubCalculationPeriodAmount/finalStub/floatingRate' document.validateNotPresent(legEl, "resetDates"); FixedRateCalculation.Builder fixedRateBuilder = FixedRateCalculation.builder(); fixedRateBuilder.rate(parseSchedule(fixedEl, document)); fixedRateBuilder.dayCount(document.parseDayCountFraction(calcEl.getChild("dayCountFraction"))); // stub legEl.findChild("stubCalculationPeriodAmount").ifPresent(stubsEl => { stubsEl.findChild("initialStub").ifPresent(el => { fixedRateBuilder.initialStub(parseStubCalculationForFixed(el, document)); }); stubsEl.findChild("finalStub").ifPresent(el => { fixedRateBuilder.finalStub(parseStubCalculationForFixed(el, document)); }); }); return(fixedRateBuilder.build()); }
//----------------------------------------------------------------------- public virtual void fixedSwapLeg() { // a PeriodicSchedule generates a schedule of accrual periods // - interest is accrued every 3 months from 2014-02-12 to 2014-07-31 // - accrual period dates are adjusted "modified following" using the "GBLO" holiday calendar // - there will be a long initial stub // - the regular accrual period dates will be at the end-of-month PeriodicSchedule accrualSchedule = PeriodicSchedule.builder().startDate(LocalDate.of(2014, 2, 12)).endDate(LocalDate.of(2016, 7, 31)).businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, HolidayCalendarIds.GBLO)).frequency(Frequency.P3M).stubConvention(StubConvention.LONG_INITIAL).rollConvention(RollConventions.EOM).build(); // a PaymentSchedule generates a schedule of payment periods, based on the accrual schedule // - payments are every 6 months // - payments are 2 business days after the end of the period // - straight compounding is used (the payments are less frequent than the accrual, so compounding occurs) PaymentSchedule paymentSchedule = PaymentSchedule.builder().paymentFrequency(Frequency.P6M).paymentRelativeTo(PaymentRelativeTo.PERIOD_END).paymentDateOffset(DaysAdjustment.ofBusinessDays(2, HolidayCalendarIds.GBLO)).compoundingMethod(CompoundingMethod.STRAIGHT).build(); // a NotionalSchedule generates a schedule of notional amounts, based on the payment schedule // - in this simple case the notional is 1 million GBP and does not change NotionalSchedule notionalSchedule = NotionalSchedule.of(Currency.GBP, 1_000_000); // a RateCalculationSwapLeg can represent a fixed or floating swap leg // - a FixedRateCalculation is used to represent a fixed rate // - the "Act/Act ISDA" day count is used // - the rate starts at 0.8% and reduces to 0.7% RateCalculationSwapLeg swapLeg = RateCalculationSwapLeg.builder().payReceive(PayReceive.PAY).accrualSchedule(accrualSchedule).paymentSchedule(paymentSchedule).notionalSchedule(notionalSchedule).calculation(FixedRateCalculation.builder().dayCount(DayCounts.ACT_ACT_ISDA).rate(ValueSchedule.of(0.008, ValueStep.of(LocalDate.of(2015, 1, 31), ValueAdjustment.ofReplace(0.007)))).build()).build(); // a ResolvedSwapLeg has all the dates of the cash flows // it remains valid so long as the holiday calendar does not change ResolvedSwapLeg resolvedLeg = swapLeg.resolve(ReferenceData.standard()); Console.WriteLine("===== Fixed ====="); Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(swapLeg)); Console.WriteLine(); Console.WriteLine("===== Fixed resolved ====="); Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(resolvedLeg)); Console.WriteLine(); }
//------------------------------------------------------------------------- // fixed rate leg private static SwapLeg fixedLeg(LocalDate start, LocalDate end, Frequency frequency, PayReceive payReceive, NotionalSchedule notional, double fixedRate, StubConvention stubConvention) { return(RateCalculationSwapLeg.builder().payReceive(payReceive).accrualSchedule(PeriodicSchedule.builder().startDate(start).endDate(end).frequency(frequency).businessDayAdjustment(BDA_MF).stubConvention(stubConvention).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(frequency).paymentDateOffset(DaysAdjustment.NONE).build()).notionalSchedule(notional).calculation(FixedRateCalculation.builder().dayCount(THIRTY_U_360).rate(ValueSchedule.of(fixedRate)).build()).build()); }
//------------------------------------------------------------------------- public virtual void test_CompoundingOisFixed2mVsFedFund12mSwapWithFixing() { SwapLeg payLeg = RateCalculationSwapLeg.builder().payReceive(PAY).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 1, 17)).endDate(LocalDate.of(2014, 3, 17)).frequency(TERM).businessDayAdjustment(BDA_MF).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(TERM).paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)).build()).notionalSchedule(NOTIONAL).calculation(FixedRateCalculation.builder().dayCount(ACT_360).rate(ValueSchedule.of(0.00123)).build()).build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder().payReceive(RECEIVE).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 1, 17)).endDate(LocalDate.of(2014, 3, 17)).frequency(TERM).businessDayAdjustment(BDA_MF).stubConvention(StubConvention.SHORT_INITIAL).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(TERM).paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)).build()).notionalSchedule(NOTIONAL).calculation(OvernightRateCalculation.builder().dayCount(ACT_360).index(USD_FED_FUND).build()).build(); ResolvedSwapTrade trade = SwapTrade.builder().info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 1, 15)).build()).product(Swap.of(payLeg, receiveLeg)).build().resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.Amount, -7352.973875972721, TOLERANCE_PV); }
//------------------------------------------------------------------------- public virtual void test_AmortizingFixedVsLibor3mSwap() { ValueAdjustment stepReduction = ValueAdjustment.ofDeltaAmount(-3_000_000); IList <ValueStep> steps = new List <ValueStep>(); for (int i = 1; i < 28; i++) { steps.Add(ValueStep.of(i, stepReduction)); } ValueSchedule notionalSchedule = ValueSchedule.of(100_000_000, steps); SwapLeg receiveLeg = RateCalculationSwapLeg.builder().payReceive(RECEIVE).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 9, 12)).endDate(LocalDate.of(2021, 9, 12)).frequency(P3M).businessDayAdjustment(BDA_MF).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(P3M).paymentDateOffset(DaysAdjustment.NONE).build()).notionalSchedule(NotionalSchedule.of(USD, notionalSchedule)).calculation(FixedRateCalculation.builder().dayCount(THIRTY_U_360).rate(ValueSchedule.of(0.016)).build()).build(); SwapLeg payLeg = RateCalculationSwapLeg.builder().payReceive(PAY).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 9, 12)).endDate(LocalDate.of(2021, 9, 12)).frequency(P3M).businessDayAdjustment(BDA_MF).stubConvention(StubConvention.SHORT_INITIAL).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(P3M).paymentDateOffset(DaysAdjustment.NONE).build()).notionalSchedule(NotionalSchedule.of(USD, notionalSchedule)).calculation(IborRateCalculation.builder().index(USD_LIBOR_3M).fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)).build()).build(); ResolvedSwapTrade trade = SwapTrade.builder().info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()).product(Swap.of(receiveLeg, payLeg)).build().resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.Amount, -1850080.2895532502, TOLERANCE_PV); }
//------------------------------------------------------------------------- public virtual void test_ZeroCouponFixedVsLibor3mSwap() { SwapLeg payLeg = RateCalculationSwapLeg.builder().payReceive(PAY).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 9, 12)).endDate(LocalDate.of(2021, 9, 12)).frequency(P12M).businessDayAdjustment(BDA_MF).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(TERM).paymentDateOffset(DaysAdjustment.NONE).compoundingMethod(CompoundingMethod.STRAIGHT).build()).notionalSchedule(NOTIONAL).calculation(FixedRateCalculation.builder().dayCount(THIRTY_U_360).rate(ValueSchedule.of(0.015)).build()).build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder().payReceive(RECEIVE).accrualSchedule(PeriodicSchedule.builder().startDate(LocalDate.of(2014, 9, 12)).endDate(LocalDate.of(2021, 9, 12)).frequency(P3M).businessDayAdjustment(BDA_MF).stubConvention(StubConvention.SHORT_INITIAL).build()).paymentSchedule(PaymentSchedule.builder().paymentFrequency(TERM).paymentDateOffset(DaysAdjustment.NONE).compoundingMethod(CompoundingMethod.STRAIGHT).build()).notionalSchedule(NOTIONAL).calculation(IborRateCalculation.builder().index(USD_LIBOR_3M).fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)).build()).build(); ResolvedSwapTrade trade = SwapTrade.builder().info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()).product(Swap.of(payLeg, receiveLeg)).build().resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.Amount, 7850279.042216873, TOLERANCE_PV); }