package com.opengamma.analytics.financial.interestrate.capletstripping; import static org.testng.AssertJUnit.assertEquals; import java.util.Arrays; import org.testng.annotations.Test; import com.opengamma.analytics.financial.model.volatility.surface.BasisSplineVolatilityTermStructureProvider; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.util.test.TestGroup; @Test(groups = TestGroup.UNIT) public class CapletStripperPSplineTermStructureTest extends CapletStrippingSetup { /** * Here we expect to recover close to the market (less than 1bps error in cap vol). We perform regression tests * against the expected chi-squares and do not explicitly check the fit parameters. */ @Test public void singleStrikeTest() { final double oneBP = 1e-4; BasisSplineVolatilityTermStructureProvider vtsp = new BasisSplineVolatilityTermStructureProvider(0, 10.0, 10, 2); int size = vtsp.getNumModelParameters(); DoubleMatrix1D guess = new DoubleMatrix1D(size, 0.5); double lambda = 1000; double[] expChi2 = new double[] {0.277676669976045, 0.0022011319414088, 0.518347393499247, 0.00007981972507487, 1.54586760016073, 0.000527042501277108, 0.0522325414771529, 0.6992013245803, 0.000432311638224547, 0.34538288663326, 0.184403889621066, 0.0985505473418442, 0.00346706710567801, 0.00710721343644138, 0.00349404965587751, 0.00379692419890176, 0.00911582614672745, 0.00894420412698515 }; int n = getNumberOfStrikes(); for (int i = 0; i < n; i++) { MultiCapFloorPricer pricer = new MultiCapFloorPricer(getCaps(i), getYieldCurves()); CapletStripper stripper = new CapletStripperPSplineTermStructure(pricer, vtsp, lambda); double[] vols = getCapVols(i); double[] prices = pricer.price(vols); double[] vega = pricer.vega(vols); int nVols = vols.length; double[] errors = new double[nVols]; Arrays.fill(errors, oneBP); // 1bps // scale vega for (int j = 0; j < nVols; j++) { vega[j] *= oneBP; } CapletStrippingResult res = stripper.solve(vols, MarketDataType.VOL, errors, guess); assertEquals(expChi2[i], res.getChiSqr(), 1e-7); // use default guess - won't get exactly the same solution due to stopping criteria and implied vol tolerance res = stripper.solve(vols, MarketDataType.VOL, errors); assertEquals(expChi2[i], res.getChiSqr(), 1e-5); // solve for price (weighted by vega), starting from vol solution - this should give a very similar chiSq res = stripper.solve(prices, MarketDataType.PRICE, vega, res.getFitParameters()); assertEquals(expChi2[i], res.getChiSqr(), 1e-4); // this is effectively setting errors to 1 - must also scale lambda. // Since we have scaled the problem, but not the stopping criteria, there is a poor match with the (scaled chi2) stripper = new CapletStripperPSplineTermStructure(pricer, vtsp, oneBP * oneBP * lambda); res = stripper.solve(vols, MarketDataType.VOL, guess); assertEquals(expChi2[i], res.getChiSqr() / oneBP / oneBP, 1e-4); // use default guess and errors = 1.0 res = stripper.solve(vols, MarketDataType.VOL); assertEquals(expChi2[i], res.getChiSqr() / oneBP / oneBP, 1e-4); } } }