final double maxT = 1.0 * tmaxT;
final double maxK = 1.1 * tmaxK;
//get the market local vol surface
//TODO local vol with non-constant (but deterministic) rates
final AbsoluteLocalVolatilitySurface marketLocalVol = LOCAL_VOL_CALC.getAbsoluteLocalVolatilitySurface(marketVolSurface, forward.getSpot(), forward.getDrift(0));
if (_print) {
PDEUtilityTools.printSurface("Market implied Vols", marketVolSurface.getSurface(), minT, maxT, minK, maxK);
PDEUtilityTools.printSurface("Market local Vols", marketLocalVol.getSurface(), minT, maxT, minK, maxK);
}
//get the local vol of basic Markov chain model
final MeshingFunction timeMesh = new ExponentialMeshing(0, tmaxT, tNodes, 2.0);
final MeshingFunction spaceMesh = new HyperbolicMeshing(0, 6.0 * forward.getForward(tmaxT), forward.getForward(0), xNodes, 0.01);
final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);
final TwoStateMarkovChainWithLocalVolDensity densityCal = new TwoStateMarkovChainWithLocalVolDensity(forward, chainData, new AbsoluteLocalVolatilitySurface(ConstantDoublesSurface.from(1.0)));
PDEFullResults1D[] denRes = densityCal.solve(grid);
if (_print) {
PDEUtilityTools.printSurface("State 1 densities", denRes[0]);
PDEUtilityTools.printSurface("State 2 densities", denRes[1]);
}
//the Local vol of the basis Markov chain model
AbsoluteLocalVolatilitySurface mcBaseLocalVol = MC_LOCAL_VOL_CALC.calc(denRes, chainData, null);
AbsoluteLocalVolatilitySurface mcLocalVol;
if (_print) {
PDEUtilityTools.printSurface("Markov local Vols", mcBaseLocalVol.getSurface(), minT, maxT, minK, maxK);
}
AbsoluteLocalVolatilitySurface lvOverlay = null;
mcLocalVol = mcBaseLocalVol;
int count = 0;
while (!converged(marketLocalVol, mcLocalVol, dataPoints) && count < 10) {
count++;
//get the local vol overlay to the Markov chain model
lvOverlay = getLocalVolOverlay(marketLocalVol, mcBaseLocalVol);
if (_print) {
PDEUtilityTools.printSurface("Local vol overlay at step " + count, lvOverlay.getSurface(), minT, maxT, minK, maxK);
}
final TwoStateMarkovChainWithLocalVolDensity lvDensityCal = new TwoStateMarkovChainWithLocalVolDensity(forward, chainData, lvOverlay);
denRes = lvDensityCal.solve(grid);
if (_print) {
PDEUtilityTools.printSurface("State 1 densities at step " + count, denRes[0]);
PDEUtilityTools.printSurface("State 2 densities at step" + count, denRes[1]);
}
//calculate mc local vol without overlay
mcBaseLocalVol = MC_LOCAL_VOL_CALC.calc(denRes, chainData, null);
//... and with overlay
mcLocalVol = MC_LOCAL_VOL_CALC.calc(denRes, chainData, lvOverlay);
}
if (_print) {
PDEUtilityTools.printSurface("Markov LV local Vols", mcLocalVol.getSurface(), minT, maxT, minK, maxK);
if (lvOverlay != null) {
PDEUtilityTools.printSurface("Local vol overlay ", lvOverlay.getSurface(), minT, maxT, minK, maxK);
}
}
//Solve the forward PDE with the local vol overlay to check match with data
final TwoStateMarkovChainPricer pricer = new TwoStateMarkovChainPricer(forward, chainData, lvOverlay);