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 |
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 > On 28 Apr 2017, at 10:12, Igor Swie <[hidden email]> wrote: > > 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 ------------------------------------------------------------------------------ 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 |
Ok the problem was the debug mode, thanks a lot, Igor 2017-04-29 19:25 GMT+02:00 Peter Caspers <[hidden email]>: Hi 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 |
This said, using a flat volatility reduces the computation time a lot, so there's something in your comment about the local volatility...
Luigi On Wed, May 3, 2017 at 10:35 PM Igor Swie <[hidden email]> wrote:
------------------------------------------------------------------------------ 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 |
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? 2017-05-08 16:17 GMT+02:00 Luigi Ballabio <[hidden email]>:
------------------------------------------------------------------------------ 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 |
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 On Tue, May 9, 2017 at 9:54 AM Igor Swie <[hidden email]> wrote:
------------------------------------------------------------------------------ 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 |
Free forum by Nabble | Edit this page |