/** * Compute the spread to be added to the rate of the instrument for which the present value of the * instrument is zero. The "rate" can be a "rate" or a "yield" and will depend of each instrument. * * @deprecated {@link YieldCurveBundle} is deprecated */ @Deprecated public final class ParSpreadRateCalculator extends InstrumentDerivativeVisitorAdapter<YieldCurveBundle, Double> { /** The unique instance of the calculator. */ private static final ParSpreadRateCalculator INSTANCE = new ParSpreadRateCalculator(); /** * Gets the calculator instance. * * @return The calculator. */ public static ParSpreadRateCalculator getInstance() { return INSTANCE; } /** Constructor. */ private ParSpreadRateCalculator() {} /** The methods and calculators. */ private static final PresentValueMCACalculator PVMCC = PresentValueMCACalculator.getInstance(); private static final PresentValueBasisPointCalculator PVBPC = PresentValueBasisPointCalculator.getInstance(); private static final CashDiscountingMethod METHOD_DEPOSIT = CashDiscountingMethod.getInstance(); private static final DepositZeroDiscountingMethod METHOD_DEPOSIT_ZERO = DepositZeroDiscountingMethod.getInstance(); private static final ForwardRateAgreementDiscountingMethod METHOD_FRA = ForwardRateAgreementDiscountingMethod.getInstance(); // private static final InterestRateFutureTransactionDiscountingMethod // METHOD_IR_FUTURES_TRANSACTION = InterestRateFutureTransactionDiscountingMethod.getInstance(); private static final InterestRateFutureSecurityDiscountingMethod METHOD_IR_FUTURES_SECURITY = InterestRateFutureSecurityDiscountingMethod.getInstance(); @Override public Double visitCash(final Cash deposit, final YieldCurveBundle curves) { return METHOD_DEPOSIT.parSpread(deposit, curves); } @Override public Double visitDepositZero(final DepositZero deposit, final YieldCurveBundle curves) { return METHOD_DEPOSIT_ZERO.parSpread(deposit, curves); } /** * For swaps the ParSpread is the spread to be added on each coupon of the first leg to obtain a * present value of zero. It is computed as the opposite of the present value of the swap divided * by the present value of a basis point of the first leg (as computed by the * PresentValueBasisPointCalculator). * * @param swap The swap. * @param curves The yield curve bundle. * @return The par spread. */ @Override public Double visitSwap(final Swap<?, ?> swap, final YieldCurveBundle curves) { Validate.notNull(curves); Validate.notNull(swap); return -curves .getFxRates() .convert(swap.accept(PVMCC, curves), swap.getFirstLeg().getCurrency()) .getAmount() / swap.getFirstLeg().accept(PVBPC, curves); } @Override public Double visitFixedCouponSwap(final SwapFixedCoupon<?> swap, final YieldCurveBundle curves) { return visitSwap(swap, curves); } /** * For ForwardRateAgreement the ParSpread is the spread to be added to the fixed rate to obtain a * present value of zero. * * @param fra The forward rate agreement. * @param curves The yield curve bundle. * @return The par spread. */ @Override public Double visitForwardRateAgreement( final ForwardRateAgreement fra, final YieldCurveBundle curves) { Validate.notNull(curves); Validate.notNull(fra); return METHOD_FRA.parSpread(fra, curves); } /** * For InterestRateFutures the ParSpread is the spread to be added to the reference price to * obtain a present value of zero. * * @param future The futures. * @param curves The yield curve bundle. * @return The par spread. */ @Override public Double visitInterestRateFutureTransaction( final InterestRateFutureTransaction future, final YieldCurveBundle curves) { return -(METHOD_IR_FUTURES_SECURITY.price(future.getUnderlying(), curves) - future.getReferencePrice()); } // /** // * For InterestRateFutures the ParSpread is the spread to be added to the reference price to // obtain a present value of zero. // * @param future The futures. // * @param curves The yield curve bundle. // * @return The par spread. // */ // @Override // public Double visitInterestRateFutureSecurity(final InterestRateFutureSecurity future, final // YieldCurveBundle curves) { // return -(METHOD_IR_FUTURES_SECURITY.presentValue(future, curves).getAmount()); // } }
/** * Get the single fixed rate that makes the PV of the instrument zero. For fixed-float swaps this is * the swap rate, for FRAs it is the forward etc. For instruments that cannot PV to zero, e.g. * bonds, a single payment of -1.0 is assumed at zero (i.e. the bond must PV to 1.0) * * @deprecated Use the par rate calculators that reference {@link ParameterProviderInterface} */ @Deprecated public final class ParRateCalculator extends InstrumentDerivativeVisitorAdapter<YieldCurveBundle, Double> { /** The unique instance of the calculator. */ private static final ParRateCalculator INSTANCE = new ParRateCalculator(); /** * Gets the calculator instance. * * @return The calculator. */ public static ParRateCalculator getInstance() { return INSTANCE; } /** Constructor. */ private ParRateCalculator() {} /** The methods and calculators. */ private static final PresentValueCalculator PVC = PresentValueCalculator.getInstance(); private static final CouponONDiscountingMethod METHOD_OIS = CouponONDiscountingMethod.getInstance(); private static final CouponIborDiscountingMethod METHOD_IBOR = CouponIborDiscountingMethod.getInstance(); private static final DepositZeroDiscountingMethod METHOD_DEPOSIT_ZERO = DepositZeroDiscountingMethod.getInstance(); private static final ForwardRateAgreementDiscountingBundleMethod METHOD_FRA = ForwardRateAgreementDiscountingBundleMethod.getInstance(); private static final SwapFixedCouponDiscountingMethod METHOD_SWAP = SwapFixedCouponDiscountingMethod.getInstance(); private static final InterestRateFutureTransactionDiscountingMethod METHOD_IRFUT_TRANSACTION = InterestRateFutureTransactionDiscountingMethod.getInstance(); private static final InterestRateFutureSecurityDiscountingMethod METHOD_IRFUT_SECURITY = InterestRateFutureSecurityDiscountingMethod.getInstance(); // ----- Deposit ----- // TODO: review @Override public Double visitCash(final Cash cash, final YieldCurveBundle curves) { final YieldAndDiscountCurve curve = curves.getCurve(cash.getYieldCurveName()); final double ta = cash.getStartTime(); final double tb = cash.getEndTime(); final double yearFrac = cash.getAccrualFactor(); // TODO need a getForwardRate method on YieldAndDiscountCurve if (yearFrac == 0.0) { if (!CompareUtils.closeEquals(ta, tb, 1e-16)) { throw new IllegalArgumentException( "Year fraction is zero, but payment time greater than trade time"); } final double eps = 1e-8; final double rate = curve.getInterestRate(ta); final double dRate = curve.getInterestRate(ta + eps); return rate + ta * (dRate - rate) / eps; } return (curve.getDiscountFactor(ta) / curve.getDiscountFactor(tb) - 1) / yearFrac; } @Override public Double visitDepositZero(final DepositZero deposit, final YieldCurveBundle curves) { return METHOD_DEPOSIT_ZERO.parRate(deposit, curves); } // ----- Payment/Coupon ------ @Override public Double visitForwardRateAgreement( final ForwardRateAgreement fra, final YieldCurveBundle curves) { return METHOD_FRA.parRate(fra, curves); } @Override public Double visitCouponIbor(final CouponIbor payment, final YieldCurveBundle data) { return METHOD_IBOR.parRate(payment, data); } @Override public Double visitCouponIborSpread(final CouponIborSpread payment, final YieldCurveBundle data) { final YieldAndDiscountCurve curve = data.getCurve(payment.getForwardCurveName()); return (curve.getDiscountFactor(payment.getFixingPeriodStartTime()) / curve.getDiscountFactor(payment.getFixingPeriodEndTime()) - 1.0) / payment.getFixingAccrualFactor(); } @Override public Double visitCouponIborGearing( final CouponIborGearing payment, final YieldCurveBundle data) { final YieldAndDiscountCurve curve = data.getCurve(payment.getForwardCurveName()); return (curve.getDiscountFactor(payment.getFixingPeriodStartTime()) / curve.getDiscountFactor(payment.getFixingPeriodEndTime()) - 1.0) / payment.getFixingAccrualFactor(); } @Override public Double visitCouponOIS(final CouponON payment, final YieldCurveBundle data) { return METHOD_OIS.parRate(payment, data); } @Override public Double visitCapFloorIbor(final CapFloorIbor payment, final YieldCurveBundle data) { return visitCouponIborSpread(payment.toCoupon(), data); } // ----- Swap ----- /** * Computes the par rate of a swap with one fixed leg. * * @param swap The Fixed coupon swap. * @param curves The curves. * @return The par swap rate. If the fixed leg has been set up with some fixed payments these are * ignored for the purposes of finding the swap rate */ @Override public Double visitFixedCouponSwap(final SwapFixedCoupon<?> swap, final YieldCurveBundle curves) { final double pvSecond = swap.getSecondLeg().accept(PVC, curves); final double pvbp = swap.getFixedLeg().withUnitCoupon().accept(PVC, curves); return -pvSecond / pvbp; } /** * Computes the swap convention-modified par rate for a fixed coupon swap. * * <p>Reference: Swaption pricing - v 1.3, OpenGamma Quantitative Research, June 2012. * * @param swap The swap. * @param dayCount The day count convention to modify the swap rate. * @param curves The curves. * @return The modified rate. */ public Double visitFixedCouponSwap( final SwapFixedCoupon<?> swap, final DayCount dayCount, final YieldCurveBundle curves) { final double pvbp = METHOD_SWAP.presentValueBasisPoint(swap, dayCount, curves); return visitFixedCouponSwap(swap, pvbp, curves); } /** * Computes the swap convention-modified par rate for a fixed coupon swap. * * <p>Reference: Swaption pricing - v 1.3, OpenGamma Quantitative Research, June 2012. * * @param swap The swap. * @param dayCount The day count convention to modify the swap rate. * @param curves The curves. * @param calendar The calendar * @return The modified rate. */ public Double visitFixedCouponSwap( final SwapFixedCoupon<?> swap, final DayCount dayCount, final YieldCurveBundle curves, final Calendar calendar) { final double pvbp = METHOD_SWAP.presentValueBasisPoint(swap, dayCount, calendar, curves); return visitFixedCouponSwap(swap, pvbp, curves); } /** * Computes the swap convention-modified par rate for a fixed coupon swap with a PVBP externally * provided. * * <p>Reference: Swaption pricing - v 1.3, OpenGamma Quantitative Research, June 2012. * * @param swap The swap. * @param pvbp The present value of a basis point. * @param curves The curves. * @return The modified rate. */ public Double visitFixedCouponSwap( final SwapFixedCoupon<?> swap, final double pvbp, final YieldCurveBundle curves) { final double pvSecond = -swap.getSecondLeg().accept(PVC, curves) * Math.signum(swap.getSecondLeg().getNthPayment(0).getNotional()); return -pvSecond / pvbp; } // ----- Futures ----- /** {@inheritDoc} Compute the future rate (1-price) without convexity adjustment. */ @Override public Double visitInterestRateFutureTransaction( final InterestRateFutureTransaction future, final YieldCurveBundle curves) { return METHOD_IRFUT_TRANSACTION.parRate(future, curves); } /** {@inheritDoc} Compute the future rate (1-price) without convexity adjustment. */ @Override public Double visitInterestRateFutureSecurity( final InterestRateFutureSecurity future, final YieldCurveBundle curves) { return METHOD_IRFUT_SECURITY.parRate(future, curves); } // TODO: review @Override public Double visitForexForward(final ForexForward fx, final YieldCurveBundle curves) { // TODO this is not a par rate, it is a forward FX rate final YieldAndDiscountCurve curve1 = curves.getCurve(fx.getPaymentCurrency1().getFundingCurveName()); final YieldAndDiscountCurve curve2 = curves.getCurve(fx.getPaymentCurrency2().getFundingCurveName()); final double t = fx.getPaymentTime(); return fx.getSpotForexRate() * curve2.getDiscountFactor(t) / curve1.getDiscountFactor(t); } // ----- Forex ------: see ForwardRateForexCalculator // ----- Bond ----- // TODO: review /** * This gives you the bond coupon, for a given yield curve, that renders the bond par (present * value of all cash flows equal to 1.0) * * @param bond the bond * @param curves the input curves * @return the par rate */ @Override public Double visitBondFixedSecurity( final BondFixedSecurity bond, final YieldCurveBundle curves) { final Annuity<CouponFixed> coupons = bond.getCoupon(); final int n = coupons.getNumberOfPayments(); final CouponFixed[] unitCoupons = new CouponFixed[n]; for (int i = 0; i < n; i++) { unitCoupons[i] = coupons.getNthPayment(i).withUnitCoupon(); } final Annuity<CouponFixed> unitCouponAnnuity = new Annuity<>(unitCoupons); final double pvann = unitCouponAnnuity.accept(PVC, curves); final double matPV = bond.getNominal().accept(PVC, curves); return (1 - matPV) / pvann; } }