com.opengamma.strata.pricer.fx.DiscountingFxSingleProductPricer Maven / Gradle / Ivy
/*
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.fx;
import java.time.LocalDate;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.FxRate;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.currency.Payment;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.DiscountingPaymentPricer;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.fx.ResolvedFxSingle;
/**
* Pricer for foreign exchange transaction products.
*
* This provides the ability to price an {@link ResolvedFxSingle}.
*/
public class DiscountingFxSingleProductPricer {
/**
* Default implementation.
*/
public static final DiscountingFxSingleProductPricer DEFAULT = new DiscountingFxSingleProductPricer(
DiscountingPaymentPricer.DEFAULT);
/**
* Pricer for {@link Payment}.
*/
private final DiscountingPaymentPricer paymentPricer;
/**
* Creates an instance.
*
* @param paymentPricer the pricer for {@link Payment}
*/
public DiscountingFxSingleProductPricer(
DiscountingPaymentPricer paymentPricer) {
this.paymentPricer = ArgChecker.notNull(paymentPricer, "paymentPricer");
}
//-------------------------------------------------------------------------
/**
* Calculates the present value of the FX product by discounting each payment in its own currency.
*
* @param fx the product
* @param provider the rates provider
* @return the present value in the two natural currencies
*/
public MultiCurrencyAmount presentValue(ResolvedFxSingle fx, RatesProvider provider) {
if (provider.getValuationDate().isAfter(fx.getPaymentDate())) {
return MultiCurrencyAmount.empty();
}
CurrencyAmount pv1 = paymentPricer.presentValue(fx.getBaseCurrencyPayment(), provider);
CurrencyAmount pv2 = paymentPricer.presentValue(fx.getCounterCurrencyPayment(), provider);
return MultiCurrencyAmount.of(pv1, pv2);
}
/**
* Calculates the present value curve sensitivity of the FX product.
*
* The present value sensitivity of the product is the sensitivity of the present value to
* the underlying curves.
*
* @param fx the product
* @param provider the rates provider
* @return the point sensitivity of the present value
*/
public PointSensitivities presentValueSensitivity(ResolvedFxSingle fx, RatesProvider provider) {
if (provider.getValuationDate().isAfter(fx.getPaymentDate())) {
return PointSensitivities.empty();
}
PointSensitivityBuilder pvcs1 = paymentPricer.presentValueSensitivity(fx.getBaseCurrencyPayment(), provider);
PointSensitivityBuilder pvcs2 = paymentPricer.presentValueSensitivity(fx.getCounterCurrencyPayment(), provider);
return pvcs1.combinedWith(pvcs2).build();
}
//-------------------------------------------------------------------------
/**
* Calculates the par spread.
*
* This is the spread that should be added to the FX points to have a zero value.
*
* @param fx the product
* @param provider the rates provider
* @return the spread
*/
public double parSpread(ResolvedFxSingle fx, RatesProvider provider) {
Payment basePayment = fx.getBaseCurrencyPayment();
Payment counterPayment = fx.getCounterCurrencyPayment();
MultiCurrencyAmount pv = presentValue(fx, provider);
double pvCounterCcy = pv.convertedTo(counterPayment.getCurrency(), provider).getAmount();
double dfEnd = provider.discountFactor(counterPayment.getCurrency(), fx.getPaymentDate());
double notionalBaseCcy = basePayment.getAmount();
return pvCounterCcy / (notionalBaseCcy * dfEnd);
}
//-------------------------------------------------------------------------
/**
* Calculates the currency exposure by discounting each payment in its own currency.
*
* @param product the product
* @param provider the rates provider
* @return the currency exposure
*/
public MultiCurrencyAmount currencyExposure(ResolvedFxSingle product, RatesProvider provider) {
return presentValue(product, provider);
}
/**
* Calculates the current cash.
*
* @param fx the product
* @param valuationDate the valuation date
* @return the current cash
*/
public MultiCurrencyAmount currentCash(ResolvedFxSingle fx, LocalDate valuationDate) {
if (valuationDate.isEqual(fx.getPaymentDate())) {
return MultiCurrencyAmount.of(fx.getBaseCurrencyPayment().getValue(), fx.getCounterCurrencyPayment().getValue());
}
return MultiCurrencyAmount.empty();
}
//-------------------------------------------------------------------------
/**
* Calculates the forward exchange rate.
*
* @param fx the product
* @param provider the rates provider
* @return the forward rate
*/
public FxRate forwardFxRate(ResolvedFxSingle fx, RatesProvider provider) {
FxForwardRates fxForwardRates = provider.fxForwardRates(fx.getCurrencyPair());
Payment basePayment = fx.getBaseCurrencyPayment();
Payment counterPayment = fx.getCounterCurrencyPayment();
double forwardRate = fxForwardRates.rate(basePayment.getCurrency(), fx.getPaymentDate());
return FxRate.of(basePayment.getCurrency(), counterPayment.getCurrency(), forwardRate);
}
/**
* Calculates the forward exchange rate point sensitivity.
*
* The returned value is based on the direction of the FX product.
*
* @param fx the product
* @param provider the rates provider
* @return the point sensitivity
*/
public PointSensitivityBuilder forwardFxRatePointSensitivity(ResolvedFxSingle fx, RatesProvider provider) {
FxForwardRates fxForwardRates = provider.fxForwardRates(fx.getCurrencyPair());
PointSensitivityBuilder forwardFxRatePointSensitivity = fxForwardRates.ratePointSensitivity(
fx.getReceiveCurrencyAmount().getCurrency(), fx.getPaymentDate());
return forwardFxRatePointSensitivity;
}
/**
* Calculates the sensitivity of the forward exchange rate to the spot rate.
*
* The returned value is based on the direction of the FX product.
*
* @param fx the product
* @param provider the rates provider
* @return the sensitivity to spot
*/
public double forwardFxRateSpotSensitivity(ResolvedFxSingle fx, RatesProvider provider) {
FxForwardRates fxForwardRates = provider.fxForwardRates(fx.getCurrencyPair());
double forwardRateSpotSensitivity = fxForwardRates.rateFxSpotSensitivity(
fx.getReceiveCurrencyAmount().getCurrency(), fx.getPaymentDate());
return forwardRateSpotSensitivity;
}
}