σμ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 ロードマップ›モジュール 2 · 市場データのためのNumPyとpandas›トピック 2.9·~40 分初級

テーブルの結合

ロードマップ上の位置モジュール 2/11 · トピック 9/20
2.9 テーブルの結合
—ラボスコア— / 100合計XP—連続日数—

キーを共有する表

実際のデータが1つの表で届くことはまれです。ポジションは1つの表、各銘柄のセクターは別の表、価格は3つ目の表にあります。それらをつなぐのがキーで、ここでは銘柄コードです。left.merge(right, on="キー") は left の各行について、同じキーを持つ right の行を探して横に並べます。SQL の結合(join)と同じ考え方です。

import pandas as pd

positions = pd.DataFrame({"symbol": ["AAPL", "MSFT", "TSLA", "GOOG"], "qty": [100, 50, 20, 10]})
reference = pd.DataFrame({"symbol": ["AAPL", "MSFT", "GOOG", "F"], "sector": ["tech", "tech", "tech", "auto"]})

merged = positions.merge(reference, on="symbol")
print(merged)
#   symbol  qty sector
# 0   AAPL  100   tech
# 1   MSFT   50   tech
# 2   GOOG   10   tech

inner・left・right・outer

上の結果から TSLA が消え、F も消えています。既定の how="inner" は両方の表にあるキーだけを残します。目的に合わせて指定しましょう。how="left" は左の表の全行を残し、右側の欠けた値を NaN にします。how="right" はその逆、how="outer" は両方のキーを残します。表に情報を足したいときはほぼ常に left です。行を黙って失わないからです。

# how="left" keeps every position; TSLA has no sector, so it gets NaN
left = positions.merge(reference, on="symbol", how="left")
print(left)
#   symbol  qty sector
# 0   AAPL  100   tech
# 1   MSFT   50   tech
# 2   TSLA   20    NaN
# 3   GOOG   10   tech

# how="outer" keeps the keys of both tables (sorted); quantities become floats because of the NaN
print(positions.merge(reference, on="symbol", how="outer"))
#   symbol    qty sector
# 0   AAPL  100.0   tech
# 1      F    NaN   auto
# 2   GOOG   10.0   tech
# 3   MSFT   50.0   tech
# 4   TSLA   20.0    NaN

一致しなかったものを見つける

黙って入る NaN はデータの問題を隠すことがあるので確認しましょう。indicator=True は各行のキーが left_only・right_only・both のどこで見つかったかを示す _merge 列を加えます。これで絞り込めば「価格のないポジションはどれか」に答えられます。もう1つの罠は重複キーです。右側で同じキーが2回現れると、一致する左の行が繰り返されます。validate="many_to_one"(または "one_to_one")を渡せば、pandas は行数を黙って変える代わりにエラーを出します。

# Which positions have no sector?
check = positions.merge(reference, on="symbol", how="left", indicator=True)
print(check)
#   symbol  qty sector     _merge
# 0   AAPL  100   tech       both
# 1   MSFT   50   tech       both
# 2   TSLA   20    NaN  left_only
# 3   GOOG   10   tech       both

print(check.loc[check["_merge"] == "left_only", "symbol"].tolist())   # ['TSLA']
# Duplicate keys repeat rows: AAPL has two quotes, so the AAPL position appears twice
quotes = pd.DataFrame({"symbol": ["AAPL", "AAPL", "MSFT"], "price": [184.25, 184.5, 410.1]})
print(len(positions.merge(quotes, on="symbol")))   # 3

# validate turns the surprise into an error
try:
    positions.merge(quotes, on="symbol", validate="one_to_one")
except Exception as error:
    print(type(error).__name__)   # MergeError

キー名の違いと列名の衝突

2つの表でキーの名前が違うときは left_on="symbol", right_on="ticker" を使います。両方の列が残ります。キー以外で同名の列がある場合(ここでは qty)、pandas は両方を残して接尾辞 _x と _y を付けます。suffixes=("_a", "_b") で分かりやすいものに変えましょう。外部結合の後は欠けた数量が NaN になり、列は浮動小数点になります。fillna(0) のあと astype("int64") で整数に戻します。

# Different key names: both columns are kept
book_a = pd.DataFrame({"symbol": ["AAPL", "MSFT"], "qty": [100, 50]})
book_b = pd.DataFrame({"ticker": ["MSFT", "TSLA"], "qty": [-20, 30]})
print(book_a.merge(book_b, left_on="symbol", right_on="ticker", how="outer", suffixes=("_a", "_b")))
#   symbol  qty_a ticker  qty_b
# 0   AAPL  100.0    NaN    NaN
# 1   MSFT   50.0   MSFT  -20.0
# 2    NaN    NaN   TSLA   30.0

# Same key name, outer join, suffixes, then back to whole numbers
both = book_a.merge(book_b.rename(columns={"ticker": "symbol"}), on="symbol", how="outer", suffixes=("_a", "_b"))
both[["qty_a", "qty_b"]] = both[["qty_a", "qty_b"]].fillna(0).astype("int64")
print(both)
#   symbol  qty_a  qty_b
# 0   AAPL    100      0
# 1   MSFT     50    -20
# 2   TSLA      0     30
結合のたびに行数を確認する行を黙って落としたり重複させたりする結合は、その後のすべてを狂わせ、エラーも出ません。前後で len() を比べ、全行を残したいときは how="left"、キーが一意だと考えるときは validate= を付けましょう。
  • left.merge(right, on="キー") はキーを共有する2つの表の行を突き合わせ、left_on / right_on は名前が違う場合に使う
  • how="inner"(既定)は両方にあるキー、"left" は左の全行、"outer" はすべてのキーを残す
  • indicator=True は一致しなかった行を示し、validate= と suffixes= は重複キーと列名の衝突を防ぐ

次は単純リターンです。価格の系列を、ある期間から次の期間への変化率に変換します。

ラボ:採点される内容

  • attach_sector で各約定にセクターを付ける25点
  • value_positions で価格のあるポジションを評価する25点
  • unpriced_symbols で価格のないポジションを見つける25点
  • combine_books で2つのブックを1つの表にまとめる25点
エクスプローラー · lab-42-1
▾ lab-42-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-42-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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