/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.finitedifference.applications; import static org.testng.AssertJUnit.assertEquals; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import com.opengamma.analytics.financial.model.finitedifference.ExponentialMeshing; import com.opengamma.analytics.financial.model.finitedifference.HyperbolicMeshing; import com.opengamma.analytics.financial.model.finitedifference.MeshingFunction; import com.opengamma.analytics.financial.model.finitedifference.PDEFullResults1D; import com.opengamma.analytics.financial.model.finitedifference.PDEGrid1D; import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve; import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory; import com.opengamma.analytics.math.interpolation.GridInterpolator2D; import com.opengamma.analytics.math.interpolation.Interpolator1D; import com.opengamma.analytics.math.interpolation.Interpolator1DFactory; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResultsWithTransform; import com.opengamma.util.monitor.OperationTimer; import com.opengamma.util.test.TestGroup; import com.opengamma.util.tuple.DoublesPair; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Test. */ @Test(groups = TestGroup.UNIT) public class TwoStateMarkovChainFitterTest { //TODO just put this in to stop failures private static final Interpolator1D INTERPOLATOR_1D = CombinedInterpolatorExtrapolatorFactory.getInterpolator(Interpolator1DFactory.DOUBLE_QUADRATIC, Interpolator1DFactory.FLAT_EXTRAPOLATOR, Interpolator1DFactory.FLAT_EXTRAPOLATOR); private static final GridInterpolator2D GRID_INTERPOLATOR2D = new GridInterpolator2D(INTERPOLATOR_1D, INTERPOLATOR_1D); private static final double THETA = 0.55; private static final double SPOT = 1.0; private static final double RATE = 0.0; private static final List<double[]> EXPIRY_AND_STRIKES = new ArrayList<>(); private static final double VOL1 = 0.15; private static final double DELTA_VOL = 0.55; private static final double LAMBDA12 = 0.2; private static final double LAMBDA21 = 2.5; private static final double P0 = 1.0; private static final double BETA = 0.5; private static final ForwardCurve FORWARD_CURVE; private static final TwoStateMarkovChainDataBundle MARKOV_CHAIN_DATA; private static final PDEFullResults1D PDE_RESULTS; private static final Map<DoublesPair, Double> DATA; private static Map<Double, Interpolator1DDataBundle> DATABUNDLE; private static final List<Pair<double[], Double>> MARKET_VOLS; static { EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 0.925 }); EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 1.075 }); EXPIRY_AND_STRIKES.add(new double[] {0.5, 0.9 }); EXPIRY_AND_STRIKES.add(new double[] {0.5, 0.95 }); EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.05 }); EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.1 }); EXPIRY_AND_STRIKES.add(new double[] {1, 0.8 }); EXPIRY_AND_STRIKES.add(new double[] {1, 0.9 }); EXPIRY_AND_STRIKES.add(new double[] {1, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {1, 1.1 }); EXPIRY_AND_STRIKES.add(new double[] {2, 0.7 }); EXPIRY_AND_STRIKES.add(new double[] {2, 0.9 }); EXPIRY_AND_STRIKES.add(new double[] {2, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {2, 1.2 }); EXPIRY_AND_STRIKES.add(new double[] {2, 1.4 }); EXPIRY_AND_STRIKES.add(new double[] {3, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {4, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {5, 0.5 }); EXPIRY_AND_STRIKES.add(new double[] {5, 0.75 }); EXPIRY_AND_STRIKES.add(new double[] {5, 0.9 }); EXPIRY_AND_STRIKES.add(new double[] {5, 1.0 }); EXPIRY_AND_STRIKES.add(new double[] {5, 1.1 }); EXPIRY_AND_STRIKES.add(new double[] {5, 1.3 }); EXPIRY_AND_STRIKES.add(new double[] {5, 1.7 }); EXPIRY_AND_STRIKES.add(new double[] {5, 2.0 }); FORWARD_CURVE = new ForwardCurve(SPOT, RATE); MARKOV_CHAIN_DATA = new TwoStateMarkovChainDataBundle(VOL1, VOL1 + DELTA_VOL, LAMBDA12, LAMBDA21, P0, BETA, BETA); final TwoStateMarkovChainPricer mc = new TwoStateMarkovChainPricer(FORWARD_CURVE, MARKOV_CHAIN_DATA); final int tNodes = 20; final int xNodes = 100; final MeshingFunction timeMesh = new ExponentialMeshing(0, 5, tNodes, 5.0); final MeshingFunction spaceMesh = new HyperbolicMeshing(0, 10 * SPOT, SPOT, xNodes, 0.01); final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh); PDE_RESULTS = mc.solve(grid, THETA); DATA = PDEUtilityTools.priceToImpliedVol(FORWARD_CURVE, PDE_RESULTS, 0.01, 5.0, SPOT / 10, 6 * SPOT, true); DATABUNDLE = GRID_INTERPOLATOR2D.getDataBundle(DATA); MARKET_VOLS = new ArrayList<>(EXPIRY_AND_STRIKES.size()); for (int i = 0; i < EXPIRY_AND_STRIKES.size(); i++) { final double[] tk = EXPIRY_AND_STRIKES.get(i); final Pair<double[], Double> pair = Pairs.of(tk, GRID_INTERPOLATOR2D.interpolate(DATABUNDLE, DoublesPair.of(tk[0], tk[1]))); MARKET_VOLS.add(pair); } } @Test(enabled = false) public void timeTest() { final int warmups = 3; final int benchmarkCycles = 10; final Logger logger = LoggerFactory.getLogger(TwoStateMarkovChainFitterTest.class); final TwoStateMarkovChainPricer mc = new TwoStateMarkovChainPricer(FORWARD_CURVE, MARKOV_CHAIN_DATA); final int tNodes = 20; final int xNodes = 100; final MeshingFunction timeMesh = new ExponentialMeshing(0, 5, tNodes, 5.0); final MeshingFunction spaceMesh = new HyperbolicMeshing(0, 6 * SPOT, SPOT, xNodes, 0.01); final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh); for (int i = 0; i < warmups; i++) { mc.solve(grid, 0.5); } if (benchmarkCycles > 0) { final OperationTimer timer = new OperationTimer(logger, "processing {} cycles on timeTest", benchmarkCycles); for (int i = 0; i < benchmarkCycles; i++) { mc.solve(grid, 0.5); } timer.finished(); } } @Test(enabled = false) public void dumpPDESurfaceTest() { PDEUtilityTools.printSurface("dumpPDESurfaceTest", PDE_RESULTS); } @Test(enabled = false) public void dumpSurfaceTest() { PDEUtilityTools.printSurface("dumpSurfaceTest", DATABUNDLE, 0, 5, SPOT / 10, SPOT * 6, 100, 100); } @Test(enabled = false) public void test() { final DoubleMatrix1D initalGuess = new DoubleMatrix1D(new double[] {0.2, 0.8, 0.3, 2.0, 0.9, 0.9 }); final TwoStateMarkovChainFitter fitter = new TwoStateMarkovChainFitter(THETA); final LeastSquareResultsWithTransform res = fitter.fit(FORWARD_CURVE, MARKET_VOLS, initalGuess); //System.out.println("chi^2:" + res.getChiSq() + "\n params: " + res.getParameters().toString()); final double[] modelParms = res.getModelParameters().getData(); assertEquals(0.0, res.getChiSq(), 1e-3); assertEquals(VOL1, modelParms[0], 1e-3); assertEquals(DELTA_VOL, modelParms[1], 2e-3); assertEquals(LAMBDA12, modelParms[2], 2e-3); assertEquals(LAMBDA21, modelParms[3], 2e-3); assertEquals(P0, modelParms[4], 1e-3); assertEquals(BETA, modelParms[5], 1e-3); } }