/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.fra.provider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.interestrate.fra.derivative.ForwardRateAgreement; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.ForwardSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.SimplyCompoundedForwardSensitivity; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.tuple.DoublesPair; /** * Method to compute the present value and its sensitivities for a FRA with * discounting. The present value is computed as the (forward rate - FRA rate) * multiplied by the notional and the payment accrual factor and discounted to * settlement. The discounting to settlement is done using the forward rate * over the fixing period. The value is further discounted from settlement to * today using the discounting curve. * $$ * \begin{equation*} * P^D(0,t_1)\frac{\delta_P(F-K)}{1+\delta_P F} \quad \mbox{and}\quad F = \frac{1}{\delta_F}\left( \frac{P^j(0,t_1)}{P^j(0,t_2)}-1\right) * \end{equation*} * $$ * This approach is valid subject to a independence hypothesis between the * discounting curve and some spread. * <p> * Reference: Henrard, M. (2010). The irony in the derivatives discounting part * II: the crisis. Wilmott Journal, 2(6):301-316. */ public final class ForwardRateAgreementDiscountingMethod { /** * The method unique instance. */ private static final ForwardRateAgreementDiscountingMethod INSTANCE = new ForwardRateAgreementDiscountingMethod(); /** * Return the unique instance of the class. * @return The instance. */ public static ForwardRateAgreementDiscountingMethod getInstance() { return INSTANCE; } /** * Private constructor. */ private ForwardRateAgreementDiscountingMethod() { } /** * Compute the present value of a FRA by discounting. * @param fra The FRA. * @param multicurve The multi-curve provider. * @return The present value. */ public MultipleCurrencyAmount presentValue(final ForwardRateAgreement fra, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(fra, "FRA"); ArgumentChecker.notNull(multicurve, "Multiurves"); final double discountFactorSettlement = multicurve.getDiscountFactor(fra.getCurrency(), fra.getPaymentTime()); final double forward = multicurve.getSimplyCompoundForwardRate(fra.getIndex(), fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction()); final double presentValue = discountFactorSettlement * fra.getPaymentYearFraction() * fra.getNotional() * (forward - fra.getRate()) / (1 + fra.getPaymentYearFraction() * forward); return MultipleCurrencyAmount.of(fra.getCurrency(), presentValue); } /** * Compute the present value sensitivity to rates of a FRA by discounting. * @param fra The FRA. * @param multicurve The multi-curve provider. * @return The present value sensitivity. */ public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final ForwardRateAgreement fra, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(fra, "FRA"); ArgumentChecker.notNull(multicurve, "Multiurves"); final double df = multicurve.getDiscountFactor(fra.getCurrency(), fra.getPaymentTime()); final double forward = multicurve.getSimplyCompoundForwardRate(fra.getIndex(), fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction()); // Backward sweep final double pvBar = 1.0; final double forwardBar = df * fra.getPaymentYearFraction() * fra.getNotional() * (1 - (forward - fra.getRate()) / (1 + fra.getPaymentYearFraction() * forward) * fra.getPaymentYearFraction()) / (1 + fra.getPaymentYearFraction() * forward); final double dfBar = fra.getPaymentYearFraction() * fra.getNotional() * (forward - fra.getRate()) / (1 + fra.getFixingYearFraction() * forward) * pvBar; final Map<String, List<DoublesPair>> mapDsc = new HashMap<>(); final List<DoublesPair> listDiscounting = new ArrayList<>(); listDiscounting.add(DoublesPair.of(fra.getPaymentTime(), -fra.getPaymentTime() * df * dfBar)); mapDsc.put(multicurve.getName(fra.getCurrency()), listDiscounting); final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction(), forwardBar)); mapFwd.put(multicurve.getName(fra.getIndex()), listForward); final MultipleCurrencyMulticurveSensitivity result = MultipleCurrencyMulticurveSensitivity.of(fra.getCurrency(), MulticurveSensitivity.of(mapDsc, mapFwd)); return result; } /** * Compute the par rate or forward rate of the FRA. * @param fra The FRA. * @param multicurve The multi-curve provider. * @return The par rate. */ public double parRate(final ForwardRateAgreement fra, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(fra, "FRA"); ArgumentChecker.notNull(multicurve, "Multiurves"); return multicurve.getSimplyCompoundForwardRate(fra.getIndex(), fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction()); } /** * Computes the par spread (spread to be added to the fixed rate to have a present value of 0). * @param fra The FRA. * @param multicurve The multi-curve provider. * @return The par spread. */ public double parSpread(final ForwardRateAgreement fra, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(fra, "FRA"); ArgumentChecker.notNull(multicurve, "Multiurves"); final double forward = multicurve.getSimplyCompoundForwardRate(fra.getIndex(), fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction()); return forward - fra.getRate(); } /** * Computes the par spread curve sensitivity. * @param fra The FRA. * @param multicurve The multi-curve provider. * @return The par spread sensitivity. */ public MulticurveSensitivity parSpreadCurveSensitivity(final ForwardRateAgreement fra, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(fra, "FRA"); ArgumentChecker.notNull(multicurve, "Multiurves"); final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(fra.getFixingPeriodStartTime(), fra.getFixingPeriodEndTime(), fra.getFixingYearFraction(), 1.0)); mapFwd.put(multicurve.getName(fra.getIndex()), listForward); return MulticurveSensitivity.ofForward(mapFwd); } }