Package com.opengamma.analytics.financial.model.finitedifference

Examples of com.opengamma.analytics.financial.model.finitedifference.ConvectionDiffusionPDESolver


    } else if (localVolatility instanceof LocalVolatilitySurfaceMoneyness) {
      pde = provider.getForwardLocalVol((LocalVolatilitySurfaceMoneyness) localVolatility);
    } else {
      throw new IllegalArgumentException();
    }
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, true);

    final double minMoneyness = Math.exp(-maxAbsProxyDelta * Math.sqrt(maxT));
    final double maxMoneyness = 1.0 / minMoneyness;
    ArgumentChecker.isTrue(minMoneyness < centreMoneyness, "min moneyness of {} greater than centreMoneyness of {}. Increase maxAbsProxydelta", minMoneyness, centreMoneyness);
    ArgumentChecker.isTrue(maxMoneyness > centreMoneyness, "max moneyness of {} less than centreMoneyness of {}. Increase maxAbsProxydelta", maxMoneyness, centreMoneyness);

    BoundaryCondition lower;
    BoundaryCondition upper;
    if (isCall) {
      //call option with low strike  is worth the forward - strike, while a put is worthless
      lower = new DirichletBoundaryCondition((1.0 - minMoneyness), minMoneyness);
      upper = new DirichletBoundaryCondition(0.0, maxMoneyness);
    } else {
      lower = new DirichletBoundaryCondition(0.0, minMoneyness);
      upper = new NeumannBoundaryCondition(1.0, maxMoneyness, false);
    }
    final MeshingFunction timeMesh = new ExponentialMeshing(0.0, maxT, nTimeSteps, timeMeshLambda);
    final MeshingFunction spaceMesh = new HyperbolicMeshing(minMoneyness, maxMoneyness, centreMoneyness, nStrikeSteps, strikeMeshBunching);
    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final Function1D<Double, Double> initialCond = (new InitialConditionsProvider()).getForwardCallPut(isCall);
    final PDEFullResults1D res = (PDEFullResults1D) solver.solve(new PDE1DDataBundle<>(pde, initialCond, lower, upper, grid));
    return res;
  }
View Full Code Here


      final double theta, final double maxT, final double maxAbsProxyDelta, final int nTimeSteps, final int nStrikeSteps,
      final double timeMeshLambda, final double strikeMeshBunching, final double centreMoneyness) {

    final PDE1DCoefficientsProvider provider = new PDE1DCoefficientsProvider();
    final ConvectionDiffusionPDE1DCoefficients pde = provider.getForwardLocalVol(localVolatility);
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, true);

    final double minMoneyness = Math.exp(-maxAbsProxyDelta * Math.sqrt(maxT));
    final double maxMoneyness = 1.0 / minMoneyness;
    ArgumentChecker.isTrue(minMoneyness < centreMoneyness, "min moneyness of {} greater than centreMoneyness of {}. Increase maxAbsProxydelta", minMoneyness, centreMoneyness);
    ArgumentChecker.isTrue(maxMoneyness > centreMoneyness, "max moneyness of {} less than centreMoneyness of {}. Increase maxAbsProxydelta", maxMoneyness, centreMoneyness);

    BoundaryCondition lower;
    BoundaryCondition upper;
    if (isCall) {
      //call option with low strike  is worth the forward - strike, while a put is worthless
      lower = new DirichletBoundaryCondition((1.0 - minMoneyness), minMoneyness);
      upper = new DirichletBoundaryCondition(0.0, maxMoneyness);
    } else {
      lower = new DirichletBoundaryCondition(0.0, minMoneyness);
      upper = new NeumannBoundaryCondition(1.0, maxMoneyness, false);
    }

    final MeshingFunction timeMesh = new ExponentialMeshing(0.0, maxT, nTimeSteps, timeMeshLambda);

    final MeshingFunction spaceMesh = new HyperbolicMeshing(minMoneyness, maxMoneyness, centreMoneyness, nStrikeSteps, strikeMeshBunching);
    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final Function1D<Double, Double> intCond = (new InitialConditionsProvider()).getForwardCallPut(isCall);
    final PDEFullResults1D res = (PDEFullResults1D) solver.solve(new PDE1DDataBundle<>(pde, intCond, lower, upper, grid));
    return res;
  }
View Full Code Here

    final PDE1DCoefficientsProvider pdeProvider = new PDE1DCoefficientsProvider();
    final InitialConditionsProvider intProvider = new InitialConditionsProvider();
    final ConvectionDiffusionPDE1DCoefficients pde = pdeProvider.getBackwardsLocalVol(forwardCurve, expiry, localVolatility);
    final Function1D<Double, Double> payoff = intProvider.getEuropeanPayoff(strike, isCall);
    // final ZZConvectionDiffusionPDEDataBundle db = provider.getBackwardsLocalVol(strike, expiry, isCall, localVolatility, forwardCurve);
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false);

    BoundaryCondition lower;
    BoundaryCondition upper;
    if (isCall) {
      lower = new DirichletBoundaryCondition(0.0, 0.0); //call option with strike zero is worth 0
      upper = new NeumannBoundaryCondition(1.0, maxFwd, false);
    } else {
      lower = new DirichletBoundaryCondition(strike, 0.0);
      upper = new NeumannBoundaryCondition(0.0, maxFwd, false);
    }

    // MeshingFunction timeMesh = new ExponentialMeshing(0.0, expiry, nTimeNodes, timeMeshLambda);
    final MeshingFunction timeMesh = new DoubleExponentialMeshing(0, expiry, expiry / 2, nTimeNodes, timeMeshLambda, -timeMeshLambda);
    //keep the grid the same regardless of spot (useful for finite-difference)
    final MeshingFunction spaceMesh = new HyperbolicMeshing(0.0, maxFwd, fwdNodeCentre, nFwdNodes, spotMeshBunching);
    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db = new PDE1DDataBundle<>(pde, payoff, lower, upper, grid);
    final PDEResults1D res = solver.solve(db);
    return res;
  }
View Full Code Here

    final PDE1DCoefficientsProvider pde_provider = new PDE1DCoefficientsProvider();
    final InitialConditionsProvider int_provider = new InitialConditionsProvider();
    //final ZZConvectionDiffusionPDEDataBundle db = provider.getBackwardsLocalVol(STRIKE, EXPIRY, true, LOCAL_VOL, FORWARD_CURVE);
    final ConvectionDiffusionPDE1DCoefficients pde = pde_provider.getBackwardsLocalVol(FORWARD_CURVE, EXPIRY, LOCAL_VOL);
    final Function1D<Double, Double> payoff = int_provider.getEuropeanPayoff(STRIKE, true);
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(0.5, false);
    final double forward = FORWARD_CURVE.getForward(EXPIRY);

    final int nTimeNodes = 50;
    final int nSpotNodes = 100;
    final double upperLevel = 3.5 * forward;

    final BoundaryCondition lower = new DirichletBoundaryCondition(0, 0);
    final BoundaryCondition upper = new NeumannBoundaryCondition(1.0, upperLevel, false);
    final MeshingFunction timeMesh = new ExponentialMeshing(0.0, EXPIRY, nTimeNodes, 6.0);
    final MeshingFunction spaceMesh = new HyperbolicMeshing(0, upperLevel, STRIKE, nSpotNodes, 0.05);
    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final PDEResults1D res = solver.solve(new PDE1DDataBundle<>(pde, payoff, lower, upper, grid));

    final int fwdIndex = grid.getLowerBoundIndexForSpace(forward);
    final double[] fwd = new double[4];
    final double[] vol = new double[4];
    for (int i = 0; i < 4; i++) {
View Full Code Here

   * Test the pricing of a 1D option with the local volatility surface produced by the mixed log-normal model solving both the forward and backwards PDE, and compare
   * with the result from the implied volatility surface. Neither solving the forward nor the backwards PDE give great accuracy
   */
  @Test
  public void shortDatedOptionTest() {
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(0.5, false);
    final PDE1DCoefficientsProvider pdeProvider = new PDE1DCoefficientsProvider();
    final InitialConditionsProvider initialConProvider = new InitialConditionsProvider();

    //set up the mixed log-normal model
    final double[] weights = new double[] {0.1, 0.8, 0.1 };
    final double[] sigmas = new double[] {0.15, 0.5, 0.9 };
    final double[] mus = new double[] {-0.1, 0, 0.1 };

    final MultiHorizonMixedLogNormalModelData mlnData = new MultiHorizonMixedLogNormalModelData(weights, sigmas, mus);
    final double spot = 100.;
    final double r = 0.1;
    final ForwardCurve fwdCurve = new ForwardCurve(spot, r);

    final double t = 1.0 / 365.;
    final double rootT = Math.sqrt(t);
    final double fwd = fwdCurve.getForward(t);

    BlackVolatilitySurfaceStrike ivs = MixedLogNormalVolatilitySurface.getImpliedVolatilitySurface(fwdCurve, mlnData);
    LocalVolatilitySurfaceStrike lvs = MixedLogNormalVolatilitySurface.getLocalVolatilitySurface(fwdCurve, mlnData);
    LocalVolatilitySurfaceMoneyness lvsm = LocalVolatilitySurfaceConverter.toMoneynessSurface(lvs, fwdCurve);

    //    PDEUtilityTools.printSurface("imp vol", ivs.getSurface(), 0, t, 0.9, 1.1);
    //    DupireLocalVolatilityCalculator dupire = new DupireLocalVolatilityCalculator();
    //    LocalVolatilitySurfaceMoneyness dlv = dupire.getLocalVolatility(BlackVolatilitySurfaceConverter.toMoneynessSurface(ivs, fwdCurve));
    //    PDEUtilityTools.printSurface("local vol (dupire)", dlv.getSurface(), 0, t, 0.99, 1.01);
    //    PDEUtilityTools.printSurface("local vol", lvsm.getSurface(), 0, t, 0.99, 1.01);

    //set up for solving the forward PDE
    //TODO shunt this setup into its own class
    ConvectionDiffusionPDE1DStandardCoefficients pde = pdeProvider.getForwardLocalVol(lvsm);
    Function1D<Double, Double> initialCond = initialConProvider.getForwardCallPut(true);
    double xL = 0.8;
    double xH = 1.2;
    BoundaryCondition lower = new NeumannBoundaryCondition(-1.0, xL, true);
    BoundaryCondition upper = new NeumannBoundaryCondition(0.0, xH, false);
    final MeshingFunction spaceMeshF = new HyperbolicMeshing(xL, xH, 1.0, 200, 0.001);
    final MeshingFunction timeMeshF = new ExponentialMeshing(0, t, 50, 4.0);
    final MeshingFunction timeMeshB = new DoubleExponentialMeshing(0, t, t / 2, 50, 2.0, -4.0);
    final PDEGrid1D grid = new PDEGrid1D(timeMeshF, spaceMeshF);
    PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> dbF = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pde, initialCond, lower, upper, grid);
    PDETerminalResults1D res = (PDETerminalResults1D) solver.solve(dbF);
    final double minK = Math.exp(-6 * rootT);
    final double maxK = Math.exp(6 * rootT);
    Map<Double, Double> vols = PDEUtilityTools.priceToImpliedVol(fwdCurve, t, res, minK, maxK, true);
    DoubleQuadraticInterpolator1D interpolator = Interpolator1DFactory.DOUBLE_QUADRATIC_INSTANCE;
    Interpolator1DDataBundle idb = interpolator.getDataBundle(vols);

    //set up for solving backwards PDE
    ConvectionDiffusionPDE1DStandardCoefficients pdeB = pdeProvider.getBackwardsLocalVol(t, lvsm);
    double sL = xL * spot;
    double sH = xH * spot;
    final MeshingFunction spaceMeshB = new HyperbolicMeshing(sL, sH, spot, 200, 0.001);
    final PDEGrid1D gridB = new PDEGrid1D(timeMeshB, spaceMeshB);
    int index = SurfaceArrayUtils.getLowerBoundIndex(gridB.getSpaceNodes(), spot);
    double s1 = gridB.getSpaceNode(index);
    double s2 = gridB.getSpaceNode(index + 1);
    final double w = (s2 - spot) / (s2 - s1);

    //solve a separate backwards PDE for each strike
    for (int i = 0; i < 10; i++) {
      double z = -5 + i;
      double k = spot * Math.exp(0.4 * rootT * z);
      double x = k / fwd;
      double vol = ivs.getVolatility(t, k);
      double volFPDE = interpolator.interpolate(idb, x);

      boolean isCall = (k >= fwd);
      BoundaryCondition lowerB = new NeumannBoundaryCondition(isCall ? 0 : -1, sL, true);
      BoundaryCondition upperB = new NeumannBoundaryCondition(isCall ? 1 : 0, sH, false);

      Function1D<Double, Double> bkdIC = initialConProvider.getEuropeanPayoff(k, isCall);
      PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> dbB = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pdeB, bkdIC, lowerB, upperB, gridB);
      PDEResults1D resB = solver.solve(dbB);
      double price1 = resB.getFunctionValue(index);
      double price2 = resB.getFunctionValue(index + 1);
      double vol1 = BlackFormulaRepository.impliedVolatility(price1, s1, k, t, isCall);
      double vol2 = BlackFormulaRepository.impliedVolatility(price2, s2, k, t, isCall);
      double volBPDE = w * vol1 + (1 - w) * vol2;
 
View Full Code Here

    final double theta = 0.5;
    final double range = Math.log(5);
    final double yL = lnFT - range;
    final double yH = lnFT + range;
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false);

    final BoundaryCondition lower = new NeumannBoundaryCondition(1.0, yL, true);
    final BoundaryCondition upper = new NeumannBoundaryCondition(1.0, yH, false);

    final MeshingFunction timeMesh = new ExponentialMeshing(0, EXPIRY, 100, 0.0);
    final MeshingFunction spaceMesh = new ExponentialMeshing(yL, yH, 101, 0.0);

    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final double[] sNodes = grid.getSpaceNodes();

    //run the PDE solver backward to the dividend date
    // PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db1 = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pde, initialCon, lower1, upper1, grid1);
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db1 = new PDE1DDataBundle<>(pde, payoff, lower, upper, grid);
    final PDETerminalResults1D res = (PDETerminalResults1D) solver.solve(db1);

    final Interpolator1DDataBundle interpolDB = INTEPOLATOR1D.getDataBundle(sNodes, res.getTerminalResults());

    final double val = INTEPOLATOR1D.interpolate(interpolDB, lnFT);
    assertEquals(0.41491529, Math.sqrt(-2 * (val) / EXPIRY), 5e-4); //Number from backwardsPDETest
View Full Code Here

    final ConvectionDiffusionPDE1DCoefficients pde = PDE_PROVIDER.getLogBackwardsLocalVol(EXPIRY, lv);

    final double theta = 0.5;
    final double yL = -0.5;
    final double yH = 0.5;
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false);

    final BoundaryCondition lower = new NeumannBoundaryCondition(1 / (1 + dStar * Math.exp(-yL)), yL, true);
    final BoundaryCondition upper = new NeumannBoundaryCondition(1.0, yH, false);

    final MeshingFunction timeMesh = new ExponentialMeshing(0.0, EXPIRY, 100, 0.0);
    final MeshingFunction spaceMesh = new ExponentialMeshing(yL, yH, 101, 0.0);

    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db = new PDE1DDataBundle<>(pde, PURE_LOG_PAY_OFF, lower, upper, grid);
    final PDEResults1D res = solver.solve(db);

    final int n = res.getNumberSpaceNodes();

    final double val = res.getFunctionValue(n / 2);
    return val;
View Full Code Here

    final Function1D<Double, Double> initialCon = INITIAL_COND_PROVIDER.getLogContractPayoffInLogCoordinate();

    final double theta = 0.5;
    final double yL = Math.log(SPOT / 6);
    final double yH = Math.log(6 * SPOT);
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false);

    final BoundaryCondition lower1 = new NeumannBoundaryCondition(1.0, yL, true);
    final BoundaryCondition upper1 = new NeumannBoundaryCondition(1.0, yH, false);

    final MeshingFunction timeMesh1 = new ExponentialMeshing(0, EXPIRY - DIVIDEND_DATE - 1e-6, 50, 0.0);
    final MeshingFunction timeMesh2 = new ExponentialMeshing(EXPIRY - DIVIDEND_DATE + 1e-6, EXPIRY, 50, 0.0);
    final MeshingFunction spaceMesh = new ExponentialMeshing(yL, yH, 101, 0.0);

    final PDEGrid1D grid1 = new PDEGrid1D(timeMesh1, spaceMesh);
    final double[] sNodes1 = grid1.getSpaceNodes();

    //run the PDE solver backward to the dividend date
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db1 = new PDE1DDataBundle<>(pde, initialCon, lower1, upper1, grid1);
    final PDETerminalResults1D res1 = (PDETerminalResults1D) solver.solve(db1);

    //Map the spot nodes after (in calendar time) the dividend payment to nodes before
    final int nSNodes = sNodes1.length;
    final double[] sNodes2 = new double[nSNodes];
    final double lnBeta = Math.log(1 - BETA);
    for (int i = 0; i < nSNodes; i++) {
      final double temp = sNodes1[i];
      if (temp < 0) {
        sNodes2[i] = Math.log(Math.exp(temp) + ALPHA) - lnBeta;
      }
      else {
        sNodes2[i] = temp + Math.log(1 + ALPHA * Math.exp(-temp)) - lnBeta;
      }
    }

    final PDEGrid1D grid2 = new PDEGrid1D(timeMesh2.getPoints(), sNodes2);
    final BoundaryCondition lower2 = new NeumannBoundaryCondition(1.0, sNodes2[0], true);
    final BoundaryCondition upper2 = new NeumannBoundaryCondition(1.0, sNodes2[nSNodes - 1], false);

    //run the PDE solver backward from the dividend date to zero
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db2 = new PDE1DDataBundle<>(pde, res1.getTerminalResults(), lower2, upper2, grid2);
    final PDETerminalResults1D res2 = (PDETerminalResults1D) solver.solve(db2);

    final Interpolator1DDataBundle interpolDB2 = INTEPOLATOR1D.getDataBundle(sNodes2, res2.getTerminalResults());
    final double val2 = INTEPOLATOR1D.interpolate(interpolDB2, Math.log(SPOT));
    return val2;
  }
View Full Code Here

  @Test
      (enabled = false)
      public void test() {

    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(1.0, true);
    final PDEFullResults1D res = (PDEFullResults1D) solver.solve(DATA);
    PDEUtilityTools.printSurface("wave", res);
  }
View Full Code Here

    final double theta = 0.5;
    final double ft = FORWARD_CURVE.getForward(EXPIRY);

    final double fL = Math.log(ft / 5.0);
    final double fH = Math.log(5.0 * ft);
    final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false);

    final BoundaryCondition lower = new NeumannBoundaryCondition(1.0, fL, true);
    final BoundaryCondition upper = new NeumannBoundaryCondition(1.0, fH, false);

    // MeshingFunction timeMesh = new ExponentialMeshing(0.0, expiry, nTimeNodes, timeMeshLambda);
    final MeshingFunction timeMesh = new ExponentialMeshing(0, EXPIRY, 100, 0.0);
    final MeshingFunction spaceMesh = new ExponentialMeshing(fL, fH, 101, 0.0);

    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db = new PDE1DDataBundle<>(PDE, INITIAL_COND, lower, upper, grid);
    final PDEResults1D res = solver.solve(db);

    final int n = res.getNumberSpaceNodes();
    //    for (int i = 0; i < n; i++) {
    //      System.out.println(res.getSpaceValue(i) + "\t" + res.getFunctionValue(i));
    //    }
View Full Code Here

TOP

Related Classes of com.opengamma.analytics.financial.model.finitedifference.ConvectionDiffusionPDESolver

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.