Cython Program Is Slower Than Plain Python (10m Options 3.5s Vs 3.25s Black Scholes) - What Am I Missing?
Okay here's my first Cython program below, the code to price European options on futures (Black Scholes without a dividend). It runs in 3.5s on 10M options, versus the code I post
Solution 1:
I added the following lines before your functions in your cython code and I got a faster result from Cython than Python 2.7
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
My results for 10M points
%timeit PyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput)
1 loops, best of 3: 3.49 s per loop
and
%timeit CyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput)
1 loops, best of 3: 2.12 s per loop
EDIT
CyBlack.pyx
from numpy cimport ndarray
cimport numpy as np
cimport cython
cdefexternfrom"math.h":
double exp(double)
double sqrt(double)
double log(double)
double fabs(double)
cdefdouble a1 = 0.254829592
cdefdouble a2 = -0.284496736
cdefdouble a3 = 1.421413741
cdefdouble a4 = -1.453152027
cdefdouble a5 = 1.061405429
cdefdouble p = 0.3275911@cython.boundscheck(False)@cython.wraparound(False)@cython.cdivision(True)
cdefinline double erf(double x):
cdefint sign = 1if (x < 0):
sign = -1
x = fabs(x)
cdefdouble t = 1.0/(1.0 + p*x)
cdefdouble y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x)
return sign*y
@cython.boundscheck(False)@cython.wraparound(False)@cython.cdivision(True)
cdefdouble std_norm_cdf(double x):
return0.5*(1+erf(x/sqrt(2.0)))
@cython.boundscheck(False)@cython.wraparound(False)@cython.cdivision(True)
cpdefCyBlack(ndarray[np.float64_t, ndim=1] BlackPnL, ndarray[np.float64_t, ndim=1] Black_S, ndarray[np.float64_t, ndim=1] Black_Texpiry, ndarray[np.float64_t, ndim=1] Black_strike, ndarray [np.float64_t, ndim=1] Black_volatility, ndarray[np.float64_t, ndim=1] Black_IR, ndarray[np.int64_t, ndim=1] Black_callput):
cdefPy_ssize_t i
cdefPy_ssize_t N = BlackPnL.shape[0]
cdefdouble d1, d2
for i inrange(N):
d1 = ((log(Black_S[i] / Black_strike[i]) + Black_Texpiry[i] * Black_volatility[i] **2 / 2)) / (Black_volatility[i] * sqrt(Black_Texpiry[i]))
d2 = d1 - Black_volatility[i] * sqrt(Black_Texpiry[i])
BlackPnL[i] = exp(-Black_IR[i] * Black_Texpiry[i]) * (Black_callput[i] * Black_S[i] * std_norm_cdf(Black_callput[i] * d1) - Black_callput[i] * Black_strike[i] * std_norm_cdf(Black_callput[i] * d2))
return BlackPnL
setup.py
try:
from setuptools import setup
from setuptools import Extension
except ImportError:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
ext_modules = [Extension("CyBlack",["CyBlack.pyx"])]
setup(
name= 'Generic model class',
cmdclass = {'build_ext': build_ext},
include_dirs = [np.get_include()],
ext_modules = ext_modules)
Post a Comment for "Cython Program Is Slower Than Plain Python (10m Options 3.5s Vs 3.25s Black Scholes) - What Am I Missing?"