##// END OF EJS Templates
Add a pure-python version of the Black-Scholes function for comparison with the Cython equivalent
Erik Tollerud -
Show More
@@ -1,6 +1,7 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": "Cython Magics"
3 "name": "",
4 "signature": "sha256:c357b93e9480d6347c6677862bf43750745cef4b30129c5bc53cb879a19d4074"
4 },
5 },
5 "nbformat": 3,
6 "nbformat": 3,
6 "nbformat_minor": 0,
7 "nbformat_minor": 0,
@@ -79,6 +80,7 b''
79 "metadata": {},
80 "metadata": {},
80 "outputs": [
81 "outputs": [
81 {
82 {
83 "metadata": {},
82 "output_type": "pyout",
84 "output_type": "pyout",
83 "prompt_number": 3,
85 "prompt_number": 3,
84 "text": [
86 "text": [
@@ -126,6 +128,7 b''
126 "metadata": {},
128 "metadata": {},
127 "outputs": [
129 "outputs": [
128 {
130 {
131 "metadata": {},
129 "output_type": "pyout",
132 "output_type": "pyout",
130 "prompt_number": 5,
133 "prompt_number": 5,
131 "text": [
134 "text": [
@@ -161,12 +164,12 b''
161 "from libc.math cimport exp, sqrt, pow, log, erf\n",
164 "from libc.math cimport exp, sqrt, pow, log, erf\n",
162 "\n",
165 "\n",
163 "@cython.cdivision(True)\n",
166 "@cython.cdivision(True)\n",
164 "cdef double std_norm_cdf(double x) nogil:\n",
167 "cdef double std_norm_cdf_cy(double x) nogil:\n",
165 " return 0.5*(1+erf(x/sqrt(2.0)))\n",
168 " return 0.5*(1+erf(x/sqrt(2.0)))\n",
166 "\n",
169 "\n",
167 "@cython.cdivision(True)\n",
170 "@cython.cdivision(True)\n",
168 "def black_scholes(double s, double k, double t, double v,\n",
171 "def black_scholes_cy(double s, double k, double t, double v,\n",
169 " double rf, double div, double cp):\n",
172 " double rf, double div, double cp):\n",
170 " \"\"\"Price an option using the Black-Scholes model.\n",
173 " \"\"\"Price an option using the Black-Scholes model.\n",
171 " \n",
174 " \n",
172 " s : initial stock price\n",
175 " s : initial stock price\n",
@@ -181,8 +184,8 b''
181 " with nogil:\n",
184 " with nogil:\n",
182 " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n",
185 " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n",
183 " d2 = d1 - v*sqrt(t)\n",
186 " d2 = d1 - v*sqrt(t)\n",
184 " optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \\\n",
187 " optprice = cp*s*exp(-div*t)*std_norm_cdf_cy(cp*d1) - \\\n",
185 " cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)\n",
188 " cp*k*exp(-rf*t)*std_norm_cdf_cy(cp*d2)\n",
186 " return optprice"
189 " return optprice"
187 ],
190 ],
188 "language": "python",
191 "language": "python",
@@ -194,12 +197,13 b''
194 "cell_type": "code",
197 "cell_type": "code",
195 "collapsed": false,
198 "collapsed": false,
196 "input": [
199 "input": [
197 "black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
200 "black_scholes_cy(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
198 ],
201 ],
199 "language": "python",
202 "language": "python",
200 "metadata": {},
203 "metadata": {},
201 "outputs": [
204 "outputs": [
202 {
205 {
206 "metadata": {},
203 "output_type": "pyout",
207 "output_type": "pyout",
204 "prompt_number": 7,
208 "prompt_number": 7,
205 "text": [
209 "text": [
@@ -210,10 +214,75 b''
210 "prompt_number": 7
214 "prompt_number": 7
211 },
215 },
212 {
216 {
217 "cell_type": "markdown",
218 "metadata": {},
219 "source": [
220 "For comparison, the same code is implemented here in pure python."
221 ]
222 },
223 {
224 "cell_type": "code",
225 "collapsed": false,
226 "input": [
227 "from math import exp, sqrt, pow, log, erf\n",
228 "\n",
229 "def std_norm_cdf_py(x):\n",
230 " return 0.5*(1+erf(x/sqrt(2.0)))\n",
231 "\n",
232 "def black_scholes_py(s, k, t, v, rf, div, cp):\n",
233 " \"\"\"Price an option using the Black-Scholes model.\n",
234 " \n",
235 " s : initial stock price\n",
236 " k : strike price\n",
237 " t : expiration time\n",
238 " v : volatility\n",
239 " rf : risk-free rate\n",
240 " div : dividend\n",
241 " cp : +1/-1 for call/put\n",
242 " \"\"\"\n",
243 " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n",
244 " d2 = d1 - v*sqrt(t)\n",
245 " optprice = cp*s*exp(-div*t)*std_norm_cdf_py(cp*d1) - \\\n",
246 " cp*k*exp(-rf*t)*std_norm_cdf_py(cp*d2)\n",
247 " return optprice"
248 ],
249 "language": "python",
250 "metadata": {},
251 "outputs": [],
252 "prompt_number": 8
253 },
254 {
213 "cell_type": "code",
255 "cell_type": "code",
214 "collapsed": false,
256 "collapsed": false,
215 "input": [
257 "input": [
216 "%timeit black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
258 "black_scholes_py(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
259 ],
260 "language": "python",
261 "metadata": {},
262 "outputs": [
263 {
264 "metadata": {},
265 "output_type": "pyout",
266 "prompt_number": 9,
267 "text": [
268 "10.327861752731728"
269 ]
270 }
271 ],
272 "prompt_number": 9
273 },
274 {
275 "cell_type": "markdown",
276 "metadata": {},
277 "source": [
278 "Below we see the runtime of the two functions: the Cython version is nearly a factor of 10 faster."
279 ]
280 },
281 {
282 "cell_type": "code",
283 "collapsed": false,
284 "input": [
285 "%timeit black_scholes_cy(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
217 ],
286 ],
218 "language": "python",
287 "language": "python",
219 "metadata": {},
288 "metadata": {},
@@ -222,11 +291,30 b''
222 "output_type": "stream",
291 "output_type": "stream",
223 "stream": "stdout",
292 "stream": "stdout",
224 "text": [
293 "text": [
225 "1000000 loops, best of 3: 821 ns per loop\n"
294 "1000000 loops, best of 3: 319 ns per loop\n"
226 ]
295 ]
227 }
296 }
228 ],
297 ],
229 "prompt_number": 8
298 "prompt_number": 10
299 },
300 {
301 "cell_type": "code",
302 "collapsed": false,
303 "input": [
304 "%timeit black_scholes_py(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
305 ],
306 "language": "python",
307 "metadata": {},
308 "outputs": [
309 {
310 "output_type": "stream",
311 "stream": "stdout",
312 "text": [
313 "100000 loops, best of 3: 2.28 \u00b5s per loop\n"
314 ]
315 }
316 ],
317 "prompt_number": 11
230 },
318 },
231 {
319 {
232 "cell_type": "heading",
320 "cell_type": "heading",
@@ -262,7 +350,7 b''
262 ]
350 ]
263 }
351 }
264 ],
352 ],
265 "prompt_number": 9
353 "prompt_number": 12
266 },
354 },
267 {
355 {
268 "cell_type": "markdown",
356 "cell_type": "markdown",
@@ -275,4 +363,4 b''
275 "metadata": {}
363 "metadata": {}
276 }
364 }
277 ]
365 ]
278 }
366 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now