@Override public void collectCurrencies(ImmutableSet.Builder<Currency> builder) { builder.add(currency); for (RatePaymentPeriod paymentPeriod : paymentPeriods) { builder.add(paymentPeriod.getCurrency()); paymentPeriod.getFxReset().ifPresent(fxr -> builder.add(fxr.getReferenceCurrency())); } paymentEvents.forEach(ev -> builder.add(ev.getCurrency())); }
@Override public double presentValue(RatePaymentPeriod period, RatesProvider provider) { // forecastValue * discountFactor double df = provider.discountFactor(period.getCurrency(), period.getPaymentDate()); return forecastValue(period, provider) * df; }
private PointSensitivityBuilder unitNotionalSensitivityNoCompounding(RatePaymentPeriod period, RatesProvider provider) { Currency ccy = period.getCurrency(); PointSensitivityBuilder sensi = PointSensitivityBuilder.none(); for (RateAccrualPeriod accrualPeriod : period.getAccrualPeriods()) { sensi = sensi.combinedWith(unitNotionalSensitivityAccrual(accrualPeriod, ccy, provider)); } return sensi; }
private double pvbpCompoundedFlat(RatePaymentPeriod paymentPeriod, RatesProvider provider) { int nbCmp = paymentPeriod.getAccrualPeriods().size(); double[] rate = paymentPeriod.getAccrualPeriods().stream() .mapToDouble(ap -> rawRate(ap, provider)) .toArray(); double df = provider.discountFactor(paymentPeriod.getCurrency(), paymentPeriod.getPaymentDate()); double rBar = 1.0; double[] cpaAccumulatedBar = new double[nbCmp + 1]; cpaAccumulatedBar[nbCmp] = paymentPeriod.getNotional() * df * rBar; double spreadBar = 0.0d; for (int j = nbCmp - 1; j >= 0; j--) { cpaAccumulatedBar[j] = (1.0d + paymentPeriod.getAccrualPeriods().get(j).getYearFraction() * rate[j] * paymentPeriod.getAccrualPeriods().get(j).getGearing()) * cpaAccumulatedBar[j + 1]; spreadBar += paymentPeriod.getAccrualPeriods().get(j).getYearFraction() * cpaAccumulatedBar[j + 1]; } return spreadBar; }
/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(RatePaymentPeriod beanToCopy) { this.paymentDate = beanToCopy.getPaymentDate(); this.accrualPeriods = beanToCopy.getAccrualPeriods(); this.dayCount = beanToCopy.getDayCount(); this.currency = beanToCopy.getCurrency(); this.fxReset = beanToCopy.fxReset; this.notional = beanToCopy.getNotional(); this.compoundingMethod = beanToCopy.getCompoundingMethod(); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1540873516: // paymentDate return ((RatePaymentPeriod) bean).getPaymentDate(); case -92208605: // accrualPeriods return ((RatePaymentPeriod) bean).getAccrualPeriods(); case 1905311443: // dayCount return ((RatePaymentPeriod) bean).getDayCount(); case 575402001: // currency return ((RatePaymentPeriod) bean).getCurrency(); case -449555555: // fxReset return ((RatePaymentPeriod) bean).fxReset; case 1585636160: // notional return ((RatePaymentPeriod) bean).getNotional(); case -1376171496: // compoundingMethod return ((RatePaymentPeriod) bean).getCompoundingMethod(); } return super.propertyGet(bean, propertyName, quiet); }
@Override public double pvbp(RatePaymentPeriod paymentPeriod, RatesProvider provider) { ArgChecker.isTrue(!paymentPeriod.getFxReset().isPresent(), "FX reset is not supported"); int accPeriodCount = paymentPeriod.getAccrualPeriods().size(); ArgChecker.isTrue(accPeriodCount == 1 || paymentPeriod.getCompoundingMethod().equals(CompoundingMethod.FLAT), "Only one accrued period or Flat compounding supported"); // no compounding if (accPeriodCount == 1) { RateAccrualPeriod accrualPeriod = paymentPeriod.getAccrualPeriods().get(0); double df = provider.discountFactor(paymentPeriod.getCurrency(), paymentPeriod.getPaymentDate()); return df * accrualPeriod.getYearFraction() * paymentPeriod.getNotional(); } else { // Flat compounding switch (paymentPeriod.getCompoundingMethod()) { case FLAT: return pvbpCompoundedFlat(paymentPeriod, provider); default: throw new UnsupportedOperationException("PVBP not implemented yet for non FLAT compounding"); } } }
@Override public PointSensitivityBuilder pvbpSensitivity(RatePaymentPeriod paymentPeriod, RatesProvider provider) { ArgChecker.isTrue(!paymentPeriod.getFxReset().isPresent(), "FX reset is not supported"); int accPeriodCount = paymentPeriod.getAccrualPeriods().size(); ArgChecker.isTrue(accPeriodCount == 1 || paymentPeriod.getCompoundingMethod().equals(CompoundingMethod.FLAT), "Only one accrued period or Flat compounding supported"); // no compounding if (accPeriodCount == 1) { RateAccrualPeriod accrualPeriod = paymentPeriod.getAccrualPeriods().get(0); DiscountFactors discountFactors = provider.discountFactors(paymentPeriod.getCurrency()); return discountFactors.zeroRatePointSensitivity(paymentPeriod.getPaymentDate()) .multipliedBy(accrualPeriod.getYearFraction() * paymentPeriod.getNotional()); } else { // Flat compounding switch (paymentPeriod.getCompoundingMethod()) { case FLAT: return pvbpSensitivtyCompoundedFlat(paymentPeriod, provider); default: throw new UnsupportedOperationException("PVBP not implemented yet for non FLAT compounding"); } } }
private PointSensitivityBuilder compoundedSpreadExclusiveSensitivity( RatePaymentPeriod paymentPeriod, RatesProvider provider) { double notionalAccrued = 1d; Currency ccy = paymentPeriod.getCurrency(); PointSensitivityBuilder sensi = PointSensitivityBuilder.none(); for (RateAccrualPeriod accrualPeriod : paymentPeriod.getAccrualPeriods()) { double investFactor = 1 + unitNotionalAccrual(accrualPeriod, 0, provider); notionalAccrued *= investFactor; PointSensitivityBuilder investFactorSensi = unitNotionalSensitivityAccrual(accrualPeriod, ccy, provider).multipliedBy(1d / investFactor); sensi = sensi.combinedWith(investFactorSensi); } return sensi.multipliedBy(notionalAccrued); }
public void test_cashFlows() { RatesProvider mockProv = mock(RatesProvider.class); SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class); double df1 = 0.98; double df2 = 0.93; double fvGBP = 1000d; double fvUSD = -500d; when(mockPeriod.forecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, mockProv)).thenReturn(fvGBP); when(mockPeriod.forecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, mockProv)).thenReturn(fvUSD); when(mockProv.getValuationDate()).thenReturn(LocalDate.of(2014, 7, 1)); when(mockProv.discountFactor(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getCurrency(), IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getPaymentDate())).thenReturn(df1); when(mockProv.discountFactor(FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getCurrency(), FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate())).thenReturn(df2); SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class); DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent); DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg); CashFlows computed = pricerSwap.cashFlows(SWAP_CROSS_CURRENCY, mockProv); CashFlow flowGBP = CashFlow.ofForecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getPaymentDate(), GBP, fvGBP, df1); CashFlow flowUSD = CashFlow.ofForecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate(), USD, fvUSD, df2); CashFlows expected = CashFlows.of(ImmutableList.of(flowGBP, flowUSD)); assertEquals(computed, expected); // test via SwapTrade DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap); assertEquals(pricerTrade.cashFlows(SWAP_TRADE, MOCK_PROV), pricerSwap.cashFlows(SWAP, MOCK_PROV)); }
private PointSensitivityBuilder compoundedStraightSensitivity( RatePaymentPeriod paymentPeriod, RatesProvider provider) { double notionalAccrued = 1d; Currency ccy = paymentPeriod.getCurrency(); PointSensitivityBuilder sensi = PointSensitivityBuilder.none(); for (RateAccrualPeriod accrualPeriod : paymentPeriod.getAccrualPeriods()) { double investFactor = 1d + unitNotionalAccrual(accrualPeriod, accrualPeriod.getSpread(), provider); notionalAccrued *= investFactor; PointSensitivityBuilder investFactorSensi = unitNotionalSensitivityAccrual(accrualPeriod, ccy, provider).multipliedBy(1d / investFactor); sensi = sensi.combinedWith(investFactorSensi); } return sensi.multipliedBy(notionalAccrued); }
public void test_explainPresentValue_single_paymentDateInPast() { SimpleRatesProvider prov = createProvider(VAL_DATE); prov.setValuationDate(VAL_DATE.plusYears(1)); DiscountingRatePaymentPeriodPricer test = DiscountingRatePaymentPeriodPricer.DEFAULT; ExplainMapBuilder builder = ExplainMap.builder(); test.explainPresentValue(PAYMENT_PERIOD_1, prov, builder); ExplainMap explain = builder.build(); Currency currency = PAYMENT_PERIOD_1.getCurrency(); assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "RatePaymentPeriod"); assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PAYMENT_PERIOD_1.getPaymentDate()); assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), currency); assertEquals(explain.get(ExplainKey.NOTIONAL).get().getCurrency(), currency); assertEquals(explain.get(ExplainKey.NOTIONAL).get().getAmount(), NOTIONAL_100, TOLERANCE_PV); assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getCurrency(), currency); assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getAmount(), NOTIONAL_100, TOLERANCE_PV); assertEquals(explain.get(ExplainKey.COMPLETED).get(), Boolean.TRUE); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), currency); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0d, TOLERANCE_PV); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), currency); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0d, TOLERANCE_PV); }
public void test_builder_twoAccrualPeriods() { RatePaymentPeriod test = RatePaymentPeriod.builder() .paymentDate(DATE_2014_10_01) .accrualPeriods(RAP1, RAP2) .dayCount(ACT_365F) .currency(GBP) .notional(1000d) .compoundingMethod(CompoundingMethod.STRAIGHT) .build(); assertEquals(test.getStartDate(), DATE_2014_03_30); assertEquals(test.getEndDate(), DATE_2014_09_30); assertEquals(test.getPaymentDate(), DATE_2014_10_01); assertEquals(test.getAccrualPeriods(), ImmutableList.of(RAP1, RAP2)); assertEquals(test.getCurrency(), GBP); assertEquals(test.getFxReset(), Optional.empty()); assertEquals(test.getNotional(), 1000d, 0d); assertEquals(test.getCompoundingMethod(), CompoundingMethod.STRAIGHT); assertEquals(test.isCompoundingApplicable(), true); }
@Override public PointSensitivityBuilder presentValueSensitivity(RatePaymentPeriod period, RatesProvider provider) { Currency ccy = period.getCurrency(); DiscountFactors discountFactors = provider.discountFactors(ccy); LocalDate paymentDate = period.getPaymentDate(); double df = discountFactors.discountFactor(paymentDate); PointSensitivityBuilder forecastSensitivity = forecastValueSensitivity(period, provider); forecastSensitivity = forecastSensitivity.multipliedBy(df); double forecastValue = forecastValue(period, provider); PointSensitivityBuilder dscSensitivity = discountFactors.zeroRatePointSensitivity(paymentDate); dscSensitivity = dscSensitivity.multipliedBy(forecastValue); return forecastSensitivity.combinedWith(dscSensitivity); }
public void test_builder_oneAccrualPeriod() { RatePaymentPeriod test = RatePaymentPeriod.builder() .paymentDate(DATE_2014_10_01) .accrualPeriods(RAP2) .dayCount(ACT_365F) .currency(GBP) .notional(1000d) .compoundingMethod(CompoundingMethod.STRAIGHT) .build(); assertEquals(test.getStartDate(), DATE_2014_06_30); assertEquals(test.getEndDate(), DATE_2014_09_30); assertEquals(test.getPaymentDate(), DATE_2014_10_01); assertEquals(test.getAccrualPeriods(), ImmutableList.of(RAP2)); assertEquals(test.getCurrency(), GBP); assertEquals(test.getFxReset(), Optional.empty()); assertEquals(test.getNotional(), 1000d, 0d); assertEquals(test.getNotionalAmount(), CurrencyAmount.of(GBP, 1000d)); assertEquals(test.getCompoundingMethod(), CompoundingMethod.STRAIGHT); assertEquals(test.isCompoundingApplicable(), false); }
public void test_builder_twoAccrualPeriods_compoundingDefaultedToNone_fxReset() { RatePaymentPeriod test = RatePaymentPeriod.builder() .paymentDate(DATE_2014_10_01) .accrualPeriods(RAP1, RAP2) .dayCount(ACT_365F) .currency(GBP) .fxReset(FX_RESET_USD) .notional(1000d) .compoundingMethod(CompoundingMethod.NONE) .build(); assertEquals(test.getStartDate(), DATE_2014_03_30); assertEquals(test.getEndDate(), DATE_2014_09_30); assertEquals(test.getPaymentDate(), DATE_2014_10_01); assertEquals(test.getAccrualPeriods(), ImmutableList.of(RAP1, RAP2)); assertEquals(test.getCurrency(), GBP); assertEquals(test.getFxReset(), Optional.of(FX_RESET_USD)); assertEquals(test.getNotional(), 1000d, 0d); assertEquals(test.getNotionalAmount(), CurrencyAmount.of(USD, 1000d)); assertEquals(test.isCompoundingApplicable(), false); }
@Override public MultiCurrencyAmount currencyExposure(RatePaymentPeriod period, RatesProvider provider) { double df = provider.discountFactor(period.getCurrency(), period.getPaymentDate()); if (period.getFxReset().isPresent()) { FxReset fxReset = period.getFxReset().get(); LocalDate fixingDate = fxReset.getObservation().getFixingDate(); FxIndexRates rates = provider.fxIndexRates(fxReset.getObservation().getIndex()); if (!fixingDate.isAfter(provider.getValuationDate()) && rates.getFixings().get(fixingDate).isPresent()) { double fxRate = rates.rate(fxReset.getObservation(), fxReset.getReferenceCurrency()); return MultiCurrencyAmount.of(period.getCurrency(), accrualWithNotional(period, period.getNotional() * fxRate * df, provider)); } double fxRateSpotSensitivity = rates.getFxForwardRates() .rateFxSpotSensitivity(fxReset.getReferenceCurrency(), fxReset.getObservation().getMaturityDate()); return MultiCurrencyAmount.of(fxReset.getReferenceCurrency(), accrualWithNotional(period, period.getNotional() * fxRateSpotSensitivity * df, provider)); } return MultiCurrencyAmount.of(period.getCurrency(), accrualWithNotional(period, period.getNotional() * df, provider)); }
public void test_currencyExposure_single() { DiscountingRatePaymentPeriodPricer pricer = DiscountingRatePaymentPeriodPricer.DEFAULT; ImmutableRatesProvider provider = MULTI_GBP_USD; MultiCurrencyAmount computed = pricer.currencyExposure(PAYMENT_PERIOD_COMPOUNDING_STRAIGHT, provider); PointSensitivities point = pricer.presentValueSensitivity(PAYMENT_PERIOD_COMPOUNDING_STRAIGHT, provider).build(); MultiCurrencyAmount expected = provider.currencyExposure(point) .plus(CurrencyAmount.of(PAYMENT_PERIOD_COMPOUNDING_STRAIGHT.getCurrency(), pricer.presentValue(PAYMENT_PERIOD_COMPOUNDING_STRAIGHT, provider))); assertEquals(computed.size(), expected.size()); assertEquals(computed.getAmount(USD).getAmount(), expected.getAmount(USD).getAmount(), TOLERANCE_PV); }
private PointSensitivityBuilder compoundedFlatSensitivity( RatePaymentPeriod paymentPeriod, RatesProvider provider) { double cpaAccumulated = 0d; Currency ccy = paymentPeriod.getCurrency(); PointSensitivityBuilder sensiAccumulated = PointSensitivityBuilder.none(); for (RateAccrualPeriod accrualPeriod : paymentPeriod.getAccrualPeriods()) { double rate = rawRate(accrualPeriod, provider); double accrualZeroSpread = unitNotionalAccrualRaw(accrualPeriod, rate, 0); PointSensitivityBuilder sensiCp = sensiAccumulated.cloned(); sensiCp = sensiCp.multipliedBy(accrualZeroSpread); PointSensitivityBuilder sensi2 = unitNotionalSensitivityAccrual(accrualPeriod, ccy, provider).multipliedBy(1d + cpaAccumulated); cpaAccumulated += cpaAccumulated * accrualZeroSpread + unitNotionalAccrualRaw(accrualPeriod, rate, accrualPeriod.getSpread()); sensiCp = sensiCp.combinedWith(sensi2); sensiAccumulated = sensiAccumulated.combinedWith(sensiCp).normalize(); } return sensiAccumulated; }
public void test_currencyExposure_fx() { DiscountingRatePaymentPeriodPricer pricer = DiscountingRatePaymentPeriodPricer.DEFAULT; LocalDate valuationDate = VAL_DATE.minusWeeks(1); ImmutableRatesProvider provider = RatesProviderDataSets.multiGbpUsd(valuationDate); // USD MultiCurrencyAmount computedUSD = pricer.currencyExposure(PAYMENT_PERIOD_FULL_GS_FX_USD, provider); PointSensitivities pointUSD = pricer.presentValueSensitivity(PAYMENT_PERIOD_FULL_GS_FX_USD, provider).build(); MultiCurrencyAmount expectedUSD = provider.currencyExposure(pointUSD.convertedTo(GBP, provider)).plus(CurrencyAmount.of( PAYMENT_PERIOD_FULL_GS_FX_USD.getCurrency(), pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_USD, provider))); assertEquals(computedUSD.getAmount(GBP).getAmount(), expectedUSD.getAmount(GBP).getAmount(), TOLERANCE_PV); assertFalse(computedUSD.contains(USD)); // 0 USD // GBP MultiCurrencyAmount computedGBP = pricer.currencyExposure(PAYMENT_PERIOD_FULL_GS_FX_GBP, provider); PointSensitivities pointGBP = pricer.presentValueSensitivity(PAYMENT_PERIOD_FULL_GS_FX_GBP, provider).build(); MultiCurrencyAmount expectedGBP = provider.currencyExposure(pointGBP.convertedTo(USD, provider)).plus(CurrencyAmount.of( PAYMENT_PERIOD_FULL_GS_FX_GBP.getCurrency(), pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_GBP, provider))); assertEquals(computedGBP.getAmount(USD).getAmount(), expectedGBP.getAmount(USD).getAmount(), TOLERANCE_PV); assertFalse(computedGBP.contains(GBP)); // 0 GBP // FD approximation ImmutableRatesProvider provUp = RatesProviderDataSets.multiGbpUsd(valuationDate).toBuilder() .fxRateProvider(FX_MATRIX_BUMP) .build(); double expectedFdUSD = (pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_USD, provUp) - pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_USD, provider)) / EPS_FD; assertEquals(computedUSD.getAmount(GBP).getAmount(), expectedFdUSD, EPS_FD * NOTIONAL_100); double expectedFdGBP = -(pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_GBP, provUp) - pricer.presentValue(PAYMENT_PERIOD_FULL_GS_FX_GBP, provider)) * FX_RATE * FX_RATE / EPS_FD; assertEquals(computedGBP.getAmount(USD).getAmount(), expectedFdGBP, EPS_FD * NOTIONAL_100); }