σμ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›الوحدة 1 · أساسيات Python للمحللين الكميين›الموضوع 1.28·~35 دمبتدئ

Dataclasses

الموضع في المسارالوحدة 1 من 11 · الموضوع 28 من 33
1.28 Dataclasses
—درجة المختبر— / 100إجمالي XP—التتابع—

كود تكراري أقل للفئات التي تحمل بيانات

توجد فئات كثيرة أساسًا لتحمل بضعة حقول: صفقة أو عرض سعر أو إعداد. وكتابة __init__ و__repr__ و__eq__ لكل منها مكررة. يكتبها لك المزخرف @dataclass من الوحدة dataclasses انطلاقًا من قائمة حقول موسومة. تعلن symbol: str وprice: float وquantity: int مرة واحدة فتحصل على دالة بانية Trade("AAPL", 184.25, 200) وعلى repr مقروء مثل Trade(symbol='AAPL', price=184.25, quantity=200) وتساوٍ حقلًا بحقل. والتوسيمات توثّق القصد؛ ولا تفرضها بايثون.

from dataclasses import dataclass

@dataclass
class Trade:
    symbol: str
    price: float
    quantity: int

a = Trade("AAPL", 184.25, 200)
b = Trade("AAPL", 184.25, 200)

print(a)                       # Trade(symbol='AAPL', price=184.25, quantity=200)
print(a == b)                  # True: compared field by field
print(a.price * a.quantity)    # 36850.0

القيم الافتراضية و field() والقيم القابلة للتعديل

يمكن أن يكون للحقل قيمة افتراضية (currency: str = "USD")، ويجب أن تأتي الحقول ذات القيم الافتراضية بعد الحقول التي بلا قيم. أما لقيمة افتراضية قابلة للتعديل كقائمة فسيتشاركها كل كائن إذا كتبت = [] (وترفضها بايثون)؛ اكتب trades: list = field(default_factory=list) ليحصل كل كائن على قائمته الجديدة. ويتيح field(...) أيضًا إخفاء حقل من repr (repr=False) أو من المقارنات (compare=False).

from dataclasses import dataclass, field

@dataclass
class Book:
    name: str
    currency: str = "USD"                       # a default
    trades: list = field(default_factory=list)  # a fresh list per object

one = Book("desk-a")
two = Book("desk-b")
one.trades.append(("AAPL", 100))

print(one)                  # Book(name='desk-a', currency='USD', trades=[('AAPL', 100)])
print(two.trades)           # []   (not shared)
print(Book("x", "EUR"))     # Book(name='x', currency='EUR', trades=[])

دوالك الخاصة و __post_init__ ودوال بانية بديلة

تبقى الفئة البيانية فئة عادية فيمكنك إضافة دوال إليها. يعمل __post_init__(self) مباشرة بعد __init__ المولَّد، وهو موضع التحقق من القيم أو تنظيفها (self.symbol = self.symbol.upper() وraise ValueError(...) لسعر سيئ). ويستقبل @classmethod الفئة باسم cls وهو الطريقة المعتادة لبناء كائن من شكل آخر كالنص: Trade.from_line("AAPL,184.25,200") تُرجع cls(symbol, float(price), int(quantity)) فيبقى التحقق يعمل وتعمل الفئات الفرعية أيضًا.

from dataclasses import dataclass

@dataclass
class Trade:
    symbol: str
    price: float
    quantity: int

    def __post_init__(self):
        self.symbol = self.symbol.strip().upper()
        if self.price <= 0:
            raise ValueError("price must be positive")

    def notional(self):
        return self.price * abs(self.quantity)

    @classmethod
    def from_line(cls, line):
        symbol, price, quantity = line.split(",")
        return cls(symbol, float(price), int(quantity))

t = Trade.from_line(" aapl,184.25,-200")
print(t)              # Trade(symbol='AAPL', price=184.25, quantity=-200)
print(t.notional())   # 36850.0

مجمّدة ومرتّبة ومتى تتفوق الفئات العادية

يجعل @dataclass(frozen=True) النسخ للقراءة فقط (الإسناد إلى حقل يرفع FrozenInstanceError) ويمنحها تجزئة فتصلح مفاتيح قاموس أو أعضاء مجموعة: مثالي للقيم التي لا ينبغي أن تتغير كمواصفات العقد. ويضيف @dataclass(order=True) المعاملات < و<= و> و>= بمقارنة الحقول بالترتيب. استخدم الفئة البيانية لسجلات البيانات؛ أما الكائنات الغنية بالسلوك والحالة الخفية فالفئة المكتوبة يدويًا بدوال مدروسة أوضح.

from dataclasses import dataclass

@dataclass(frozen=True, order=True)
class Contract:
    symbol: str
    expiry: str          # ISO dates sort correctly as text

a = Contract("ESZ5", "2025-12-19")
b = Contract("ESZ5", "2026-03-20")
print(a < b)                          # True
print({a: "front", b: "next"}[a])     # front  (frozen => hashable)

try:
    a.symbol = "NQZ5"
except Exception as error:
    print(type(error).__name__)       # FrozenInstanceError
تحقق عند دخول البياناتلا تمنع توسيمات مثل price: float إنشاء Trade("AAPL", "abc", 1). فإذا كانت القيم السيئة ستفسد حسابات لاحقة بصمت فتحقق منها في __post_init__ وارفع ValueError فلا يمكن أن يوجد سجل معطوب. وأنشئ الكائنات دائمًا عبر الدالة البانية العادية، ومنها من from_line، حتى لا يمكن تخطي الفحص.
  • @dataclass يحوّل الحقول الموسومة إلى __init__ و__repr__ و__eq__.
  • تأتي القيم الافتراضية أخيرًا؛ واستخدم field(default_factory=list) للقوائم والقواميس.
  • __post_init__ تتحقق؛ و@classmethod تبني من أشكال أخرى؛ وfrozen=True يجعل القيم للقراءة فقط.

التالي: المشتقات في الكود، تقدير سرعة تغيّر كمية ما، وهي الفكرة وراء حساسيات الخيارات كدلتا وغاما.

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

  • نظّف صفقة وتحقق منها باستخدام __post_init__25 نقطة
  • احسب القيمة المتداولة باستخدام notional25 نقطة
  • ابنِ صفقة من نص باستخدام from_line25 نقطة
  • اجمع صافي صفقات رمز واحد باستخدام net_quantity25 نقطة
المستكشف · lab-28-1
▾ lab-28-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-28-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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