pandas-taで100行のコードが10行に!テクニカル指標を一括計算してバックテストを爆速化する方法

基礎知識・戦略

PythonでRSIとMACDを「ゼロから」計算するコードを書いていたとき、気がついたら100行近いコードになっていました。。。「なんか絶対もっと楽な方法あるだろ」と思ってQiitaをさまよっていたらpandas-taというライブラリに出会って、一気に問題が解決した話です。日本株の製造メーカー銘柄でバックテストを組んでいる僕にとって、指標計算のコードがスッキリするだけでモチベーションが全然違うんですよね。「コードが汚いと続かない」→「続かないとバックテストも進まない」という悪循環を断ち切るために、ぜひ使ってほしいライブラリです。

pandas-taとは何か

pandas-ta(Technical Analysis Library for pandas)は、130種類以上のテクニカル指標をpandasのDataFrameに直接追加できるライブラリです。移動平均・RSI・MACD・ボリンジャーバンド・ATR・ストキャスティクスなど、バックテストでよく使う指標がほぼ全て揃っています。

最大のメリットは「書き方がシンプル」なこと。普通にゼロから書くと面倒なRSIも、pandas-taなら1行で終わります:

# pandas-taを使う場合(1行)
df.ta.rsi(length=14, append=True)

# ゼロから書く場合(10行以上かかる)
delta = df["Close"].diff()
gain = delta.where(delta > 0, 0).rolling(14).mean()
loss = -delta.where(delta < 0, 0).rolling(14).mean()
rs = gain / loss
df["RSI_14"] = 100 - (100 / (1 + rs))

これを全指標でやると差は歴然です。

インストールと基本的な使い方

pip install pandas-ta yfinance

インストール後、基本的な流れはこうです:

import yfinance as yf
import pandas as pd
import pandas_ta as ta

# データ取得(トヨタ自動車)
df = yf.download("7203.T", start="2023-01-01", end="2026-06-01", progress=False)

# カラム名をフラットにする
if df.columns.nlevels > 1:
    df.columns = df.columns.droplevel(1)

# pandas-taで一括指標追加(append=Trueでdfに直接追加)
df.ta.rsi(length=14, append=True)           # RSI_14
df.ta.macd(fast=12, slow=26, signal=9, append=True)  # MACD関連
df.ta.bbands(length=20, std=2, append=True) # ボリンジャーバンド
df.ta.atr(length=14, append=True)           # ATR
df.ta.sma(length=25, append=True)           # 25日単純移動平均
df.ta.sma(length=75, append=True)           # 75日単純移動平均
df.ta.stoch(append=True)                    # ストキャスティクス

print(df.tail())
print(f"\n追加されたカラム数: {len(df.columns)}")
print(df.columns.tolist())

これだけで20以上のカラムが一気に追加されます。カラム名はpandas-taが自動でつけてくれます(例:RSI_14MACD_12_26_9BBU_20_2.0など)。

一括でStrategy(戦略)を作る機能

さらに便利なのがta.Strategyを使って指標セットをまとめて定義できる機能です:

import pandas_ta as ta

# バックテスト用の指標セットを定義
my_strategy = ta.Strategy(
    name="製造株バックテスト用指標セット",
    description="日本株製造メーカー向けに最適化した指標セット",
    ta=[
        {"kind": "sma", "length": 25},
        {"kind": "sma", "length": 75},
        {"kind": "ema", "length": 9},
        {"kind": "rsi", "length": 14},
        {"kind": "macd", "fast": 12, "slow": 26, "signal": 9},
        {"kind": "bbands", "length": 20},
        {"kind": "atr", "length": 14},
        {"kind": "adx", "length": 14},    # 方向性指数
        {"kind": "obv"},                   # 出来高指標
    ]
)

# 実行(一括計算)
df.ta.strategy(my_strategy)
print("指標計算完了")
print(df.columns.tolist())

このStrategyオブジェクトを保存しておけば、複数銘柄に対して同じ指標セットを一発で適用できます。これがめちゃくちゃ便利。

実践:ゴールデンクロス戦略のバックテスト

pandas-taで指標を計算したあと、簡単なバックテストを組んでみましょう。25日SMAが75日SMAを上抜けたらBuy、下抜けたらSellというシンプルなゴールデンクロス戦略です:

import yfinance as yf
import pandas as pd
import pandas_ta as ta
import matplotlib.pyplot as plt

# データ取得
df = yf.download("7203.T", start="2020-01-01", end="2026-06-01", progress=False)
if df.columns.nlevels > 1:
    df.columns = df.columns.droplevel(1)

# 移動平均計算
df.ta.sma(length=25, append=True)
df.ta.sma(length=75, append=True)
df = df.dropna()

# シグナル生成
df["signal"] = 0
df.loc[df["SMA_25"] > df["SMA_75"], "signal"] = 1   # Buy
df.loc[df["SMA_25"] < df["SMA_75"], "signal"] = -1  # Sell

# ポジション変化点を特定
df["position"] = df["signal"].diff()

# リターン計算
df["daily_return"] = df["Close"].pct_change()
df["strategy_return"] = df["daily_return"] * df["signal"].shift(1)

# 累積リターン
df["cumulative_market"] = (1 + df["daily_return"]).cumprod()
df["cumulative_strategy"] = (1 + df["strategy_return"]).cumprod()

# 結果表示
final_market = df["cumulative_market"].iloc[-1]
final_strategy = df["cumulative_strategy"].iloc[-1]
print(f"市場(Buy&Hold): {final_market:.2%}")
print(f"ゴールデンクロス戦略: {final_strategy:.2%}")

# グラフ
plt.figure(figsize=(12, 6))
plt.plot(df.index, df["cumulative_market"], label="Buy&Hold", color="#94a3b8")
plt.plot(df.index, df["cumulative_strategy"], label="GC Strategy", color="#34d399")
plt.title("Toyota (7203) - Golden Cross Strategy Backtest")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("gc_backtest.png", dpi=150, facecolor="#0d1117")
plt.show()

利用時の注意点

pandas-taは本当に便利なんですが、いくつか気をつけることがあります:

  • カラム名のバージョン差異:pandas-taのバージョンによってカラム名が微妙に違うことがある。df.columns.tolist()で確認する癖をつけましょう
  • yfinanceとの組み合わせ:yfinanceで取得したデータはMultiIndexになっていることがある。df.columns.droplevel(1)でフラットにしてから使う
  • 過去データへの先読みバイアスappend=Trueで追加された指標をそのままシグナルに使うとき、shift(1)を忘れずに(当日の終値で計算した指標を当日のエントリーに使えない)

まとめ

「コードを短くしたい」というズボラな動機で始めたpandas-taですが、今では僕のバックテストの必須ライブラリになりました。130種類以上の指標が1行で使えるので、「この指標も試してみよう」という試行錯誤のスピードが格段に上がります。次はStrategy機能を使って日本株製造メーカー30銘柄に同じ指標セットを一括適用するスクリプトを作る予定です。スクリーニング自動化の第一歩として取り組んでみます。

タイトルとURLをコピーしました