Login  Register

Monte Carlo pricer slow compared to other financial softwares

Posted by Igor Swie on Apr 28, 2017; 8:12am
URL: http://quantlib.414.s1.nabble.com/Monte-Carlo-pricer-slow-compared-to-other-financial-softwares-tp18232.html

Hi,
I have tried to price arithmetic asian options with the Monte Carlo pricer and a complete volatility surface.
There are about 80 points for the construction of the volatility surface and I run the Monte Carlo simulation with 1500 paths.
I get the result after 1 or 2 minutes which is incredibly slow compared to other fiancnial softwares (less than 1s).
Who would have an idea of the problem?

Besides is the code I used:

/*************************************code********************************/

void asian()
{
// Calendar set up
Calendar calendar = TARGET();
Date todaysDate(4, April, 2017);
Settings::instance().evaluationDate() = todaysDate;

DayCounter dayCounter = Actual360();

// Option parameters Asian FX
Option::Type optionType(Option::Call);
Average::Type averageType = Average::Arithmetic;
Date maturity(4, April, 2018);
Real strike = 0.74;
Volatility volatility = 0.07053702474;
Date obsStart(4, March, 2018);

Real runningSum = 0;
Size pastFixings = 0;
vector<Date> fixingDates;
for (Date incrementedDate = obsStart; incrementedDate <= maturity; incrementedDate += 1)
{
if (calendar.isBusinessDay(incrementedDate))
{
fixingDates.push_back(incrementedDate);
}
}

// Option exercise type
boost::shared_ptr<Exercise> europeanExercise(
new EuropeanExercise(maturity));

//Model param
Real underlying = 0.748571186;
Spread dividendYield = 0.04125; 
Rate riskFreeRate = 0.0225377;


// Quote handling
Handle<Quote> underlyingH(
boost::shared_ptr<Quote>(new SimpleQuote(underlying)));

// Yield term structure handling
Handle<YieldTermStructure> flatTermStructure(
boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, dividendYield, dayCounter)));

// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, riskFreeRate, dayCounter)));

// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));

string path = "E:\\Libraries\\QuantLib-1.9.1\\VolMatrixA.csv";
vector<Real> strikes = {};
GetStrikes(path, strikes);
vector<Date> expirations;
GetExpiryDates(path, expirations);
Matrix volMatrix = GetVolData(path, expirations, strikes);


BlackVarianceSurface volatilitySurface(Settings::instance().evaluationDate(),
calendar, expirations, strikes, volMatrix, dayCounter);


volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);

const boost::shared_ptr<BlackVarianceSurface> volatilitySurfaceH(
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure> volTermStructure(volatilitySurfaceH);

// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH, flatDividendTermStructure, flatTermStructure, volTermStructure));


// Payoff
boost::shared_ptr<StrikedTypePayoff> payoffAsianOption(
new PlainVanillaPayoff(
Option::Type(optionType),
strike));

// Options
DiscreteAveragingAsianOption discreteArithmeticAsianAverageOption(
averageType,
runningSum,
pastFixings,
fixingDates,
payoffAsianOption,
europeanExercise);

// Ouputting on the screen
cout << "Option type = " << optionType << endl;
cout << "Option maturity = " << maturity << endl;
cout << "Underlying  = " << underlying << endl;
cout << "Strike = " << strike << endl;
cout << "Risk-free interest rate = " << setprecision(4) << io::rate(riskFreeRate) << endl;
cout << "Dividend yield = " << setprecision(4) << io::rate(dividendYield) << endl;
cout << "Volatility = " << setprecision(4) << io::volatility(volatility) << endl;
cout << "Time-length between successive fixings = weekly time step" << endl;
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;

boost::timer timer;

//Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy>(bsmProcess)
.withSamples(1500)));

timer.restart();
try
{
cout << "Discrete  ArithMC Price: " << discreteArithmeticAsianAverageOption.NPV() << endl;
}
catch (exception const& e) { cout << "Erreur: " << e.what() << endl; }
cout << " in " << timer.elapsed() << " s" << endl;

timer.restart();
}

/**************************end ************************************************/

and the volatility data used in .csv format: first column the strikes, second column volatilities at maturity 6/27/2017 for the corresponding strikes ans so on.


/***************************volatility data**************************************/
 Strike ,6/27/2017,9/27/2017,12/27/2017,6/27/2018,
0.67263,0.144183920277296,0.139374695503699,0.135526204819277,0.12885
0.71865,0.133703802426343,0.129893056346044,0.126909006024096,0.12175
0.7487,0.126860526863085,0.123701764371087,0.121209416342412,0.11695
0.77129,0.121720863192182,0.118881707209199,0.116979766476388,0.11381
0.78984,0.117581136690647,0.115218428824572,0.113899219047619,0.11163
0.80587,0.114363421052632,0.112523118729097,0.111637193240265,0.11019
0.82034,0.111728795180723,0.110489402985075,0.109987692307692,0.10921
0.83379,0.109805703883495,0.109100413723512,0.108870460584588,0.1086
0.84658,0.108581646586345,0.108250493273543,0.108197213114754,0.10829
0.85792,0.108190964125561,0.107986172506739,0.10796631037213,0.10822
0.87354,0.10859510460251,0.108310304612707,0.108232350773766,0.10849
0.89085,0.110043016488846,0.109404567049808,0.109102906403941,0.10919
0.90904,0.112447321958457,0.111343238289206,0.110615417475728,0.11036
0.9289,0.115567066189624,0.113888152866242,0.112830993150685,0.11201
0.95157,0.119454321849106,0.117151688909342,0.115569047072331,0.11433
0.97862,0.123858310308183,0.121275916334661,0.119199029605263,0.11731
1.01337,0.129434558979809,0.126231870274572,0.123929902439024,0.12145
1.06261,0.137335982996812,0.133099606048548,0.12994278699187,0.12723
1.14631,0.150767120085016,0.144773641066454,0.140163713821138,0.13547

/********************************end vol data ***************************/

I think it's because too many calls are made to get the local volatility.

Thanks,

Igor

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users