σμ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.10·~40 分初級

スコープとクロージャ

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

名前が存在する場所

名前のスコープとは、その名前を使えるプログラム上の範囲です。関数の中で作った名前はローカルで、その関数が動いている間だけ存在し、外からは見えません。ファイルの最上位で作った名前はグローバルで、関数から読めます。Pythonは名前に出会うと、まず関数内、次に外側の関数、次にファイル、最後に組み込みの名前の順に探します。

rate = 0.001            # global: defined outside any function

def fee(notional):
    minimum = 1.0       # local: exists only during the call
    return max(minimum, notional * rate)

print(fee(36850.0))     # 36.85
# print(minimum)        # would raise NameError: minimum is not defined

代入するとローカル名ができる

関数の中からグローバルな名前を読むのは問題ありません。しかし関数の中で名前に代入すると、同名のグローバルがあっても新しいローカル名ができ、グローバルはそのまま残ります。これでデータが守られますが、関数からグローバルの状態を変えるのに余分なキーワード(global)が必要になる理由でもあり、これはめったに使わないはずのものです。値は引数で渡し、結果は return で返しましょう。

# Assigning inside a function makes a new local name
balance = 1000

def deposit(amount):
    balance = amount     # a different, local balance
    return balance

print(deposit(50))  # 50
print(balance)      # 1000 (the global one is unchanged)

関数を作る関数

関数の中に別の関数を定義して return で返せます。内側の関数は、外側の関数が終わったあとでも、外側の変数にアクセスし続けます。この「関数と、それが覚えている値」のひとまとまりがクロージャです。設定から使えるツールを作る便利な方法で、株式用と ETF 用の別々の計算機を作れます。

# A closure remembers the variables of the function that made it
def make_fee_calculator(rate, minimum):
    def fee(notional):
        return max(minimum, notional * rate)
    return fee

stock_fee = make_fee_calculator(0.001, 1.0)
etf_fee = make_fee_calculator(0.0005, 0.5)
print(stock_fee(36850.0))  # 36.85
print(etf_fee(36850.0))    # 18.425

呼び出しの間で続く状態:nonlocal

クロージャは、覚えている値を変更することもできます。代入するとローカル名が新しくできてしまうため、内側の関数は先に nonlocal count と宣言します。「この名前は外側の関数のもの」という意味です。外側の関数を呼ぶたびに独立した記憶が作られるので、2つのカウンターが干渉することはありません。注文IDの発行や移動平均が、グローバル変数なしで状態を保てるのはこの仕組みのおかげです。

# nonlocal lets the inner function rebind the outer variable
def make_counter():
    count = 0
    def next_id():
        nonlocal count
        count += 1
        return count
    return next_id

order_ids = make_counter()
print(order_ids(), order_ids(), order_ids())  # 1 2 3
other = make_counter()
print(other())                                # 1 (its own count)
# State between calls: an exponential moving average
def make_ema(alpha):
    value = None
    def update(price):
        nonlocal value
        value = price if value is None else alpha * price + (1 - alpha) * value
        return value
    return update

ema = make_ema(0.5)
print(ema(100.0), ema(110.0), ema(110.0))  # 100.0 105.0 107.5
クロージャが保持するのは変数であり、コピーではない内側の関数は実行時に変数を参照するため、最新の値が見えます。カウンターや平均が動くのはそのおかげです。同じ理由で、ループの中で作ったクロージャは、引数やデフォルト値で渡さない限り、ループ変数の最終的な値を見ることになります。
  • 関数内で代入した名前はローカル。データは引数で渡し、return で返す
  • 関数を作って返す関数は、設定をツールにまとめる
  • 呼び出しの間で保持したい状態には nonlocal(クロージャごとに別の記憶)

次はリスト内包表記です。別のリストから新しいリストを、読みやすい1行で作ります。

ラボ:採点される内容

  • make_counter で count を覚えるカウンターを作る25点
  • make_fee_calculator で手数料の設定を関数にまとめる25点
  • make_ema で呼び出しをまたいで移動平均を保つ25点
  • make_limit_checker で上限から価格チェックを作る25点
エクスプローラー · lab-10-1
▾ lab-10-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-10-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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