σμ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.2·~45 分上級

型ヒントと静的型チェック

ロードマップ上の位置モジュール 10/11 · トピック 2/13
10.2 型ヒントと静的型チェック
—ラボスコア— / 100合計XP—連続日数—

型ヒントはツールが検査できるドキュメント

Python は動的型付けで、変数には何でも入り、間違った型は該当行が実行されて初めて、場合によっては取引中に分かります。型ヒントを使えば、関数が何を受け取り何を返すかを書き残せます:def mid_price(bid: float, ask: float) -> float。Python 自体は実行時にこれを無視します。価値は、エディタや mypy・pyright などの静的チェッカーがこれを読み、実行前に誤った呼び出しを警告してくれること、そして古くなるコメントよりよく関数を説明してくれることです。

# Hints describe the function; Python does not enforce them when it runs
def mid_price(bid: float, ask: float) -> float:
    return (bid + ask) / 2

print(mid_price(100.0, 100.5))                      # 100.25
print(mid_price.__annotations__)                    # {'bid': <class 'float'>, 'ask': <class 'float'>, 'return': <class 'float'>}
print(mid_price(10, 12))                            # 11.0   an int is accepted where float is hinted
try:
    mid_price("a", "b")                             # a checker flags this line before the code runs
except TypeError as error:
    print("only fails when it runs:", error)       # only fails when it runs: unsupported operand type(s) for /

コンテナ、None、ユニオン

組み込みコンテナは要素の型を角括弧で受け取ります:list[float]、dict[str, float]、tuple[str, float](位置ごとに1つの型)。欠けるかもしれない値は float | None と書き、呼び出し側に None の処理を強制します。確認せずに結果を数値として使うと、チェッカーが警告します。関数の中では if x is None: return で型が絞り込まれ、以降は float だと分かります。読むだけの引数には list[float] よりも Sequence[float](リスト、タプル)のような一般的な型を選ぶと、より多くの呼び出しに合います。戻り値は list[float] のように具体的な型にします。

# Containers, an optional result, and narrowing with an is None check
def best_quote(quotes: list[tuple[str, float]]) -> tuple[str, float] | None:
    if not quotes:
        return None
    return min(quotes, key=lambda quote: quote[1])

def describe(quotes: list[tuple[str, float]]) -> str:
    best = best_quote(quotes)
    if best is None:                                 # after this check the checker knows best is a tuple
        return "no quotes"
    venue, price = best
    return f"{venue} at {price:.2f}"

print(describe([("XNAS", 100.02), ("ARCX", 100.01)]))     # ARCX at 100.01
print(describe([]))                                       # no quotes

データの形と、チェッカーの働き

注文のようにキーが固定された辞書は、dict のままにせず記述したほうが良いです。TypedDict や dataclass は各フィールドとその型に名前を付けるので、order["quantiy"] のようなタイプミスは 15:59 の KeyError ではなくエディタ上のエラーになります。チェッカーはコマンドライン(mypy main.py)で実行し、コードがヒントに反する箇所をすべて表示して非ゼロで終了するので、後で学ぶ自動チェックに組み込めます。ヒントは少しずつ追加できます。Any はその値のチェックを無効にし、型のないコードは単に無視されます。ヒントはデータでもあり、typing.get_type_hints を使えばツールが実行時に読めます。このラボもまさにその方法で検査します。

# A TypedDict names the fields of an order; the checker would flag order["quantiy"]
from typing import TypedDict

class Order(TypedDict):
    symbol: str
    quantity: int
    price: float

def notional(order: Order) -> float:
    return order["quantity"] * order["price"]

order: Order = {"symbol": "AAPL", "quantity": 100, "price": 184.5}
print(notional(order))                              # 18450.0
print(Order.__annotations__)                        # {'symbol': <class 'str'>, 'quantity': <class 'int'>, 'price': <class 'float'>}
# The hints can be read at run time, which is how tools (and this lab) inspect a function
import typing

def apply_fee(prices: typing.Sequence[float], fee_rate: float = 0.001) -> list[float]:
    return [price * (1 + fee_rate) for price in prices]

hints = typing.get_type_hints(apply_fee)
print(hints["fee_rate"], hints["return"])           # <class 'float'> list[float]
print(typing.get_origin(hints["prices"]).__name__)  # Sequence
print(apply_fee((100.0, 200.0)))                    # a tuple is accepted: [100.1, 200.2]
型ヒントは検証ではない型ヒントは実行時に誤った値を止めません。ファイルや API、WebSocket から届くデータは、届いたままです。外部データは明示的に検証し(またはヒントからオブジェクトを作るライブラリで)、型ヒントは関数間の自分の呼び出しのミスを見つけるのに使います。チェッカーが緑なのは、ヒント同士が矛盾していないという意味であって、数値が正しいという意味ではありません。それはテストの仕事です。
  • ヒント(bid: float、-> float)は関数を説明し、実行時は無視される。mypy のようなチェッカーが読む
  • コンテナは要素の型を取る(list[tuple[str, float]])。欠ける値は float | None。読むだけの引数は一般的な Sequence[float] にできる
  • レコードには TypedDict か dataclass を使い、自動チェックでチェッカーを走らせる。外部データの検証と数値のテストは引き続き必要

次は pytest によるテストです。フィクスチャ、パラメータ化したケース、戦略の誠実さを保つチェックを学びます。

ラボ:採点される内容

  • mid_price で数値に型ヒントを付ける25点
  • best_quote でコンテナに型を付ける25点
  • safe_ratio で値が無い場合を許す25点
  • apply_fee で任意のシーケンスを受け取る25点
エクスプローラー · lab-118-1
▾ lab-118-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-118-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

このトピックをリセットしますか?

lab-118-1 の内容はすべてスターターファイルに戻り、ターミナルも消去されます。現在の解答は失われ、元に戻せません。

リセットされるもの
  • main.py → スターターコード
  • ターミナル履歴とテスト出力
  • 未提出の変更
保持されるもの
  • ラボの最高スコア
  • XPと連続日数
  • 講義の進捗とメモ

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

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

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