TA-Lib は単発で 1 指標を呼ぶよりも、複数指標をまとめて DataFrame の列に追加 する用途で真価を発揮します。本記事では、オーバーラップ系・モメンタム系・パターン認識関数を組み合わせて 30 種類以上の特徴量を一括生成する手順と、自前実装との結果比較を行います。

目次

  1. 関数カテゴリの確認
  2. サンプルデータの準備
  3. 一括生成関数を書く
  4. パターン認識関数を一括で呼ぶ
  5. 全部つなげる
  6. NaN の扱い
  7. 自前実装との一致確認
  8. パフォーマンスの目安

関数カテゴリの確認

TA-Lib の関数は次のカテゴリに分かれます。

import talib
groups = talib.get_function_groups()
for k, v in groups.items():
print(f"{k}: {len(v)} functions")

主要なカテゴリは次のとおりです。

カテゴリ
Overlap StudiesSMA, EMA, BBANDS, KAMA, SAR
Momentum IndicatorsRSI, MACD, ADX, CCI, STOCH
Volume IndicatorsOBV, AD, ADOSC
Volatility IndicatorsATR, NATR, TRANGE
Cycle IndicatorsHT_DCPERIOD など
Pattern RecognitionCDLDOJI, CDLHAMMER, CDLENGULFING など

パターン認識(Pattern Recognition)は約 60 種類あり、3 値(-100 / 0 / 100) を返します。陽の数値はブル(強気)、陰はベア(弱気)、0 は該当なしという意味です。

サンプルデータの準備

import numpy as np
import pandas as pd
import talib
rng = np.random.default_rng(seed=12345)
n = 400
returns = rng.normal(loc=0.0005, scale=0.013, size=n)
close = 1700 * np.exp(np.cumsum(returns))
high = close * (1 + np.abs(rng.normal(scale=0.008, size=n)))
low = close * (1 - np.abs(rng.normal(scale=0.008, size=n)))
open_ = np.concatenate([[close[0]], close[:-1]])
volume = rng.integers(50_000, 800_000, size=n).astype(float)
ohlc = pd.DataFrame(
{"O": open_, "H": high, "L": low, "C": close, "Vo": volume},
index=pd.date_range("2025-04-01", periods=n, freq="B"),
)

OHLCV(O, H, L, C, Vo)を持つ DataFrame を入力にします。

一括生成関数を書く

カテゴリごとに分けて関数化します。引数の timeperiod は標準値を使い、複数期間が欲しい場合はループで列を増やします。

def add_overlap(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
c = df["C"].values
out["sma_5"] = talib.SMA(c, timeperiod=5)
out["sma_25"] = talib.SMA(c, timeperiod=25)
out["sma_75"] = talib.SMA(c, timeperiod=75)
out["ema_12"] = talib.EMA(c, timeperiod=12)
out["ema_26"] = talib.EMA(c, timeperiod=26)
out["wma_25"] = talib.WMA(c, timeperiod=25)
out["kama_30"] = talib.KAMA(c, timeperiod=30)
upper, mid, lower = talib.BBANDS(c, timeperiod=20, nbdevup=2, nbdevdn=2)
out["bb_upper"], out["bb_mid"], out["bb_lower"] = upper, mid, lower
out["sar"] = talib.SAR(df["H"].values, df["L"].values)
return out
def add_momentum(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
h, l, c = df["H"].values, df["L"].values, df["C"].values
out["rsi_14"] = talib.RSI(c, timeperiod=14)
macd, sig, hist = talib.MACD(c, fastperiod=12, slowperiod=26, signalperiod=9)
out["macd"], out["macd_signal"], out["macd_hist"] = macd, sig, hist
out["adx_14"] = talib.ADX(h, l, c, timeperiod=14)
out["cci_14"] = talib.CCI(h, l, c, timeperiod=14)
k, d = talib.STOCH(h, l, c, fastk_period=14, slowk_period=3, slowd_period=3)
out["stoch_k"], out["stoch_d"] = k, d
out["roc_10"] = talib.ROC(c, timeperiod=10)
out["mom_10"] = talib.MOM(c, timeperiod=10)
out["willr_14"] = talib.WILLR(h, l, c, timeperiod=14)
return out
def add_volume(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
h, l, c, v = (df["H"].values, df["L"].values, df["C"].values, df["Vo"].values)
out["obv"] = talib.OBV(c, v)
out["ad"] = talib.AD(h, l, c, v)
out["adosc"] = talib.ADOSC(h, l, c, v, fastperiod=3, slowperiod=10)
return out
def add_volatility(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
h, l, c = df["H"].values, df["L"].values, df["C"].values
out["atr_14"] = talib.ATR(h, l, c, timeperiod=14)
out["natr_14"] = talib.NATR(h, l, c, timeperiod=14)
out["trange"] = talib.TRANGE(h, l, c)
return out

パターン認識関数を一括で呼ぶ

パターン認識関数(CDL...)は引数の形が共通(O, H, L, C)です。get_function_groups() から名前を取り、ループで一括呼び出しできます。

def add_patterns(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
o, h, l, c = (df["O"].values, df["H"].values, df["L"].values, df["C"].values)
pattern_names = talib.get_function_groups()["Pattern Recognition"]
for name in pattern_names:
func = getattr(talib, name)
out[name.lower()] = func(o, h, l, c)
return out

pattern_names["CDL2CROWS", "CDL3BLACKCROWS", ...] のような形になります。出力は -100 / 0 / 100 の整数列です。

全部つなげる

ラッパー関数 make_features で 4 つを順に呼びます。

def make_features(df: pd.DataFrame) -> pd.DataFrame:
out = (
df.pipe(add_overlap)
.pipe(add_momentum)
.pipe(add_volume)
.pipe(add_volatility)
.pipe(add_patterns)
)
return out
features = make_features(ohlc)
print(features.shape)
print(features.columns.tolist()[:20])

OHLCV の 5 列に加えて、30 列以上の特徴量とパターン列が追加されます。パターンを除いてもオーバーラップ・モメンタム・出来高・ボラの 4 系統で 25 列前後になります。

NaN の扱い

最初の 75 日(SMA(75) の確定まで)は多くの列が NaN になります。学習・分析の前に確認します。

nan_rate = features.isna().mean().sort_values(ascending=False)
print(nan_rate.head(10))
features_clean = features.dropna()
print(features_clean.shape)

NaN を埋めると、初期の値が「平均回帰っぽいバイアス」を入れることになるため、原則は dropna で先頭を切り落とす のが安全です。

自前実装との一致確認

代表的な指標を、自前実装と TA-Lib の両方で計算して差を比較します。

sma25_own = ohlc["C"].rolling(25).mean()
sma25_tal = pd.Series(talib.SMA(ohlc["C"].values, 25), index=ohlc.index)
print((sma25_own - sma25_tal).abs().max()) # 期待値: ほぼ 0
# RSI(14) Wilder
def rsi_own(close, n=14):
delta = close.diff()
up = delta.clip(lower=0).ewm(alpha=1/n, adjust=False, min_periods=n).mean()
dn = (-delta).clip(lower=0).ewm(alpha=1/n, adjust=False, min_periods=n).mean()
rs = up / dn.replace(0, np.nan)
return 100 - 100 / (1 + rs)
rsi14_own = rsi_own(ohlc["C"], 14)
rsi14_tal = pd.Series(talib.RSI(ohlc["C"].values, 14), index=ohlc.index)
print((rsi14_own - rsi14_tal).abs().describe())

SMA は数値レベルで一致、RSI も Wilder の seed が同じなら一致します。一致しないときは ddof・初期化・adjust の差を確認します。

パフォーマンスの目安

TA-Lib は C で実装されているため、自前 pandas 実装より高速です。1 銘柄 1000 行程度では差は小さいですが、数百銘柄 × 数年 のような大量データでは差がはっきり出ます。

import time
t0 = time.perf_counter()
for _ in range(100):
ohlc["C"].rolling(25).mean()
t_pd = time.perf_counter() - t0
t0 = time.perf_counter()
for _ in range(100):
talib.SMA(ohlc["C"].values, 25)
t_tl = time.perf_counter() - t0
print(f"pandas: {t_pd*1000:.1f} ms / 100 runs")
print(f"talib : {t_tl*1000:.1f} ms / 100 runs")

数値はマシンに依存します。「pandas でも十分速い」「TA-Lib のほうが速い」のどちらの判断もありえるので、自分の用途に合わせて測ってから選びます。

注意点

  • 入力は NumPy 配列: pandas Series を渡すなら .values を付ける。Series 直渡しでも動くが、index が落ちることに注意
  • NaN の混入: np.nan を含む入力は出力も NaN になる。事前に dropna するか、ffill / bfill の方針を決める
  • パターン認識の解釈は慎重に: -100 / 100 はあくまで「形として一致」のフラグ。それが将来の値動きに直結するかは別問題
  • 特徴量の多重共線性: 30 列以上を機械学習にそのまま投入すると、似た指標が競合して係数が不安定になる。相関の高いものを削るか、PCA などで縮約する

生成AI へのプロンプト例

複数銘柄に対して一括計算するパイプラインを依頼します。

入力 DataFrame:
- columns: Date, Code, O, H, L, C, Vo
Code ごとに、以下の TA-Lib 指標を一括計算する関数 build_features(df) を書いてください。
- SMA(5, 25, 75), EMA(12, 26)
- RSI(14), MACD(12, 26, 9), ADX(14), CCI(14), STOCH(14, 3, 3)
- BBANDS(20, 2)
- ATR(14), NATR(14)
- OBV, AD, ADOSC(3, 10)
- パターン認識を全種類
要件:
- pandas 2.2 系
- Code 内で日付昇順に整列してから計算
- 戻り値は元の列 + 上記指標を追加した DataFrame
- Code をまたいだ計算は行わない(groupby + transform / apply)
- 末尾に動作確認サンプルを付ける

まとめ

  • TA-Lib は 特徴量の一括生成 で力を発揮する
  • カテゴリは Overlap / Momentum / Volume / Volatility / Pattern Recognition の 5 系統
  • パターン認識関数は get_function_groups() から名前を取得してループで呼ぶ
  • 自前実装との一致確認(SMA・RSI など)で、ライブラリの挙動を把握しておく
  • 大量銘柄 × 多指標では、自前実装より速度面で優位