com.opengamma.strata.pricer.impl.rate.ForwardIborInterpolatedRateComputationFn 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.impl.rate;
import java.time.LocalDate;
import com.opengamma.strata.basics.index.IborIndexObservation;
import com.opengamma.strata.collect.tuple.DoublesPair;
import com.opengamma.strata.market.explain.ExplainKey;
import com.opengamma.strata.market.explain.ExplainMapBuilder;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.rate.IborIndexRates;
import com.opengamma.strata.pricer.rate.RateComputationFn;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.rate.IborInterpolatedRateComputation;
/**
* Rate computation implementation for rate based on the weighted average of the fixing
* on a single date of two Ibor indices.
*
* The rate computation queries the rates from the {@code RatesProvider} and interpolates them.
* There is no convexity adjustment computed in this implementation.
*/
public class ForwardIborInterpolatedRateComputationFn
implements RateComputationFn {
/**
* Default instance.
*/
public static final ForwardIborInterpolatedRateComputationFn DEFAULT = new ForwardIborInterpolatedRateComputationFn();
/**
* Creates an instance.
*/
public ForwardIborInterpolatedRateComputationFn() {
}
//-------------------------------------------------------------------------
@Override
public double rate(
IborInterpolatedRateComputation computation,
LocalDate startDate,
LocalDate endDate,
RatesProvider provider) {
IborIndexObservation obs1 = computation.getShortObservation();
IborIndexObservation obs2 = computation.getLongObservation();
IborIndexRates rates1 = provider.iborIndexRates(obs1.getIndex());
IborIndexRates rates2 = provider.iborIndexRates(obs2.getIndex());
double rate1 = rates1.rate(obs1);
double rate2 = rates2.rate(obs2);
DoublesPair weights = weights(obs1, obs2, endDate);
return ((rate1 * weights.getFirst()) + (rate2 * weights.getSecond())) / (weights.getFirst() + weights.getSecond());
}
@Override
public PointSensitivityBuilder rateSensitivity(
IborInterpolatedRateComputation computation,
LocalDate startDate,
LocalDate endDate,
RatesProvider provider) {
// computes the dates related to the underlying deposits associated to the indices
IborIndexObservation obs1 = computation.getShortObservation();
IborIndexObservation obs2 = computation.getLongObservation();
DoublesPair weights = weights(obs1, obs2, endDate);
double totalWeight = weights.getFirst() + weights.getSecond();
IborIndexRates ratesIndex1 = provider.iborIndexRates(obs1.getIndex());
PointSensitivityBuilder sens1 = ratesIndex1.ratePointSensitivity(obs1)
.multipliedBy(weights.getFirst() / totalWeight);
IborIndexRates ratesIndex2 = provider.iborIndexRates(obs2.getIndex());
PointSensitivityBuilder sens2 = ratesIndex2.ratePointSensitivity(obs2)
.multipliedBy(weights.getSecond() / totalWeight);
return sens1.combinedWith(sens2);
}
@Override
public double explainRate(
IborInterpolatedRateComputation computation,
LocalDate startDate,
LocalDate endDate,
RatesProvider provider,
ExplainMapBuilder builder) {
IborIndexObservation obs1 = computation.getShortObservation();
IborIndexObservation obs2 = computation.getLongObservation();
DoublesPair weights = weights(obs1, obs2, endDate);
IborIndexRates rates1 = provider.iborIndexRates(obs1.getIndex());
IborIndexRates rates2 = provider.iborIndexRates(obs2.getIndex());
rates1.explainRate(obs1, builder, child -> child.put(ExplainKey.WEIGHT, weights.getFirst()));
rates2.explainRate(obs2, builder, child -> child.put(ExplainKey.WEIGHT, weights.getSecond()));
double rate = rate(computation, startDate, endDate, provider);
builder.put(ExplainKey.COMBINED_RATE, rate);
return rate;
}
// computes the weights related to the two indices
private DoublesPair weights(IborIndexObservation obs1, IborIndexObservation obs2, LocalDate endDate) {
// weights: linear interpolation on the number of days between the fixing date and the maturity dates of the
// actual coupons on one side and the maturity dates of the underlying deposit on the other side.
long fixingEpochDay = obs1.getFixingDate().toEpochDay();
double days1 = obs1.getMaturityDate().toEpochDay() - fixingEpochDay;
double days2 = obs2.getMaturityDate().toEpochDay() - fixingEpochDay;
double daysN = endDate.toEpochDay() - fixingEpochDay;
double weight1 = (days2 - daysN) / (days2 - days1);
double weight2 = (daysN - days1) / (days2 - days1);
return DoublesPair.of(weight1, weight2);
}
}