/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.model; import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ISDA; import static com.opengamma.strata.collect.TestHelper.coverImmutableBean; import static com.opengamma.strata.market.curve.interpolator.CurveInterpolators.LINEAR; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.market.ValueType; import com.opengamma.strata.market.curve.ConstantCurve; import com.opengamma.strata.market.curve.Curve; 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.param.ParameterMetadata; /** * Test {@link SabrParameters}. */ @Test public class SabrParametersTest { private static final InterpolatedNodalCurve ALPHA_CURVE = InterpolatedNodalCurve.of( Curves.sabrParameterByExpiry("SabrAlpha", ACT_ACT_ISDA, ValueType.SABR_ALPHA), DoubleArray.of(0, 10), DoubleArray.of(0.2, 0.2), LINEAR); private static final InterpolatedNodalCurve BETA_CURVE = InterpolatedNodalCurve.of(Curves.sabrParameterByExpiry("SabrBeta", ACT_ACT_ISDA, ValueType.SABR_BETA), DoubleArray.of(0, 10), DoubleArray.of(1, 1), LINEAR); private static final InterpolatedNodalCurve RHO_CURVE = InterpolatedNodalCurve.of( Curves.sabrParameterByExpiry("SabrRho", ACT_ACT_ISDA, ValueType.SABR_RHO), DoubleArray.of(0, 10), DoubleArray.of(-0.5, -0.5), LINEAR); private static final InterpolatedNodalCurve NU_CURVE = InterpolatedNodalCurve.of( Curves.sabrParameterByExpiry("SabrNu", ACT_ACT_ISDA, ValueType.SABR_NU), DoubleArray.of(0, 10), DoubleArray.of(0.5, 0.5), LINEAR); private static final SabrVolatilityFormula FORMULA = SabrVolatilityFormula.hagan(); private static final SabrParameters PARAMETERS = SabrParameters.of(ALPHA_CURVE, BETA_CURVE, RHO_CURVE, NU_CURVE, FORMULA); public void getter() { assertEquals(PARAMETERS.getAlphaCurve(), ALPHA_CURVE); assertEquals(PARAMETERS.getBetaCurve(), BETA_CURVE); assertEquals(PARAMETERS.getRhoCurve(), RHO_CURVE); assertEquals(PARAMETERS.getNuCurve(), NU_CURVE); assertEquals(PARAMETERS.getSabrVolatilityFormula(), FORMULA); assertEquals(PARAMETERS.getShiftCurve().getName(), CurveName.of("Zero shift")); assertEquals(PARAMETERS.getDayCount(), ACT_ACT_ISDA); assertEquals(PARAMETERS.getParameterCount(), 9); double expiry = 2.0; double alpha = ALPHA_CURVE.yValue(expiry); double beta = BETA_CURVE.yValue(expiry); double rho = RHO_CURVE.yValue(expiry); double nu = NU_CURVE.yValue(expiry); assertEquals(PARAMETERS.alpha(expiry), alpha); assertEquals(PARAMETERS.beta(expiry), beta); assertEquals(PARAMETERS.rho(expiry), rho); assertEquals(PARAMETERS.nu(expiry), nu); double strike = 1.1; double forward = 1.05; assertEquals(PARAMETERS.volatility(expiry, strike, forward), FORMULA.volatility(forward, strike, expiry, alpha, beta, rho, nu)); double[] adjCmp = PARAMETERS.volatilityAdjoint(expiry, strike, forward).getDerivatives().toArray(); double[] adjExp = FORMULA.volatilityAdjoint(forward, strike, expiry, alpha, beta, rho, nu).getDerivatives().toArray(); for (int i = 0; i < 6; ++i) { assertEquals(adjCmp[i], adjExp[i]); } for (int i = 0; i < 9; ++i) { if (i < 2) { assertEquals(PARAMETERS.getParameterMetadata(i), ALPHA_CURVE.getParameterMetadata(i)); assertEquals(PARAMETERS.getParameter(i), ALPHA_CURVE.getParameter(i)); } else if (i < 4) { assertEquals(PARAMETERS.getParameterMetadata(i), BETA_CURVE.getParameterMetadata(i - 2)); assertEquals(PARAMETERS.getParameter(i), BETA_CURVE.getParameter(i - 2)); } else if (i < 6) { assertEquals(PARAMETERS.getParameterMetadata(i), RHO_CURVE.getParameterMetadata(i - 4)); assertEquals(PARAMETERS.getParameter(i), RHO_CURVE.getParameter(i - 4)); } else if (i < 8) { assertEquals(PARAMETERS.getParameterMetadata(i), NU_CURVE.getParameterMetadata(i - 6)); assertEquals(PARAMETERS.getParameter(i), NU_CURVE.getParameter(i - 6)); } else { assertEquals(PARAMETERS.getParameterMetadata(i), ParameterMetadata.empty()); assertEquals(PARAMETERS.getParameter(i), 0d); } } } public void negativeRates() { double shift = 0.05; Curve surface = ConstantCurve.of("shfit", shift); SabrParameters params = SabrParameters.of(ALPHA_CURVE, BETA_CURVE, RHO_CURVE, NU_CURVE, surface, FORMULA); double expiry = 2.0; assertEquals(params.alpha(expiry), ALPHA_CURVE.yValue(expiry)); assertEquals(params.beta(expiry), BETA_CURVE.yValue(expiry)); assertEquals(params.rho(expiry), RHO_CURVE.yValue(expiry)); assertEquals(params.nu(expiry), NU_CURVE.yValue(expiry)); double strike = -0.02; double forward = 0.015; double alpha = ALPHA_CURVE.yValue(expiry); double beta = BETA_CURVE.yValue(expiry); double rho = RHO_CURVE.yValue(expiry); double nu = NU_CURVE.yValue(expiry); assertEquals(params.volatility(expiry, strike, forward), FORMULA.volatility(forward + shift, strike + shift, expiry, alpha, beta, rho, nu)); double[] adjCmp = params.volatilityAdjoint(expiry, strike, forward).getDerivatives().toArray(); double[] adjExp = FORMULA.volatilityAdjoint( forward + shift, strike + shift, expiry, alpha, beta, rho, nu).getDerivatives().toArray(); for (int i = 0; i < 4; ++i) { assertEquals(adjCmp[i], adjExp[i]); } } public void perturbation() { SabrParameters test = PARAMETERS.withPerturbation((i, v, m) -> (2d + i) * v); SabrParameters expected = PARAMETERS; for (int i = 0; i < PARAMETERS.getParameterCount(); ++i) { expected = expected.withParameter(i, (2d + i) * expected.getParameter(i)); } assertEquals(test, expected); } //------------------------------------------------------------------------- public void coverage() { coverImmutableBean(PARAMETERS); } }