{"id":4619,"date":"2012-10-07T11:24:43","date_gmt":"2012-10-07T10:24:43","guid":{"rendered":"http:\/\/www.walkingrandomly.com\/?p=4619"},"modified":"2012-10-28T15:34:11","modified_gmt":"2012-10-28T14:34:11","slug":"european-option-pricing-in-julia-and-matlab","status":"publish","type":"post","link":"https:\/\/walkingrandomly.com\/?p=4619","title":{"rendered":"European Option Pricing in Julia and MATLAB"},"content":{"rendered":"<p>I felt like playing with <a href=\"http:\/\/julialang.org\/\">Julia<\/a> and <a href=\"http:\/\/www.mathworks.co.uk\/products\/matlab\/\">MATLAB<\/a> this Sunday morning.\u00a0 I found some code that prices <a href=\"http:\/\/en.wikipedia.org\/wiki\/Option_style\">European Options<\/a> in MATLAB using Monte Carlo simulations <a href=\"http:\/\/computeraidedfinance.com\/2012\/06\/11\/matlab-gpu-toolbox-benchmarking-accelereyes-vs-mathworks-vs-gp-you\/\">over at computeraidedfinance.com<\/a> and thought that I&#8217;d port this over to Julia.\u00a0 Here&#8217;s the original MATLAB code<\/p>\n<pre>function V = bench_CPU_European(numPaths)\r\n%Simple European\r\nsteps = 250;\r\nr = (0.05);\r\nsigma = (0.4);\r\nT = (1);\r\ndt = T\/(steps);\r\nK = (100);\r\n\r\nS = 100 * ones(numPaths,1);\r\n\r\nfor i=1:steps\r\n rnd = randn(numPaths,1);\r\n S = S .* exp((r-0.5*sigma.^2)*dt + sigma*sqrt(dt)*rnd);\r\nend\r\nV = mean( exp(-r*T)*max(K-S,0) )<\/pre>\n<p>I ran this a couple of times to see what results I should be getting and how long it would take for 1 million paths:<\/p>\n<pre>tic;bench_CPU_European(1000000);toc\r\nV =\r\n   13.1596\r\nElapsed time is 6.035635 seconds.\r\n&gt;&gt; tic;bench_CPU_European(1000000);toc\r\nV =\r\n   13.1258\r\nElapsed time is 5.924104 seconds.\r\n&gt;&gt; tic;bench_CPU_European(1000000);toc\r\nV =\r\n   13.1479\r\nElapsed time is 5.936475 seconds.<\/pre>\n<p>The result varies because this is a stochastic process but we can see that it should be around 13.1 or so and takes around 6 seconds on my laptop. Since it&#8217;s Sunday morning, I am feeling lazy and have no intention of considering if this code is optimal or not right now. I&#8217;m just going to copy and paste it into a julia file and hack at the syntax until it becomes valid Julia code. The following seems to work<\/p>\n<pre>function bench_CPU_European(numPaths)\r\n\r\nsteps = 250\r\nr = 0.05\r\nsigma = .4;\r\nT = 1;\r\ndt = T\/(steps)\r\nK = 100;\r\n\r\nS = 100 * ones(numPaths,1);\r\n\r\nfor i=1:steps\r\n rnd = randn(numPaths,1)\r\n S = S .* exp((r-0.5*sigma.^2)*dt + sigma*sqrt(dt)*rnd)\r\nend\r\nV = mean( exp(-r*T)*max(K-S,0) )\r\nend<\/pre>\n<p>I ran this on Julia and got the following<\/p>\n<pre>julia&gt; tic();bench_CPU_European(1000000);toc()\r\nelapsed time: 36.259000062942505 seconds\r\n36.259000062942505\r\n\r\njulia&gt; bench_CPU_European(1000000)\r\n13.114855104505445<\/pre>\n<p>The Julia code appears to be valid, it gives the correct result of 13.1 ish but at 36.25 seconds is around <strong>6 times slower<\/strong> than the MATLAB version.\u00a0 The dog needs walking so I&#8217;m going to think about this another time but comments are welcome.<\/p>\n<p><strong>Update (9pm 7th October 2012):<\/strong>\u00a0\u00a0 I&#8217;ve just tried this Julia code on the Linux partition of the same laptop and 1 million paths took 14 seconds or so:<\/p>\n<pre>tic();bench_CPU_European(1000000);toc()\r\nelapsed time: 14.146281957626343 seconds<\/pre>\n<p>I built this version of Julia from source and so it&#8217;s at the current bleeding edge (version 0.0.0+98589672.r65a1 Commit 65a1f3dedc (2012-10-07 06:40:18). The code is still slower than the MATLAB version but better than the older Windows build<\/p>\n<p><strong>Update: 13th October 2012<\/strong><\/p>\n<p><a href=\"https:\/\/groups.google.com\/forum\/?fromgroups=#!topic\/julia-dev\/ImhGsqX_IHc\">Over on the Julia mailing list<\/a>, someone posted a faster version of this simulation in Julia<\/p>\n<pre>function bench_eu(numPaths)\r\n    steps = 250\r\n    r = 0.05\r\n    sigma = .4;\r\n    T = 1;\r\n    dt = T\/(steps)\r\n    K = 100;\r\n\r\n    S = 100 * ones(numPaths,1);\r\n\r\n    t1 = (r-0.5*sigma.^2)*dt\r\n    t2 = sigma*sqrt(dt)\r\n    for i=1:steps\r\n        for j=1:numPaths\r\n            S[j] .*= exp(t1 + t2*randn())\r\n        end\r\n    end\r\n\r\n    V = mean( exp(-r*T)*max(K-S,0) )\r\nend<\/pre>\n<p>On the Linux partition of my test machine, this got through 1000000 paths in 8.53 seconds, very close to the MATLAB speed:<\/p>\n<pre>julia&gt; tic();bench_eu(1000000);toc()\r\nelapsed time: 8.534484148025513 seconds<\/pre>\n<p>It seems that, when using Julia, one needs to unlearn everything you&#8217;ve ever learned about vectorisation in MATLAB.<\/p>\n<p><strong>Update: 28th October 2012<\/strong><\/p>\n<p>Members of the Julia team have been improving the performance of the randn() function used in the above code (see <a href=\"https:\/\/groups.google.com\/forum\/?fromgroups=#!topic\/julia-dev\/ImhGsqX_IHc\">here<\/a> and <a href=\"https:\/\/github.com\/JuliaLang\/julia\/issues\/1348\">here<\/a> for details).\u00a0 Using the de-vectorised code above, execution time for 1 million paths in Julia is now down to 7.2 seconds on my machine on Linux.\u00a0 Still slower than the MATLAB 2012a implementation but it&#8217;s getting there.\u00a0 This was using Julia version \u00a00.0.0+100403134.r0999 Commit 099936aec6 (2012-10-28 05:24:40)<\/p>\n<pre>tic();bench_eu(1000000);toc()\r\nelapsed time: 7.223690032958984 seconds\r\n7.223690032958984<\/pre>\n<ul>\n<li>Laptop model: Dell XPS L702X<\/li>\n<li>CPU:<a href=\"http:\/\/www.notebookcheck.net\/Intel-Core-i7-2630QM-Notebook-Processor.41483.0.html\">Intel Core i7-2630QM<\/a> @2Ghz software overclockable to 2.9Ghz. 4 physical cores but total 8 virtual cores due to Hyperthreading.<\/li>\n<li>RAM: 8 Gb<\/li>\n<li>OS: Windows 7 Home Premium 64 bit and Ubuntu 12.04<\/li>\n<li>MATLAB: 2012a<\/li>\n<li>Julia: Original windows version was Version 0.0.0+94063912.r17f5, Commit 17f50ea4e0 (2012-08-15 22:30:58).\u00a0 Several versions used on Linux since, see text for details.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I felt like playing with Julia and MATLAB this Sunday morning.\u00a0 I found some code that prices European Options in MATLAB using Monte Carlo simulations over at computeraidedfinance.com and thought that I&#8217;d port this over to Julia.\u00a0 Here&#8217;s the original MATLAB code function V = bench_CPU_European(numPaths) %Simple European steps = 250; r = (0.05); sigma [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[58,59,45,11],"tags":[62],"class_list":["post-4619","post","type-post","status-publish","format-standard","hentry","category-financial-math","category-julia","category-just-for-fun","category-matlab","tag-julia-2"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3swhs-1cv","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/4619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4619"}],"version-history":[{"count":13,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/4619\/revisions"}],"predecessor-version":[{"id":4626,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/4619\/revisions\/4626"}],"wp:attachment":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}