Discussion:
[Quantlib-users] Monte Carlo pricer slow compared to other financial softwares
Igor Swie
2017-04-28 08:12:08 UTC
Permalink
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
Peter Caspers
2017-04-29 17:25:21 UTC
Permalink
Hi Igor,

this is what I get

~/tmp$ ./igor
Option type = Call
Option maturity = April 4th, 2018
Underlying = 0.748571
Strike = 0.74
Risk-free interest rate = 2.2538 %
Dividend yield = 4.1250 %
Volatility = 7.0537 %
Time-length between successive fixings = weekly time step
Previous fixings = 0

Discrete ArithMC Price: 0.04753356095
in 0.821526 s

Are you on Windows? Maybe you compiled in Debug mode then? That activates a lot of runtime diagnostics.

Best Regards
Peter
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?
/*************************************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
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Igor Swie
2017-05-02 12:24:57 UTC
Permalink
Ok the problem was the debug mode,
thanks a lot,

Igor
Post by Peter Caspers
Hi Igor,
this is what I get
~/tmp$ ./igor
Option type = Call
Option maturity = April 4th, 2018
Underlying = 0.748571
Strike = 0.74
Risk-free interest rate = 2.2538 %
Dividend yield = 4.1250 %
Volatility = 7.0537 %
Time-length between successive fixings = weekly time step
Previous fixings = 0
Discrete ArithMC Price: 0.04753356095
in 0.821526 s
Are you on Windows? Maybe you compiled in Debug mode then? That activates
a lot of runtime diagnostics.
Best Regards
Peter
Post by Igor Swie
Hi,
I have tried to price arithmetic asian options with the Monte Carlo
pricer and a complete volatility surface.
Post by Igor Swie
There are about 80 points for the construction of the volatility surface
and I run the Monte Carlo simulation with 1500 paths.
Post by Igor Swie
I get the result after 1 or 2 minutes which is incredibly slow compared
to other fiancnial softwares (less than 1s).
Post by Igor Swie
Who would have an idea of the problem?
/*************************************code******************
**************/
Post by Igor Swie
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)
Post by Igor Swie
{
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)));
Post by Igor Swie
// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new
FlatForward(todaysDate, riskFreeRate, dayCounter)));
Post by Igor Swie
// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new
BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));
Post by Igor Swie
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);
instance().evaluationDate(),
Post by Igor Swie
calendar, expirations, strikes, volMatrix, dayCounter);
volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);
const boost::shared_ptr<BlackVarianceSurface> volatilitySurfaceH(
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure> volTermStructure(
volatilitySurfaceH);
Post by Igor Swie
// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH,
flatDividendTermStructure, flatTermStructure, volTermStructure));
Post by Igor Swie
// 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;
Post by Igor Swie
cout << "Dividend yield = " << setprecision(4) <<
io::rate(dividendYield) << endl;
Post by Igor Swie
cout << "Volatility = " << setprecision(4) <<
io::volatility(volatility) << endl;
Post by Igor Swie
cout << "Time-length between successive fixings = weekly time
step" << endl;
Post by Igor Swie
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;
boost::timer timer;
//Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngi
ne<LowDiscrepancy>(bsmProcess)
Post by Igor Swie
.withSamples(1500)));
timer.restart();
try
{
cout << "Discrete ArithMC Price: " <<
discreteArithmeticAsianAverageOption.NPV() << endl;
Post by Igor Swie
}
catch (exception const& e) { cout << "Erreur: " << e.what() <<
endl; }
Post by Igor Swie
cout << " in " << timer.elapsed() << " s" << endl;
timer.restart();
}
/**************************end ******************************
******************/
Post by Igor Swie
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.
Post by Igor Swie
/***************************volatility data**************************
************/
Post by Igor Swie
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
***************************/
Post by Igor Swie
I think it's because too many calls are made to get the local volatility.
Thanks,
Igor
------------------------------------------------------------
------------------
Post by Igor Swie
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot______
_________________________________________
Post by Igor Swie
QuantLib-users mailing list
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Luigi Ballabio
2017-05-08 14:17:38 UTC
Permalink
This said, using a flat volatility reduces the computation time a lot, so
there's something in your comment about the local volatility...

Luigi
Post by Igor Swie
Ok the problem was the debug mode,
thanks a lot,
Igor
Post by Peter Caspers
Hi Igor,
this is what I get
~/tmp$ ./igor
Option type = Call
Option maturity = April 4th, 2018
Underlying = 0.748571
Strike = 0.74
Risk-free interest rate = 2.2538 %
Dividend yield = 4.1250 %
Volatility = 7.0537 %
Time-length between successive fixings = weekly time step
Previous fixings = 0
Discrete ArithMC Price: 0.04753356095
in 0.821526 s
Are you on Windows? Maybe you compiled in Debug mode then? That activates
a lot of runtime diagnostics.
Best Regards
Peter
Post by Igor Swie
Hi,
I have tried to price arithmetic asian options with the Monte Carlo
pricer and a complete volatility surface.
Post by Igor Swie
There are about 80 points for the construction of the volatility
surface and I run the Monte Carlo simulation with 1500 paths.
Post by Igor Swie
I get the result after 1 or 2 minutes which is incredibly slow compared
to other fiancnial softwares (less than 1s).
Post by Igor Swie
Who would have an idea of the problem?
/*************************************code********************************/
Post by Igor Swie
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)
Post by Igor Swie
{
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)));
Post by Igor Swie
// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new
FlatForward(todaysDate, riskFreeRate, dayCounter)));
Post by Igor Swie
// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new
BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));
Post by Igor Swie
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(),
Post by Igor Swie
calendar, expirations, strikes, volMatrix, dayCounter);
volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);
const boost::shared_ptr<BlackVarianceSurface> volatilitySurfaceH(
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure>
volTermStructure(volatilitySurfaceH);
Post by Igor Swie
// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH,
flatDividendTermStructure, flatTermStructure, volTermStructure));
Post by Igor Swie
// 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;
Post by Igor Swie
cout << "Dividend yield = " << setprecision(4) <<
io::rate(dividendYield) << endl;
Post by Igor Swie
cout << "Volatility = " << setprecision(4) <<
io::volatility(volatility) << endl;
Post by Igor Swie
cout << "Time-length between successive fixings = weekly time
step" << endl;
Post by Igor Swie
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;
boost::timer timer;
//Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy>(bsmProcess)
Post by Igor Swie
.withSamples(1500)));
timer.restart();
try
{
cout << "Discrete ArithMC Price: " <<
discreteArithmeticAsianAverageOption.NPV() << endl;
Post by Igor Swie
}
catch (exception const& e) { cout << "Erreur: " << e.what() <<
endl; }
Post by Igor Swie
cout << " in " << timer.elapsed() << " s" << endl;
timer.restart();
}
/**************************end
************************************************/
Post by Igor Swie
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.
Post by Igor Swie
/***************************volatility
data**************************************/
Post by Igor Swie
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
<+52%201%20842%20882%204572>,0.113899219047619,0.11163
Post by Igor Swie
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
***************************/
Post by Igor Swie
I think it's because too many calls are made to get the local
volatility.
Post by Igor Swie
Thanks,
Igor
------------------------------------------------------------------------------
Post by Igor Swie
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org!
http://sdm.link/slashdot_______________________________________________
Post by Igor Swie
QuantLib-users mailing list
https://lists.sourceforge.net/lists/listinfo/quantlib-users
------------------------------------------------------------------------------
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
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Igor Swie
2017-05-09 07:54:24 UTC
Permalink
Yes, after some tests it is still much slower than other implementations.
The other thing curiuous for me is that the running time depends on the
length of the averaging time.
Can you tell the algorithm used concerning the evaluation of the pay-off on
a Monte Carlo path?
Is the local volatility computed a priori before running the MC simulations
or on the fly?
Post by Luigi Ballabio
This said, using a flat volatility reduces the computation time a lot, so
there's something in your comment about the local volatility...
Luigi
Post by Igor Swie
Ok the problem was the debug mode,
thanks a lot,
Igor
Post by Peter Caspers
Hi Igor,
this is what I get
~/tmp$ ./igor
Option type = Call
Option maturity = April 4th, 2018
Underlying = 0.748571
Strike = 0.74
Risk-free interest rate = 2.2538 %
Dividend yield = 4.1250 %
Volatility = 7.0537 %
Time-length between successive fixings = weekly time step
Previous fixings = 0
Discrete ArithMC Price: 0.04753356095
in 0.821526 s
Are you on Windows? Maybe you compiled in Debug mode then? That
activates a lot of runtime diagnostics.
Best Regards
Peter
Post by Igor Swie
Hi,
I have tried to price arithmetic asian options with the Monte Carlo
pricer and a complete volatility surface.
Post by Igor Swie
There are about 80 points for the construction of the volatility
surface and I run the Monte Carlo simulation with 1500 paths.
Post by Igor Swie
I get the result after 1 or 2 minutes which is incredibly slow
compared to other fiancnial softwares (less than 1s).
Post by Igor Swie
Who would have an idea of the problem?
/*************************************code******************
**************/
Post by Igor Swie
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)
Post by Igor Swie
{
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)));
Post by Igor Swie
// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new
FlatForward(todaysDate, riskFreeRate, dayCounter)));
Post by Igor Swie
// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new
BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));
Post by Igor Swie
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);
instance().evaluationDate(),
Post by Igor Swie
calendar, expirations, strikes, volMatrix, dayCounter);
volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);
const boost::shared_ptr<BlackVarianceSurface>
volatilitySurfaceH(
Post by Igor Swie
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure> volTermStructure(
volatilitySurfaceH);
Post by Igor Swie
// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH,
flatDividendTermStructure, flatTermStructure, volTermStructure));
Post by Igor Swie
// Payoff
boost::shared_ptr<StrikedTypePayoff> payoffAsianOption(
new PlainVanillaPayoff(
Option::Type(optionType),
strike));
// Options
DiscreteAveragingAsianOption discreteArithmeticAsianAverage
Option(
Post by Igor Swie
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;
Post by Igor Swie
cout << "Dividend yield = " << setprecision(4) <<
io::rate(dividendYield) << endl;
Post by Igor Swie
cout << "Volatility = " << setprecision(4) <<
io::volatility(volatility) << endl;
Post by Igor Swie
cout << "Time-length between successive fixings = weekly time
step" << endl;
Post by Igor Swie
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;
boost::timer timer;
//Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngi
ne<LowDiscrepancy>(bsmProcess)
Post by Igor Swie
.withSamples(1500)));
timer.restart();
try
{
cout << "Discrete ArithMC Price: " <<
discreteArithmeticAsianAverageOption.NPV() << endl;
Post by Igor Swie
}
catch (exception const& e) { cout << "Erreur: " << e.what() <<
endl; }
Post by Igor Swie
cout << " in " << timer.elapsed() << " s" << endl;
timer.restart();
}
/**************************end ******************************
******************/
Post by Igor Swie
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.
Post by Igor Swie
/***************************volatility data**************************
************/
Post by Igor Swie
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
<+52%201%20842%20882%204572>,0.113899219047619,0.11163
Post by Igor Swie
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
***************************/
Post by Igor Swie
I think it's because too many calls are made to get the local
volatility.
Post by Igor Swie
Thanks,
Igor
------------------------------------------------------------
------------------
Post by Igor Swie
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot______
_________________________________________
Post by Igor Swie
QuantLib-users mailing list
https://lists.sourceforge.net/lists/listinfo/quantlib-users
------------------------------------------------------------
------------------
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
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Luigi Ballabio
2017-05-18 14:03:30 UTC
Permalink
I just had a look. The local volatility would be an instance of
LocalVolSurface, which calculates the volatility at (t, x) on the fly for
each call of the corresponding method localVol. So yes, I expect it to be
inefficient. Implementing it so that it samples the volatility on a given
grid and then interpolates it would probably give a speedup.

Luigi
Post by Igor Swie
Yes, after some tests it is still much slower than other implementations.
The other thing curiuous for me is that the running time depends on the
length of the averaging time.
Can you tell the algorithm used concerning the evaluation of the pay-off
on a Monte Carlo path?
Is the local volatility computed a priori before running the MC
simulations or on the fly?
Post by Luigi Ballabio
This said, using a flat volatility reduces the computation time a lot, so
there's something in your comment about the local volatility...
Luigi
Post by Igor Swie
Ok the problem was the debug mode,
thanks a lot,
Igor
Post by Peter Caspers
Hi Igor,
this is what I get
~/tmp$ ./igor
Option type = Call
Option maturity = April 4th, 2018
Underlying = 0.748571
Strike = 0.74
Risk-free interest rate = 2.2538 %
Dividend yield = 4.1250 %
Volatility = 7.0537 %
Time-length between successive fixings = weekly time step
Previous fixings = 0
Discrete ArithMC Price: 0.04753356095
in 0.821526 s
Are you on Windows? Maybe you compiled in Debug mode then? That
activates a lot of runtime diagnostics.
Best Regards
Peter
Post by Igor Swie
Hi,
I have tried to price arithmetic asian options with the Monte Carlo
pricer and a complete volatility surface.
Post by Igor Swie
There are about 80 points for the construction of the volatility
surface and I run the Monte Carlo simulation with 1500 paths.
Post by Igor Swie
I get the result after 1 or 2 minutes which is incredibly slow
compared to other fiancnial softwares (less than 1s).
Post by Igor Swie
Who would have an idea of the problem?
/*************************************code********************************/
Post by Igor Swie
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)
Post by Igor Swie
{
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)));
Post by Igor Swie
// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new
FlatForward(todaysDate, riskFreeRate, dayCounter)));
Post by Igor Swie
// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new
BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));
Post by Igor Swie
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(),
Post by Igor Swie
calendar, expirations, strikes, volMatrix, dayCounter);
volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);
const boost::shared_ptr<BlackVarianceSurface>
volatilitySurfaceH(
Post by Igor Swie
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure>
volTermStructure(volatilitySurfaceH);
Post by Igor Swie
// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH,
flatDividendTermStructure, flatTermStructure, volTermStructure));
Post by Igor Swie
// Payoff
boost::shared_ptr<StrikedTypePayoff> payoffAsianOption(
new PlainVanillaPayoff(
Option::Type(optionType),
strike));
// Options
DiscreteAveragingAsianOption
discreteArithmeticAsianAverageOption(
Post by Igor Swie
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;
Post by Igor Swie
cout << "Dividend yield = " << setprecision(4) <<
io::rate(dividendYield) << endl;
Post by Igor Swie
cout << "Volatility = " << setprecision(4) <<
io::volatility(volatility) << endl;
Post by Igor Swie
cout << "Time-length between successive fixings = weekly time
step" << endl;
Post by Igor Swie
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;
boost::timer timer;
//Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy>(bsmProcess)
Post by Igor Swie
.withSamples(1500)));
timer.restart();
try
{
cout << "Discrete ArithMC Price: " <<
discreteArithmeticAsianAverageOption.NPV() << endl;
Post by Igor Swie
}
catch (exception const& e) { cout << "Erreur: " << e.what() <<
endl; }
Post by Igor Swie
cout << " in " << timer.elapsed() << " s" << endl;
timer.restart();
}
/**************************end
************************************************/
Post by Igor Swie
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.
Post by Igor Swie
/***************************volatility
data**************************************/
Post by Igor Swie
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
<+52%201%20842%20882%204572>,0.113899219047619,0.11163
Post by Igor Swie
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
***************************/
Post by Igor Swie
I think it's because too many calls are made to get the local
volatility.
Post by Igor Swie
Thanks,
Igor
------------------------------------------------------------------------------
Post by Igor Swie
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org!
http://sdm.link/slashdot_______________________________________________
Post by Igor Swie
QuantLib-users mailing list
https://lists.sourceforge.net/lists/listinfo/quantlib-users
------------------------------------------------------------------------------
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
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Loading...