/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ResolvedTermDeposit beanToCopy) { this.currency = beanToCopy.getCurrency(); this.notional = beanToCopy.getNotional(); this.startDate = beanToCopy.getStartDate(); this.endDate = beanToCopy.getEndDate(); this.yearFraction = beanToCopy.getYearFraction(); this.rate = beanToCopy.getRate(); }
/** * Calculates the current cash. * * @param trade the trade * @param provider the rates provider * @return the current cash */ public CurrencyAmount currentCash(ResolvedTermDepositTrade trade, RatesProvider provider) { ResolvedTermDeposit product = trade.getProduct(); if (product.getStartDate().isEqual(provider.getValuationDate())) { return CurrencyAmount.of(product.getCurrency(), -product.getNotional()); } if (product.getEndDate().isEqual(provider.getValuationDate())) { return CurrencyAmount.of(product.getCurrency(), product.getNotional() + product.getInterest()); } return CurrencyAmount.zero(product.getCurrency()); }
/** * Calculates the deposit fair rate given the start and end time and the accrual factor. * <p> * When the deposit has already started the number may not be meaningful as the remaining period * is not in line with the accrual factor. * * @param deposit the product * @param provider the rates provider * @return the par rate */ public double parRate(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.getCurrency(); DiscountFactors discountFactors = provider.discountFactors(currency); double dfStart = discountFactors.discountFactor(deposit.getStartDate()); double dfEnd = discountFactors.discountFactor(deposit.getEndDate()); double accrualFactor = deposit.getYearFraction(); return (dfStart / dfEnd - 1d) / accrualFactor; }
private double initialAmount(ResolvedTermDeposit deposit, RatesProvider provider) { return provider.getValuationDate().isAfter(deposit.getStartDate()) ? 0d : deposit.getNotional(); }
public void test_presentValue_onStart() { SimpleRatesProvider prov = provider(START_DATE, 1.0d, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = ((1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END - 1.0d) * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); }
private LocalDate calculateEnd(LocalDate valuationDate, ReferenceData refData) { TermDepositTrade trade = template.createTrade(valuationDate, BuySell.BUY, 0d, 0d, refData); ResolvedTermDeposit deposit = trade.getProduct().resolve(refData); return deposit.getEndDate(); }
public void test_currentCash_onStartDate() { RatesProvider prov = ImmutableRatesProvider.builder(RDEPOSIT_TRADE.getProduct().getStartDate()) .discountCurve(EUR, CURVE) .build(); assertEquals(PRICER_TRADE.currentCash(RDEPOSIT_TRADE, prov), CurrencyAmount.of(EUR, -NOTIONAL)); }
/** * Calculates the spread to be added to the deposit rate to have a zero present value. * <p> * The calculation is based on both the initial and final payments. * Thus the resulting number may not be meaningful when deposit has already started and only the final * payment remains (no initial payment). * * @param deposit the product * @param provider the rates provider * @return the par spread */ public double parSpread(ResolvedTermDeposit deposit, RatesProvider provider) { double parRate = parRate(deposit, provider); return parRate - deposit.getRate(); }
@Override public ResolvedTermDeposit resolve(ReferenceData refData) { DateAdjuster bda = getBusinessDayAdjustment().orElse(BusinessDayAdjustment.NONE).resolve(refData); LocalDate start = bda.adjust(startDate); LocalDate end = bda.adjust(endDate); double yearFraction = dayCount.yearFraction(start, end); return ResolvedTermDeposit.builder() .startDate(start) .endDate(end) .yearFraction(yearFraction) .currency(getCurrency()) .notional(buySell.normalize(notional)) .rate(rate) .build(); }
/** * Calculates the par spread curve sensitivity. * <p> * The calculation is based on both of initial and final payments. * Thus the number resulting may not be meaningful when deposit has already started and only the final * payment remains (no initial payment). * * @param deposit the product * @param provider the rates provider * @return the par spread curve sensitivity */ public PointSensitivities parSpreadSensitivity(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.getCurrency(); double accrualFactorInv = 1d / deposit.getYearFraction(); double dfStart = provider.discountFactor(currency, deposit.getStartDate()); double dfEndInv = 1d / provider.discountFactor(currency, deposit.getEndDate()); DiscountFactors discountFactors = provider.discountFactors(currency); PointSensitivityBuilder sensStart = discountFactors.zeroRatePointSensitivity(deposit.getStartDate()) .multipliedBy(dfEndInv * accrualFactorInv); PointSensitivityBuilder sensEnd = discountFactors.zeroRatePointSensitivity(deposit.getEndDate()) .multipliedBy(-dfStart * dfEndInv * dfEndInv * accrualFactorInv); return sensStart.combinedWith(sensEnd).build(); }
public void test_presentValue_onEnd() { SimpleRatesProvider prov = provider(END_DATE, 1.2d, 1.0d); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = (1d + RATE * RTERM_DEPOSIT.getYearFraction()) * 1.0d * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); }
public void test_currentCash_onEndDate() { RatesProvider prov = ImmutableRatesProvider.builder(RDEPOSIT_TRADE.getProduct().getEndDate()) .discountCurve(EUR, CURVE) .build(); assertEquals(PRICER_TRADE.currentCash(RDEPOSIT_TRADE, prov), CurrencyAmount.of(EUR, NOTIONAL + INTEREST)); }
public void test_builder_wrongDates() { assertThrowsIllegalArg(() -> ResolvedTermDeposit.builder() .currency(GBP) .notional(PRINCIPAL) .startDate(START_DATE) .endDate(LocalDate.of(2013, 1, 22)) .yearFraction(YEAR_FRACTION) .rate(RATE) .build()); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 575402001: // currency return ((ResolvedTermDeposit) bean).getCurrency(); case 1585636160: // notional return ((ResolvedTermDeposit) bean).getNotional(); case -2129778896: // startDate return ((ResolvedTermDeposit) bean).getStartDate(); case -1607727319: // endDate return ((ResolvedTermDeposit) bean).getEndDate(); case -1731780257: // yearFraction return ((ResolvedTermDeposit) bean).getYearFraction(); case 3493088: // rate return ((ResolvedTermDeposit) bean).getRate(); } return super.propertyGet(bean, propertyName, quiet); }
/** * Calculates the present value by discounting the final cash flow (nominal + interest) * and the initial payment (initial amount). * <p> * The present value of the product is the value on the valuation date. * * @param deposit the product * @param provider the rates provider * @return the present value of the product */ public CurrencyAmount presentValue(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.getCurrency(); if (provider.getValuationDate().isAfter(deposit.getEndDate())) { return CurrencyAmount.of(currency, 0.0d); } DiscountFactors discountFactors = provider.discountFactors(currency); double dfStart = discountFactors.discountFactor(deposit.getStartDate()); double dfEnd = discountFactors.discountFactor(deposit.getEndDate()); double pvStart = initialAmount(deposit, provider) * dfStart; double pvEnd = (deposit.getNotional() + deposit.getInterest()) * dfEnd; double pv = pvEnd - pvStart; return CurrencyAmount.of(currency, pv); }
public void test_presentValue_notStarted() { SimpleRatesProvider prov = provider(VAL_DATE, DF_START, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = ((1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END - DF_START) * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); }
public void test_serialization() { ResolvedTermDeposit test = ResolvedTermDeposit.builder() .currency(GBP) .notional(PRINCIPAL) .startDate(START_DATE) .endDate(END_DATE) .yearFraction(YEAR_FRACTION) .rate(RATE) .build(); assertSerialization(test); }
public void test_builder() { ResolvedTermDeposit test = ResolvedTermDeposit.builder() .currency(GBP) .notional(PRINCIPAL) .startDate(START_DATE) .endDate(END_DATE) .yearFraction(YEAR_FRACTION) .rate(RATE) .build(); assertEquals(test.getCurrency(), GBP); assertEquals(test.getNotional(), PRINCIPAL); assertEquals(test.getStartDate(), START_DATE); assertEquals(test.getEndDate(), END_DATE); assertEquals(test.getYearFraction(), YEAR_FRACTION); assertEquals(test.getRate(), RATE); assertEquals(test.getInterest(), RATE * YEAR_FRACTION * PRINCIPAL, PRINCIPAL * EPS); }
/** * Calculates the present value sensitivity by discounting the final cash flow (nominal + interest) * and the initial payment (initial amount). * * @param deposit the product * @param provider the rates provider * @return the point sensitivity of the present value */ public PointSensitivities presentValueSensitivity(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.getCurrency(); // backward sweep double dfEndBar = deposit.getNotional() + deposit.getInterest(); double dfStartBar = -initialAmount(deposit, provider); // sensitivity DiscountFactors discountFactors = provider.discountFactors(currency); PointSensitivityBuilder sensStart = discountFactors.zeroRatePointSensitivity(deposit.getStartDate()) .multipliedBy(dfStartBar); PointSensitivityBuilder sensEnd = discountFactors.zeroRatePointSensitivity(deposit.getEndDate()) .multipliedBy(dfEndBar); return sensStart.combinedWith(sensEnd).build(); }
public void test_presentValue_started() { SimpleRatesProvider prov = provider(date(2014, 2, 22), 1.2d, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = (1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); }