/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.finitedifference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import com.opengamma.util.monitor.OperationTimer;
import com.opengamma.util.test.TestGroup;
/**
* Test ThetaMethodFiniteDifference when theta = 0.5 (i.e. A Crank-Nicolson scheme)
*/
@Test(groups = TestGroup.UNIT)
public class ThetaMethodFiniteDifferenceTest {
private static final ConvectionDiffusionPDESolverTestCase TESTER = new ConvectionDiffusionPDESolverTestCase();
private static final ThetaMethodFiniteDifference SOLVER = new ThetaMethodFiniteDifference(0.5, false);
@Test
public void testBlackScholesEquation1() {
int timeSteps = 10; //10 // with this few steps get massive oscillations in implied vol & gamma around ATM
int priceSteps = 100;
double lowerMoneyness = 0.4;
double upperMoneyness = 3.0;
double volTol = 5e-3;
double priceTol = 5e-2;
double deltaTol = 5e-2;
double gammaTol = 1.0; // Crank-Nicolson gives awful greeks around ATM - this is why it shouldn't be used
boolean print = false; // set to false before pushing
TESTER.testBlackScholesEquationUniformGrid(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, priceTol, deltaTol, gammaTol, print);
}
@Test
public void testBlackScholesEquation2() {
int warmups = 1;
int benchmarkCycles = 0;
final Logger logger = LoggerFactory.getLogger(ThetaMethodFiniteDifferenceTest.class);
int timeSteps = 20;
int priceSteps = 100;
double lowerMoneyness = 0.4;
double upperMoneyness = 3.0;
double volTol = 5e-3;
double priceTol = 1e-2; // 5 times better than with 10 time steps
double deltaTol = 5e-3; // 10 times better than with 10 time steps
double gammaTol = 2e-2; // 50 times better than with 10 time steps
boolean print = false; // set to false before pushing
for (int i = 0; i < warmups; i++) {
TESTER.testBlackScholesEquationUniformGrid(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, priceTol, deltaTol, gammaTol, print);
}
if (benchmarkCycles > 0) {
final OperationTimer timer = new OperationTimer(logger, "processing {} cycles on testBlackScholesEquation2", benchmarkCycles);
for (int i = 0; i < benchmarkCycles; i++) {
TESTER.testBlackScholesEquationUniformGrid(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, priceTol, deltaTol, gammaTol, print);
}
timer.finished();
}
}
@Test
public void testBlackScholesEquationNonuniformGrid() {
int timeSteps = 10;
int priceSteps = 100;
double lowerMoneyness = 0.4;
double upperMoneyness = 3.0;
double volTol = 2e-2; // Crank-Nicolson does not play well with non-uniform grids
double priceTol = 5e-2;
double deltaTol = 5e-1;
double gammaTol = 2e1;// Doesn't even get the sign of gamma right ATM
boolean print = false; // set to false before pushing
TESTER.testBlackScholesEquationNonuniformGrid(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, priceTol, deltaTol, gammaTol, print);
}
@Test
public void testLogBlackScholesEquation() {
int timeSteps = 10;
int priceSteps = 100;
double lowerMoneyness = 0.3;
double upperMoneyness = 4.0;
double volTol = 5e-3;
double priceTol = 5e-2;
double deltaTol = 5e-2;
double gammaTol = 5.0; // Crank-Nicolson gives awful greeks around ATM - this is why it shouldn't be used
boolean print = false; // set to false before pushing
TESTER.testLogTransformedBlackScholesEquation(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, priceTol, deltaTol, gammaTol, print);
}
@Test
public void testCEV() {
int timeSteps = 10;
int priceSteps = 100;
double lowerMoneyness = 0.3;
double upperMoneyness = 3.0;
double volTol = 1e-2;
boolean print = false; // set to false before pushing
TESTER.testCEV(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, volTol, print);
}
@Test
public void testAmericanPrice() {
int timeSteps = 10;
int priceSteps = 100;
double lowerMoneyness = 0.4;
double upperMoneyness = 3.0;
boolean print = false; // set to false before pushing
TESTER.testAmericanPrice(SOLVER, timeSteps, priceSteps, lowerMoneyness, upperMoneyness, print);
}
}