/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.cash.provider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.opengamma.analytics.financial.interestrate.cash.derivative.DepositCounterpart;
import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.tuple.DoublesPair;
/**
* The methods associated to the pricing of cash deposit by discounting.
*/
public final class DepositCounterpartDiscountingMethod {
/**
* The method unique instance.
*/
private static final DepositCounterpartDiscountingMethod INSTANCE = new DepositCounterpartDiscountingMethod();
/**
* Return the unique instance of the class.
* @return The instance.
*/
public static DepositCounterpartDiscountingMethod getInstance() {
return INSTANCE;
}
/**
* Private constructor.
*/
private DepositCounterpartDiscountingMethod() {
}
/**
* Compute the present value by discounting the final cash flow (nominal + interest) and the initial payment (initial amount).
* @param deposit The deposit.
* @param multicurves The multi-curves and issuer curves provider.
* @return The present value.
*/
public MultipleCurrencyAmount presentValue(final DepositCounterpart deposit, final IssuerProviderInterface multicurves) {
ArgumentChecker.notNull(deposit, "Deposit");
ArgumentChecker.notNull(multicurves, "Multicurves");
final double dfStart = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getStartTime());
final double dfEnd = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getEndTime());
final double pv = (deposit.getNotional() + deposit.getInterestAmount()) * dfEnd - deposit.getInitialAmount() * dfStart;
return MultipleCurrencyAmount.of(deposit.getCurrency(), pv);
}
/**
* Compute the present value by discounting the final cash flow (nominal + interest) and the initial payment (initial amount).
* @param deposit The deposit.
* @param multicurves The multi-curves and issuer curves provider.
* @return The present value.
*/
public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final DepositCounterpart deposit, final IssuerProviderInterface multicurves) {
ArgumentChecker.notNull(deposit, "Deposit");
ArgumentChecker.notNull(multicurves, "Multicurves");
final double dfStart = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getStartTime());
final double dfEnd = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getEndTime());
// Backward sweep
final double pvBar = 1.0;
final double dfEndBar = deposit.getNotional() + deposit.getInterestAmount() * pvBar;
final double dfStartBar = -deposit.getInitialAmount() * pvBar;
final Map<String, List<DoublesPair>> mapDsc = new HashMap<>();
final List<DoublesPair> listDiscounting = new ArrayList<>();
listDiscounting.add(DoublesPair.of(deposit.getStartTime(), -deposit.getStartTime() * dfStart * dfStartBar));
listDiscounting.add(DoublesPair.of(deposit.getEndTime(), -deposit.getEndTime() * dfEnd * dfEndBar));
mapDsc.put(multicurves.getName(deposit.getCounterparty()), listDiscounting);
MultipleCurrencyMulticurveSensitivity result = new MultipleCurrencyMulticurveSensitivity();
result = result.plus(deposit.getCurrency(), MulticurveSensitivity.ofYieldDiscounting(mapDsc));
return result;
}
/**
* Computes the spread to be added to the deposit rate to have a zero present value.
* When deposit has already start the number may not be meaning full as only the final payment remains (no initial payment).
* @param deposit The deposit.
* @param multicurves The multi-curves and issuer curves provider.
* @return The spread.
*/
public double parSpread(final DepositCounterpart deposit, final IssuerProviderInterface multicurves) {
ArgumentChecker.notNull(deposit, "Deposit");
ArgumentChecker.notNull(multicurves, "Multicurves");
ArgumentChecker.isTrue(deposit.getNotional() != 0.0, "Notional is 0");
final double dfStart = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getStartTime());
final double dfEnd = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getEndTime());
return (deposit.getInitialAmount() * dfStart - (deposit.getNotional() + deposit.getInterestAmount()) * dfEnd) / (deposit.getNotional() * deposit.getAccrualFactor() * dfEnd);
}
/**
* Computes the par spread curve sensitivity.
* When deposit has already start the number may not be meaning full as only the final payment remains (no initial payment).
* @param deposit The deposit.
* @param multicurves The multi-curves and issuer curves provider.
* @return The spread curve sensitivity.
*/
public MulticurveSensitivity parSpreadCurveSensitivity(final DepositCounterpart deposit, final IssuerProviderInterface multicurves) {
ArgumentChecker.notNull(deposit, "Deposit");
ArgumentChecker.notNull(multicurves, "Multicurves");
ArgumentChecker.isTrue(deposit.getNotional() != 0.0, "Notional is 0");
final double dfStart = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getStartTime());
final double dfEnd = multicurves.getDiscountFactor(deposit.getCounterparty(), deposit.getEndTime());
// Backward sweep
final double parSpreadBar = 1.0;
final double dfEndBar = -(deposit.getInitialAmount() * dfStart / (dfEnd * dfEnd)) / (deposit.getNotional() * deposit.getAccrualFactor()) * parSpreadBar;
final double dfStartBar = (deposit.getInitialAmount() / dfEnd) / (deposit.getNotional() * deposit.getAccrualFactor()) * parSpreadBar;
final Map<String, List<DoublesPair>> mapDsc = new HashMap<>();
final List<DoublesPair> listDiscounting = new ArrayList<>();
listDiscounting.add(DoublesPair.of(deposit.getStartTime(), -deposit.getStartTime() * dfStart * dfStartBar));
listDiscounting.add(DoublesPair.of(deposit.getEndTime(), -deposit.getEndTime() * dfEnd * dfEndBar));
mapDsc.put(multicurves.getName(deposit.getCounterparty()), listDiscounting);
return MulticurveSensitivity.ofYieldDiscounting(mapDsc);
}
}