【Python】RSIの計算方法と使い方

移動平均線で「トレンドの方向」を掴んだら、次に欲しくなるのは「過熱感」の指標です。そこで登場するのが、オシレーター系の王道「RSI(相対力指数)」

ただし、RSIには実は複数の計算方法があり、使い方を間違えると「TradingViewと値が違う…」ということも起こります。実際に私も「あれ?TradingViewと値が違うぞ」となりました。

この記事では下のことを書いています。

  • RSIの基本
  • Pythonでの実装方法
  • Wilder方式との違い
目次

RSIとは

RSI(相対力指数)とは、相場の過熱感(買われ過ぎ、売られ過ぎ)を示すテクニカル指標のことです。
RSIは0〜100%の数値で表され、一般的に70%以上なら買われ過ぎ、30%以下なら売られ過ぎと判断されます。

RSIの計算方法は、主にワイルダー式カトラー式の2種類があります。

  • ワイルダー式:平滑化移動平均を用いて平滑なトレンドを描くオリジナルの計算方法
  • カトラー式:単純移動平均を用いて短期間の価格変動をより敏感に反映する計算方法

PythonでRSIを実装する

実際にコードを書いて説明していきます。
今回もトヨタ自動車(7203.T)の株価を使用して確認してみます。

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

# 単純移動平均(SMA)版
def calculate_rsi_sma(df, period=14):
    delta = df["Close"].diff()

    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)

    avg_gain = gain.rolling(window=period).mean()
    avg_loss = loss.rolling(window=period).mean()

    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))

# Wilder方式版
def calculate_rsi_wilder(df, period=14):
    delta = df["Close"].diff()

    gain = delta.clip(lower=0)
    loss = -delta.clip(upper=0)

    avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
    avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()

    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))

if __name__ == "__main__":

    # トヨタ自動車の証券コード+「.T」
    ticker = "7203.T"
    # Tickerオブジェクトを作成
    toyota = yf.Ticker(ticker)
    # periodを使って過去6ヶ月分のデータを取得
    df = toyota.history(period='6mo')

    # 単純移動平均(SMA)版
    df["rsi_sma"] = calculate_rsi_sma(df)
    # Wilder方式版
    df["rsi_wilder"] = calculate_rsi_wilder(df)

    # 計算できない行を削除する
    df = df.dropna()

    # 取得したデータを出力
    print(df)

    # グラフ表示
    plt.figure(figsize=(12,6))

    # RSI比較
    plt.plot(df["rsi_sma"], label="RSI (SMA)")
    plt.plot(df["rsi_wilder"], label="RSI (Wilder)")

    plt.axhline(70, linestyle="--")
    plt.axhline(30, linestyle="--")

    plt.legend()
    plt.title("RSI Comparison")

    plt.show()

実行結果:

                                  Open         High          Low        Close    Volume  Dividends  Stock Splits    rsi_sma  rsi_wilder
Date                                                                                                                                   
・・・
2026-04-16 00:00:00+09:00  3416.000000  3468.000000  3392.000000  3392.000000  20154600        0.0           0.0  52.485380   53.470308
2026-04-17 00:00:00+09:00  3400.000000  3400.000000  3343.000000  3343.000000  14251500        0.0           0.0  59.933222   49.580738
2026-04-20 00:00:00+09:00  3413.000000  3413.000000  3380.000000  3390.000000  14589600        0.0           0.0  69.520548   53.104500

グラフ表示:

コード解説

ライブラリのインポート

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

株価データの取得や分析、グラフ表示に必要なライブラリを読み込んでいます。下の3つで「取得・加工・可視化」ができるようになります。

  • yfinance:株価データを取得するためのライブラリ(Yahoo Financeから取得)
  • pandas:データを表形式(DataFrame)で扱うためのライブラリ
  • matplotlib.pyplot:グラフを描画するためのライブラリ

単純移動平均(SMA)版の関数化

def calculate_rsi_sma(df, period=14):
    delta = df["Close"].diff()

    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)

    avg_gain = gain.rolling(window=period).mean()
    avg_loss = loss.rolling(window=period).mean()

    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))

もっとも直感的な計算方法です。rolling(window=period).mean() を使い、指定期間(14日間)の「値上がり幅の平均」と「値下がり幅の平均」を単純に算出しています。

  • df[“Close”].diff():株価の「上げ・下げ」を求める
  • delta.where(delta > 0, 0):上昇した日
  • delta.where(delta < 0, 0):下落した日
  • mean():その平均値を計算
  • avg_gain / avg_loss | 100 – (100 / (1 + rs)) :RSIの基本式

Wilder方式版の関数化

def calculate_rsi_wilder(df, period=14):
    delta = df["Close"].diff()

    gain = delta.clip(lower=0)
    loss = -delta.clip(upper=0)

    avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
    avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()

    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))

J.W.ワイルダー氏が考案した本来の手法です。最大のポイントは ewm(指数平滑移動平均)の使用です。
単純移動平均(SMA)版との違いは下の通りです。

  • delta.clip(lower=0):前日比(delta)のうち、0未満(マイナス)の値をすべて0に置き換えます。これで「値上がりした時の値」だけが残ります。
  • -delta.clip(upper=0):逆に0より大きい値をすべて0に置き換えます。これで「値下がりした時の値」だけが残ります。このままだと数値がマイナス(例:-50)なので、頭に – をつけて正の数(絶対値)に変換しています。
  • gain.ewm(alpha=1/period, adjust=False).mean():「指数平滑移動平均」を計算するメソッドです。

株価データ取得

ticker = "7203.T"
toyota = yf.Ticker(ticker)
df = toyota.history(period='6mo')

ここでは、例にトヨタ自動車(7203.T)の株価データを取得しています。

  • “7203.T”:日本株の場合は「証券コード + .T」を指定
  • yf.Ticker():銘柄情報を扱うオブジェクトを作成
  • history(period=’6mo’):過去6ヶ月分の株価データを取得

株価データの取得は下の記事で詳しく説明しているから参考にしてね

RSIの計算(関数呼び出し)

df["rsi_sma"] = calculate_rsi_sma(df)
df["rsi_wilder"] = calculate_rsi_wilder(df)

ここでは、先ほど作成した関数を使ってRSI(単純移動平均(SMA)版 / Wilder方式版)を計算しています。

グラフで可視化

plt.figure(figsize=(12,6))

plt.plot(df["rsi_sma"], label="RSI (SMA)")
plt.plot(df["rsi_wilder"], label="RSI (Wilder)")

plt.axhline(70, linestyle="--")
plt.axhline(30, linestyle="--")

plt.legend()
plt.title("RSI Comparison")

plt.show()

最後に、RSI(単純移動平均(SMA)版 / Wilder方式版)をグラフで表示しています。

まとめ

RSIはシンプルなようでいて、計算手法一つで戦略が変わる奥深い指標です。
「なんとなくライブラリを使う」のではなく、ロジックの裏側(Wilderの手法など)を理解して実装することで、ツールの信頼性は格段に向上します。

今回、説明したRSIの計算を使って自作の株価分析ツールもつくっているので、ぜひ下の記事も読んでみてね

【投資に関する免責事項】
本ブログで紹介している株価解析ツールによるスコアリングおよび銘柄分析は、あくまで個人の学習・研究および技術検証を目的としたものであり、特定の銘柄の売買を推奨するものではありません。

ツールの算出結果や掲載情報の正確性については万全を期しておりますが、その内容を保証するものではありません。投資の最終決定は、必ずご自身の判断と責任において行っていただきますようお願いいたします。

万一、本ブログの情報に基づいて被ったいかなる損害についても、当サイトおよび運営者は一切の責任を負いかねますのであらかじめご了承ください。

目次