/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.swaption;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ISDA;
import static com.opengamma.strata.collect.TestHelper.coverBeanEquals;
import static com.opengamma.strata.collect.TestHelper.coverImmutableBean;
import static com.opengamma.strata.collect.TestHelper.dateUtc;
import static com.opengamma.strata.market.model.SabrParameterType.ALPHA;
import static com.opengamma.strata.market.model.SabrParameterType.BETA;
import static com.opengamma.strata.market.model.SabrParameterType.NU;
import static com.opengamma.strata.market.model.SabrParameterType.RHO;
import static org.testng.Assert.assertEquals;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Optional;
import org.testng.annotations.Test;
import com.opengamma.strata.collect.DoubleArrayMath;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.param.CurrencyParameterSensitivity;
import com.opengamma.strata.market.param.UnitParameterSensitivity;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.market.surface.SurfaceName;
import com.opengamma.strata.pricer.model.SabrInterestRateParameters;
import com.opengamma.strata.product.swap.type.FixedIborSwapConvention;
/**
* Test {@link SabrSwaptionVolatilities}.
*/
@Test
public class SabrSwaptionVolatilitiesTest {
private static final LocalDate DATE = LocalDate.of(2014, 1, 3);
private static final LocalTime TIME = LocalTime.of(10, 0);
private static final ZoneId ZONE = ZoneId.of("Europe/London");
private static final ZonedDateTime DATE_TIME = DATE.atTime(TIME).atZone(ZONE);
private static final SabrInterestRateParameters PARAM = SwaptionSabrRateVolatilityDataSet.SABR_PARAM_SHIFT_USD;
private static final FixedIborSwapConvention CONV = SwaptionSabrRateVolatilityDataSet.SWAP_CONVENTION_USD;
private static final ZonedDateTime[] TEST_OPTION_EXPIRY = new ZonedDateTime[] {
dateUtc(2014, 1, 3), dateUtc(2014, 1, 3), dateUtc(2015, 1, 3), dateUtc(2017, 1, 3)};
private static final int NB_TEST = TEST_OPTION_EXPIRY.length;
private static final double[] TEST_TENOR = new double[] {2.0, 6.0, 7.0, 15.0};
private static final double TEST_FORWARD = 0.025;
private static final double[] TEST_STRIKE = new double[] {0.02, 0.025, 0.03};
private static final int NB_STRIKE = TEST_STRIKE.length;
static final SwaptionVolatilitiesName NAME = SwaptionVolatilitiesName.of("Test-SABR");
static final SwaptionVolatilitiesName NAME2 = SwaptionVolatilitiesName.of("Test-SABR2");
private static final double TOLERANCE_VOL = 1.0E-10;
public void test_of() {
SabrParametersSwaptionVolatilities test = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
assertEquals(test.getConvention(), CONV);
assertEquals(test.getDayCount(), ACT_ACT_ISDA);
assertEquals(test.getParameters(), PARAM);
assertEquals(test.getValuationDateTime(), DATE_TIME);
}
public void test_findData() {
SabrParametersSwaptionVolatilities test = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
assertEquals(test.findData(PARAM.getAlphaSurface().getName()), Optional.of(PARAM.getAlphaSurface()));
assertEquals(test.findData(PARAM.getBetaSurface().getName()), Optional.of(PARAM.getBetaSurface()));
assertEquals(test.findData(PARAM.getRhoSurface().getName()), Optional.of(PARAM.getRhoSurface()));
assertEquals(test.findData(PARAM.getNuSurface().getName()), Optional.of(PARAM.getNuSurface()));
assertEquals(test.findData(PARAM.getShiftSurface().getName()), Optional.of(PARAM.getShiftSurface()));
assertEquals(test.findData(SurfaceName.of("Rubbish")), Optional.empty());
}
public void test_calc() {
SabrParametersSwaptionVolatilities test = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
assertEquals(test.alpha(1d, 2d), PARAM.alpha(1d, 2d));
assertEquals(test.beta(1d, 2d), PARAM.beta(1d, 2d));
assertEquals(test.rho(1d, 2d), PARAM.rho(1d, 2d));
assertEquals(test.nu(1d, 2d), PARAM.nu(1d, 2d));
assertEquals(test.shift(1d, 2d), PARAM.shift(1d, 2d));
}
public void test_tenor() {
SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
double test1 = prov.tenor(DATE, DATE);
assertEquals(test1, 0d);
double test2 = prov.tenor(DATE, DATE.plusYears(2));
double test3 = prov.tenor(DATE, DATE.minusYears(2));
assertEquals(test2, -test3);
double test4 = prov.tenor(DATE, LocalDate.of(2019, 2, 2));
double test5 = prov.tenor(DATE, LocalDate.of(2018, 12, 31));
assertEquals(test4, 5d);
assertEquals(test5, 5d);
}
public void test_relativeTime() {
SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
double test1 = prov.relativeTime(DATE_TIME);
assertEquals(test1, 0d);
double test2 = prov.relativeTime(DATE_TIME.plusYears(2));
double test3 = prov.relativeTime(DATE_TIME.minusYears(2));
assertEquals(test2, -test3, 1e-2);
}
public void test_volatility() {
SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
for (int i = 0; i < NB_TEST; i++) {
for (int j = 0; j < NB_STRIKE; ++j) {
double expiryTime = prov.relativeTime(TEST_OPTION_EXPIRY[i]);
double volExpected = PARAM.volatility(expiryTime, TEST_TENOR[i], TEST_STRIKE[j], TEST_FORWARD);
double volComputed = prov.volatility(TEST_OPTION_EXPIRY[i], TEST_TENOR[i], TEST_STRIKE[j], TEST_FORWARD);
assertEquals(volComputed, volExpected, TOLERANCE_VOL);
}
}
}
public void test_parameterSensitivity() {
double alphaSensi = 2.24, betaSensi = 3.45, rhoSensi = -2.12, nuSensi = -0.56;
SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
for (int i = 0; i < NB_TEST; i++) {
double expiryTime = prov.relativeTime(TEST_OPTION_EXPIRY[i]);
PointSensitivities point = PointSensitivities.of(
SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], ALPHA, USD, alphaSensi),
SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], BETA, USD, betaSensi),
SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], RHO, USD, rhoSensi),
SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], NU, USD, nuSensi));
CurrencyParameterSensitivities sensiComputed = prov.parameterSensitivity(point);
UnitParameterSensitivity alphaSensitivities = prov.getParameters().getAlphaSurface()
.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]);
UnitParameterSensitivity betaSensitivities = prov.getParameters().getBetaSurface()
.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]);
UnitParameterSensitivity rhoSensitivities = prov.getParameters().getRhoSurface()
.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]);
UnitParameterSensitivity nuSensitivities = prov.getParameters().getNuSurface()
.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]);
CurrencyParameterSensitivity alphaSensiObj = sensiComputed.getSensitivity(
SwaptionSabrRateVolatilityDataSet.META_ALPHA.getSurfaceName(), USD);
CurrencyParameterSensitivity betaSensiObj = sensiComputed.getSensitivity(
SwaptionSabrRateVolatilityDataSet.META_BETA_USD.getSurfaceName(), USD);
CurrencyParameterSensitivity rhoSensiObj = sensiComputed.getSensitivity(
SwaptionSabrRateVolatilityDataSet.META_RHO.getSurfaceName(), USD);
CurrencyParameterSensitivity nuSensiObj = sensiComputed.getSensitivity(
SwaptionSabrRateVolatilityDataSet.META_NU.getSurfaceName(), USD);
DoubleArray alphaNodeSensiComputed = alphaSensiObj.getSensitivity();
DoubleArray betaNodeSensiComputed = betaSensiObj.getSensitivity();
DoubleArray rhoNodeSensiComputed = rhoSensiObj.getSensitivity();
DoubleArray nuNodeSensiComputed = nuSensiObj.getSensitivity();
assertEquals(alphaSensitivities.getSensitivity().size(), alphaNodeSensiComputed.size());
assertEquals(betaSensitivities.getSensitivity().size(), betaNodeSensiComputed.size());
assertEquals(rhoSensitivities.getSensitivity().size(), rhoNodeSensiComputed.size());
assertEquals(nuSensitivities.getSensitivity().size(), nuNodeSensiComputed.size());
for (int k = 0; k < alphaNodeSensiComputed.size(); ++k) {
assertEquals(alphaNodeSensiComputed.get(k), alphaSensitivities.getSensitivity().get(k) * alphaSensi, TOLERANCE_VOL);
}
for (int k = 0; k < betaNodeSensiComputed.size(); ++k) {
assertEquals(betaNodeSensiComputed.get(k), betaSensitivities.getSensitivity().get(k) * betaSensi, TOLERANCE_VOL);
}
for (int k = 0; k < rhoNodeSensiComputed.size(); ++k) {
assertEquals(rhoNodeSensiComputed.get(k), rhoSensitivities.getSensitivity().get(k) * rhoSensi, TOLERANCE_VOL);
}
for (int k = 0; k < nuNodeSensiComputed.size(); ++k) {
assertEquals(nuNodeSensiComputed.get(k), nuSensitivities.getSensitivity().get(k) * nuSensi, TOLERANCE_VOL);
}
}
}
public void test_parameterSensitivity_multi() {
double[] points1 = new double[] {2.24, 3.45, -2.12, -0.56};
double[] points2 = new double[] {-0.145, 1.01, -5.0, -11.0};
double[] points3 = new double[] {1.3, -4.32, 2.1, -7.18};
SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
double expiryTime0 = prov.relativeTime(TEST_OPTION_EXPIRY[0]);
double expiryTime3 = prov.relativeTime(TEST_OPTION_EXPIRY[3]);
for (int i = 0; i < NB_TEST; i++) {
PointSensitivities sensi1 = PointSensitivities.of(
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], ALPHA, USD, points1[0]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], BETA, USD, points1[1]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], RHO, USD, points1[2]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], NU, USD, points1[3]));
PointSensitivities sensi2 = PointSensitivities.of(
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], ALPHA, USD, points2[0]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], BETA, USD, points2[1]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], RHO, USD, points2[2]),
SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], NU, USD, points2[3]));
PointSensitivities sensi3 = PointSensitivities.of(
SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], ALPHA, USD, points3[0]),
SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], BETA, USD, points3[1]),
SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], RHO, USD, points3[2]),
SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], NU, USD, points3[3]));
PointSensitivities sensis = sensi1.combinedWith(sensi2).combinedWith(sensi3).normalized();
CurrencyParameterSensitivities computed = prov.parameterSensitivity(sensis);
CurrencyParameterSensitivities expected = prov.parameterSensitivity(sensi1)
.combinedWith(prov.parameterSensitivity(sensi2))
.combinedWith(prov.parameterSensitivity(sensi3));
DoubleArrayMath.fuzzyEquals(
computed.getSensitivity(PARAM.getAlphaSurface().getName(), USD).getSensitivity().toArray(),
expected.getSensitivity(PARAM.getAlphaSurface().getName(), USD).getSensitivity().toArray(),
TOLERANCE_VOL);
DoubleArrayMath.fuzzyEquals(
computed.getSensitivity(PARAM.getBetaSurface().getName(), USD).getSensitivity().toArray(),
expected.getSensitivity(PARAM.getBetaSurface().getName(), USD).getSensitivity().toArray(),
TOLERANCE_VOL);
DoubleArrayMath.fuzzyEquals(
computed.getSensitivity(PARAM.getRhoSurface().getName(), USD).getSensitivity().toArray(),
expected.getSensitivity(PARAM.getRhoSurface().getName(), USD).getSensitivity().toArray(),
TOLERANCE_VOL);
DoubleArrayMath.fuzzyEquals(
computed.getSensitivity(PARAM.getNuSurface().getName(), USD).getSensitivity().toArray(),
expected.getSensitivity(PARAM.getNuSurface().getName(), USD).getSensitivity().toArray(),
TOLERANCE_VOL);
}
}
public void coverage() {
SabrParametersSwaptionVolatilities test1 = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM);
coverImmutableBean(test1);
SabrParametersSwaptionVolatilities test2 = SabrParametersSwaptionVolatilities.of(
NAME2,
SwaptionSabrRateVolatilityDataSet.SWAP_CONVENTION_EUR,
DATE_TIME.plusDays(1),
SwaptionSabrRateVolatilityDataSet.SABR_PARAM_USD);
coverBeanEquals(test1, test2);
}
}