带有numpy数组的Cython程序不允许矢量化输入(只接受长度为1的数组),如何修复?

时间:2016-05-11 15:29:29

标签: python numpy cython

已修复:请参阅下面的更新代码。

这是我的第一次Cython尝试并且有一个有效的构建,但它不允许numpy数组(向量)作为输入,这是我的真正目的。它是Black模型(Black Scholes,欧洲期权定价没有股息)。它只接受长度为1的数组作为输入(如果我尝试用长度为2的数组计算它是错误的:TypeError: CyBlack() takes exactly 7 positional arguments (14 given),如果我传递长度为10的数组,(70 given)等等。我不确定为什么我在Cython代码中定义了numpy数组。作为参考,你可以使用下面的代码编译它然后使用它:from CyBlack.CyBlack import CyBlack然后调用CyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput)所以这里的代码(保存为CyBlack.pyx文件进行编译):< / p>

from numpy cimport ndarray
cimport numpy as np
cimport cython

cdef extern from "math.h":
    double exp(double)
    double sqrt(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)
cpdef 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.int64_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

以下是setup.py,因此其他人可以构建此类型:python setup.py build_ext --inplace使用VS2015为Python 3.5 64位Windows构建。

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

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

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

上面的代码在使用变量类型的修复程序后编译并运行(Black_callput实际上是int64),你必须按原样传递numpy数组(没有星号)并且它可以正常工作。

1 个答案:

答案 0 :(得分:3)

这里有两个问题:

  1. TypeError: CyBlack() takes exactly 7 positional arguments (14 given)

    这是因为您使用*(“splat”)运算符解压缩输入数组。你需要将它们作为7个单独的参数传递给它们。

  2. ValueError: Buffer dtype mismatch, expected 'float64_t' but got 'long long'

    此错误告诉您其中一个输入数组的C类型为long long(64位整数),而不是输入类型声明中指定的float64_t。您需要将所有输入数组转换为np.float64