σμ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 分初級

データクラス

ロードマップ上の位置モジュール 1/11 · トピック 28/33
1.28 データクラス
—ラボスコア— / 100合計XP—連続日数—

データを持つクラスの定型コードを減らす

取引、気配値、設定のように、いくつかのフィールドを持つことが主目的のクラスは多くあります。それぞれに __init__、__repr__、__eq__ を書くのは繰り返しになります。dataclasses モジュールの @dataclass デコレーターは、型注釈付きフィールドの一覧からそれらを自動で書いてくれます。symbol: str、price: float、quantity: int を一度宣言するだけで、コンストラクター Trade("AAPL", 184.25, 200)、Trade(symbol='AAPL', price=184.25, quantity=200) のような読みやすい repr、フィールド単位の等価比較が得られます。注釈は意図を示すもので、Python は強制しません。

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")。デフォルト付きのフィールドは、付いていないフィールドの後ろに置きます。リストのような変更可能なデフォルト値を単に = [] と書くと全オブジェクトで共有されてしまうため(Python は拒否します)、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 は第1引数にクラスを 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

frozen、order、そして通常のクラスが向くとき

@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点
  • notional で約定金額を計算する25点
  • from_line でテキストから約定を作る25点
  • net_quantity で1つのシンボルの約定を差し引き合計する25点
エクスプローラー · 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と連続日数
  • 講義の進捗とメモ

コードを実行するにはログインしてください。

レクチャーはすべて無料で読めます。コードの実行、テスト、ラボの提出にはアカウントの作成かログインが必要です。

  • ブラウザ内IDEとbashターミナル。インストール不要
  • 即時採点、XP、ロードマップでの現在地
アカウントを作成ログイン
または
GitHubで続ける