σμ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 Academyالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
المسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Python›الوحدة 10 · هندسة Python عالية الأداء›الموضوع 10.7·~1 سمتقدم

Cython

الموضع في المسارالوحدة 10 من 11 · الموضوع 7 من 13
10.7 Cython
—درجة المختبر— / 100إجمالي XP—التتابع—

بايثون بأنواع C مترجمة

Cython مترجم للغة هي بايثون مضافًا إليها تصريحات أنواع C اختيارية. تكتب ملف .pyx ويترجمه Cython إلى C ثم يحوّله مترجم C إلى وحدة امتداد فتستوردها كأي وحدة أخرى. وشيفرة بايثون العادية المترجمة هكذا تعمل أسرع قليلًا أصلًا، لكن المكسب الحقيقي يأتي عند التصريح بالأنواع: cdef double total تخبر Cython أن total عدد آلة لا كائن بايثون فتعمل الحلقة على أرقام خام بلا كلفة المفسّر. ويمكن للحلقات العددية الثقيلة أن تصير أسرع بخمسين إلى مئة مرة كما مع Numba، لكنك تحصل على وحدة مترجمة عادية يمكنك توزيعها.

# 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

التصريح بالأنواع: cdef وcpdef وعروض الذاكرة

يصرّح cdef بمتغير C (cdef double total وcdef long i) أو بدالة لا يستدعيها إلا شيفرة C. ويصرّح cpdef بدالة قابلة للاستدعاء من بايثون ومن C، وهو المناسب لنقاط دخول الوحدة. أما def فتبقى دالة بايثون عادية. وتُمرَّر المصفوفات عروض ذاكرة مُنمَّطة مثل double[:] لمصفوفة أحادية البعد من doubles: تقبل مصفوفات NumPy دون نسخ وتُفهرَس بسرعة C. فتوقيع مثل cpdef double mean(double[:] x, long n) يستبدل الأنواع الديناميكية في بايثون بأنواع دقيقة، والنوع المحذوف أو المصرَّح به object يبقى كائن بايثون بطيئًا.

# 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)

بناء الوحدة ومعرفة ما يجب تحديد نوعه

يطلب setup.py مع cythonize(["pricing.pyx"]) من setuptools ترجمة الملف وبناءه؛ ويُنتج python setup.py build_ext --inplace مكتبة مشتركة بجوار شيفرتك ويحمّلها import pricing. وللتجارب السريعة يترجم pyximport عند الاستيراد. ولمعرفة ما يبقى بطيئًا شغّل cython -a pricing.pyx: يكتب صفحة HTML يُظلَّل فيها كل سطر بالأصفر بقدر ما يستعمله من آلية بايثون، والأسطر البيضاء C خالصة. حدّد أنواع المتغيرات في الأسطر الصفراء داخل حلقاتك الساخنة ثم عطّل الفحوص التي أثبتَّ عدم لزومها بـ @cython.boundscheck(False) و@cython.wraparound(False) ليصير الفهرسة رخيصة كما في 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 أم لا هذا ولا ذاك؟Numba الخيار الأخف: مزخرِف واحد وبلا خطوة بناء ومثالي للدوال العددية. أما Cython فيكلف خطوة بناء ونوع ملف ثانيًا لكنه يعطي وحدة عادية توزَّع دون بدء JIT ويتيح استدعاء مكتبات C وخلط شيفرة C وبايثون بحرية. جرّب أولًا التوجيه بـ NumPy ثم Numba ثم Cython؛ وقارن في كل حال الناتج بنسخة بايثون العادية قبل أن تثق به.
  • يترجم Cython ملف .pyx (بايثون مع أنواع C اختيارية) إلى C ثم إلى وحدة امتداد تستوردها بـ import كالمعتاد.
  • cdef يصرّح بمتغيرات C ودوال C فقط وcpdef بدالة قابلة للاستدعاء من بايثون وC؛ والمصفوفات عروض ذاكرة مُنمَّطة مثل double[:].
  • ابنِ بـ cythonize في setup.py واستخدم cython -a لإيجاد الأسطر الصفراء (البطيئة) في الحلقات الساخنة وتحقق بنتيجة بايثون العادية.

التالي: استدعاء C++ باستخدام pybind11، إتاحة شيفرة C++ الموجودة لبايثون.

المختبر: ما الذي يُقيَّم

  • اربط أنواع بايثون بأنواع C باستخدام c_type25 نقطة
  • اكتب ترويسة دالة باستخدام cdef_signature25 نقطة
  • حدّد أنواع المتغيرات المحلية باستخدام declare_locals25 نقطة
  • اكتب سكربت البناء باستخدام build_setup25 نقطة
المستكشف · lab-123-1
▾ lab-123-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-123-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-123-1 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات

سجّل الدخول لتشغيل الكود الخاص بك.

قراءة كل المحاضرات مجانية. أنشئ حسابًا أو سجّل الدخول لتشغيل الكود وتنفيذ الاختبارات وتسليم هذا المختبر.

  • بيئة تطوير داخل المتصفح مع طرفية bash — لا حاجة لتثبيت أي شيء
  • تصحيح فوري ونقاط خبرة ومكانك في المسار
إنشاء حسابتسجيل الدخول
أو
المتابعة عبر GitHub