/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.forex.method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.Validate;
import com.opengamma.analytics.financial.forex.derivative.ForexNonDeliverableForward;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.InterestRateCurveSensitivity;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.tuple.DoublesPair;
/**
* Pricing method for Forex non-deliverable forward transactions by discounting.
* @deprecated {@link YieldCurveBundle} is deprecated.
* Use {@link com.opengamma.analytics.financial.forex.provider.ForexNonDeliverableForwardDiscountingMethod}
*/
@Deprecated
public final class ForexNonDeliverableForwardDiscountingMethod implements ForexPricingMethod {
/**
* The method unique instance.
*/
private static final ForexNonDeliverableForwardDiscountingMethod INSTANCE = new ForexNonDeliverableForwardDiscountingMethod();
/**
* Return the unique instance of the class.
* @return The instance.
*/
public static ForexNonDeliverableForwardDiscountingMethod getInstance() {
return INSTANCE;
}
/**
* Private constructor.
*/
private ForexNonDeliverableForwardDiscountingMethod() {
}
/**
* Computes the present value of the non-deliverable forward. The present value is in currency2 and equal to P*N*(1-X/F) where
* <i>P</i> is the currency2 discount factor for the payment date, <i>N</i> is the notional, <i>X</i> is NDF rate and <i>F</i> the estimated forward exchange rate at the payment date.
* @param ndf The non-deliverable forward.
* @param curves The curve bundle (with FX rates).
* @return The present value.
*/
public MultipleCurrencyAmount presentValue(final ForexNonDeliverableForward ndf, final YieldCurveBundle curves) {
final double df2 = curves.getCurve(ndf.getDiscountingCurve2Name()).getDiscountFactor(ndf.getPaymentTime());
final double df1 = curves.getCurve(ndf.getDiscountingCurve1Name()).getDiscountFactor(ndf.getPaymentTime());
final double spot = curves.getFxRates().getFxRate(ndf.getCurrency2(), ndf.getCurrency1());
final double pv2 = ndf.getNotionalCurrency2() * (df2 - ndf.getExchangeRate() / spot * df1);
return MultipleCurrencyAmount.of(ndf.getCurrency2(), pv2);
}
@Override
public MultipleCurrencyAmount presentValue(final InstrumentDerivative instrument, final YieldCurveBundle curves) {
Validate.isTrue(instrument instanceof ForexNonDeliverableForward, "Derivative should be ForexNonDeliverableForward");
return presentValue((ForexNonDeliverableForward) instrument, curves);
}
/**
* Computes the currency exposure of the non-deliverable forward. The currency exposure is P_2 * N in currency2 and -P_1 * N * X in currency1
* where <i>P_2</i> is the currency2 discount factor for the payment date, <i>N</i> is the notional, <i>P_1</i> is the currency1 discount factor for the payment date
* and <i>X</i> is NDF rate.
* @param ndf The non-deliverable forward.
* @param curves The curve bundle (with FX rates).
* @return The currency exposure.
*/
public MultipleCurrencyAmount currencyExposure(final ForexNonDeliverableForward ndf, final YieldCurveBundle curves) {
final double df2 = curves.getCurve(ndf.getDiscountingCurve2Name()).getDiscountFactor(ndf.getPaymentTime());
final double df1 = curves.getCurve(ndf.getDiscountingCurve1Name()).getDiscountFactor(ndf.getPaymentTime());
final double pv1 = -ndf.getNotionalCurrency2() * ndf.getExchangeRate() * df1;
final double pv2 = ndf.getNotionalCurrency2() * df2;
return MultipleCurrencyAmount.of(new Currency[] {ndf.getCurrency1(), ndf.getCurrency2()}, new double[] {pv1, pv2});
}
@Override
public MultipleCurrencyAmount currencyExposure(final InstrumentDerivative instrument, final YieldCurveBundle curves) {
Validate.isTrue(instrument instanceof ForexNonDeliverableForward, "Derivative should be ForexNonDeliverableForward");
return currencyExposure((ForexNonDeliverableForward) instrument, curves);
}
/**
* Computes the forward exchange rate associated to the NDF (1 Cyy2 = fwd Cyy1).
* @param ndf The non-deliverable forward.
* @param curves The curve bundle (with FX rates).
* @return The forward rate.
*/
public double forwardForexRate(final ForexNonDeliverableForward ndf, final YieldCurveBundle curves) {
final double dfDelivery = curves.getCurve(ndf.getDiscountingCurve2Name()).getDiscountFactor(ndf.getPaymentTime());
final double dfNonDelivery = curves.getCurve(ndf.getDiscountingCurve1Name()).getDiscountFactor(ndf.getPaymentTime());
final double spot = curves.getFxRates().getFxRate(ndf.getCurrency2(), ndf.getCurrency1());
return spot * dfDelivery / dfNonDelivery;
}
/**
* The present value curve sensitivity for the non-deliverable forward.
* @param ndf The non-deliverable forward.
* @param curves The curve bundle (with FX rates).
* @return The present value currency exposure.
*/
public MultipleCurrencyInterestRateCurveSensitivity presentValueCurveSensitivity(final ForexNonDeliverableForward ndf, final YieldCurveBundle curves) {
// Validate.isTrue(curves instanceof YieldCurveWithFXBundle, "Bundle should contain FX rate");
// YieldCurveWithFXBundle curvesFX = (YieldCurveWithFXBundle) curves;
final double df2 = curves.getCurve(ndf.getDiscountingCurve2Name()).getDiscountFactor(ndf.getPaymentTime());
final double df1 = curves.getCurve(ndf.getDiscountingCurve1Name()).getDiscountFactor(ndf.getPaymentTime());
final double spot = curves.getFxRates().getFxRate(ndf.getCurrency2(), ndf.getCurrency1());
// Backward sweep
final double pvBar = 1.0;
final double df1Bar = -ndf.getNotionalCurrency2() * ndf.getExchangeRate() / spot * pvBar;
final double df2Bar = ndf.getNotionalCurrency2() * pvBar;
final Map<String, List<DoublesPair>> resultMap = new HashMap<>();
final List<DoublesPair> listDiscounting1 = new ArrayList<>();
listDiscounting1.add(DoublesPair.of(ndf.getPaymentTime(), -ndf.getPaymentTime() * df1 * df1Bar));
resultMap.put(ndf.getDiscountingCurve1Name(), listDiscounting1);
final List<DoublesPair> listDiscounting2 = new ArrayList<>();
listDiscounting2.add(DoublesPair.of(ndf.getPaymentTime(), -ndf.getPaymentTime() * df2 * df2Bar));
resultMap.put(ndf.getDiscountingCurve2Name(), listDiscounting2);
final InterestRateCurveSensitivity result = new InterestRateCurveSensitivity(resultMap);
return MultipleCurrencyInterestRateCurveSensitivity.of(ndf.getCurrency2(), result);
}
@Override
public MultipleCurrencyInterestRateCurveSensitivity presentValueCurveSensitivity(final InstrumentDerivative instrument, final YieldCurveBundle curves) {
Validate.isTrue(instrument instanceof ForexNonDeliverableForward, "Forex non-deliverable forward");
return presentValueCurveSensitivity((ForexNonDeliverableForward) instrument, curves);
}
}