/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.rate;
import static com.opengamma.strata.basics.currency.Currency.GBP;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.date.DayCounts.ACT_365F;
import static com.opengamma.strata.basics.index.OvernightIndices.GBP_SONIA;
import static com.opengamma.strata.basics.index.OvernightIndices.USD_FED_FUND;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.coverBeanEquals;
import static com.opengamma.strata.collect.TestHelper.coverImmutableBean;
import static com.opengamma.strata.collect.TestHelper.date;
import static org.testng.Assert.assertEquals;
import java.time.LocalDate;
import java.util.Optional;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.index.OvernightIndexObservation;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.market.curve.CurveMetadata;
import com.opengamma.strata.market.curve.CurveName;
import com.opengamma.strata.market.curve.Curves;
import com.opengamma.strata.market.curve.InterpolatedNodalCurve;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolator;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolators;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.ZeroRateDiscountFactors;
/**
* Test {@link DiscountOvernightIndexRates}.
*/
@Test
public class DiscountOvernightIndexRatesTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final LocalDate DATE_VAL = date(2015, 6, 3);
private static final LocalDate DATE_BEFORE = date(2015, 6, 2);
private static final LocalDate DATE_AFTER = date(2015, 7, 30);
private static final LocalDate DATE_AFTER_END = date(2015, 7, 31);
private static final OvernightIndexObservation GBP_SONIA_VAL =
OvernightIndexObservation.of(GBP_SONIA, DATE_VAL, REF_DATA);
private static final OvernightIndexObservation GBP_SONIA_BEFORE =
OvernightIndexObservation.of(GBP_SONIA, DATE_BEFORE, REF_DATA);
private static final OvernightIndexObservation GBP_SONIA_AFTER =
OvernightIndexObservation.of(GBP_SONIA, DATE_AFTER, REF_DATA);
private static final OvernightIndexObservation GBP_SONIA_AFTER_END =
OvernightIndexObservation.of(GBP_SONIA, DATE_AFTER_END, REF_DATA);
private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.LINEAR;
private static final CurveName NAME = CurveName.of("TestCurve");
private static final CurveMetadata METADATA = Curves.zeroRates(NAME, ACT_365F);
private static final InterpolatedNodalCurve CURVE =
InterpolatedNodalCurve.of(METADATA, DoubleArray.of(0, 10), DoubleArray.of(0.01, 0.02), INTERPOLATOR);
private static final InterpolatedNodalCurve CURVE2 =
InterpolatedNodalCurve.of(METADATA, DoubleArray.of(0, 10), DoubleArray.of(0.01, 0.03), INTERPOLATOR);
private static final ZeroRateDiscountFactors DFCURVE = ZeroRateDiscountFactors.of(GBP, DATE_VAL, CURVE);
private static final ZeroRateDiscountFactors DFCURVE2 = ZeroRateDiscountFactors.of(GBP, DATE_VAL, CURVE2);
private static final double RATE_BEFORE = 0.013d;
private static final double RATE_VAL = 0.014d;
private static final LocalDateDoubleTimeSeries SERIES = LocalDateDoubleTimeSeries.builder()
.put(DATE_BEFORE, RATE_BEFORE)
.put(DATE_VAL, RATE_VAL)
.build();
private static final LocalDateDoubleTimeSeries SERIES_MINIMAL = LocalDateDoubleTimeSeries.of(DATE_VAL, RATE_VAL);
private static final LocalDateDoubleTimeSeries SERIES_EMPTY = LocalDateDoubleTimeSeries.empty();
//-------------------------------------------------------------------------
public void test_of_withoutFixings() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE);
assertEquals(test.getIndex(), GBP_SONIA);
assertEquals(test.getValuationDate(), DATE_VAL);
assertEquals(test.getFixings(), SERIES_EMPTY);
assertEquals(test.getDiscountFactors(), DFCURVE);
assertEquals(test.getParameterCount(), DFCURVE.getParameterCount());
assertEquals(test.getParameter(0), DFCURVE.getParameter(0));
assertEquals(test.getParameterMetadata(0), DFCURVE.getParameterMetadata(0));
assertEquals(test.withParameter(0, 1d).getDiscountFactors(), DFCURVE.withParameter(0, 1d));
assertEquals(test.withPerturbation((i, v, m) -> v + 1d).getDiscountFactors(), DFCURVE.withPerturbation((i, v, m) -> v + 1d));
assertEquals(test.findData(CURVE.getName()), Optional.of(CURVE));
assertEquals(test.findData(CurveName.of("Rubbish")), Optional.empty());
// check IborIndexRates
OvernightIndexRates test2 = OvernightIndexRates.of(GBP_SONIA, DATE_VAL, CURVE);
assertEquals(test, test2);
}
public void test_of_withFixings() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertEquals(test.getIndex(), GBP_SONIA);
assertEquals(test.getValuationDate(), DATE_VAL);
assertEquals(test.getFixings(), SERIES);
assertEquals(test.getDiscountFactors(), DFCURVE);
}
//-------------------------------------------------------------------------
public void test_withDiscountFactors() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
test = test.withDiscountFactors(DFCURVE2);
assertEquals(test.getIndex(), GBP_SONIA);
assertEquals(test.getValuationDate(), DATE_VAL);
assertEquals(test.getFixings(), SERIES);
assertEquals(test.getDiscountFactors(), DFCURVE2);
}
//-------------------------------------------------------------------------
public void test_rate_beforeValuation_fixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertEquals(test.rate(GBP_SONIA_BEFORE), RATE_BEFORE);
}
public void test_rate_beforeValuation_noFixing_emptySeries() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES_EMPTY);
assertThrowsIllegalArg(() -> test.rate(GBP_SONIA_BEFORE));
}
public void test_rate_beforeValuation_noFixing_notEmptySeries() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES_MINIMAL);
assertThrowsIllegalArg(() -> test.rate(GBP_SONIA_BEFORE));
}
public void test_rate_onValuation_fixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertEquals(test.rate(GBP_SONIA_VAL), RATE_VAL);
}
public void test_rateIgnoringFixings_onValuation_fixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
LocalDate startDate = GBP_SONIA_VAL.getEffectiveDate();
LocalDate endDate = GBP_SONIA_VAL.getMaturityDate();
double accrualFactor = GBP_SONIA_VAL.getYearFraction();
double expected = (DFCURVE.discountFactor(startDate) / DFCURVE.discountFactor(endDate) - 1) / accrualFactor;
assertEquals(test.rateIgnoringFixings(GBP_SONIA_VAL), expected, 1e-8);
}
public void test_rate_onPublication_noFixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES_EMPTY);
LocalDate startDate = GBP_SONIA_VAL.getEffectiveDate();
LocalDate endDate = GBP_SONIA_VAL.getMaturityDate();
double accrualFactor = GBP_SONIA.getDayCount().yearFraction(startDate, endDate);
double expected = (DFCURVE.discountFactor(startDate) / DFCURVE.discountFactor(endDate) - 1) / accrualFactor;
assertEquals(test.rate(GBP_SONIA_VAL), expected, 1e-4);
}
public void test_rate_afterPublication() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
LocalDate startDate = GBP_SONIA_AFTER.getEffectiveDate();
LocalDate endDate = GBP_SONIA_AFTER.getMaturityDate();
double accrualFactor = GBP_SONIA.getDayCount().yearFraction(startDate, endDate);
double expected = (DFCURVE.discountFactor(startDate) / DFCURVE.discountFactor(endDate) - 1) / accrualFactor;
assertEquals(test.rate(GBP_SONIA_AFTER), expected, 1e-8);
}
//-------------------------------------------------------------------------
public void test_ratePointSensitivity_fixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertEquals(test.ratePointSensitivity(GBP_SONIA_BEFORE), PointSensitivityBuilder.none());
assertEquals(test.ratePointSensitivity(GBP_SONIA_VAL), PointSensitivityBuilder.none());
}
public void test_rateIgnoringFixingsPointSensitivity_onValuation() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
OvernightRateSensitivity expected = OvernightRateSensitivity.of(GBP_SONIA_VAL, 1d);
assertEquals(test.rateIgnoringFixingsPointSensitivity(GBP_SONIA_VAL), expected);
}
public void test_ratePointSensitivity_onPublication_noFixing() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES_EMPTY);
OvernightRateSensitivity expected = OvernightRateSensitivity.of(GBP_SONIA_VAL, 1d);
assertEquals(test.ratePointSensitivity(GBP_SONIA_VAL), expected);
}
public void test_ratePointSensitivity_afterPublication() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
OvernightRateSensitivity expected = OvernightRateSensitivity.of(GBP_SONIA_AFTER, 1d);
assertEquals(test.ratePointSensitivity(GBP_SONIA_AFTER), expected);
}
//-------------------------------------------------------------------------
public void test_periodRate() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
double accrualFactor = GBP_SONIA.getDayCount().yearFraction(DATE_AFTER, DATE_AFTER_END);
double expected = (DFCURVE.discountFactor(DATE_AFTER) / DFCURVE.discountFactor(DATE_AFTER_END) - 1) / accrualFactor;
assertEquals(test.periodRate(GBP_SONIA_AFTER, DATE_AFTER_END), expected, 1e-8);
}
public void test_periodRate_badDates() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertThrowsIllegalArg(() -> test.periodRate(GBP_SONIA_BEFORE, DATE_VAL));
assertThrowsIllegalArg(() -> test.periodRate(GBP_SONIA_AFTER_END, DATE_AFTER));
}
//-------------------------------------------------------------------------
public void test_periodRatePointSensitivity() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
OvernightRateSensitivity expected = OvernightRateSensitivity.ofPeriod(GBP_SONIA_AFTER, DATE_AFTER_END, GBP, 1d);
assertEquals(test.periodRatePointSensitivity(GBP_SONIA_AFTER, DATE_AFTER_END), expected);
}
public void test_periodRatePointSensitivity_badDates() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
assertThrowsIllegalArg(() -> test.periodRatePointSensitivity(GBP_SONIA_BEFORE, DATE_VAL));
assertThrowsIllegalArg(() -> test.periodRatePointSensitivity(GBP_SONIA_AFTER_END, DATE_AFTER));
}
//-------------------------------------------------------------------------
// proper end-to-end tests are elsewhere
public void test_parameterSensitivity() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
OvernightRateSensitivity point = OvernightRateSensitivity.ofPeriod(GBP_SONIA_AFTER, DATE_AFTER_END, GBP, 1d);
assertEquals(test.parameterSensitivity(point).size(), 1);
}
//-------------------------------------------------------------------------
public void test_createParameterSensitivity() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
DoubleArray sensitivities = DoubleArray.of(0.12, 0.15);
CurrencyParameterSensitivities sens = test.createParameterSensitivity(USD, sensitivities);
assertEquals(sens.getSensitivities().get(0), CURVE.createParameterSensitivity(USD, sensitivities));
}
//-------------------------------------------------------------------------
public void coverage() {
DiscountOvernightIndexRates test = DiscountOvernightIndexRates.of(GBP_SONIA, DFCURVE, SERIES);
coverImmutableBean(test);
DiscountOvernightIndexRates test2 = DiscountOvernightIndexRates.of(USD_FED_FUND, DFCURVE2, SERIES_EMPTY);
coverBeanEquals(test, test2);
}
}