/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate; import static org.testng.AssertJUnit.assertEquals; import java.util.ArrayList; import java.util.List; import org.testng.annotations.Test; import org.threeten.bp.Period; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity; import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityCouponFixed; import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityPaymentFixed; import com.opengamma.analytics.financial.interestrate.bond.definition.BondFixedSecurity; import com.opengamma.analytics.financial.interestrate.cash.derivative.Cash; import com.opengamma.analytics.financial.interestrate.fra.derivative.ForwardRateAgreement; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborSpread; import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment; import com.opengamma.analytics.financial.interestrate.payments.derivative.PaymentFixed; import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve; import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve; import com.opengamma.analytics.math.curve.ConstantDoublesCurve; import com.opengamma.financial.convention.businessday.BusinessDayConvention; import com.opengamma.financial.convention.businessday.BusinessDayConventions; import com.opengamma.financial.convention.daycount.DayCount; import com.opengamma.financial.convention.daycount.DayCounts; import com.opengamma.financial.convention.yield.SimpleYieldConvention; import com.opengamma.util.money.Currency; import com.opengamma.util.test.TestGroup; /** * @deprecated This class tests deprecated functionality. */ @Deprecated @Test(groups = TestGroup.UNIT) public class PresentValueCalculatorTest { private static final PresentValueCalculator PVC = PresentValueCalculator.getInstance(); private static final String FIVE_PC_CURVE_NAME = "5%"; private static final String FOUR_PC_CURVE_NAME = "4%"; private static final String ZERO_PC_CURVE_NAME = "0%"; private static final YieldCurveBundle CURVES; private static final Currency CUR = Currency.EUR; private static final Period TENOR = Period.ofMonths(6); private static final int SETTLEMENT_DAYS = 2; private static final DayCount DAY_COUNT_INDEX = DayCounts.ACT_360; private static final BusinessDayConvention BUSINESS_DAY = BusinessDayConventions.MODIFIED_FOLLOWING; private static final boolean IS_EOM = true; private static final IborIndex INDEX = new IborIndex(CUR, TENOR, SETTLEMENT_DAYS, DAY_COUNT_INDEX, BUSINESS_DAY, IS_EOM, "Ibor"); static { YieldAndDiscountCurve curve = YieldCurve.from(ConstantDoublesCurve.from(0.05)); CURVES = new YieldCurveBundle(); CURVES.setCurve(FIVE_PC_CURVE_NAME, curve); curve = YieldCurve.from(ConstantDoublesCurve.from(0.04)); CURVES.setCurve(FOUR_PC_CURVE_NAME, curve); curve = YieldCurve.from(ConstantDoublesCurve.from(0.0)); CURVES.setCurve(ZERO_PC_CURVE_NAME, curve); } @Test public void testCash() { final double t = 7 / 365.0; final YieldAndDiscountCurve curve = CURVES.getCurve(FIVE_PC_CURVE_NAME); double r = 1 / t * (1 / curve.getDiscountFactor(t) - 1); Cash cash = new Cash(CUR, 0, t, 1, r, t, FIVE_PC_CURVE_NAME); double pv = cash.accept(PVC, CURVES); assertEquals(0.0, pv, 1e-12); final double tradeTime = 2.0 / 365.0; final double yearFrac = 5.0 / 360.0; r = 1 / yearFrac * (curve.getDiscountFactor(tradeTime) / curve.getDiscountFactor(t) - 1); cash = new Cash(CUR, tradeTime, t, 1, r, yearFrac, FIVE_PC_CURVE_NAME); pv = cash.accept(PVC, CURVES); assertEquals(0.0, pv, 1e-12); } @Test public void testFRA() { final double paymentTime = 0.5; final double fixingPeriodEnd = 7. / 12.; String fundingCurveName = ZERO_PC_CURVE_NAME; final String forwardCurveName = FIVE_PC_CURVE_NAME; double paymentYearFraction = fixingPeriodEnd - paymentTime; final double notional = 1; final IborIndex index = new IborIndex(CUR, Period.ofMonths(1), 2, DayCounts.ACT_365, BusinessDayConventions.FOLLOWING, true); double fixingTime = paymentTime; final double fixingPeriodStart = paymentTime; double fixingYearFraction = paymentYearFraction; final YieldAndDiscountCurve forwardCurve = CURVES.getCurve(FIVE_PC_CURVE_NAME); final double rate = (forwardCurve.getDiscountFactor(paymentTime) / forwardCurve.getDiscountFactor(fixingPeriodEnd) - 1.0) * 12.0; ForwardRateAgreement fra = new ForwardRateAgreement(CUR, paymentTime, fundingCurveName, paymentYearFraction, notional, index, fixingTime, fixingPeriodStart, fixingPeriodEnd, fixingYearFraction, rate, forwardCurveName); double pv = fra.accept(PVC, CURVES); assertEquals(0.0, pv, 1e-12); fixingTime = paymentTime - 2. / 365.; fixingYearFraction = 31. / 365; paymentYearFraction = 30. / 360; fundingCurveName = FIVE_PC_CURVE_NAME; final double forwardRate = (forwardCurve.getDiscountFactor(fixingPeriodStart) / forwardCurve.getDiscountFactor(fixingPeriodEnd) - 1) / fixingYearFraction; final double fv = (forwardRate - rate) * paymentYearFraction / (1 + forwardRate * paymentYearFraction); final double pv2 = fv * forwardCurve.getDiscountFactor(paymentTime); fra = new ForwardRateAgreement(CUR, paymentTime, fundingCurveName, paymentYearFraction, notional, index, fixingTime, fixingPeriodStart, fixingPeriodEnd, fixingYearFraction, rate, forwardCurveName); pv = fra.accept(PVC, CURVES); assertEquals(pv, pv2, 1e-12); } // @Test // public void testFutures() { // final IborIndex iborIndex = new IborIndex(CUR, Period.ofMonths(3), 2, new MondayToFridayCalendar("A"), DayCounts.ACT_365, // BusinessDayConventions.FOLLOWING, true); // final double lastTradingTime = 1.473; // final double fixingPeriodStartTime = 1.467; // final double fixingPeriodEndTime = 1.75; // final double fixingPeriodAccrualFactor = 0.267; // final double paymentAccrualFactor = 0.25; // final double referencePrice = 0.0; // TODO CASE - Future refactor - referencePrice = 0.0 // final YieldAndDiscountCurve curve = CURVES.getCurve(FIVE_PC_CURVE_NAME); // final double rate = (curve.getDiscountFactor(fixingPeriodStartTime) / curve.getDiscountFactor(fixingPeriodEndTime) - 1.0) / fixingPeriodAccrualFactor; // final double price = 1 - rate; // final double notional = 1; // final int quantity = 123; // InterestRateFutureTransaction ir = new InterestRateFutureTransaction(lastTradingTime, iborIndex, fixingPeriodStartTime, fixingPeriodEndTime, fixingPeriodAccrualFactor, referencePrice, notional, paymentAccrualFactor, // quantity, "A", FIVE_PC_CURVE_NAME, FIVE_PC_CURVE_NAME); // double pv = ir.accept(PVC, CURVES); // assertEquals(price * notional * paymentAccrualFactor * quantity, pv, 1e-12); // final double deltaPrice = 0.01; // ir = new InterestRateFutureTransaction(lastTradingTime, iborIndex, fixingPeriodStartTime, fixingPeriodEndTime, fixingPeriodAccrualFactor, deltaPrice, notional, paymentAccrualFactor, quantity, "A", // FIVE_PC_CURVE_NAME, FIVE_PC_CURVE_NAME); // pv = ir.accept(PVC, CURVES); // assertEquals((price - deltaPrice) * notional * paymentAccrualFactor * quantity, pv, 1e-12); // } @Test public void testFixedCouponAnnuity() { AnnuityCouponFixed annuityReceiver = new AnnuityCouponFixed(CUR, new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 1.0, ZERO_PC_CURVE_NAME, false); double pv = annuityReceiver.accept(PVC, CURVES); assertEquals(10.0, pv, 1e-12); final int n = 15; final double alpha = 0.49; final double yearFrac = 0.51; final double[] paymentTimes = new double[n]; final double[] coupons = new double[n]; final double[] yearFracs = new double[n]; final YieldAndDiscountCurve curve = CURVES.getCurve(FIVE_PC_CURVE_NAME); final double rate = curve.getInterestRate(0.0); for (int i = 0; i < n; i++) { paymentTimes[i] = (i + 1) * alpha; coupons[i] = Math.exp((i + 1) * rate * alpha); yearFracs[i] = yearFrac; } annuityReceiver = new AnnuityCouponFixed(CUR, paymentTimes, Math.PI, rate, yearFracs, ZERO_PC_CURVE_NAME, false); pv = annuityReceiver.accept(PVC, CURVES); assertEquals(n * yearFrac * rate * Math.PI, pv, 1e-12); final AnnuityCouponFixed annuityPayer = new AnnuityCouponFixed(CUR, paymentTimes, Math.PI, rate, yearFracs, ZERO_PC_CURVE_NAME, true); assertEquals(pv, -annuityPayer.accept(PVC, CURVES), 1e-12); } @Test public void testBond() { final int n = 20; final double tau = 0.5; final double yearFrac = 180 / 365.0; final YieldAndDiscountCurve curve = CURVES.getCurve(FIVE_PC_CURVE_NAME); final double coupon = (1.0 / curve.getDiscountFactor(tau) - 1.0) / yearFrac; final CouponFixed[] coupons = new CouponFixed[n]; for (int i = 0; i < n; i++) { coupons[i] = new CouponFixed(CUR, tau * (i + 1), FIVE_PC_CURVE_NAME, yearFrac, coupon); } final AnnuityPaymentFixed nominal = new AnnuityPaymentFixed(new PaymentFixed[] {new PaymentFixed(CUR, tau * n, 1, FIVE_PC_CURVE_NAME)}); final BondFixedSecurity bond = new BondFixedSecurity(nominal, new AnnuityCouponFixed(coupons), 0, 0, 0.5, SimpleYieldConvention.TRUE, 2, FIVE_PC_CURVE_NAME, "S"); final double pv = bond.accept(PVC, CURVES); assertEquals(1.0, pv, 1e-12); } @Test public void testGenericAnnuity() { final double time = 3.4; final double amount = 34.3; final double coupon = 0.05; final double yearFrac = 0.5; final double resetTime = 2.9; final double notional = 56; final List<Payment> list = new ArrayList<>(); double expected = 0.0; Payment temp = new PaymentFixed(CUR, time, amount, FIVE_PC_CURVE_NAME); expected += amount * CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(time); list.add(temp); temp = new CouponFixed(CUR, time, FIVE_PC_CURVE_NAME, yearFrac, notional, coupon); expected += notional * yearFrac * coupon * CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(time); list.add(temp); temp = new CouponIborSpread(CUR, time, ZERO_PC_CURVE_NAME, yearFrac, notional, resetTime, INDEX, resetTime, time, yearFrac, 0.0, FIVE_PC_CURVE_NAME); expected += notional * (CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(resetTime) / CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(time) - 1); list.add(temp); final Annuity<Payment> annuity = new Annuity<>(list, Payment.class, true); final double pv = annuity.accept(PVC, CURVES); assertEquals(expected, pv, 1e-12); } @Test public void testFixedPayment() { final double time = 1.23; final double amount = 4345.3; final PaymentFixed payment = new PaymentFixed(CUR, time, amount, FIVE_PC_CURVE_NAME); final double expected = amount * CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(time); final double pv = payment.accept(PVC, CURVES); assertEquals(expected, pv, 1e-8); } @Test public void testFixedCouponPayment() { final double time = 1.23; final double yearFrac = 0.56; final double coupon = 0.07; final double notional = 1000; final CouponFixed payment = new CouponFixed(CUR, time, ZERO_PC_CURVE_NAME, yearFrac, notional, coupon); final double expected = notional * yearFrac * coupon; final double pv = payment.accept(PVC, CURVES); assertEquals(expected, pv, 1e-8); } @Test public void forwardLiborPayment() { final double time = 2.45; final double resetTime = 2.0; final double maturity = 2.5; final double paymentYF = 0.48; final double forwardYF = 0.5; final double spread = 0.04; final double notional = 4.53; CouponIborSpread payment = new CouponIborSpread(CUR, time, FIVE_PC_CURVE_NAME, paymentYF, notional, resetTime, INDEX, resetTime, maturity, forwardYF, spread, ZERO_PC_CURVE_NAME); double expected = notional * paymentYF * spread * CURVES.getCurve(FIVE_PC_CURVE_NAME).getDiscountFactor(time); double pv = payment.accept(PVC, CURVES); assertEquals(expected, pv, 1e-8); payment = new CouponIborSpread(CUR, time, ZERO_PC_CURVE_NAME, paymentYF, 1.0, resetTime, INDEX, resetTime, maturity, forwardYF, spread, FIVE_PC_CURVE_NAME); final double forward = (Math.exp(0.05 * (maturity - resetTime)) - 1) / forwardYF; expected = paymentYF * (forward + spread); pv = payment.accept(PVC, CURVES); assertEquals(expected, pv, 1e-8); } }