/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.horizon;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.instrument.bond.BondTotalReturnSwapDefinition;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor;
import com.opengamma.analytics.financial.interestrate.bond.definition.BondTotalReturnSwap;
import com.opengamma.analytics.financial.provider.calculator.issuer.PresentValueIssuerCalculator;
import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderInterface;
import com.opengamma.analytics.financial.provider.description.interestrate.ParameterIssuerProviderInterface;
import com.opengamma.analytics.util.time.TimeCalculator;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.timeseries.precise.zdt.ImmutableZonedDateTimeDoubleTimeSeries;
import com.opengamma.timeseries.precise.zdt.ZonedDateTimeDoubleTimeSeries;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.CurrencyAmount;
import com.opengamma.util.money.MultipleCurrencyAmount;
/**
* Calculates the difference in the present value of a bond total return swap between two dates without
* rate slide i.e. assumes that the market moves in such a way that the discount factors or rates for the
* same maturity <b>dates</b> will be equal.
*/
public final class BondTrsConstantSpreadHorizonCalculator extends HorizonCalculator<BondTotalReturnSwapDefinition, IssuerProviderInterface, ZonedDateTimeDoubleTimeSeries> {
/** Rolls down a yield curve provider */
private static final CurveProviderConstantSpreadRolldownFunction CURVE_ROLLDOWN = CurveProviderConstantSpreadRolldownFunction.getInstance();
/** The present value calculator */
private static final InstrumentDerivativeVisitor<ParameterIssuerProviderInterface, MultipleCurrencyAmount> PV_CALCULATOR =
PresentValueIssuerCalculator.getInstance();
/** The singleton instance */
private static final HorizonCalculator<BondTotalReturnSwapDefinition, IssuerProviderInterface, ZonedDateTimeDoubleTimeSeries> INSTANCE =
new BondTrsConstantSpreadHorizonCalculator();
/**
* Gets the singleton instance.
* @return The instance
*/
public static HorizonCalculator<BondTotalReturnSwapDefinition, IssuerProviderInterface, ZonedDateTimeDoubleTimeSeries> getInstance() {
return INSTANCE;
}
/**
* Private constructor
*/
private BondTrsConstantSpreadHorizonCalculator() {
}
@Override
public MultipleCurrencyAmount getTheta(final BondTotalReturnSwapDefinition definition, final ZonedDateTime date,
final IssuerProviderInterface data, final int daysForward, final Calendar calendar,
final ZonedDateTimeDoubleTimeSeries fixingSeries) {
ArgumentChecker.notNull(definition, "definition");
ArgumentChecker.notNull(date, "date");
ArgumentChecker.notNull(data, "data");
ArgumentChecker.isTrue(daysForward == 1 || daysForward == -1, "daysForward must be either 1 or -1");
final BondTotalReturnSwap instrumentToday = definition.toDerivative(date, fixingSeries);
final ZonedDateTime horizonDate = date.plusDays(daysForward);
final double shiftTime = TimeCalculator.getTimeBetween(date, horizonDate);
final BondTotalReturnSwap instrumentTomorrow = definition.toDerivative(horizonDate, fixingSeries);
final IssuerProviderInterface dataTomorrow = (IssuerProviderInterface) CURVE_ROLLDOWN.rollDown(data, shiftTime);
final MultipleCurrencyAmount fundingLegPvTomorrow = instrumentTomorrow.getFundingLeg().accept(PV_CALCULATOR, dataTomorrow);
final MultipleCurrencyAmount fundingLegPvToday = instrumentToday.getFundingLeg().accept(PV_CALCULATOR, data);
final MultipleCurrencyAmount bondLegPvTomorrow = instrumentTomorrow.getAsset().accept(PV_CALCULATOR, dataTomorrow).multipliedBy(instrumentTomorrow.getQuantity());
final MultipleCurrencyAmount bondLegPvToday = instrumentToday.getAsset().accept(PV_CALCULATOR, data).multipliedBy(instrumentToday.getQuantity());
final Currency assetCurrency = instrumentToday.getAsset().getCurrency();
final Currency fundingCurrency = instrumentToday.getFundingLeg().getCurrency();
final double fxRate = data.getMulticurveProvider().getFxRate(fundingCurrency, assetCurrency);
final MultipleCurrencyAmount pvToday = bondLegPvToday.plus(CurrencyAmount.of(assetCurrency, fundingLegPvToday.getAmount(fundingCurrency) * fxRate));
final MultipleCurrencyAmount pvTomorrow = bondLegPvTomorrow.plus(CurrencyAmount.of(assetCurrency, fundingLegPvTomorrow.getAmount(fundingCurrency) * fxRate));
return subtract(pvTomorrow, pvToday);
}
@Override
public MultipleCurrencyAmount getTheta(final BondTotalReturnSwapDefinition definition, final ZonedDateTime date, final IssuerProviderInterface data,
final int daysForward, final Calendar calendar) {
return getTheta(definition, date, data, daysForward, calendar, ImmutableZonedDateTimeDoubleTimeSeries.ofEmptyUTC());
}
}