0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

空気で買うな:株式スクリーニング前に使える相場スコアの設計とPython実装

Posted at

株式投資において相場をどのように把握すれば良いか

はじめに

株式投資において定期的に売買を行う際、「このタイミングで本当に買っていいのか?」という迷いが毎回出てきます。
経済ニュースでは「堅調な値動き」「難航」「揉み合い」などの言葉がよく使われますが、それが実際にどのような相場状況を指しているのかは文脈次第であり、明確に判断するには経験が必要です。

だからこそ、こうした「雰囲気」を定量的に捉える指標があると便利だと考えられます。そこで、市場の空気感を数字に落とし込むために「地合いスコア」という指標を設計しました。


株価データや既存のテクニカル指標だけでは「勢い」と「相場局面」が分かりずらい問題

価格データでは「流れ」がつかみにくい

TOPIXや日経平均などの株価指数は、たしかにその日の価格を示していますが、

  • 上昇トレンドのどの段階なのか
  • 反転が近いのか、まだ下げ続けそうなのか

といった流れ・勢いまでは分かりません。

連続値の指標は「ここから悪い/良い」があいまい

RCIのようなテクニカル指標もトレンドの傾向を掴むのに有用ですが、+100〜-100の間を滑らかに動くため、

「どこから悪いか/どこから良いか」が分かりづらい

という特徴があります。


設計:地合いスコア

目的と仕様

こうした課題をカバーするために、加点・減点式の「地合いスコア(-3〜+3)」をつくりました。
TOPIX(連動銘柄1306.T)から以下の3つの指標を算出し、それをもとに、ルールベースでスコアをつけていきます。

  • 直近5営業日のリターン(R₅)
  • 終値と25日移動平均の乖離(D₂₅)
  • RSI(14日間:RSI₁₄)

スコア加点ルール

指標 条件 点数
R₅ > +1% +1
< -1% -1
D₂₅ > 0 +1
< 0 -1
RSI₁₄ > 55 +1
< 45 -1

※ しきい値の設定について

  • R₅ ±1%:TOPIXの標準的な日変動(約±0.9%)を参考にしています。
  • RSI:過去の分布から、上位・下位30%の目安として設定しています。
    ここで使用している閾値は一例であり、ご自身の分析方針に応じて調整して構いません。

指標の選定理由:なぜこの3つか?

  • R₅(リターン)**は、短期的な価格の勢いを測るために使います。プラスなら価格が上昇中、マイナスなら下落中という判断が可能です。

  • D₂₅(移動平均乖離)**は、中期トレンドの中で価格がどの位置にあるかを示します。0より上なら上昇トレンド中、下なら下降トレンドと見なすことができます。

  • RSI₁₄は、買われすぎ・売られすぎといった市場心理を数値化したものです。55以上で強気、45以下で弱気として、相場の“感情の偏り”を反映させます。

この3つを組み合わせることで、勢い・位置・心理をシンプルに把握でき、
日々のスクリーニング前に「今の相場がどういう状態か」を段階的数値で判断する補助になると思い設計しました。


実装

import os
import yfinance as yf
import pandas as pd
import numpy as np

# --- 保存先のパス ---
gdrive_base = os.path.expanduser("/Users/shuheihenmi/Library/CloudStorage/GoogleDrive-3kana.hemirin.723@gmail.com/My Drive/stock_prediction/ver.1/market_sentiment/dropdown")
os.makedirs(gdrive_base, exist_ok=True)

# --- データ取得(1306.T←TOPIX連動銘柄) ---
df = yf.download("1306.T", start="2010-01-01", end="2025-05-03")

# MultiIndex対策(不要な階層を外す)
if isinstance(df.columns, pd.MultiIndex):
    df.columns = df.columns.get_level_values(0)

# --- 必要な指標のみ計算 ---
df["LogReturn"] = np.log(df["Close"] / df["Close"].shift(1))
df["MA25"] = df["Close"].rolling(25).mean()
df["MA25_diff"] = (df["Close"] - df["MA25"]) / df["MA25"]

delta = df["Close"].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
avg_gain = pd.Series(gain, index=df.index).rolling(14).mean()
avg_loss = pd.Series(loss, index=df.index).rolling(14).mean()
rs = avg_gain / (avg_loss + 1e-10)
df["RSI_14"] = 100 - (100 / (1 + rs))

# --- 地合いスコアの算出 ---
df["score_today"] = 0
df["score_today"] += (df["LogReturn"].rolling(5).sum() > 0.01).astype(int)
df["score_today"] += (df["MA25_diff"] > 0).astype(int)
df["score_today"] += (df["RSI_14"] > 55).astype(int)
df["score_today"] -= (df["RSI_14"] < 45).astype(int)
df["score_today"] -= (df["LogReturn"].rolling(5).sum() < -0.01).astype(int)
df["score_today"] -= (df["MA25_diff"] < 0).astype(int)

df["score_mean"] = df["score_today"].rolling(10).mean()
df["score_std"] = df["score_today"].rolling(10).std()
df["score_trend"] = df["score_today"].diff().rolling(10).mean()

# --- 保存 ---
df = df.dropna().copy()
save_path = os.path.join(gdrive_base, "1306_score.csv")
df.to_csv(save_path)
print(f"✅ 地合いスコア保存完了: {save_path}")

検証:地合いスコアの動き

暴落前後のスコア推移

過去の暴落局面を振り返ってみると、数日前〜当日にスコアが急激に下がり、極小値をつけるパターンがいくつか見られました。また、スコアの回復が値動きよりも早く現れることもあり、相場の変動の兆候を捉える指標として使える可能性がありそうです。

ただし、地合いスコアは価格の変動に敏感に反応するため、
大幅下落だけでなく、比較的小さな下げでも急激にスコアが落ちることがあります。
そのため、「スコアが急落した=株価が暴落する」という単純な対応関係ではなく、
市場の変調を広く捉える包括的な兆候として扱うべき指標だと考えています。

東日本大震災
crash_window_2011-03-15.png

2013年のVaRショック 
crash_window_2013-05-27.png

チャイナ・ショック ブラックマンデー2015
crash_window_2015-08-24.png

2016年の世界同時株安
crash_window_2016-02-12.png

COVID-19感染拡大 原油価格の暴落
crash_window_2020-03-09.png

2024年夏のショック(仮称)
crash_window_2024-08-02.png

2025年春のショック(仮称)
crash_window_2025-04-07.png

RCIとの比較

RCI(Rank Correlation Index)は、終値の順位と時間の順位の相関をとることでトレンドの強さを測る指標です。RCIと地合いスコアのグラフは、形がよく似ているように見えます。

算出式:

RCI = [1 - (6 × Σ(Pi - Ti)^2) / (n(n² - 1))] × 100

  • Pi:価格順位
  • Ti:時間順位(直近ほど高順位)
  • n:期間

RCIはなめらかに推移するので、トレンドの“強さ”を見るには向いていますが、「この値を超えたらOK/NG」といった分かりやすい区切りはつけづらいです。

それに対して、地合いスコアは合計7段階に分かれているため、スクリーニングを行う際に実用的に条件の使い分けを行うときに、扱いやすいと考えられます。

RCIは終値と時間の順位の相関からトレンドの強さを測るもので、地合いスコアとは全く異なるロジックで算出されていますが、それにも関わらず、似たような動きをすることがあるというのは、興味深いと感じました。数理的な根拠までは分かりませんが、異なる指標で似た形状が得られるという点は、
地合いスコアにも一定の信頼性があるように思える理由のひとつかもしれません。

RCI vs 地合いスコア
RCI_vs_Score.png

RCI vs 終値の前日比
RCI_vs_Return.png

地合いスコア vs 終値の前日比
Score_vs_Return.png

年ごとのスコアの安定性

スコアが特定の年に偏っていないかをチェックするために、2010〜2024年のスコアの平均と標準偏差を出してみました。

年度 平均スコア 標準偏差
2010 0.12 1.15
2011 -0.28 1.09
2012 0.03 1.08
2020 -0.34 1.20
2024 -0.05 1.12

平均値はイベントの有無で多少ブレますが、標準偏差は概ね一定で、スコア自体が特定の時期に偏って壊れるような性質はなさそうです。


活用に向けた展望

地合いスコアは「未来を当てる」ための予測指標ではありませんが、

  • 暴落前にスコアが下がりやすい
  • 回復局面でスコアが上昇しやすい

といった傾向が見られるため、兆しを捉える、手がかりになるかもしれません。

たとえば、今後は下記の使い方ができるかを検討したいと考えています:

  • 地合いが良い状態が長く続いている時は、下落が生じる可能性があるため、銘柄選抜の条件を厳しくする。もしくは、リスク分散をする。
  • 地合いが悪化後、改善傾向を示したら、チャンスと捉え、ベッド額を増やす。

これらの運用が本当に有効かどうかを確かめていく予定です。


次回予告:スクリーニングルールは地合い次第?相場との相性を検証する

以前の記事で、複数のテクニカル条件に基づいてスクリーニングを実施し、それぞれの選抜条件で得られた銘柄のリターンを計算しました。その際、あとから参照できるように各スクリーニング結果に地合いスコア(当日・平均・傾向など)をタグとして添付しています。

次回は、それらのタグを使って、地合いスコアと各選抜条件のリターンに関連があるのかを検証します。

地合いが良いときに機能しやすい条件、あるいは地合いが悪いときでも安定している条件はあるのか? 本スコアを投資戦略選択の軸として使えるかどうかを、データから探っていく予定です。

最後に

この記事で紹介したスコアは、学術的な精密モデルを目指したものではなく、あくまで投資判断を現実的に補助するための定量ツールです。

数理や指標設計についてはまだ勉強中の立場ですが、それでも「結果に繋がるならやる価値がある」と考えて試行錯誤を重ねています。

理論的な整合性よりも、有用性を重視して改良を続けていく予定です。

また、本記事ではyfinanceを用いてデータを取得していますが、最近、接続エラーやRate Limitが頻発しており、安定性に課題があります。将来的には、より安定した日本株データソースとして、J-Quantsなどの公式APIへの切り替えも検討しています。今回のスコア設計は取得元に依存しない構造なので、データソースを変えても同様の仕組みで運用可能です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?