σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademySkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
Skills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python-Skill›Modul 10 · Hochleistungs-Python-Entwicklung›Thema 10.7·~1 Std.Fortgeschritten

Cython

Position in der SkillModul 10 von 11 · Thema 7 von 13
10.7 Cython
—Lab-Punkte— / 100XP gesamt—Serie—

Python mit C-Typen, kompiliert

Cython ist ein Compiler für eine Sprache, die Python plus optionale C-Typdeklarationen ist. Sie schreiben eine .pyx-Datei, Cython übersetzt sie nach C, ein C-Compiler macht daraus ein Erweiterungsmodul, und Sie importieren es wie jedes andere Modul. Schlichter, so kompilierter Python-Code läuft schon etwas schneller, der echte Gewinn kommt aber mit deklarierten Typen: cdef double total sagt Cython, dass total eine Maschinenzahl ist, kein Python-Objekt, sodass die Schleife auf rohen Zahlen ohne Interpreter-Overhead arbeitet. Schwere numerische Schleifen können fünfzig- bis hundertmal schneller werden, wie mit Numba, aber Sie erhalten ein gewöhnliches kompiliertes Modul, das sich ausliefern lässt.

# What a Cython file looks like: Python with cdef type declarations (shown here as text)
pyx = """\
cpdef double dot(double[:] a, double[:] b):
    cdef double total = 0.0
    cdef long i
    for i in range(a.shape[0]):
        total += a[i] * b[i]
    return total
"""
print(pyx.splitlines()[0])                           # cpdef double dot(double[:] a, double[:] b):
print(sum("cdef" in line for line in pyx.splitlines()))     # 2   two typed declarations inside the function

Typen deklarieren: cdef, cpdef und Memoryviews

cdef deklariert eine C-Variable (cdef double total, cdef long i) oder eine Funktion, die nur C-Code aufrufen kann. cpdef deklariert eine Funktion, die von Python und von C aus aufrufbar ist, passend für die Einstiegspunkte eines Moduls. def bleibt eine gewöhnliche Python-Funktion. Arrays werden als typisierte Memoryviews übergeben, etwa double[:] für ein eindimensionales Array aus Doubles: Sie nehmen NumPy-Arrays ohne Kopie an und werden mit C-Geschwindigkeit indiziert. Eine Signatur wie cpdef double mean(double[:] x, long n) ersetzt also Pythons dynamische Typen durch exakte, und ein ausgelassener oder als object deklarierter Typ bleibt ein langsames Python-Objekt.

# Building the declarations as text: one table from Python type names to C types
C_TYPES = {"int": "long", "float": "double", "bool": "bint", "array[float]": "double[:]"}

def c_type(py_type):
    return C_TYPES.get(py_type, "object")

def cdef_signature(name, params, returns):
    result = "void" if returns is None else c_type(returns)
    arguments = ", ".join(f"{c_type(t)} {p}" for p, t in params)
    return f"cpdef {result} {name}({arguments})"

print(cdef_signature("mean", [("x", "array[float]"), ("n", "int")], "float"))    # cpdef double mean(double[:] x, long n)
print(cdef_signature("log_event", [("message", "dict")], None))                  # cpdef void log_event(object message)

Das Modul bauen und herausfinden, was zu typisieren ist

Ein setup.py mit cythonize(["pricing.pyx"]) weist setuptools an, die Datei zu übersetzen und zu kompilieren; python setup.py build_ext --inplace erzeugt neben Ihrem Code eine Shared Library, und import pricing lädt sie. Für schnelle Experimente kompiliert pyximport beim Import. Um zu sehen, was noch langsam ist, führen Sie cython -a pricing.pyx aus: Es schreibt eine HTML-Seite, in der jede Zeile je nach genutzter Python-Maschinerie gelb schattiert ist, die weißen Zeilen sind reines C. Typisieren Sie die Variablen der gelben Zeilen in Ihren heißen Schleifen und schalten Sie dann Prüfungen, die Sie als unnötig erwiesen haben, mit @cython.boundscheck(False) und @cython.wraparound(False) ab, damit Indizierung so billig wird wie in C.

# The build script is a few lines of text; this generates it for a list of modules
def build_setup(modules):
    files = ", ".join(f'"{module}.pyx"' for module in modules)
    return "from setuptools import setup\nfrom Cython.Build import cythonize\n\n" + f"setup(ext_modules=cythonize([{files}]))\n"

print(build_setup(["pricing", "risk"]), end="")
# from setuptools import setup
# from Cython.Build import cythonize
#
# setup(ext_modules=cythonize(["pricing.pyx", "risk.pyx"]))
# The loop a .pyx file would hold, as plain Python: same result, compiled once types are added
def dot(a, b):
    total = 0.0
    for i in range(len(a)):
        total += a[i] * b[i]
    return total

prices = [184.25, 410.5, 99.0]
quantities = [100.0, 50.0, 200.0]
print(dot(prices, quantities))                       # 58750.0  the compiled version returns exactly this number
print(dot(prices, quantities) == sum(p * q for p, q in zip(prices, quantities)))     # True
Cython, Numba oder keins von beiden?Numba ist die leichtere Wahl: ein Dekorator, kein Build-Schritt, ideal für numerische Funktionen. Cython kostet einen Build-Schritt und einen zweiten Dateityp, liefert aber ein gewöhnliches Modul, das sich ohne JIT-Start ausliefern lässt, und erlaubt, C-Bibliotheken aufzurufen und C- und Python-Code frei zu mischen. Probieren Sie zuerst NumPy-Vektorisierung, dann Numba, dann Cython; und vergleichen Sie in jedem Fall die Ausgabe mit der einfachen Python-Version, bevor Sie ihr vertrauen.
  • Cython kompiliert eine .pyx-Datei (Python plus optionale C-Typen) nach C und dann zu einem Erweiterungsmodul, das man normal importiert.
  • cdef deklariert C-Variablen und reine C-Funktionen, cpdef eine von Python und C aufrufbare Funktion; Arrays sind typisierte Memoryviews wie double[:].
  • Bauen Sie mit cythonize in setup.py, finden Sie mit cython -a die gelben (langsamen) Zeilen in heißen Schleifen und prüfen Sie gegen das einfache Python-Ergebnis.

Als Nächstes: C++ mit pybind11 aufrufen, vorhandenen C++-Code für Python verfügbar machen.

Lab: Was bewertet wird

  • Python-Typen mit c_type auf C abbilden25 Pkt.
  • Mit cdef_signature einen Funktionskopf schreiben25 Pkt.
  • Lokale Variablen mit declare_locals typisieren25 Pkt.
  • Mit build_setup das Build-Skript schreiben25 Pkt.
Explorer · lab-123-1
▾ lab-123-1
…
bash · im Browser
learner@quantcraft:~/lab-123-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-123-1 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen

Melde dich an, um deinen Code auszuführen.

Alle Lektionen kannst du kostenlos lesen. Erstelle ein Konto oder melde dich an, um Code auszuführen, Tests zu starten und dieses Lab abzugeben.

  • IDE im Browser mit Bash-Terminal — nichts zu installieren
  • Sofortige Bewertung, XP und dein Platz auf der Skill
Konto erstellenAnmelden
ODER
Weiter mit GitHub