TA-Lib は単発で 1 指標を呼ぶよりも、複数指標をまとめて DataFrame の列に追加 する用途で真価を発揮します。本記事では、オーバーラップ系・モメンタム系・パターン認識関数を組み合わせて 30 種類以上の特徴量を一括生成する手順と、自前実装との結果比較を行います。
目次
- 関数カテゴリの確認
- サンプルデータの準備
- 一括生成関数を書く
- パターン認識関数を一括で呼ぶ
- 全部つなげる
- NaN の扱い
- 自前実装との一致確認
- パフォーマンスの目安
関数カテゴリの確認
TA-Lib の関数は次のカテゴリに分かれます。
import talibgroups = talib.get_function_groups()for k, v in groups.items(): print(f"{k}: {len(v)} functions")主要なカテゴリは次のとおりです。
| カテゴリ | 例 |
|---|---|
| Overlap Studies | SMA, EMA, BBANDS, KAMA, SAR |
| Momentum Indicators | RSI, MACD, ADX, CCI, STOCH |
| Volume Indicators | OBV, AD, ADOSC |
| Volatility Indicators | ATR, NATR, TRANGE |
| Cycle Indicators | HT_DCPERIOD など |
| Pattern Recognition | CDLDOJI, CDLHAMMER, CDLENGULFING など |
パターン認識(Pattern Recognition)は約 60 種類あり、3 値(-100 / 0 / 100) を返します。陽の数値はブル(強気)、陰はベア(弱気)、0 は該当なしという意味です。
サンプルデータの準備
import numpy as npimport pandas as pdimport talib
rng = np.random.default_rng(seed=12345)n = 400returns = 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 outpattern_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) Wilderdef 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 など)で、ライブラリの挙動を把握しておく
- 大量銘柄 × 多指標では、自前実装より速度面で優位