/** * 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(); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3575610: // type return ((ResolvedSwapLeg) bean).getType(); case -885469925: // payReceive return ((ResolvedSwapLeg) bean).getPayReceive(); case -1674414612: // paymentPeriods return ((ResolvedSwapLeg) bean).getPaymentPeriods(); case 1031856831: // paymentEvents return ((ResolvedSwapLeg) bean).getPaymentEvents(); } return super.propertyGet(bean, propertyName, quiet); }
/** * 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; }
double forecastValueEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { double total = 0d; for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { total += paymentEventPricer.forecastValue(event, provider); } } return total; }
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; }
private double currentCashEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { double total = 0d; for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { total += paymentEventPricer.currentCash(event, provider); } } return total; } }
CashFlows cashFlowEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { ImmutableList.Builder<CashFlow> builder = ImmutableList.builder(); for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { double forecastValue = paymentEventPricer.forecastValue(event, provider); if (forecastValue != 0d) { Currency currency = event.getCurrency(); LocalDate paymentDate = event.getPaymentDate(); double discountFactor = provider.discountFactor(currency, paymentDate); CashFlow singleCashFlow = CashFlow.ofForecastValue(paymentDate, currency, forecastValue, discountFactor); builder.add(singleCashFlow); } } } return CashFlows.of(builder.build()); }
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)); }
private MultiCurrencyAmount currencyExposureEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { MultiCurrencyAmount total = MultiCurrencyAmount.empty(); for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { total = total.plus(paymentEventPricer.currencyExposure(event, provider)); } } return total; }
PointSensitivityBuilder presentValueSensitivityEventsInternal(ResolvedSwapLeg leg, RatesProvider provider) { PointSensitivityBuilder builder = PointSensitivityBuilder.none(); for (SwapPaymentEvent event : leg.getPaymentEvents()) { if (!event.getPaymentDate().isBefore(provider.getValuationDate())) { builder = builder.combinedWith(paymentEventPricer.presentValueSensitivity(event, provider)); } } return builder; }
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; }
public void test_forecastValueSensitivity() { ResolvedSwapLeg expSwapLeg = IBOR_SWAP_LEG_REC_GBP; PointSensitivityBuilder sensiPeriod = IborRateSensitivity.of(IBOR_RATE_COMP.getObservation(), 140.0); PointSensitivities expected = sensiPeriod.build(); SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class); SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class); when(mockPeriod.forecastValueSensitivity(expSwapLeg.getPaymentPeriods().get(0), MOCK_PROV)) .thenReturn(sensiPeriod); when(mockEvent.forecastValueSensitivity(expSwapLeg.getPaymentEvents().get(0), MOCK_PROV)) .thenReturn(PointSensitivityBuilder.none()); DiscountingSwapLegPricer test = new DiscountingSwapLegPricer(mockPeriod, mockEvent); PointSensitivities res = test.forecastValueSensitivity(expSwapLeg, MOCK_PROV).build(); assertTrue(res.equalWithTolerance(expected, TOLERANCE)); }
/** * 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); }
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)); }
public void test_cashFlowEquivalentAndSensitivity() { ResolvedSwap swap = ResolvedSwap.of(IBOR_LEG, FIXED_LEG); ImmutableMap<Payment, PointSensitivityBuilder> computedFull = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap, PROVIDER); ImmutableList<Payment> keyComputedFull = computedFull.keySet().asList(); ImmutableList<PointSensitivityBuilder> valueComputedFull = computedFull.values().asList(); ImmutableMap<Payment, PointSensitivityBuilder> computedIborLeg = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityIborLeg(IBOR_LEG, PROVIDER); ImmutableMap<Payment, PointSensitivityBuilder> computedFixedLeg = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityFixedLeg(FIXED_LEG, PROVIDER); assertEquals(computedFixedLeg.keySet().asList(), keyComputedFull.subList(0, 2)); assertEquals(computedIborLeg.keySet().asList(), keyComputedFull.subList(2, 6)); assertEquals(computedFixedLeg.values().asList(), valueComputedFull.subList(0, 2)); assertEquals(computedIborLeg.values().asList(), valueComputedFull.subList(2, 6)); double eps = 1.0e-7; RatesFiniteDifferenceSensitivityCalculator calc = new RatesFiniteDifferenceSensitivityCalculator(eps); int size = keyComputedFull.size(); for (int i = 0; i < size; ++i) { final int index = i; CurrencyParameterSensitivities expected = calc.sensitivity(PROVIDER, p -> ((NotionalExchange) CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, p) .getPaymentEvents().get(index)).getPaymentAmount()); SwapPaymentEvent event = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, PROVIDER).getPaymentEvents().get(index); PointSensitivityBuilder point = computedFull.get(((NotionalExchange) event).getPayment()); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point.build()); assertTrue(computed.equalWithTolerance(expected, eps * NOTIONAL)); } }
public void test_presentValueSensitivity() { ResolvedSwapLeg expSwapLeg = IBOR_SWAP_LEG_REC_GBP; Currency ccy = GBP_LIBOR_3M.getCurrency(); IborRateSensitivity fwdSense = IborRateSensitivity.of(IBOR_RATE_COMP.getObservation(), 140.0); ZeroRateSensitivity dscSense = ZeroRateSensitivity.of(ccy, 3d, -162.0); PointSensitivityBuilder sensiPeriod = fwdSense.combinedWith(dscSense); PointSensitivityBuilder sensiEvent = ZeroRateSensitivity.of(ccy, 4d, -134.0); PointSensitivities expected = sensiPeriod.build().combinedWith(sensiEvent.build()); SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class); SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class); when(mockPeriod.presentValueSensitivity(expSwapLeg.getPaymentPeriods().get(0), MOCK_PROV)) .thenReturn(sensiPeriod); when(mockEvent.presentValueSensitivity(expSwapLeg.getPaymentEvents().get(0), MOCK_PROV)) .thenReturn(sensiEvent); DiscountingSwapLegPricer test = new DiscountingSwapLegPricer(mockPeriod, mockEvent); PointSensitivities res = test.presentValueSensitivity(expSwapLeg, MOCK_PROV).build(); assertTrue(res.equalWithTolerance(expected, TOLERANCE)); }
public void test_forecastValueSensitivity() { // ibor leg PointSensitivityBuilder sensiFloating = IborRateSensitivity.of(IBOR_RATE_COMP.getObservation(), GBP, 140.0); // fixed leg PointSensitivityBuilder sensiFixed = PointSensitivityBuilder.none(); // events PointSensitivityBuilder sensiEvent = PointSensitivityBuilder.none(); PointSensitivities expected = sensiFloating.build(); SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class); SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class); when(mockPeriod.forecastValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentPeriods().get(0), MOCK_PROV)) .thenAnswer(t -> sensiFloating.build().toMutable()); when(mockPeriod.forecastValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentPeriods().get(0), MOCK_PROV)) .thenAnswer(t -> sensiFixed.build().toMutable()); when(mockEvent.forecastValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentEvents().get(0), MOCK_PROV)) .thenAnswer(t -> sensiEvent.build().toMutable()); when(mockEvent.forecastValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentEvents().get(0), MOCK_PROV)) .thenAnswer(t -> sensiEvent.build().toMutable()); DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent); DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg); PointSensitivities res = pricerSwap.forecastValueSensitivity(SWAP, MOCK_PROV).build(); assertTrue(res.equalWithTolerance(expected, TOLERANCE_RATE)); // test via SwapTrade DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap); assertEquals( pricerTrade.forecastValueSensitivity(SWAP_TRADE, MOCK_PROV), pricerSwap.forecastValueSensitivity(SWAP, MOCK_PROV).build()); }
public void test_presentValue() { CurrencyAmount computedRec = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER); CurrencyAmount computedPay = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER); SwapPaymentEventPricer<SwapPaymentEvent> paymentEventPricer = SwapPaymentEventPricer.standard(); ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(RSWAP_REC, RATE_PROVIDER); LocalDate expiryDate = MATURITY.toLocalDate(); int nPayments = cashFlowEquiv.getPaymentEvents().size(); double[] alpha = new double[nPayments]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { SwapPaymentEvent payment = cashFlowEquiv.getPaymentEvents().get(loopcf); alpha[loopcf] = HW_PROVIDER.alpha(RATE_PROVIDER.getValuationDate(), expiryDate, expiryDate, payment.getPaymentDate()); discountedCashFlow[loopcf] = paymentEventPricer.presentValue(payment, RATE_PROVIDER); } double omegaPay = -1d; double kappa = HW_PROVIDER.getModel().kappa(DoubleArray.copyOf(discountedCashFlow), DoubleArray.copyOf(alpha)); double expectedRec = 0.0; double expectedPay = 0.0; for (int loopcf = 0; loopcf < nPayments; loopcf++) { expectedRec += discountedCashFlow[loopcf] * NORMAL.getCDF((kappa + alpha[loopcf])); expectedPay += discountedCashFlow[loopcf] * NORMAL.getCDF(omegaPay * (kappa + alpha[loopcf])); } assertEquals(computedRec.getCurrency(), EUR); assertEquals(computedRec.getAmount(), expectedRec, NOTIONAL * TOL); assertEquals(computedPay.getCurrency(), EUR); assertEquals(computedPay.getAmount(), expectedPay, NOTIONAL * TOL); }
@ImmutableValidator private void validate() { ArgChecker.inOrderOrEqual(deliveryDate, underlyingSwap.getStartDate(), "deliveryDate", "startDate"); ArgChecker.isFalse(underlyingSwap.isCrossCurrency(), "underlying swap must not be cross currency"); for (ResolvedSwapLeg swapLeg : underlyingSwap.getLegs()) { if (swapLeg.getType().equals(SwapLegType.FIXED)) { ArgChecker.isTrue(swapLeg.getPayReceive().isReceive(), "underlying must be receiver swap"); } for (SwapPaymentEvent event : swapLeg.getPaymentEvents()) { ArgChecker.isTrue(event instanceof NotionalExchange, "PaymentEvent must be NotionalExchange"); NotionalExchange notioanlEvent = (NotionalExchange) event; ArgChecker.isTrue(Math.abs(notioanlEvent.getPaymentAmount().getAmount()) == 1d, "notional of underlying swap must be unity"); } for (SwapPaymentPeriod period : swapLeg.getPaymentPeriods()) { ArgChecker.isTrue(period instanceof NotionalPaymentPeriod, "PaymentPeriod must be NotionalPaymentPeriod"); NotionalPaymentPeriod notioanlPeriod = (NotionalPaymentPeriod) period; ArgChecker.isTrue(Math.abs(notioanlPeriod.getNotionalAmount().getAmount()) == 1d, "notional of underlying swap must be unity"); } } ArgChecker.inOrderOrEqual(lastTradeDate, deliveryDate, "lastTradeDate", "deliveryDate"); }
/** * Explain present value builder used to build large explain map from the individual legs. * * @param leg the swap log * @param provider the rates provider * @param builder the explain map builder which will be populated but the leg */ void explainPresentValueInternal(ResolvedSwapLeg leg, RatesProvider provider, ExplainMapBuilder builder) { builder.put(ExplainKey.ENTRY_TYPE, "Leg"); builder.put(ExplainKey.PAY_RECEIVE, leg.getPayReceive()); builder.put(ExplainKey.LEG_TYPE, leg.getType().toString()); for (SwapPaymentPeriod period : leg.getPaymentPeriods()) { builder.addListEntry( ExplainKey.PAYMENT_PERIODS, child -> paymentPeriodPricer.explainPresentValue(period, provider, child)); } for (SwapPaymentEvent event : leg.getPaymentEvents()) { builder.addListEntry( ExplainKey.PAYMENT_EVENTS, child -> paymentEventPricer.explainPresentValue(event, provider, child)); } builder.put(ExplainKey.FORECAST_VALUE, forecastValue(leg, provider)); builder.put(ExplainKey.PRESENT_VALUE, presentValue(leg, provider)); }