/** * Copyright (C) 2015 - 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.surface.ConstantSurface; import com.opengamma.strata.market.surface.InterpolatedNodalSurface; import com.opengamma.strata.market.surface.Surface; import com.opengamma.strata.market.surface.SurfaceName; import com.opengamma.strata.market.surface.Surfaces; import com.opengamma.strata.market.surface.interpolator.GridSurfaceInterpolator; /** * Test {@link SabrInterestRateParameters}. */ @Test public class SabrInterestRateParametersTest { private static final GridSurfaceInterpolator GRID = GridSurfaceInterpolator.of(LINEAR, LINEAR); private static final InterpolatedNodalSurface ALPHA_SURFACE = InterpolatedNodalSurface.of( Surfaces.sabrParameterByExpiryTenor("SabrAlpha", ACT_ACT_ISDA, ValueType.SABR_ALPHA), DoubleArray.of(0, 0, 10, 10), DoubleArray.of(0, 10, 0, 10), DoubleArray.of(0.2, 0.2, 0.2, 0.2), GRID); private static final InterpolatedNodalSurface BETA_SURFACE = InterpolatedNodalSurface.of( Surfaces.sabrParameterByExpiryTenor("SabrBeta", ACT_ACT_ISDA, ValueType.SABR_BETA), DoubleArray.of(0, 0, 10, 10), DoubleArray.of(0, 10, 0, 10), DoubleArray.of(1, 1, 1, 1), GRID); private static final InterpolatedNodalSurface RHO_SURFACE = InterpolatedNodalSurface.of( Surfaces.sabrParameterByExpiryTenor("SabrRho", ACT_ACT_ISDA, ValueType.SABR_RHO), DoubleArray.of(0, 0, 10, 10), DoubleArray.of(0, 10, 0, 10), DoubleArray.of(-0.5, -0.5, -0.5, -0.5), GRID); private static final InterpolatedNodalSurface NU_SURFACE = InterpolatedNodalSurface.of( Surfaces.sabrParameterByExpiryTenor("SabrNu", ACT_ACT_ISDA, ValueType.SABR_NU), DoubleArray.of(0, 0, 10, 10), DoubleArray.of(0, 10, 0, 10), DoubleArray.of(0.5, 0.5, 0.5, 0.5), GRID); private static final SabrVolatilityFormula FORMULA = SabrVolatilityFormula.hagan(); private static final SabrInterestRateParameters PARAMETERS = SabrInterestRateParameters.of(ALPHA_SURFACE, BETA_SURFACE, RHO_SURFACE, NU_SURFACE, FORMULA); public void hashEqualGetter() { assertEquals(PARAMETERS.getAlphaSurface(), ALPHA_SURFACE); assertEquals(PARAMETERS.getBetaSurface(), BETA_SURFACE); assertEquals(PARAMETERS.getRhoSurface(), RHO_SURFACE); assertEquals(PARAMETERS.getNuSurface(), NU_SURFACE); assertEquals(PARAMETERS.getSabrVolatilityFormula(), FORMULA); assertEquals(PARAMETERS.getShiftSurface().getName(), SurfaceName.of("Zero shift")); double expiry = 2.0; double tenor = 3.0; double alpha = ALPHA_SURFACE.zValue(expiry, tenor); double beta = BETA_SURFACE.zValue(expiry, tenor); double rho = RHO_SURFACE.zValue(expiry, tenor); double nu = NU_SURFACE.zValue(expiry, tenor); assertEquals(PARAMETERS.alpha(expiry, tenor), alpha); assertEquals(PARAMETERS.beta(expiry, tenor), beta); assertEquals(PARAMETERS.rho(expiry, tenor), rho); assertEquals(PARAMETERS.nu(expiry, tenor), nu); double strike = 1.1; double forward = 1.05; assertEquals(PARAMETERS.volatility(expiry, tenor, strike, forward), FORMULA.volatility(forward, strike, expiry, alpha, beta, rho, nu)); double[] adjCmp = PARAMETERS.volatilityAdjoint(expiry, tenor, 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]); } SabrInterestRateParameters other = SabrInterestRateParameters.of(ALPHA_SURFACE, BETA_SURFACE, RHO_SURFACE, NU_SURFACE, FORMULA); assertEquals(PARAMETERS, other); assertEquals(PARAMETERS.hashCode(), other.hashCode()); } public void negativeRates() { double shift = 0.05; Surface surface = ConstantSurface.of("shfit", shift); SabrInterestRateParameters params = SabrInterestRateParameters.of(ALPHA_SURFACE, BETA_SURFACE, RHO_SURFACE, NU_SURFACE, surface, FORMULA); double expiry = 2.0; double tenor = 3.0; assertEquals(params.alpha(expiry, tenor), ALPHA_SURFACE.zValue(expiry, tenor)); assertEquals(params.beta(expiry, tenor), BETA_SURFACE.zValue(expiry, tenor)); assertEquals(params.rho(expiry, tenor), RHO_SURFACE.zValue(expiry, tenor)); assertEquals(params.nu(expiry, tenor), NU_SURFACE.zValue(expiry, tenor)); double strike = -0.02; double forward = 0.015; double alpha = ALPHA_SURFACE.zValue(expiry, tenor); double beta = BETA_SURFACE.zValue(expiry, tenor); double rho = RHO_SURFACE.zValue(expiry, tenor); double nu = NU_SURFACE.zValue(expiry, tenor); assertEquals(params.volatility(expiry, tenor, strike, forward), FORMULA.volatility(forward + shift, strike + shift, expiry, alpha, beta, rho, nu)); double[] adjCmp = params.volatilityAdjoint(expiry, tenor, 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 coverage() { coverImmutableBean(PARAMETERS); } }