private double unitNotionalAccrualRaw(RateAccrualPeriod accrualPeriod, double rawRate, double spread) { double treatedRate = rawRate * accrualPeriod.getGearing() + spread; return accrualPeriod.getNegativeRateMethod().adjust(treatedRate * accrualPeriod.getYearFraction()); }
private double compoundedSpreadExclusive(RatePaymentPeriod paymentPeriod, double notional, RatesProvider provider) { double notionalAccrued = notional; double spreadAccrued = 0; for (RateAccrualPeriod accrualPeriod : paymentPeriod.getAccrualPeriods()) { double investFactor = 1 + unitNotionalAccrual(accrualPeriod, 0, provider); notionalAccrued *= investFactor; spreadAccrued += notional * accrualPeriod.getSpread() * accrualPeriod.getYearFraction(); } return (notionalAccrued - notional + spreadAccrued); }
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; }
public void test_pvbp_onePeriod() { RatesProvider mockProv = mock(RatesProvider.class); double df = 0.99d; when(mockProv.discountFactor(USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate())) .thenReturn(df); double expected = df * FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getNotional() * FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getAccrualPeriods().get(0).getYearFraction(); DiscountingSwapLegPricer test = DiscountingSwapLegPricer.DEFAULT; assertEquals(test.pvbp(FIXED_SWAP_LEG_PAY_USD, mockProv), expected, TOLERANCE); }
private PointSensitivityBuilder unitNotionalSensitivityAccrual( RateAccrualPeriod period, Currency ccy, RatesProvider provider) { PointSensitivityBuilder sensi = rateComputationFn.rateSensitivity( period.getRateComputation(), period.getStartDate(), period.getEndDate(), provider); return sensi.multipliedBy(period.getGearing() * period.getYearFraction()); }
RateAccrualPeriod accrualPeriod = paymentPeriod.getAccrualPeriods().get(j); cpaAccumulatedB1[j] = (1.0d + accrualPeriod.getYearFraction() * rate[j] * accrualPeriod.getGearing()) * cpaAccumulatedB1[j + 1]; for (int j = 0; j < nbCmp; j++) { RateAccrualPeriod accrualPeriod = paymentPeriod.getAccrualPeriods().get(j); cpaAccumulatedB1B2[j + 1] += accrualPeriod.getYearFraction() * pvbpB2; cpaAccumulatedB1B2[j + 1] += (1.0d + accrualPeriod.getYearFraction() * rate[j] * accrualPeriod.getGearing()) * cpaAccumulatedB1B2[j]; rateB2[j] += accrualPeriod.getYearFraction() * accrualPeriod.getGearing() * cpaAccumulatedB1[j + 1] * cpaAccumulatedB1B2[j];
@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"); } } }
return Triple.of(false, 0, 0.0d); // Should have a gearing of 1. if (accrualPeriods.get(i).getYearFraction() != 1.0d) { return Triple.of(false, 0, 0.0d); // Should have a year fraction of 1.
@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"); } } }
this.nbFixedPeriod = fixedLeg.getPaymentPeriods().size(); this.nbFixedPaymentYear = (int) Math.round(1d / ((RatePaymentPeriod) fixedLeg.getPaymentPeriods().get(0)).getAccrualPeriods().get(0).getYearFraction()); this.tau = 1d / nbFixedPaymentYear; this.eta = eta;
/** * 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_schedulePeriod() { SchedulePeriod schedulePeriod = SchedulePeriod.of(DATE_2014_03_31, DATE_2014_07_01, DATE_2014_03_30, DATE_2014_06_30); RateAccrualPeriod test = RateAccrualPeriod.builder(schedulePeriod) .yearFraction(0.25d) .rateComputation(GBP_LIBOR_3M_2014_03_28) .build(); assertEquals(test.getStartDate(), DATE_2014_03_31); assertEquals(test.getEndDate(), DATE_2014_07_01); assertEquals(test.getUnadjustedStartDate(), DATE_2014_03_30); assertEquals(test.getUnadjustedEndDate(), DATE_2014_06_30); assertEquals(test.getYearFraction(), 0.25d, 0d); assertEquals(test.getRateComputation(), GBP_LIBOR_3M_2014_03_28); assertEquals(test.getGearing(), 1d, 0d); assertEquals(test.getSpread(), 0d, 0d); assertEquals(test.getNegativeRateMethod(), ALLOW_NEGATIVE); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -2129778896: // startDate return ((RateAccrualPeriod) bean).getStartDate(); case -1607727319: // endDate return ((RateAccrualPeriod) bean).getEndDate(); case 1457691881: // unadjustedStartDate return ((RateAccrualPeriod) bean).getUnadjustedStartDate(); case 31758114: // unadjustedEndDate return ((RateAccrualPeriod) bean).getUnadjustedEndDate(); case -1731780257: // yearFraction return ((RateAccrualPeriod) bean).getYearFraction(); case 625350855: // rateComputation return ((RateAccrualPeriod) bean).getRateComputation(); case -91774989: // gearing return ((RateAccrualPeriod) bean).getGearing(); case -895684237: // spread return ((RateAccrualPeriod) bean).getSpread(); case 1969081334: // negativeRateMethod return ((RateAccrualPeriod) bean).getNegativeRateMethod(); } return super.propertyGet(bean, propertyName, quiet); }
/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(RateAccrualPeriod beanToCopy) { this.startDate = beanToCopy.getStartDate(); this.endDate = beanToCopy.getEndDate(); this.unadjustedStartDate = beanToCopy.getUnadjustedStartDate(); this.unadjustedEndDate = beanToCopy.getUnadjustedEndDate(); this.yearFraction = beanToCopy.getYearFraction(); this.rateComputation = beanToCopy.getRateComputation(); this.gearing = beanToCopy.getGearing(); this.spread = beanToCopy.getSpread(); this.negativeRateMethod = beanToCopy.getNegativeRateMethod(); }
public void test_pvbp_twoPeriods() { ResolvedSwapLeg leg = ResolvedSwapLeg.builder() .type(FIXED) .payReceive(PAY) .paymentPeriods(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2) .build(); RatesProvider mockProv = mock(RatesProvider.class); double df1 = 0.99d; when(mockProv.discountFactor(USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate())) .thenReturn(df1); double df2 = 0.98d; when(mockProv.discountFactor(USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2.getPaymentDate())) .thenReturn(df2); double expected = df1 * FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getNotional() * FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getAccrualPeriods().get(0).getYearFraction(); expected += df2 * FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2.getNotional() * FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2.getAccrualPeriods().get(0).getYearFraction(); DiscountingSwapLegPricer test = DiscountingSwapLegPricer.DEFAULT; assertEquals(test.pvbp(leg, mockProv), expected, TOLERANCE); }
public void test_builder_defaultDates() { RateAccrualPeriod test = RateAccrualPeriod.builder() .startDate(DATE_2014_03_31) .endDate(DATE_2014_07_01) .yearFraction(0.25d) .rateComputation(GBP_LIBOR_3M_2014_03_28) .build(); assertEquals(test.getStartDate(), DATE_2014_03_31); assertEquals(test.getEndDate(), DATE_2014_07_01); assertEquals(test.getUnadjustedStartDate(), DATE_2014_03_31); assertEquals(test.getUnadjustedEndDate(), DATE_2014_07_01); assertEquals(test.getYearFraction(), 0.25d, 0d); assertEquals(test.getRateComputation(), GBP_LIBOR_3M_2014_03_28); assertEquals(test.getGearing(), 1d, 0d); assertEquals(test.getSpread(), 0d, 0d); assertEquals(test.getNegativeRateMethod(), ALLOW_NEGATIVE); }
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);
public void test_builder() { RateAccrualPeriod test = RateAccrualPeriod.builder() .startDate(DATE_2014_03_31) .endDate(DATE_2014_07_01) .unadjustedStartDate(DATE_2014_03_30) .unadjustedEndDate(DATE_2014_06_30) .yearFraction(0.25d) .rateComputation(GBP_LIBOR_3M_2014_03_28) .build(); assertEquals(test.getStartDate(), DATE_2014_03_31); assertEquals(test.getEndDate(), DATE_2014_07_01); assertEquals(test.getUnadjustedStartDate(), DATE_2014_03_30); assertEquals(test.getUnadjustedEndDate(), DATE_2014_06_30); assertEquals(test.getYearFraction(), 0.25d, 0d); assertEquals(test.getRateComputation(), GBP_LIBOR_3M_2014_03_28); assertEquals(test.getGearing(), 1d, 0d); assertEquals(test.getSpread(), 0d, 0d); assertEquals(test.getNegativeRateMethod(), ALLOW_NEGATIVE); }
ratesProvider.discountFactor(paymentPeriod.getCurrency(), paymentPeriod.getPaymentDate()) / ratesProvider.discountFactor(paymentPeriod.getCurrency(), fixingStartDate); double ycRatio = rateAccrualPeriod.getYearFraction() / fixingYearFraction; NotionalExchange payStart = NotionalExchange.of(notional.multipliedBy(beta * ycRatio), fixingStartDate); NotionalExchange payEnd = NotionalExchange.of(notional.multipliedBy(-ycRatio), paymentDate);
private void explainPresentValue( RateAccrualPeriod accrualPeriod, DayCount dayCount, Currency currency, double notional, RatesProvider provider, ExplainMapBuilder builder) { double rawRate = rateComputationFn.explainRate( accrualPeriod.getRateComputation(), accrualPeriod.getStartDate(), accrualPeriod.getEndDate(), provider, builder); double payOffRate = rawRate * accrualPeriod.getGearing() + accrualPeriod.getSpread(); double ua = unitNotionalAccrual(accrualPeriod, accrualPeriod.getSpread(), provider); // Note that the forecast value is not published since this is potentially misleading when // compounding is being applied, and when it isn't then it's the same as the forecast // value of the payment period. builder.put(ExplainKey.ENTRY_TYPE, "AccrualPeriod"); builder.put(ExplainKey.START_DATE, accrualPeriod.getStartDate()); builder.put(ExplainKey.UNADJUSTED_START_DATE, accrualPeriod.getUnadjustedStartDate()); builder.put(ExplainKey.END_DATE, accrualPeriod.getEndDate()); builder.put(ExplainKey.UNADJUSTED_END_DATE, accrualPeriod.getUnadjustedEndDate()); builder.put(ExplainKey.ACCRUAL_YEAR_FRACTION, accrualPeriod.getYearFraction()); builder.put(ExplainKey.ACCRUAL_DAYS, dayCount.days(accrualPeriod.getStartDate(), accrualPeriod.getEndDate())); builder.put(ExplainKey.DAYS, (int) DAYS.between(accrualPeriod.getStartDate(), accrualPeriod.getEndDate())); builder.put(ExplainKey.GEARING, accrualPeriod.getGearing()); builder.put(ExplainKey.SPREAD, accrualPeriod.getSpread()); builder.put(ExplainKey.PAY_OFF_RATE, accrualPeriod.getNegativeRateMethod().adjust(payOffRate)); builder.put(ExplainKey.UNIT_AMOUNT, ua); }