先週、RSIが70超えで「売りシグナルだ!」と喜んで空売りしたら、そのままズルズルと上がり続けてぼっこぼこにされました。。。RSI単体って、過熱状態がいつまでも続く相場ではまるで無力なんですよね。そこで「もっと精度の高いタイミング指標はないか」と調べ始めたのが、今回紹介するストキャスティクスRSI(Stochastic RSI)との出会いです。
なぜストキャスティクスRSIを調べたのか
僕がメインで見ている製造メーカー株(素材系・機械系)って、決算前後に独特の値動きをするんです。トレンドがはっきりしているときはMACDで十分なんですが、決算通過後の「じわじわと巻き戻す」フェーズで何度も誤ったエントリーをしてしまって。。。同じ悩みを持つ方、いませんか?
ストキャスティクスRSIは「RSIのストキャスティクス」—つまり、RSI自体をさらにストキャスティクス化したもの。RSIが「過熱かどうか」を見るのに対して、ストキャスティクスRSIは「RSI自体が過熱かどうか」を見るので、より短期的な反転ポイントを拾えます。
ストキャスティクスRSIの計算式
計算式はシンプルです。まずRSI(一般的に14日)を計算し、その値を直近N期間のRSIの中でのポジション(0〜1の範囲)に変換します:
StochRSI = (RSI - RSIの最小値) / (RSIの最大値 - RSIの最小値)
さらに、この値を3日間移動平均した「%K」と、%Kを3日間移動平均した「%D」を使うことが多いです。%Kが%Dを下から上に抜けたら買い、上から下に抜けたら売りというシグナルです。
Pythonで実装する(pandas-ta使用)
手計算する必要はありません。pandas-taを使えば一発です。以下のコードを実行すれば、yfinanceで取得した製造メーカー株にストキャスティクスRSIを適用できます。
import yfinance as yf
import pandas_ta as ta
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# 対象銘柄:例として東レ(3402)、日立(6501)、クボタ(6326)
tickers = ["3402.T", "6501.T", "6326.T"]
target = "6501.T" # 日立製作所で試してみる
# データ取得(直近1年)
df = yf.download(target, period="1y", auto_adjust=True)
df.columns = df.columns.get_level_values(0)
# ストキャスティクスRSIを計算(デフォルト: length=14, rsi_length=14, k=3, d=3)
stoch_rsi = ta.stochrsi(df["Close"], length=14, rsi_length=14, k=3, d=3)
df = pd.concat([df, stoch_rsi], axis=1)
# カラム名を確認
print(df.columns.tolist())
# → ['Open', 'High', 'Low', 'Close', 'Volume', 'STOCHRSIk_14_14_3_3', 'STOCHRSId_14_14_3_3']
k_col = "STOCHRSIk_14_14_3_3"
d_col = "STOCHRSId_14_14_3_3"
# ゴールデンクロス(%Kが%Dを下から上に抜けた)シグナル
df["signal"] = 0
df.loc[(df[k_col] > df[d_col]) & (df[k_col].shift(1) <= df[d_col].shift(1)), "signal"] = 1 # 買い
df.loc[(df[k_col] < df[d_col]) & (df[k_col].shift(1) >= df[d_col].shift(1)), "signal"] = -1 # 売り
# 過売り領域(0.2以下)でのゴールデンクロスに絞る
df["buy_signal"] = (df["signal"] == 1) & (df[k_col] < 0.3)
df["sell_signal"] = (df["signal"] == -1) & (df[k_col] > 0.7)
# プロット
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 8), sharex=True)
ax1.plot(df.index, df["Close"], color="#f0f6fc", linewidth=1.2)
ax1.scatter(df.index[df["buy_signal"]], df["Close"][df["buy_signal"]],
color="#34d399", marker="^", s=100, label="買いシグナル")
ax1.scatter(df.index[df["sell_signal"]], df["Close"][df["sell_signal"]],
color="#f87171", marker="v", s=100, label="売りシグナル")
ax1.set_title(f"{target} 株価 + ストキャスティクスRSIシグナル", color="#f0f6fc")
ax1.set_facecolor("#0d1117")
ax1.legend()
ax2.plot(df.index, df[k_col], label="%K", color="#38bdf8")
ax2.plot(df.index, df[d_col], label="%D", color="#f87171", linestyle="--")
ax2.axhline(0.8, color="#f87171", alpha=0.4, linestyle=":")
ax2.axhline(0.2, color="#34d399", alpha=0.4, linestyle=":")
ax2.fill_between(df.index, 0.8, 1.0, alpha=0.1, color="#f87171")
ax2.fill_between(df.index, 0.0, 0.2, alpha=0.1, color="#34d399")
ax2.set_title("ストキャスティクスRSI", color="#f0f6fc")
ax2.set_facecolor("#0d1117")
ax2.legend()
fig.patch.set_facecolor("#0d1117")
plt.tight_layout()
plt.savefig("stochrsi_signal.png", dpi=150, bbox_inches="tight")
plt.show()
print("完了")
複数銘柄をスクリーニングする
さらに実用的な使い方として、複数の製造メーカー株を一括チェックして「今日の買い候補」を絞り込む方法を紹介します。
import yfinance as yf
import pandas_ta as ta
import pandas as pd
from datetime import datetime, timedelta
# 製造メーカー銘柄リスト(一部)
tickers = {
"3402.T": "東レ",
"6501.T": "日立製作所",
"6326.T": "クボタ",
"7011.T": "三菱重工業",
"6752.T": "パナソニック",
"6301.T": "小松製作所",
"5201.T": "AGC",
"3861.T": "王子HD"
}
results = []
for ticker, name in tickers.items():
try:
df = yf.download(ticker, period="3mo", auto_adjust=True, progress=False)
df.columns = df.columns.get_level_values(0)
stoch = ta.stochrsi(df["Close"], length=14, rsi_length=14, k=3, d=3)
df = pd.concat([df, stoch], axis=1)
k = df["STOCHRSIk_14_14_3_3"].iloc[-1]
d = df["STOCHRSId_14_14_3_3"].iloc[-1]
k_prev = df["STOCHRSIk_14_14_3_3"].iloc[-2]
d_prev = df["STOCHRSId_14_14_3_3"].iloc[-2]
# 過売り領域(0.3以下)でゴールデンクロス発生
is_buy = (k > d) and (k_prev <= d_prev) and (k < 0.4)
results.append({
"銘柄コード": ticker,
"銘柄名": name,
"%K": round(k, 3),
"%D": round(d, 3),
"買いシグナル": "★" if is_buy else ""
})
except Exception as e:
print(f"{ticker} エラー: {e}")
result_df = pd.DataFrame(results)
print(result_df.to_string(index=False))
# 買いシグナルが出ている銘柄だけ表示
buy_candidates = result_df[result_df["買いシグナル"] == "★"]
print(f"\n本日の買い候補: {len(buy_candidates)}銘柄")
print(buy_candidates.to_string(index=False))
実際に使ってみての注意点
ストキャスティクスRSIはシグナルの頻度が高いのが特徴でもあり、落とし穴でもあります。日足では細かすぎるシグナルが出ることも多く、僕は最初これをそのまま信じて製造株を何度も売り買いして手数料貧乏になりかけました(笑)。
使うコツとしては:
① 週足と日足を組み合わせる(週足が過売り→日足でゴールデンクロスで初めてエントリー)
② 0.2以下、0.8以上の「極端な領域」のシグナルだけを使う
③ トレンドフィルターと組み合わせる(200日MAより上の銘柄だけ買いシグナルを採用)
特に③は製造メーカー株の長期上昇トレンドと組み合わせると精度が上がる印象があります。もちろんバックテストで確認することが先ですが。。。
まとめ
ストキャスティクスRSIは「RSIのRSI」とも言われる指標で、RSI単体よりも短期の反転タイミングを精度よく捉えられます。pandas-taを使えばワンライナーで計算でき、複数銘柄のスクリーニングも簡単に実装できます。
個人的には、決算発表後に一時的に売られすぎた製造メーカー株を拾う「押し目狙い」でこの指標が活躍しそうだと感じています。次は200日MAとの組み合わせでバックテストしてみて、結果をまた共有したいと思います!

