public void test_builder() { ResolvedSwapLeg test = ResolvedSwapLeg.builder() .type(IBOR) .payReceive(RECEIVE) .paymentPeriods(RPP1) .paymentEvents(NOTIONAL_EXCHANGE) .build(); assertEquals(test.getType(), IBOR); assertEquals(test.getPayReceive(), RECEIVE); assertEquals(test.getStartDate(), DATE_2014_06_30); assertEquals(test.getEndDate(), DATE_2014_09_30); assertEquals(test.getCurrency(), GBP); assertEquals(test.getPaymentPeriods(), ImmutableList.of(RPP1)); assertEquals(test.getPaymentEvents(), ImmutableList.of(NOTIONAL_EXCHANGE)); }
/** * Calculates the accrued interest since the last payment. * <p> * This determines the payment period applicable at the valuation date and calculates * the accrued interest since the last payment. * The result is returned using the payment currency of the leg. * * @param leg the leg * @param provider the rates provider * @return the accrued interest of the swap leg */ public CurrencyAmount accruedInterest(ResolvedSwapLeg leg, RatesProvider provider) { Optional<SwapPaymentPeriod> period = leg.findPaymentPeriod(provider.getValuationDate()); if (period.isPresent()) { double accruedInterest = paymentPeriodPricer.accruedInterest(period.get(), provider); return CurrencyAmount.of(leg.getCurrency(), accruedInterest); } return CurrencyAmount.zero(leg.getCurrency()); }
private static ImmutableSet<Index> buildIndices(List<ResolvedSwapLeg> legs) { // avoid streams as profiling showed a hotspot ImmutableSet.Builder<Index> builder = ImmutableSet.builder(); for (ResolvedSwapLeg leg : legs) { leg.collectIndices(builder); } return builder.build(); }
/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ResolvedSwapLeg beanToCopy) { this.type = beanToCopy.getType(); this.payReceive = beanToCopy.getPayReceive(); this.paymentPeriods = beanToCopy.getPaymentPeriods(); this.paymentEvents = beanToCopy.getPaymentEvents(); }
/** * Obtains an instance from a swap leg and amount. * * @param leg the swap leg * @param amount the amount * @return the swap leg amount */ public static SwapLegAmount of(ResolvedSwapLeg leg, CurrencyAmount amount) { return builder() .amount(amount) .payReceive(leg.getPayReceive()) .type(leg.getType()) .currency(leg.getCurrency()) .build(); }
/** * Calculates the present value of the swaption. * <p> * The result is expressed using the currency of the swaption. * * @param swaption the swaption * @param ratesProvider the rates provider * @param swaptionVolatilities the volatilities * @return the present value */ public CurrencyAmount presentValue( ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.getExpiry()); ResolvedSwap underlying = swaption.getUnderlying(); ResolvedSwapLeg fixedLeg = fixedLeg(underlying); if (expiry < 0d) { // Option has expired already return CurrencyAmount.of(fixedLeg.getCurrency(), 0d); } double forward = swapPricer.parRate(underlying, ratesProvider); double numeraire = calculateNumeraire(swaption, fixedLeg, forward, ratesProvider); double strike = calculateStrike(fixedLeg); double tenor = swaptionVolatilities.tenor(fixedLeg.getStartDate(), fixedLeg.getEndDate()); double volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward); PutCall putCall = PutCall.ofPut(fixedLeg.getPayReceive().isReceive()); double price = numeraire * swaptionVolatilities.price(expiry, tenor, putCall, strike, forward, volatility); return CurrencyAmount.of(fixedLeg.getCurrency(), price * swaption.getLongShort().sign()); }
ArgChecker.isTrue(fixedLeg.getType().equals(SwapLegType.FIXED), "Leg type should be FIXED"); ArgChecker.isTrue(fixedLeg.getPaymentEvents().isEmpty(), "PaymentEvent should be empty"); List<NotionalExchange> paymentEvents = new ArrayList<NotionalExchange>(); for (SwapPaymentPeriod paymentPeriod : fixedLeg.getPaymentPeriods()) { ArgChecker.isTrue(paymentPeriod instanceof RatePaymentPeriod, "rate payment should be RatePaymentPeriod"); RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod) paymentPeriod; paymentEvents.add(pay); ResolvedSwapLeg leg = ResolvedSwapLeg.builder() .paymentEvents(paymentEvents) .payReceive(PayReceive.RECEIVE)
private Optional<FixedOvernightCompoundedAnnualRateComputation> findAnnualRateComputation(ResolvedSwapLeg fixedLeg) { SwapPaymentPeriod firstPeriod = fixedLeg.getPaymentPeriods().get(0); if (firstPeriod instanceof RatePaymentPeriod) { RatePaymentPeriod payment = (RatePaymentPeriod) firstPeriod; RateAccrualPeriod firstAccrualPeriod = payment.getAccrualPeriods().get(0); if (firstAccrualPeriod.getRateComputation() instanceof FixedOvernightCompoundedAnnualRateComputation) { return Optional.of((FixedOvernightCompoundedAnnualRateComputation) firstAccrualPeriod.getRateComputation()); } } return Optional.empty(); }
/** * Computes cash flow equivalent and sensitivity of fixed leg. * <p> * The return type is a map of {@code NotionalExchange} and {@code PointSensitivityBuilder}. * * @param fixedLeg the fixed leg * @param ratesProvider the rates provider * @return the cash flow equivalent and sensitivity */ public static ImmutableMap<Payment, PointSensitivityBuilder> cashFlowEquivalentAndSensitivityFixedLeg( ResolvedSwapLeg fixedLeg, RatesProvider ratesProvider) { ArgChecker.isTrue(fixedLeg.getType().equals(SwapLegType.FIXED), "Leg type should be FIXED"); ArgChecker.isTrue(fixedLeg.getPaymentEvents().isEmpty(), "PaymentEvent should be empty"); Map<Payment, PointSensitivityBuilder> res = new HashMap<Payment, PointSensitivityBuilder>(); for (SwapPaymentPeriod paymentPeriod : fixedLeg.getPaymentPeriods()) { ArgChecker.isTrue(paymentPeriod instanceof RatePaymentPeriod, "rate payment should be RatePaymentPeriod"); RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod) paymentPeriod; ArgChecker.isTrue(ratePaymentPeriod.getAccrualPeriods().size() == 1, "rate payment should not be compounding"); RateAccrualPeriod rateAccrualPeriod = ratePaymentPeriod.getAccrualPeriods().get(0); double factor = rateAccrualPeriod.getYearFraction() * ((FixedRateComputation) rateAccrualPeriod.getRateComputation()).getRate(); CurrencyAmount notional = ratePaymentPeriod.getNotionalAmount().multipliedBy(factor); LocalDate paymentDate = ratePaymentPeriod.getPaymentDate(); Payment pay = Payment.of(notional, paymentDate); res.put(pay, PointSensitivityBuilder.none()); } return ImmutableMap.copyOf(res); }
private PointSensitivityBuilder legValueSensitivity( ResolvedSwapLeg leg, RatesProvider provider, BiFunction<SwapPaymentPeriod, RatesProvider, PointSensitivityBuilder> periodFn, BiFunction<SwapPaymentEvent, RatesProvider, PointSensitivityBuilder> eventFn) { PointSensitivityBuilder builder = PointSensitivityBuilder.none(); for (SwapPaymentPeriod period : leg.getPaymentPeriods()) { if (!period.getPaymentDate().isBefore(provider.getValuationDate())) { builder = builder.combinedWith(periodFn.apply(period, provider)); } } for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { builder = builder.combinedWith(eventFn.apply(event, provider)); } } return builder; }
private static ImmutableSet<Currency> buildCurrencies(List<ResolvedSwapLeg> legs) { // avoid streams as profiling showed a hotspot ImmutableSet.Builder<Currency> builder = ImmutableSet.builder(); for (ResolvedSwapLeg leg : legs) { builder.add(leg.getCurrency()); } return builder.build(); }
LocalDate expiryDate = swaption.getExpiryDate(); if (expiryDate.isBefore(ratesProvider.getValuationDate())) { // Option has expired already return CurrencyAmount.of(swap.getLegs().get(0).getCurrency(), 0d); int nPayments = cashFlowEquiv.getPaymentEvents().size(); double[] alpha = new double[nPayments]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { NotionalExchange payment = (NotionalExchange) cashFlowEquiv.getPaymentEvents().get(loopcf); LocalDate maturityDate = payment.getPaymentDate(); alpha[loopcf] = hwProvider.alpha(ratesProvider.getValuationDate(), expiryDate, expiryDate, maturityDate); discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.getPayment(), ratesProvider); double omega = (swap.getLegs(SwapLegType.FIXED).get(0).getPayReceive().isPay() ? -1d : 1d); double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega); double pv = 0.0; pv += discountedCashFlow[loopcf] * NORMAL.getCDF(omega * (kappa + alpha[loopcf])); return CurrencyAmount.of(cashFlowEquiv.getCurrency(), pv * (swaption.getLongShort().isLong() ? 1d : -1d));
public void test_annuityCash_twoPeriods() { ResolvedSwapLeg leg = ResolvedSwapLeg.builder() .type(FIXED) .payReceive(PAY) .paymentPeriods(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2) .build(); double yield = 0.01; DiscountingSwapLegPricer test = DiscountingSwapLegPricer.DEFAULT; double computed = test.annuityCash(leg, yield); double expected = SwapDummyData.NOTIONAL * (1d - Math.pow(1d + yield / 4d, -2)) / yield; assertEquals(computed, expected, SwapDummyData.NOTIONAL * TOLERANCE); }
public void test_currentCash_payPeriod() { ResolvedSwapLeg expSwapLeg = FIXED_SWAP_LEG_PAY_USD; LocalDate paymentDate = expSwapLeg.getPaymentPeriods().get(0).getPaymentDate(); RatesProvider prov = new MockRatesProvider(paymentDate); SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class); double expected = 1234d; when(mockPeriod.currentCash(expSwapLeg.getPaymentPeriods().get(0), prov)).thenReturn(expected); DiscountingSwapLegPricer pricer = new DiscountingSwapLegPricer(mockPeriod, SwapPaymentEventPricer.standard()); CurrencyAmount computed = pricer.currentCash(expSwapLeg, prov); assertEquals(computed, CurrencyAmount.of(expSwapLeg.getCurrency(), expected)); }
double presentValueEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { double total = 0d; for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { total += paymentEventPricer.presentValue(event, provider); } } return total; }
public void test_currentCash_payEvent() { ResolvedSwapLeg expSwapLeg = FIXED_SWAP_LEG_PAY_USD; LocalDate paymentDate = expSwapLeg.getPaymentEvents().get(0).getPaymentDate(); RatesProvider prov = new MockRatesProvider(paymentDate); SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class); double expected = 1234d; when(mockEvent.currentCash(expSwapLeg.getPaymentEvents().get(0), prov)).thenReturn(expected); DiscountingSwapLegPricer pricer = new DiscountingSwapLegPricer(SwapPaymentPeriodPricer.standard(), mockEvent); CurrencyAmount computed = pricer.currentCash(expSwapLeg, prov); assertEquals(computed, CurrencyAmount.of(expSwapLeg.getCurrency(), expected)); }
/** * Gets the first pay or receive leg of the swap. * <p> * This returns the first pay or receive leg of the swap, empty if no matching leg. * * @param payReceive the pay or receive flag * @return the first matching leg of the swap */ public Optional<ResolvedSwapLeg> getLeg(PayReceive payReceive) { return legs.stream().filter(leg -> leg.getPayReceive() == payReceive).findFirst(); }
/** * Computes cash flow equivalent of swap. * <p> * The swap should be a fix-for-Ibor swap without compounding, and its swap legs * should not involve {@code PaymentEvent}. * <p> * The return type is {@code ResolvedSwapLeg} in which individual payments are * represented in terms of {@code NotionalExchange}. * * @param swap the swap product * @param ratesProvider the rates provider * @return the cash flow equivalent */ public static ResolvedSwapLeg cashFlowEquivalentSwap(ResolvedSwap swap, RatesProvider ratesProvider) { validateSwap(swap); ResolvedSwapLeg cfFixed = cashFlowEquivalentFixedLeg(swap.getLegs(SwapLegType.FIXED).get(0), ratesProvider); ResolvedSwapLeg cfIbor = cashFlowEquivalentIborLeg(swap.getLegs(SwapLegType.IBOR).get(0), ratesProvider); ResolvedSwapLeg leg = ResolvedSwapLeg.builder() .paymentEvents( Stream.concat(cfFixed.getPaymentEvents().stream(), cfIbor.getPaymentEvents().stream()).collect(Collectors.toList())) .payReceive(PayReceive.RECEIVE) .type(SwapLegType.OTHER) .build(); return leg; }
ResolvedSwap underlying = swaption.getUnderlying(); ResolvedSwapLeg fixedLeg = fixedLeg(underlying); double tenor = swaptionVolatilities.tenor(fixedLeg.getStartDate(), fixedLeg.getEndDate()); double shift = swaptionVolatilities.shift(expiry, tenor); double strike = calculateStrike(fixedLeg); BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility); Currency ccy = fixedLeg.getCurrency(); SwaptionVolatilitiesName name = swaptionVolatilities.getName(); return PointSensitivityBuilder.of(
public void test_findPaymentPeriod() { ResolvedSwapLeg test = ResolvedSwapLeg.builder() .type(IBOR) .payReceive(RECEIVE) .paymentPeriods(RPP1, RPP2) .build(); assertEquals(test.findPaymentPeriod(RPP1.getStartDate()), Optional.empty()); assertEquals(test.findPaymentPeriod(RPP1.getStartDate().plusDays(1)), Optional.of(RPP1)); assertEquals(test.findPaymentPeriod(RPP1.getEndDate()), Optional.of(RPP1)); assertEquals(test.findPaymentPeriod(RPP2.getStartDate()), Optional.of(RPP1)); assertEquals(test.findPaymentPeriod(RPP2.getStartDate().plusDays(1)), Optional.of(RPP2)); assertEquals(test.findPaymentPeriod(RPP2.getEndDate()), Optional.of(RPP2)); assertEquals(test.findPaymentPeriod(RPP2.getEndDate().plusDays(1)), Optional.empty()); }