public void test_of() { DeformedSurface test = DeformedSurface.of(METADATA, SURFACE_ORG, FUNCTION); assertEquals(test.getDeformationFunction(), FUNCTION); assertEquals(test.getMetadata(), METADATA); assertEquals(test.getName(), METADATA.getSurfaceName()); assertEquals(test.getOriginalSurface(), SURFACE_ORG); assertEquals(test.getParameterCount(), SIZE); assertEquals(test.getParameter(2), SURFACE_ORG.getParameter(2)); assertEquals(test.getParameterMetadata(2), SURFACE_ORG.getParameterMetadata(2)); }
@Override public DeformedSurface build() { return new DeformedSurface( metadata, originalSurface, deformationFunction); }
/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(DeformedSurface beanToCopy) { this.metadata = beanToCopy.getMetadata(); this.originalSurface = beanToCopy.getOriginalSurface(); this.deformationFunction = beanToCopy.getDeformationFunction(); }
public void test_withParameter() { assertThrowsIllegalArg(() -> DeformedSurface.of(METADATA, SURFACE_ORG, FUNCTION).withParameter(1, 1.2d)); }
public void test_zValue() { double tol = 1.0e-14; double x = 2.5; double y = 1.44; DeformedSurface test = DeformedSurface.of(METADATA, SURFACE_ORG, FUNCTION); double computedValue1 = test.zValue(x, y); double computedValue2 = test.zValue(DoublesPair.of(x, y)); UnitParameterSensitivity computedSensi1 = test.zValueParameterSensitivity(x, y); UnitParameterSensitivity computedSensi2 = test.zValueParameterSensitivity(DoublesPair.of(x, y)); ValueDerivatives expected = FUNCTION.apply(DoublesPair.of(x, y)); assertEquals(computedValue1, expected.getValue()); assertEquals(computedValue2, expected.getValue()); assertTrue(DoubleArrayMath.fuzzyEquals( computedSensi1.getSensitivity().toArray(), expected.getDerivatives().toArray(), tol)); assertTrue(DoubleArrayMath.fuzzyEquals( computedSensi2.getSensitivity().toArray(), expected.getDerivatives().toArray(), tol)); }
double computedVol = CALC .localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate) .zValue(time, strike); double expectedVol = volFromFormula(r, q, time, strike, VOL_SURFACE); assertEquals(computedVol, expectedVol, FD_EPS); UnitParameterSensitivity computedSensi = CALC.localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate) .zValueParameterSensitivity(time, strike); for (int i = 0; i < VOLS.size(); ++i) { InterpolatedNodalSurface surfaceUp = VOL_SURFACE.withZValues(VOLS.with(i, VOLS.get(i) + FD_EPS)); InterpolatedNodalSurface surfaceDw = VOL_SURFACE.withZValues(VOLS.with(i, VOLS.get(i) - FD_EPS)); double volUp = CALC.localVolatilityFromImpliedVolatility( surfaceUp, SPOT, interestRate, dividendRate).zValue(time, strike); double volDw = CALC.localVolatilityFromImpliedVolatility( surfaceDw, SPOT, interestRate, dividendRate).zValue(time, strike); double expectedSensi = 0.5 * (volUp - volDw) / FD_EPS; assertEquals(computedSensi.getSensitivity().get(i), expectedSensi, FD_EPS * 10d);
public void coverage() { DeformedSurface test1 = DeformedSurface.of(METADATA, SURFACE_ORG, FUNCTION); coverImmutableBean(test1); Surface surface1 = InterpolatedNodalSurface.of(DefaultSurfaceMetadata.of("TestSurface1"), XVALUES, YVALUES, ZVALUES, INTERPOLATOR); DeformedSurface test2 = DeformedSurface.of(DefaultSurfaceMetadata.of("DeformedTestSurface1"), surface1, new Function<DoublesPair, ValueDerivatives>() { @Override public ValueDerivatives apply(DoublesPair x) { return ValueDerivatives.of(surface1.zValue(x), surface1.zValueParameterSensitivity(x).getSensitivity()); } }); coverBeanEquals(test1, test2); }
public void flatVolTest() { double constantVol = 0.15; ConstantSurface impliedVolSurface = ConstantSurface.of("impliedVol", constantVol); Function<Double, Double> zeroRate = new Function<Double, Double>() { @Override public Double apply(Double x) { return 0.05d; } }; Function<Double, Double> zeroRate1 = new Function<Double, Double>() { @Override public Double apply(Double x) { return 0.02d; } }; double[] strikes = new double[] {90d, 100d, 115d }; for (double strike : strikes) { for (double time : TEST_TIMES) { DeformedSurface localVolSurface = CALC.localVolatilityFromImpliedVolatility(impliedVolSurface, 100d, zeroRate, zeroRate1); assertEquals(localVolSurface.zValue(time, strike), constantVol); } } }
@Override public UnitParameterSensitivity zValueParameterSensitivity(double x, double y) { return getMetadata().getParameterMetadata().isPresent() ? UnitParameterSensitivity.of( getMetadata().getSurfaceName(), getMetadata().getParameterMetadata().get(), deformationFunction.apply(DoublesPair.of(x, y)).getDerivatives()) : UnitParameterSensitivity.of( getMetadata().getSurfaceName(), deformationFunction.apply(DoublesPair.of(x, y)).getDerivatives()); }
/** * Obtains an instance. * * @param metadata the surface metadata * @param originalSurface the original surface * @param deformationFunction the deformation function * @return the surface */ public static DeformedSurface of( SurfaceMetadata metadata, Surface originalSurface, Function<DoublesPair, ValueDerivatives> deformationFunction) { return DeformedSurface.builder() .metadata(metadata) .originalSurface(originalSurface) .deformationFunction(deformationFunction) .build(); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -450004177: // metadata return ((DeformedSurface) bean).getMetadata(); case 1982430620: // originalSurface return ((DeformedSurface) bean).getOriginalSurface(); case -360086200: // deformationFunction return ((DeformedSurface) bean).getDeformationFunction(); } return super.propertyGet(bean, propertyName, quiet); }
double computedVol = CALC .localVolatilityFromPrice(PRICE_SURFACE, SPOT, interestRate, dividendRate) .zValue(time, strike); double expectedVol = volFromFormulaPrice(r, q, time, strike, PRICE_SURFACE); assertEquals(computedVol, expectedVol, FD_EPS); UnitParameterSensitivity computedSensi = CALC.localVolatilityFromPrice(PRICE_SURFACE, SPOT, interestRate, dividendRate) .zValueParameterSensitivity(time, strike); for (int i = 0; i < PRICES.size(); ++i) { InterpolatedNodalSurface surfaceUp = PRICE_SURFACE.withZValues(PRICES.with(i, PRICES.get(i) + FD_EPS)); InterpolatedNodalSurface surfaceDw = PRICE_SURFACE.withZValues(PRICES.with(i, PRICES.get(i) - FD_EPS)); double priceUp = CALC.localVolatilityFromPrice( surfaceUp, SPOT, interestRate, dividendRate).zValue(time, strike); double priceDw = CALC.localVolatilityFromPrice( surfaceDw, SPOT, interestRate, dividendRate).zValue(time, strike); double expectedSensi = 0.5 * (priceUp - priceDw) / FD_EPS; assertEquals(computedSensi.getSensitivity().get(i), expectedSensi, FD_EPS * 100d); // tiny call price
.surfaceName(SurfaceName.of("localVol_" + callPriceSurface.getName())) .build(); return DeformedSurface.of(metadata, callPriceSurface, func);
for (double strike : sampleStrikes[i]) { double volTri = resTri.zValue(time, strike); double volDup = resDup.zValue(time, strike); assertEquals(volTri, volDup, tol);
double computedVol = CALC .localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate) .zValue(time, strike); double expectedVol = volFromFormula(r, q, time, strike, VOL_SURFACE); assertEquals(computedVol, expectedVol, FD_EPS); UnitParameterSensitivity computedSensi = CALC.localVolatilityFromImpliedVolatility(VOL_SURFACE, SPOT, interestRate, dividendRate) .zValueParameterSensitivity(time, strike); for (int i = 0; i < VOLS.size(); ++i) { InterpolatedNodalSurface surfaceUp = VOL_SURFACE.withZValues(VOLS.with(i, VOLS.get(i) + FD_EPS)); InterpolatedNodalSurface surfaceDw = VOL_SURFACE.withZValues(VOLS.with(i, VOLS.get(i) - FD_EPS)); double volUp = CALC.localVolatilityFromImpliedVolatility( surfaceUp, SPOT, interestRate, dividendRate).zValue(time, strike); double volDw = CALC.localVolatilityFromImpliedVolatility( surfaceDw, SPOT, interestRate, dividendRate).zValue(time, strike); double expectedSensi = 0.5 * (volUp - volDw) / FD_EPS; assertEquals(computedSensi.getSensitivity().get(i), expectedSensi, FD_EPS * 10d);
.surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.getName())) .build(); return DeformedSurface.of(metadata, impliedVolatilitySurface, func);
for (double strike : sampleStrikes[i]) { double volTri = resTri.zValue(time, strike); double volDup = resDup.zValue(time, strike); assertEquals(volTri, volDup, tol);
@Override public DeformedSurface withMetadata(SurfaceMetadata metadata) { return new DeformedSurface(metadata, originalSurface, deformationFunction); }
public void flatVolPriceTest() { double tol = 2.0e-2; double constantVol = 0.15; double spot = 100d; double maxTime = 1d; int nSteps = 9; ConstantSurface impliedVolSurface = ConstantSurface.of("impliedVol", constantVol); Function<Double, Double> zeroRate = new Function<Double, Double>() { @Override public Double apply(Double x) { return 0d; } }; Function<DoublesPair, ValueDerivatives> func = new Function<DoublesPair, ValueDerivatives>() { @Override public ValueDerivatives apply(DoublesPair x) { double price = BlackFormulaRepository.price(spot, x.getSecond(), x.getFirst(), constantVol, true); return ValueDerivatives.of(price, DoubleArray.EMPTY); } }; DeformedSurface priceSurface = DeformedSurface.of(DefaultSurfaceMetadata.of("price"), impliedVolSurface, func); ImpliedTrinomialTreeLocalVolatilityCalculator calc = new ImpliedTrinomialTreeLocalVolatilityCalculator(nSteps, maxTime, INTERP_TIMESQ_LINEAR); InterpolatedNodalSurface localVolSurface = calc.localVolatilityFromPrice(priceSurface, spot, zeroRate, zeroRate); assertEquals(localVolSurface.getZValues().stream().filter(d -> !DoubleMath.fuzzyEquals(d, constantVol, tol)).count(), 0); }