2016-05-11 8 views
0

FIXED: siehe aktualisierten Code unten.Cython-Programm mit numpy Arrays erlaubt keine vektorisierten Eingaben (akzeptiert nur Länge 1 Arrays), wie zu beheben?

Dies ist meine erste Cython-Versuch und haben einen funktionierenden Build, aber es erlaubt keine numpy Array (Vektoren) als Eingaben, das ist mein wirklicher Zweck hier. Es ist das Black-Modell (Black Scholes für europäische Optionspreise ohne Dividende). Es wird nur Arrays der Länge 1 als Eingaben akzeptieren (wenn ich versuche, mit Arrays der Länge 2 zu berechnen, sind es Fehler: TypeError: CyBlack() takes exactly 7 positional arguments (14 given), wenn ich Arrays der Länge 10 übergebe, (70 given), etc.). Ich bin nicht sicher, warum, wie ich im Cython-Code numpy Arrays definiert habe. Als Referenz Sie es mit dem folgenden Code kompilieren kann sie dann als solche verwendet werden: from CyBlack.CyBlack import CyBlack dann CyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput) Also hier ist der Code der Rufnummer (speichern als CyBlack.pyx Datei zu kompilieren):

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 

Hier ist die setup.py so andere können diese Typisierung bauen : python setup.py build_ext --inplace mit VS2015 für Python 3.5 64bit Windows gebaut.

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) 

Die oben kompiliert und funktioniert nach dem Update auf den Variablentyp mit (Black_callput war eigentlich ein int64) und Sie haben die numpy Arrays zu übergeben, da sie (kein Stern) sind und es funktioniert einwandfrei.

+0

* "Es wird immer nur 1 Wert berechnet" * - was genau meinst du damit? –

+1

"Sie müssen die Nummernfelder mit einem Stern an die Funktion übergeben" - was? warum machen Sie das? Das ist entweder Ihr gesamtes Problem oder ein sehr großer Teil Ihres Problems. Zeigen Sie uns, welche Argumente Sie weitergeben und wie. – user2357112

+0

* "Sie müssen die Nummernfelder an die Funktion mit einem Stern übergeben, * Black_PnL als Beispiel" * - uh, nein, Sie nicht! Übergeben Sie sie als separate Argumente. –

Antwort

3

Es gab zwei Probleme hier:

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

    Dies wird durch die Tatsache verursacht wurde, dass Sie Ihre Eingabe-Arrays wurden Entpacken der * ("Klecks") Operator. Sie mussten sie stattdessen als 7 separate Argumente übergeben.

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

    Dieser Fehler Ihr erzählt, dass einer der Eingabefelder einen C-Typen von long long hatte (das ist ein 64-Bit-Integer ist), anstatt float64_t wie in Ihrer Eingangstypdeklaration angegeben. Sie mussten alle Ihre Eingabearrays in np.float64 umwandeln.