RSI(Relative Strength Index、相対力指数)は、テクニカル分析で用いられるモメンタム系オシレーターで、1978年にJ・ウェルズ・ワイルダーによって提唱されました。RSIは、一定期間における価格の上昇幅と下落幅を比較することで、価格変動の勢い(スピードと大きさ)を測定します。主に「買われすぎ」や「売られすぎ」を判断するために使用され、売買判断の一助となります。

RSIの基本原理

RSIの核となる考え方は「相対的な強さ」にあります。これは、特定の期間における価格変化の比率を意味します。RSIの値は0〜100の範囲で表され、一般的には以下のように解釈されます:

  • RSIが70を超える → 買われすぎ(売りシグナルの可能性)
  • RSIが30を下回る → 売られすぎ(買いシグナルの可能性)

この背景には、「強い短期的な価格変動はやがて勢いを失い、反転する傾向がある」という前提があります。RSIは、価格変動におけるノイズを平滑化し、市場全体の傾向を反映するために、平均化された上昇/下落値を用いて計算されます。

RSIの計算方法

RSIは以下のステップで計算されます:

1. 期間を設定

標準では「14日間」が使用されますが、戦略に応じて変更可能です。

2. 日ごとの価格変化を算出

各日の終値から前日の終値を引き、変化幅を求めます。

  • プラスの値:上昇日
  • マイナスの値:下落日

3. 平均上昇幅・平均下落幅を計算

  • 平均上昇幅 = 上昇日の合計値 ÷ 期間
  • 平均下落幅 = 下落日の絶対値合計 ÷ 期間

4. 相対力(RS)を計算

RS = 平均上昇幅 ÷ 平均下落幅

5. RSIを算出

RSI = 100 − [100 ÷ (1 + RS)]

【計算例】

14日間において:

  • 上昇日が8日、合計120ポイント
  • 下落日が6日、合計40ポイント

平均上昇幅 = 120 ÷ 14 ≒ 8.57
平均下落幅 = 40 ÷ 14 ≒ 2.86
RS = 8.57 ÷ 2.86 ≒ 3
RSI = 100 − [100 ÷ (1 + 3)] = 75

→ この場合、RSI 75 は買われすぎを示唆します。

RSIの期間設定について

RSIの期間は調整可能で、用途により異なります:

  • 14日RSI:ワイルダー推奨。バランス良好で短〜中期トレード向き
  • 7日RSI:感度が高く、短期トレードに適すがダマシも多い
  • 21日RSI:ノイズが少なく長期向き。ただし反応は遅い

市場によっても最適設定は異なります。

  • 米国株では14日が標準
  • A株市場では9日RSIがよく使われます
  • 外為(FX)は7日または9日が主流
  • 仮想通貨のような高ボラティリティ資産では、5〜7日RSIが好まれます

バックテストによる調整が必須です。

RSIを活用したトレード戦略

RSIは主に「反転シグナル」を見つけるために用いられます。

売られすぎ戦略

  • RSI < 30 → 買いサイン(反発期待)
  • RSIが30を上回ることで反転確認とみなす
    ※ 他の指標と併用し、ダマシ回避が重要

買われすぎ戦略

  • RSI > 70 → 売りサイン(反落警戒)
  • RSIが70を下回るタイミングで売りエントリーを検討

ダイバージェンス戦略(逆行現象)

価格とRSIの動きが逆になる現象で、トレンド転換の兆候:

  • 弱気ダイバージェンス:価格が高値更新、RSIが下落 → 下落の可能性
  • 強気ダイバージェンス:価格が安値更新、RSIが上昇 → 上昇の可能性

タイミングの精度を高める手法として有効です。

RSIは優れた指標ですが、単独での使用ではダマシもあります。他のテクニカル指標(たとえばMACD)と併用することで精度が高まります。

import pandas as pd
import requests
import ta
import time

def get_realtime_data(stock_code):
    url = f"https://api.alltick.io/v1/quotes/{stock_code}"
    response = requests.get(url)
    data = response.json()
    return data

def rsi_strategy(data, rsi_period=14, rsi_oversold=30, rsi_overbought=70):
    data['RSI'] = ta.momentum.rsi(data['close'], window=rsi_period)
    data['Signal'] = 0
    data['Signal'][data['RSI'] < rsi_oversold] = 1
    data['Signal'][data['RSI'] > rsi_overbought] = -1
    return data

def simulate_trading(stock_code, interval=60):
    while True:
        data = get_realtime_data(stock_code)

        df = pd.DataFrame(data)

        df = rsi_strategy(df)

        latest_signal = df['Signal'].iloc[-1]

        if latest_signal == 1:
            print("Buy")
        elif latest_signal == -1:
            print("Sell")
        else:
            print("No Signal")
        
        time.sleep(interval)

if __name__ == "__main__":
    stock_code = "00941.HK"
    simulate_trading(stock_code)