2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自動売買のバックテストで Pandas の `iterrows()` を使って絶望した話。数時間を「数秒」に変えるベクトル化の魔法

2
Posted at

はじめに:バックテストが終わらない夜

Pythonで株の自動売買(スイングトレード)モデルを作り、過去10年分の株価データ(約2000銘柄 × 2500日 = 500万行)でバックテストを回そうとしました。
「よし、1行ずつループしてシグナルを判定しよう!」
私は何も疑わずに、Pandasの伝家の宝刀 iterrows() を抜きました。

# ❌ 初心者がやりがちな絶望コード
for index, row in df.iterrows():
    if row['close'] > row['sma_25']:
        df.at[index, 'signal'] = 1
    else:
        df.at[index, 'signal'] = 0

スクリプトを実行。……終わらない。
プログレスバーは1秒に1%も進みません。計算が終わるまでに推定4時間かかると表示されました。
「Pythonってこんなに遅いの…?」と絶望した夜の話です。

なぜ iterrows() は罪なのか

Pandasのデータフレームは、内部的にはC言語の配列(NumPy)でメモリ上に綺麗に並んでいます。
しかし iterrows() を使うと、Pythonは「1行ごとにCの世界からPythonの世界へデータを変換し、Pythonの遅いループで処理し、また戻す」というオーバーヘッドを500万回繰り返します。これは東京から大阪まで、歩いて荷物を1個ずつ運ぶようなものです。

救世主:「ベクトル化(Vectorization)」

Pandas(NumPy)の真の力は**「ベクトル化」**にあります。ループを回さず、列全体に対して一気に計算を適用するのです。

# ✅ ベクトル化を使った神コード
df['signal'] = np.where(df['close'] > df['sma_25'], 1, 0)

この1行に書き換えてスクリプトを実行しました。
処理時間は 0.2秒 になりました。
4時間かかっていた処理が、一瞬で終わったのです。

Pandasループの「やってはいけない」ランキング

データ分析やシストレで処理が遅いと感じたら、以下の順に改善を検討してください。

  1. 【最悪】 iterrows():絶対に避けるべき。遅さの極み。
  2. 【マシ】 itertuples():どうしてもループが必要ならこっち。数倍速い。
  3. 【普通】 apply():便利だが、内部的にはループしているので巨大データには向かない。
  4. 【最強】 ベクトル化(NumPy関数):条件分岐には np.wherenp.select を使う。圧倒的に最速。
    Pythonは「遅い言語」ではありません。「遅い書き方ができてしまう言語」なだけです。データフレームをループで回そうとした時、それは「あ、自分は今、重罪を犯そうとしているな」と気づくためのサインです。
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?