Matt
Matt

Reputation: 2822

Cython compiled module does not allow access to the function defined 'module' not callable

ORIGINAL ERROR FOUND -> from CyBlack.CyBlack import CyBlack then pass *numpy_value as inputs. A new issue has arisen so creating a new post for that. Cython program with numpy arrays does not allow vectorized inputs (only accepts length 1 arrays), how to fix?

I am new to Cython and tried converting the Black (Black Scholes without a stock dividend) over from Python to Cython. After getting it to compile, it doesn't let me actually use the function. I'm sure someone with more experience can look at this easily and figure out why. The error I get after compiling and importing the function from CyBlack import CyBlack and calling CyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput) is TypeError: 'module' object is not callable: So here's the code:

from numpy cimport ndarray
cimport numpy as np
cimport cython

cdef extern from "math.h":
    double exp(double)
    double sqrt(double)
    double pow(double)
    double log(double)
    double erf(double)

cdef double std_norm_cdf(double x):
    return 0.5*(1+erf(x/sqrt(2.0)))

@cython.boundscheck(False)
cdef CyBlack(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.float64_t, ndim=1] Black_callput):

    cdef Py_ssize_t i
    cdef Py_ssize_t N = BlackPnL.shape[0]
    cdef double d1, d2


    for i in range(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

Thanks for any help here! I can post python fake data if you need something to test off of - although just calling it with any data will expose the error... Something points me to the variables not being exposed to Python from the C code.

Adding my setup.py here so others can build this typing: python setup.py build_ext --inplace built with VS2015 for Python 3.5 64bit Windows.

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize("CyBlack.pyx"), include_dirs =["C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//include", "C://Program Files (x86)//Windows Kits//10//Include//10.0.1.0240.0//ucrt", "C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//lib//amd64", "C://Anaconda3//Lib//site-packages//numpy//core//include", "C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//lib//amd64"])

Upvotes: 1

Views: 1272

Answers (2)

val
val

Reputation: 8689

I managed to get (something like it) working in the following way:

C:/dev/tmp/CyBlack/
                   __init__.py
                   setup.py
                   CyBlack.pyx

Where CyBlack.pyx is just like yours, except with CyBlack function being cpdef'd. setup.py contains:

from distutils.core import setup
import numpy
from Cython.Build import cythonize

extra_compile_args = ['/EHsc', '/openmp', '/favor:INTEL64']

setup(
    ext_modules=cythonize("CyBlack.pyx"),
    include_dirs=['.', numpy.get_include()],
    extra_compile_args=extra_compile_args
)

Running then:

C:\dev\tmp\CyBlack> python .\setup.py build_ext --compiler=msvc --inplace

Will produce C:/dev/tmp/CyBlack/CyBlack.pyd, and I then managed to run the code from Python:

>>> from sys import path
>>> path.insert(0, "C:/dev/tmp")
>>> from CyBlack.CyBlack import CyBlack
>>> CyBlack(*[np.array([1.0]) for _ in xrange(7)]) # I'm too lazy to put proper values here...
array([ 0.14087021])

This was done with Python 2.7, and overall setup might be slightly different, but hopefully, that might help you getting a minimum working example and trace back how to make yours run correctly.

Upvotes: 2

davo36
davo36

Reputation: 714

Instead of

from CyBlack import CyBlack

Why don't you just do

import CyBlack

?

Upvotes: -2

Related Questions