🙌

Python株価分析【後編】:続・yfinanceで取得したデータをAIアナリストに自動分析させてみた

に公開

1. はじめに:データの海で溺れないために 🌊

前回の記事「Pythonとyfinanceで始める株価分析入門!」では、yfinanceライブラリを使い、わずか数行のコードでプロも使うような詳細な株価データを取得する方法を学びました。

           Open    High     Low   Close    Volume
Date
2025-08-01  XXXX.X  XXXX.X  XXXX.X  XXXX.X  XXXXXXXX
2025-08-04  XXXX.X  XXXX.X  XXXX.X  XXXX.X  XXXXXXXX
...            ...     ...     ...     ...       ...

きっと皆さんの手元にも、お気に入りの銘柄の価格データがpandasのDataFrameとして存在することでしょう。しかし、同時にこんな悩みも生まれていませんか?

「確かにデータは取得できたけど、この数字の羅列からどうやって『買い』や『売り』の判断をすればいいんだろう…?」
「毎日たくさんの銘柄のデータを眺めているけど、分析に時間がかかりすぎる…」

そう、データを取得することは、分析のスタートラインに立ったに過ぎません。膨大な価格データの海を航海するためには、信頼できる「羅針盤」と、優秀な「航海士」が必要です。

この記事では、その「羅針盤」としてテクニカル指標を、「航海士」として**AI(大規模言語モデル, LLM)**を迎えます。

最終的なゴールは、あなたが指定した銘柄のデータをPythonが自動でテクニカル指標を付与し、そのデータを基にAIがプロのアナリスト顔負けの分析レポートを生成する、そんな仕組みを構築することです。

さあ、データ取得の次の一歩へ。あなただけのAIアナリストを育てる旅に出かけましょう!


2. Step 1:チャートに"武器"を授ける - テクニカル指標の実装 ⚔️

株価の生データ(四本値と出来高)は、いわば素の状態の兵士です。その兵士に「移動平均線」という剣や、「RSI」という盾を授けることで、戦況(相場の状況)をより有利に読み解くことができます。この武器こそがテクニカル指標です。

ここでは、提供されたコードの中から特に重要ないくつかのテクニカル指標を計算する関数をピックアップし、そのロジックと実装方法を見ていきましょう。

なぜ関数化するのか?

今後、様々な銘柄や期間で何度も同じ計算をすることになります。処理をdefを使って関数化しておくことで、コードがスッキリし、再利用が非常に簡単になります。

① 移動平均線 (Moving Average: MA) - トレンドの道筋を知る

最もシンプルかつ強力なトレンド系指標です。一定期間の終値の平均値を結んだ線で、相場の大きな流れを示してくれます。

  • ゴールデンクロス: 短期線が長期線を下から上に突き抜ける。買いのサイン。
  • デッドクロス: 短期線が長期線を上から下に突き抜ける。売りのサイン。
# 移動平均線(Moving Average:MA)を計算する関数
def MA(df):
  """
  DataFrameに5日、25日、75日の移動平均線を追加する。
  Args:
    df (pd.DataFrame): 'Close'カラムを持つDataFrame
  Returns:
    pd.DataFrame: MA5, MA25, MA75カラムが追加されたDataFrame
  """
  df1 = df.copy()
  df1['MA5'] = round(df1['Close'].rolling(5).mean(), 2)
  df1['MA25'] = round(df1['Close'].rolling(25).mean(), 2)
  df1['MA75'] = round(df1['Close'].rolling(75).mean(), 2)
  return df1
ma_describe = """
### 移動平均線
MA5:5日, MA25:25日, MA75:75日, MA100:100日, MA200:200日の移動平均線: 一定期間の株価の平均値を結んだ線で、トレンドの方向性や強さを示します。
ゴールデンクロス: 短期線が長期線を下から上に突き抜ける現象で、強い買いシグナルとされます。
デッドクロス: 短期線が長期線を上から下に突き抜ける現象で、強い売りシグナルとされます。
線の傾きと位置: 線の傾きが上向けば上昇トレンド、下向けば下降トレンドです。株価が移動平均線より上にあれば強気、下にあれば弱気と判断されます。
"""

pandasrolling(window).mean()を使うだけで、驚くほど簡単に計算できてしまいます。windowに日数を指定するだけです。

② MACD (Moving Average Convergence Divergence) - トレンドの勢いと転換点を探る

MACDは、2つの移動平均線(短期と長期のEMA)の差を見ることで、トレンドの方向性、強さ、そして転換点を捉えようとするトレンド系のテクニカル指標です。

  • ゴールデンクロス: MACD線がシグナル線を下から上に抜ける。買いのサイン。
  • デッドクロス: MACD線がシグナル線を上から下に抜ける。売りのサイン。
  • 0ライン: MACDが0より上なら上昇トレンド、下なら下降トレンドと判断できる。
# MACDを計算する関数
def MACD(df, period_short=12, period_long=26, period_signal=9):
  """
  DataFrameにMACD, シグナル, ヒストグラムを追加する。
  Args:
    df (pd.DataFrame): 'Close'カラムを持つDataFrame
    period_short (int): 短期EMAの期間
    period_long (int): 長期EMAの期間
    period_signal (int): シグナルの期間
  Returns:
    pd.DataFrame: MACD, MACD_S, MACD_Hカラムが追加されたDataFrame
  """
  df1 = df.copy()
  # 短期と長期の指数平滑移動平均(EMA)を計算
  exp12 = df1['Close'].ewm(span=period_short, adjust=False).mean()
  exp26 = df1['Close'].ewm(span=period_long, adjust=False).mean()
  
  # MACD、シグナル、ヒストグラムを計算
  df1['MACD'] = exp12 - exp26
  df1['MACD_S'] = df1['MACD'].ewm(span=period_signal, adjust=False).mean() # シグナル
  df1['MACD_H'] = df1['MACD'] - df1['MACD_S'] # ヒストグラム
  
  return df1
macd_describe = """
### MACD
MACD(マックディー)は、2つの指数平滑移動平均線の差を用いて、相場のトレンドの方向性、強さ、そして転換点を探るための指標です。「MACD線:MACD」「シグナル線:MACD_S」「ヒストグラム:MACD_H」の3つの要素で構成されます。
ゴールデンクロス(買いシグナル): MACD線が、その移動平均であるシグナル線を下から上に突き抜ける現象です。これは、短期的な勢いが中長期的な勢いを上回り始めたことを示し、上昇トレンドへの転換の可能性を示唆します。
デッドクロス(売りシグナル): MACD線がシグナル線を上から下に突き抜ける現象です。これは、短期的な勢いが弱まり始めたことを示し、下降トレンドへの転換の可能性を示唆します。
0ラインとの関係: MACD線が0ラインより上に位置する場合、相場は強気(上昇トレンド)、0ラインより下に位置する場合は**弱気(下降トレンド)**と判断されます。
ヒストグラムの役割: MACD線とシグナル線の差を棒グラフで表したものです。ヒストグラムがプラス圏で増加している場合は上昇の勢いが強いことを、マイナス圏で増加している(0に向かっている)場合は下降の勢いが弱まっていることを示し、トレンドの勢いを視覚的に判断できます。

分析の指示
以下のデータに基づき、上記の定義を用いて「ゴールデンクロス」「デッドクロス」の発生状況、MACD線の0ラインとの位置関係、そしてヒストグラムの増減を分析してください。それらを総合的に評価して現在のトレンドと勢いを判断し、今後の株価動-向を予測して、その根拠を詳細に解説してください。
"""

ewm()を使うことで、単純な平均(SMA)ではなく、直近の価格に比重を置いた**指数平滑移動平均(EMA)**を計算できるのがポイントです。

③ RSI (Relative Strength Index) - 相場の"過熱感"を測る

オシレーター系(振り子のように一定の範囲を行き来する)指標の代表格です。「買われすぎ」か「売られすぎ」かを判断するのに役立ちます。

  • 70%以上: 買われすぎ。反落の可能性。売りのサイン。
  • 30%以下: 売られすぎ。反発の可能性。買いのサイン。
# RSIを計算する関数
def RSI(df, period=14):
  """
  DataFrameにRSIを追加する。
  Args:
    df (pd.DataFrame): 'Close'カラムを持つDataFrame
    period (int): RSIの計算期間
  Returns:
    pd.DataFrame: 'RSI_period'カラムが追加されたDataFrame
  """
  df1 = df.copy()
  # 前日との価格差を計算
  df1['DIFF'] = df1['Close'].diff()
  
  # 上昇幅と下落幅を計算
  df1['UP'] = df1['DIFF'].apply(lambda x: x if x > 0 else 0)
  df1['DOWN'] = df1['DIFF'].apply(lambda x: -x if x < 0 else 0)
  
  # 上昇幅と下落幅の移動平均を計算
  df1['UP_rolling'] = df1['UP'].rolling(period).mean()
  df1['DOWN_rolling'] = df1['DOWN'].rolling(period).mean()
  
  # RSIを計算
  df1['RSI_' + str(period)] = 100 * df1['UP_rolling'] / (df1['UP_rolling'] + df1['DOWN_rolling'])
  
  # 不要なカラムを削除
  df1 = df1.drop(columns=['DIFF', 'UP', 'DOWN', 'UP_rolling', 'DOWN_rolling'])
  return df1
rsi_describe = """
### RSI(Relative Strength Index):
「相対力指数」と訳され、一定期間の価格の変動幅から市場の**「買われすぎ」または「売られすぎ」**を判断するためのオシレーター系指標です。数値は0から100%の間で推移します。
分析方法:
一般的に、RSIが70%以上に達すると「買われすぎ」と判断され、価格が反落する可能性が高まるため、売りシグナルと見なされます。
逆に、RSIが30%以下に低下すると「売られすぎ」と判断され、価格が反発する可能性が高まるため、買いシグナルと見なされます。
"""

④ 一目均衡表 (Ichimoku Cloud) - "時間"と"波動"で相場を立体的に捉える

日本発の由緒あるテクニカル指標で、「売り手」「買い手」「時間」の三者の均衡が崩れた方向に相場が動くという考えに基づいています。5本の線と、特に「」と呼ばれる抵抗帯が特徴的です。

  • 三役好転: 「転換線が基準線を上抜ける」「価格が雲を上抜ける」「遅行スパンが価格を上抜ける」の3つが揃う、非常に強い買いサイン。
  • 雲の役割: 価格が雲より上にあれば強気相場、下にあれば弱気相場。雲は強力なサポート(支持)やレジスタンス(抵抗)として機能します。
# 一目均衡表を計算する関数
def ichimoku(df):
    """
    DataFrameに一目均衡表の各線を追加する。
    Args:
        df (pd.DataFrame): 'High', 'Low', 'Close'カラムを持つDataFrame
    Returns:
        pd.DataFrame: 一目均衡表の各カラムが追加されたDataFrame
    """
    df1 = df.copy()
    # 転換線: 短期線 (過去9日間)
    turn_line_high = df1['High'].rolling(window=9).max()
    turn_line_low = df1['Low'].rolling(window=9).min()
    df1['turn_line'] = (turn_line_high + turn_line_low) / 2

    # 基準線: 中期線 (過去26日間)
    base_line_high = df1['High'].rolling(window=26).max()
    base_line_low = df1['Low'].rolling(window=26).min()
    df1['base_line'] = (base_line_high + base_line_low) / 2

    # 先行スパン1: 転換線と基準線の中間値を26日先にずらす
    df1['span1'] = ((df1['turn_line'] + df1['base_line']) / 2).shift(25)

    # 先行スパン2: 過去52日間の高値と安値の中間値を26日先にずらす
    span2_high = df1['High'].rolling(window=52).max()
    span2_low = df1['Low'].rolling(window=52).min()
    df1['span2'] = ((span2_high + span2_low) / 2).shift(25)

    # 遅行スパン: 当日の終値を26日前にずらす (描画用)
    df1['slow_line'] = df1['Close'].shift(-25)

    return df1
ichimoku_describe = """
### 一目均衡表:
テクニカル指標の定義と使い方
一目均衡表は、「転換線:turn_line」「基準線:base_line」「先行スパン1:span1」「先行スパン2:span2」「遅行スパン:slow_line」の5本の線と、先行スパンで形成される「雲」を用いて、相場のトレンド、サポート/レジスタンス、売買シグナルを総合的に判断する指標です。

転換線と基準線の関係:
好転(ゴールデンクロス): 短期的な勢いを示す転換線が、中期的なトレンドを示す基準線を上抜く現象。買いシグナルです。
逆転(デッドクロス): 転換線が基準線を下抜く現象。売りシグナルです。

価格と「雲」の関係:
「雲」は先行スパン1と2で形成され、**抵抗帯(レジスタンス)や支持帯(サポート)**として機能します。
先行スパン1と先行スパン2の価格を比べ高い価格が雲の上限、低い価格が雲の下限を示して上限下限の間が雲となります。
価格が雲を上抜けると強い上昇トレンド、下抜けると強い下降トレンドと判断されます。価格が雲の中にある場合は、方向感のない「もみ合い相場」とされます。

遅行スパンの役割:
現在の終値を過去にずらして表示したもので、トレンドの最終確認に使います。
遅行スパンが過去の価格を上抜いていれば強気相場、下抜いていれば弱気相場と判断されます。

総合判断(三役好転・三役逆転):
三役好転: 「転換線と基準線の好転」「価格が雲を上抜ける」「遅行スパンが価格を上抜ける」の3つが揃った状態で、非常に強い買いシグナルとされます。
三役逆転: 上記の逆の3つの条件が揃った状態で、非常に強い売りシグナルとされます。

分析の指示
以下のデータに基づき、上記の各要素(線の関係、雲との位置、遅行スパン)を個別に分析し、最終的に「三役好転」または「三役逆転」が成立しているかを含めた総合的な市場環境を判断してください。
その上で、今後の株価動向を予測し、その根拠を詳細に解説してください。
"""

⑤ ボリンジャーバンド (Bollinger Bands) - 価格変動の"幅"を読む

移動平均線を中心に、その上下に統計学的なばらつき(標準偏差, σ)を示した線を追加したものです。価格の**ボラティリティ(変動率)**を視覚的に捉えるのに非常に優れています。

  • スクイーズ: バンドの幅が狭くなる状態。エネルギーを溜めているサインで、大きな値動きの前兆。
  • エクスパンション: スクイーズ後にバンド幅が急拡大する状態。トレンド発生のサイン。
  • バンドウォーク: 価格が±2σの線に沿って動く状態。非常に強いトレンドを示唆。
# ボリンジャーバンドを計算する関数
def BB(df, period=21):
    """
    DataFrameにボリンジャーバンドの各線を追加する。
    Args:
        df (pd.DataFrame): 'Close'カラムを持つDataFrame
        period (int): 計算期間
    Returns:
        pd.DataFrame: ボリンジャーバンドの各カラムが追加されたDataFrame
    """
    df1 = df.copy()
    df1['BB_mean'] = df1['Close'].rolling(period).mean()
    df1['BB_std'] = df1['Close'].rolling(period).std()

    # 各バンドを計算 (+-1σ, 2σ, 3σ)
    df1[f'BB_P1_{period}'] = df1['BB_mean'] + df1['BB_std']
    df1[f'BB_P2_{period}'] = df1['BB_mean'] + df1['BB_std'] * 2
    df1[f'BB_P3_{period}'] = df1['BB_mean'] + df1['BB_std'] * 3
    df1[f'BB_N1_{period}'] = df1['BB_mean'] - df1['BB_std']
    df1[f'BB_N2_{period}'] = df1['BB_mean'] - df1['BB_std'] * 2
    df1[f'BB_N3_{period}'] = df1['BB_mean'] - df1['BB_std'] * 3
    
    df1 = df1.drop(columns=['BB_mean', 'BB_std'])
    return df1
bb_describe = """
### ボリンジャーバンド:
カラム例:BB_P1_21:21日の+1σ, BB_P2_21:21日の+2σ, BB_P3_21:21日の+3σ, BB_N1_21:21日の-1σ, BB_N2_21:21日の-2σ, BB_N3_21:21日の-3σ
ボリンジャーバンドは、移動平均線とその上下に値動きの幅を示す線を加えたもので、相場の**ボラティリティ(変動率)**やトレンドの方向性、売買のタイミングを判断するために使われます。
価格の大部分(約95%)は±2σ(シグマ)のバンド内に収まるという統計学的な性質を利用します。

分析方法①:順張り(トレンドフォロー)
スクイーズ: バンドの幅が狭くなること。ボラティリティが低下し、エネルギーを溜めている状態を示し、大きな価格変動(ブレイクアウト)の前兆とされます。
エクスパンション: スクイーズ後にバンドの幅が急拡大すること。トレンドが発生した可能性を示します。
バンドウォーク: 価格が+2σのバンドに沿って上昇、または-2σのバンドに沿って下落する現象。非常に強いトレンドが発生していることを示します。

分析方法②:逆張り(カウンタートレード)
価格が**+2σのバンド**にタッチまたは超えた場合は「買われすぎ」と判断し、反落を予測する売りシグナルと見なせます。
価格が**-2σのバンド**にタッチまたは下回った場合は「売られすぎ」と判断し、反発を予測する買いシグナルと見なせます。
注意:強いトレンドが発生している(バンドウォーク中)場合は、逆張りは機能しにくくなります。

分析の指示
以下のデータに基づき、上記の分析方法を用いて現在の市場を評価してください。
特に、バンドの幅(スクイーズやエクスパンションの有無)からボラティリティを判断し、価格と各バンド(±1σ, ±2σ, ±3σ)の位置関係からトレンドの強さや過熱感を分析し、今後の株価動向を予測して、その根拠を詳細に解説してください。
"""

⑥ ストキャスティクス (Stochastics) - 価格レンジの中での現在位置を知る

RSIと同じくオシレーター系の指標で、一定期間の価格レンジの中で現在の終値がどのあたりに位置するかを示します。相場の過熱感を測るのに使われます。

  • 80%以上: 買われすぎ。
  • 20%以下: 売られすぎ。
  • ゴールデン/デッドクロス: %D線とSlow%D線のクロスで売買サインを判断する。
# ストキャスティクスを計算する関数
def STCHS(df, period=9):
    """
    DataFrameにストキャスティクスの各線を追加する。
    Args:
        df (pd.DataFrame): 'High', 'Low', 'Close'カラムを持つDataFrame
        period (int): 計算期間
    Returns:
        pd.DataFrame: ストキャスティクスの各カラムが追加されたDataFrame
    """
    df1 = df.copy()
    highest = df1['High'].rolling(period).max()
    lowest = df1['Low'].rolling(period).min()
    
    # %K, %D, Slow%Dを計算
    df1['STCHS_K'] = ((df1['Close'] - lowest) / (highest - lowest)) * 100
    df1['STCHS_D'] = df1['STCHS_K'].rolling(3).mean()
    df1['STCHS_SLOW_D'] = df1['STCHS_D'].rolling(3).mean()
    
    return df1
stchs_describe = """
### ストキャスティクス
ストキャスティクスは、一定期間の価格レンジの中で現在の終値がどの位置にあるかを示し、市場の**「買われすぎ」や「売られすぎ」といった過熱感**を判断するためのオシレーター系指標です。
先行する「%K線:STCHS_K」と、%Kを移動平均化することにより遅行する「%D線:STCHS_D」の動きが異なる2本の線を表示し、その位置水準やクロスの仕方から、相場の転換点や、割高、割安の売買タイミングを探すことを目的とします。
「SLOW%D:STCHS_SLOW_D」は、やや遅行性がありますが%Kと%Dよりダマシが少ないのが特徴です。

買われすぎ・売られすぎの判断:
指標は0%から100%の間で推移し、一般的に80%以上で「買われすぎ」、**20%以下で「売られすぎ」**と判断され、相場の反転が近いことを示唆します。

ゴールデンクロス(買いシグナル):
主要線である**%Dが、その移動平均であるSlow%Dを下から上に突き抜ける現象です。特に、20%以下の「売られすぎ」水準でこのクロスが発生すると、信頼性の高い買いシグナル**と見なされます。

デッドクロス(売りシグナル):
%DがSlow%Dを上から下に突き抜ける現象です。特に、80%以上の「買われすぎ」水準でこのクロスが発生すると、信頼性の高い売りシグナルと見なされます。

分析の指示
以下のデータに基づき、上記の定義を用いて現在の市場の過熱感(買われすぎ・売られすぎ)を判断してください。
さらに、「ゴールデンクロス」や「デッドクロス」の発生状況を分析し、短期的な相場の反転ポイントを探り、今後の株価動向を予測して、その根拠を詳細に解説してください。
"""

⑦ DMI (Directional Movement Index) - トレンドの"方向"と"強さ"を同時に測る

相場にトレンドがあるのかどうか、そしてそのトレンドは上昇と下降のどちらが強いのかを判断するための指標です。+DI(上昇の勢い)、-DI(下降の勢い)、ADX(トレンドの強さ)の3本の線で構成されます。

  • +DI > -DI: 上昇トレンドが優勢。
  • -DI > +DI: 下降トレンドが優勢。
  • ADX: この線の傾きが重要。ADXが上昇していれば、トレンド(上昇・下降問わず)が強まっていることを示します。
# DMIを計算する関数
def DMI(df, period=14):
    """
    DataFrameにDMIの各線を追加する。
    Args:
        df (pd.DataFrame): 'High', 'Low', 'Close'カラムを持つDataFrame
        period (int): 計算期間
    Returns:
        pd.DataFrame: pDI, nDI, ADXカラムが追加されたDataFrame
    """
    df1 = df.copy()
    df1['pDM'] = df1['High'].diff()
    df1['nDM'] = -df1['Low'].diff()
    
    df1['pDM'][(df1['pDM'] < 0) | (df1['pDM'] < df1['nDM'])] = 0
    df1['nDM'][(df1['nDM'] < 0) | (df1['nDM'] < df1['pDM'])] = 0

    TR_i = pd.concat([df1['High'] - df1['Low'], 
                      abs(df1['High'] - df1['Close'].shift(1)), 
                      abs(df1['Low'] - df1['Close'].shift(1))], axis=1).max(axis=1)

    df1['pDI'] = (df1['pDM'].rolling(period).sum() / TR_i.rolling(period).sum()) * 100
    df1['nDI'] = (df1['nDM'].rolling(period).sum() / TR_i.rolling(period).sum()) * 100
    
    DX = (abs(df1['pDI'] - df1['nDI']) / (df1['pDI'] + df1['nDI'])) * 100
    df1['ADX'] = DX.rolling(period).mean()

    return df1.drop(columns=['pDM', 'nDM'])
dmi_describe = """
### DMI
DMI(Directional Movement Index)は、相場のトレンドの方向性と強さを同時に分析するためのテクニカル指標です。「+DI:pDI」「-DI:nDI」「ADX:ADX」の3本の線で構成されます。

トレンドの方向性(+DIと-DIの関係):
ゴールデンクロス(買いシグナル): 上昇の勢いを示す +DI が、下降の勢いを示す -DI を下から上に突き抜けた場合。上昇トレンドの開始を示唆します。
デッドクロス(売りシグナル): +DI が -DI を上から下に突き抜けた場合。下降トレンドの開始を示唆します。

トレンドの強さ(ADXの役割):
ADXはトレンドの強さを表す線で、方向性は示しません。
ADXが上昇: 現在のトレンド(上昇・下降問わず)が強まっていることを示します。一般的にADXが25以上で上昇している場合、強いトレンドが発生していると判断します。
ADXが下降: 現在のトレンドが弱まっている、またはトレンドレスな状況(もみ合い相場)であることを示します。

分析の指示
以下のデータに基づき、上記の定義を用いて現在の市場トレンドを分析してください。
トレンドの方向: 「+DI」と「-DI」のクロス状況から、現在のトレンドが上昇、下降、または中立のいずれであるかを判断してください。
トレンドの強さ: 「ADX」の数値とその変化(上昇または下降)から、そのトレンドの勢いが強いのか弱いのかを評価してください。

これら2つの要素を総合的に評価し、現在の市場が「強い上昇トレンド」なのか、「勢いを失いつつある下降トレンド」なのかなどを具体的に判断した上で、今後の株価動向を予測し、その根拠を詳細に解説してください。
"""

⑧ ボリュームレシオ (Volume Ratio) - "出来高"から市場エネルギーを測る

価格だけでなく、取引の活発さを示す**出来高(Volume)**にも注目した指標です。一定期間中の株価上昇日の出来高と下落日の出来高を比較し、市場の過熱感を判断します。

  • 150%以上: 買いが過熱している「買われすぎ」。
  • 80%以下: 投げ売りが一巡した「売られすぎ」。
# ボリュームレシオを計算する関数
def volume_ratio(df, window=25):
    """
    DataFrameにボリュームレシオを追加する。
    Args:
        df (pd.DataFrame): 'Close', 'Volume'カラムを持つDataFrame
        window (int): 計算期間
    Returns:
        pd.DataFrame: VR1, VR2カラムが追加されたDataFrame
    """
    df1 = df.copy()
    price_change = df1['Close'].diff()

    up_volume = df1['Volume'].where(price_change > 0, 0).rolling(window=window).sum()
    down_volume = df1['Volume'].where(price_change < 0, 0).rolling(window=window).sum()
    same_volume = df1['Volume'].where(price_change == 0, 0).rolling(window=window).sum()

    denominator = down_volume + same_volume / 2
    df1['VR1'] = ((up_volume + same_volume / 2) / denominator * 100).fillna(100)
    
    return df1
vr_describe = """
### ボリュームレシオ(VR1, VR2)
ボリュームレシオは、**出来高(Volume)**を利用して市場のエネルギーを測り、「買われすぎ」や「売られすぎ」といった市場の過熱感を判断するためのオシレーター系指標です。
一定期間中の株価上昇日の出来高と下落日の出来高を比較することで、買い圧力と売り圧力のバランスを分析します。

分析方法(逆張りでの利用が中心):
買われすぎ(売りシグナル): 一般的に、レシオが150%以上に達すると、買いが過熱している「買われすぎ」状態と判断され、価格が反落する可能性を示唆します。(※活況な相場では250%以上が目安になることもあります)
売られすぎ(買いシグナル): 逆に、レシオが80%以下に低下すると、投げ売りが一巡した「売られすぎ」状態と判断され、価格が反発する可能性を示唆します。
中立: 100%近辺は、買いと売りのエネルギーが均衡している状態を示します。

分析の指示
以下のデータに基づき、上記の定義を用いて現在の市場の過熱感を判断してください。
ボリュームレシオが「買われすぎ」または「売られすぎ」の水準に達しているかどうかに着目し、短期的な相場の反転ポイントを探り、今後の株価動向を予測して、その根拠を詳細に解説してください。
"""

⑨ すべての指標を統合する

これら強力な武器(関数)をすべて適用してみましょう。

# yfinanceでデータを取得
ticker_symbol = '7203.T' # 例:トヨタ自動車
data = yf.download(ticker_symbol, start='2024-01-01', end='2025-08-31', interval='1d')
df = data[['Open', 'High', 'Low', 'Close', 'Volume']]

# これまで定義した関数を使って、テクニカル指標を一気に追加!
df_tech = df.copy()
df_tech = MA(df_tech)
df_tech = MACD(df_tech, period_short=12, period_long=26, period_signal=9)
df_tech = RSI(df_tech, 14)
df_tech = ichimoku(df_tech)
df_tech = BB(df_tech, 21)
df_tech = STCHS(df_tech, 9)
df_tech = DMI(df_tech, 14)
df_tech = volume_ratio(df_tech, window=25)

# 末尾の5行を表示して、指標が追加されたことを確認
print(df_tech.tail())

これで、元のOHLCVデータに多数の分析用「武器」が追加された、強力なデータフレームが完成しました。


3. Step 2:AIアナリストへの"通訳"術 - LLM連携のためのデータ整形 🤖

さて、強力なデータは手に入りました。しかし、この巨大な表をそのまま「はい、分析して」とAIに渡しても、最高のパフォーマンスは引き出せません。AIが理解しやすく、かつ効率的に処理できる形に**通訳(データ整形)**してあげる必要があります。

なぜJSON形式なのか?

LLMは、人間が書くような自然言語だけでなく、**JSON (JavaScript Object Notation)**のような構造化されたデータ形式を非常に得意とします。pandasのDataFrameをJSONに変換することで、AIは「いつの」「どの指標が」「いくらだったのか」を正確に認識できるのです。

トークン節約の秘訣:orientオプション

pandasto_json()メソッドにはorientという重要な引数があります。これはJSONの構造を決めるもので、AIに渡す際には**トークン数(≒コストや処理時間)**に大きく影響します。

  • orient='records':

    [
        {"Date": "2025-08-28", "Close": 41350.0, "MA5": 40204.0},
        {"Date": "2025-08-29", "Close": 41350.0, "MA5": 40746.0}
    ]
    

    人間には分かりやすいですが、日付ごとに"Date", "Close"といったキー名が繰り返され、トークンを多く消費します。

  • orient='split' (推奨):

    {
        "columns": ["Date", "Close", "MA5"],
        "data": [
            ["2025-08-28", 41350.0, 40204.0],
            ["2025-08-29", 41350.0, 40746.0]
        ]
    }
    

    カラム名とデータが分離されているため、繰り返しが無く、圧倒的にトークンを節約できます。AIもこの形式を問題なく解釈できます。

数値を整形する理由

12345678.9のような大きな数値や、33.3333333のような細かい小数点以下の数値は、AIにとって不要な情報(ノイズ)になることがあります。数値を丸めたり、大きな数字は1.23e+07のような指数表記に変換したりすることで、トークンを節約しつつ、AIが本質的な情報に集中できるよう手助けします。

提供されたformat_df_for_llm関数は、まさにこの処理を自動で行ってくれる優れものです。

# (format_df_for_llm関数は提供コードを参照)

# LLMに渡すための最終的なJSON文字列を作成する関数
def df_4_llm(df: pd.DataFrame) -> str:
    # 数値のフォーマットを適用
    df4llm = format_df_for_llm(df)
    
    # トークン効率の良い'split'形式でJSON文字列に変換
    # index=FalseでDataFrameのインデックスを含めないようにするのもポイント
    df_json = df4llm.to_json(orient='split', force_ascii=False, index=False)
    
    return df_json

# 実行
df_json_for_llm = df_4_llm(df_tech[-100:]) # 直近100日分のデータを整形
print(df_json_for_llm)

これで、AIアナリストへの通訳は完了です。


4. Step 3:AIに"魂"を吹き込む - 最強のプロンプトエンジニアリング ✍️

最高のデータを用意しても、AIへの「指示」が曖昧では、平凡な答えしか返ってきません。AIにプロのアナリストとして振る舞ってもらうためには、こちらの意図を正確に伝え、思考の道筋を示すプロンプトエンジニアリングが不可欠です。

提供されたcreate_prompt_tech関数内のプロンプトは、まさにそのための工夫が凝縮されています。

最強プロンプトの構成要素

  1. 役割(Role)の設定:

    # あなたは、長年の経験を持つプロのテクニカルアナリストです。
    最初に役割を与えることで、AIはそのペルソナになりきり、専門的な視点と語り口で回答を生成しようとします。

  2. 明確なゴールと出力形式の指定:

    **重要** チャートを分析し、売買期待度を -100~100の数値で表してください。
    売買期待度をタイトルにして目立つようにしてください。
    何をしてほしいのか、どんな形式で出力してほしいのかを具体的に、かつ強調して伝えます。これにより、期待する形式の回答が得られやすくなります。

  3. 思考プロセスの提供:

    # 実行手順
    ステップ1:分析の基礎となる前提の確認
    ステップ2:マルチタイムフレームによる環境認識
    ...
    単に「分析して」ではなく、「この手順で思考してください」とガイドラインを示すことで、AIは闇雲に分析するのではなく、構造化された論理的な分析を行うようになります。これは**思考の連鎖 (Chain of Thought)**を促すテクニックの応用です。

  4. 事前知識の提供:

    ## テクニカル指標の解説・活用方法
    {tech_describe}
    AIが各テクニカル指標(MA, MACDなど)をどのように解釈すれば良いか、こちらの定義を先に教えておきます。これにより、分析のズレを防ぎ、我々の意図に沿った深い分析を可能にします。

  5. データの埋め込み:

    ## テクニカルデータ(JSON形式、一部または全部)
    ````{df_json}```
    Step2で準備した、AIにとって最高の料理(整形済みJSONデータ)をここで提供します。

これらの要素を組み合わせることで、AIは単なる計算機から、思考する**専門家(エージェント)**へと昇華するのです。

def create_prompt_tech(df_json, tech_describe):

    # プロンプトテンプレート 
    prompt = f"""# あなたは、長年の経験を持つプロのテクニカルアナリストです。与えられた銘柄のチャートとデータに基づき、以下の思考プロセスと手順に従って、
現在の株価に対する評価と今後の投資戦略を詳細に分析・構築してください。

**重要** チャートを分析し、売買期待度を -100~100の数値で表してください。
チャートのピーク(頂点)の場合は売り時と判断し、-100としてください。
チャートのボトム(底)の場合は買い時と判断して、100としてください。
もみあいの時で売り買い判断つかないときを0付近で表してください。
売買期待度をタイトルにして目立つようにしてください。
売買期待度の数値の意味するところ(マイナスが売り時、プラスが買い時の期待数値)の基準の説明をタイトルの下に注釈で入れるようにしてください。
そのあとに各テクニカルの解説をしてください。

分析の各ステップでは、その結論に至った根拠を明確に示し、客観的な事実と専門的な解釈を分けて記述してください。
以下の株価テクニカルデータ(JSON形式、一部または全部)に基づいて、チャートの状況を詳細に解説してください。
与えられたデータはユーザーがグラフで見ていますのでそのうえでポイントを説明してください。
特に最終的な日付の株価の状態が売りなのか買いなのかテクニカルから分析してください。
テクニカル指標をもとに的確で素晴らしく、ユーザーが感嘆する売買の推奨をしてください。
過去の時点は参考にするだけで今の状態がどうなのかだけを判断してください。
参考に過去の状況を総括するのはよいことですが、重要なのは最新の状況です。
データは日付ごとに、始値(Open)、高値(High)、安値(Low)、終値(Close)、出来高(Volume)、および選択されたテクニカル指標の値が含まれています。

# 役割と目標
役割: プロフェッショナル・テクニカルアナリスト
目標: 対象銘柄の現在の状況を多角的に評価し、具体的なエントリーポイント、損切りポイント、利益確定ターゲットを含む、実行可能な投資戦略を策定する。

# 実行手順
実行の手順は結論を導くための考え方のため、出力する必要はありません。
このステップに沿って株価を分析し回答を出力してください。

ステップ1:分析の基礎となる前提の確認
まず、テクニカル分析の3大原則を思考の土台として意識します。

市場の動きは全てを織り込む: ファンダメンタルズも含め、あらゆる情報が現在の価格に反映されている。
価格はトレンドを形成する: 価格はランダムに動くのではなく、一定期間、一定の方向に動く傾向がある。
歴史は繰り返される: 投資家の心理は普遍的であり、過去に現れたチャートパターンは将来も機能する可能性が高い。


ステップ2:マルチタイムフレームによる環境認識(長期→中期→短期)
大きな流れから詳細へ分析を進め、相場の全体像を把握します。
各テクニカル指標の値を過去から振り返り、長期、中期、短期でステップバイステップで把握します。
【長期トレンドの分析(月足・週足)】
ダウ理論によるトレンド定義: 長期チャート上の重要な高値と安値の位置関係を特定し、「上昇トレンド(高値・安値の切り上げ)」「下降トレンド(高値・安値の切り下げ)」「レンジ相場」のいずれにあるかを定義してください。
【中期トレンドの分析(日足)】
トレンドライン: 明確な上昇・下降トレンドが存在する場合、支持線(安値同士を結ぶ)または抵抗線(高値同士を結ぶ)を引いてください。ラインの角度や、価格がラインにどのように反応しているかを記述してください。
過去の転換点の日付、株価を把握しそこからのトレンドを認識してください。
過去の転換点は複数(年間2~4回ほど転換する可能性あり)明確に指摘しトレンドがどのように形成されているか指摘してください。


ステップ3:重要な支持線(サポート)と抵抗線(レジスタンス)の特定
価格が反転または停滞する可能性のある重要な価格帯を特定します。
水平線: 過去に何度も価格が反転している高値(レジスタンス)と安値(サポート)に水平線を引いてください。
動的な支持/抵抗: ステップ2で分析したトレンドラインや移動平均線、一目均衡表の雲が、動的な支持/抵抗として機能しているか評価してください。
価格帯別出来高: 出来高が特に集中している価格帯を特定してください。この価格帯は強力な支持/抵抗帯となる可能性があります。
心理的節目: ¥1,000や¥5,000のようなキリの良い価格が意識されているか確認してください。


ステップ4:オシレーター系指標による市場の過熱感とタイミングの分析
トレンドの勢いや、短期的な売買タイミングを計ります。

ステップ5:チャートパターンと出来高の分析
投資家心理が作り出す特定の形状を特定し、将来の値動きを予測します。
チャートパターンの特定: ヘッドアンドショルダー、ダブルトップ/ボトムなどの「反転パターン」や、三角保ち合い、フラッグ、ペナントなどの「継続パターン」が形成されていないか確認してください。
出来高の確認:
現在のトレンド方向への値動きに伴い、出来高は増加していますか?(トレンドの信頼性)
支持/抵抗ラインやチャートパターンのブレイクアウト時に、出来高が急増していますか?(ブレイクアウトの信頼性)出来高を伴わないブレイクアウトは「ダマシ」の可能性があります。

ステップ6:総合的な評価とシナリオプランニング
全ての分析結果を統合し、最も可能性の高いシナリオを構築します。
分析結果の要約: ステップ2から5までの分析で得られた「強気の材料」と「弱気の材料」を箇条書きで整理してください。
シグナルの確認(コンフルエンス): 異なる分析(例:トレンドラインのブレイクとMACDのゴールデンクロス)が同じ方向を示している箇所を特定し、シグナルの信頼性を評価してください。
矛盾するシグナルの評価: 分析結果が矛盾する場合(例:中期トレンドは上昇だが、RSIで弱気のダイバージェンスが出ている)、その矛盾点を明記し、どちらのシナリオが優位かを慎重に評価してください。

メインシナリオ(最も可能性の高い値動き):
総合的に判断して、株価が今後向かう可能性が最も高い方向性(上昇/下落/レンジ)を記述してください。
現在の株価水準が「割高」「割安」「妥当」かを、テクニカルな観点から評価してください。
代替シナリオ: メインシナリオが否定された場合に起こりうる、次に可能性の高い値動きを記述してください。


ステップ7:具体的な投資戦略の策定
分析を基に、リスク管理を組み込んだ実行可能なアクションプランを策定します。
売買の方向: 「買い(ロング)」または「売り(ショート)」または「待ち(様子見)」を明確にしてください。
エントリーポイント:
どのような条件が満たされたらエントリーするかを具体的に定義してください。(例:「レジスタンスラインである¥XXXXを、出来高を伴って明確に上抜けたら買い」)
ストップロス(損切り)ポイント:
エントリー後に想定と逆方向に動いた場合に、損失を限定するための撤退ポイントを価格で指定してください。(例:「直近の安値である¥YYYYを明確に下回ったら損切り」)
プロフィットターゲット(利益確定)ポイント:
利益を確定する目標価格を、最低2つ設定してください。(例:「ターゲット1:次のレジスタンスである¥ZZZZ」「ターゲット2:チャートパターンの値幅から算出した¥AAAA」)
リスク・リワード比率:
このトレードの(リスク:リワード)比率を計算してください。(リスク = |エントリー価格 - 損切り価格|, リワード = |利益確定価格 - エントリー価格|)。比率が1:2以上であることが望ましいです。


テクニカル分析の観点から、特に注目すべき点(例:ローソク足のパターン、トレンドラインの形成可能性、支持線・抵抗線の水準、移動平均線のクロス、オシレーター系の指標のダイバージェンスや買われすぎ・売られすぎサインなど)を指摘し、それらが市場の今後の動きについて何を示唆している可能性があるか説明してください。
分析は具体的かつ客観的に行い、専門用語を用いる場合は簡単な解説も加えてください。

## テクニカル指標の解説・活用方法
{tech_describe}

## テクニカルデータ(JSON形式、一部または全部)
{df_json}

上記のデータから読み取れる情報を元に分析してください。
もしデータが不完全、または情報が少なすぎて詳細な分析が難しい場合は、その旨を正直に指摘してください。

# 出力形式
売買期待指数を一番初めに出し、その結論に至った理由をわかりやすく記述してください。
専門用語には簡単な注釈を加えてください。
チャート上にラインやパターンを書き込むことはできないため、価格や日付を用いて具体的に記述してください。
分析結果はマークダウン形式で、見出しや箇条書きを効果的に使用して、読みやすくまとめてください。
留意事項・免責事項は別途表示しますので重複を防ぐために文章に含まないでください。
"""

    return prompt

5. 最終章:すべてを繋ぎ、AIアナリストを召喚する ✨

さあ、すべてのパーツが揃いました。これらを一つにまとめ、銘柄コードを指定するだけでAIアナリストが分析レポートを生成する、夢のようなパイプラインを完成させましょう。

import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# --- ここにテクニカル指標の関数群 (MA, MACD, RSI, etc.) をすべて貼り付ける ---
# --- ここにデータ整形・プロンプト生成の関数群 (format_df_for_llm, df_4_llm, create_prompt_tech) をすべて貼り付ける ---

# ===== 実行メイン部分 =====
# 1. 銘柄と期間を指定
ticker_symbol = '6758.T' # 分析したい銘柄コード(例:ソニーグループ)
end_date = datetime.now()
start_date = end_date - timedelta(days=500) # 過去500日分のデータを取得

# 2. yfinanceで株価データを取得
data = yf.download(ticker_symbol, start=start_date.strftime('%Y-%m-%d'), end=end_date.strftime('%Y-%m-%d'), interval='1d')
df = data[['Open', 'High', 'Low', 'Close', 'Volume']].reset_index()
df['Date'] = pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')


# 3. テクニカル指標を計算
df_tech = df.copy()
df_tech = MA(df_tech)
df_tech = RSI(df_tech, 14)
df_tech = ichimoku(df_tech)
df_tech = BB(df_tech, 21)
df_tech = MACD(df_tech, period_short=12, period_long=26, period_signal=9)
df_tech = STCHS(df_tech, 9)
df_tech = DMI(df_tech, 14)
df_tech = volume_ratio(df_tech, window=25)


# 4. テクニカル指標の解説文を作成
tech_describe = f"""
{ma_describe}
{rsi_describe}
{macd_describe}
{ichimoku_describe}
{bb_describe}
... (各指標のdescribe変数を結合) ...
"""

# 5. LLM用のJSONデータを作成 (分析対象は直近300日分)
df_json = df_4_llm(df_tech.tail(300))

# 6. 最終的なプロンプトを生成
final_prompt = create_prompt_tech(df_json, tech_describe)

# 7. プロンプトを出力
print("--- 以下をコピーして、GeminiなどのLLMに貼り付けてください ---")
print(final_prompt)

このコードを実行すると、ターミナルに長大なプロンプトが出力されます。あとはその内容をすべてコピーし、Google GeminiやChatGPTのようなLLMのチャット画面に貼り付けて送信するだけです。

実行結果サンプル (AIによる分析レポート)

売買期待度:+75 (強気の買い推奨)

注釈:この指数は-100(強い売り時)から+100(強い買い時)の範囲で示されます。現在は短期的な押し目からの反発を狙う絶好の機会と判断します。

総括

現在の株価は、長期的な上昇トレンドの中での一時的な調整局面を終え、再び上昇に転じる可能性が非常に高い状況と分析します。複数のテクニカル指標が強気のサインを示しており、リスクを管理しつつ、積極的に買いを検討すべき局面です。

長期・中期トレンド分析

  • 移動平均線(MA): 75日移動平均線がサポートとして機能しており、これを下値に反発しています。また、5日線が25日線を上抜けるゴールデンクロスが形成間近であり、上昇の勢いが加速する兆候が見られます。
  • 一目均衡表: 価格は「雲」の上限を明確に上抜けており、三役好転の条件を満たしています。これは非常に強い上昇トレンドを示唆しています。

オシレーター系指標による過熱感分析

  • RSI: 一時30%近くまで下落して「売られすぎ」の状態でしたが、現在は50%ラインを回復し、過熱感のない健全な上昇を示しています。
  • MACD: MACD線がシグナル線を下から上に突き抜けるゴールデンクロスを形成しました。ヒストグラムもプラス圏に転じており、上昇の勢いが再燃していることを示しています。

投資戦略

  • 売買の方向: 買い(ロング)
  • エントリーポイント: 直近高値である XXXX円 を明確に上抜けたタイミング。
  • 損切りポイント: 75日移動平均線が位置する YYYY円 を下回った場合。
  • 利益確定目標:
    • ターゲット1: ZZZZ円(過去のレジスタンスライン)
    • ターゲット2: AAAA円(フィボナッチ・エクスパンションから算出)

(上記はあくまでAIによる生成例です)


6. おわりに:分析の自動化、その先へ 🚀

今回は、yfinanceで取得したデータにテクニカル指標という「武器」を与え、さらにAIという優秀な「航海士」に分析を任せるまでの壮大な旅を体験しました。

  • テクニカル指標の関数化で、分析の基盤を整えた。
  • JSONへの整形で、AIとの円滑なコミュニケーションを可能にした。
  • 緻密なプロンプト設計で、AIの能力を最大限に引き出した。

これまで手作業でチャートを眺め、感覚的に行っていた分析が、PythonとAIの力で体系的かつ自動的に行えるようになったのです。

この仕組みは、あなたのアイデア次第でさらに進化します。

  • 完全自動化: このスクリプトを毎日定時に自動実行し、分析結果をLINEやDiscordに通知する。
  • 多銘柄比較: 監視リストにある複数の銘柄を一度に分析させ、最も有望な銘柄をAIに選ばせる。
  • バックテスト: AIが提案した戦略が過去の相場で有効だったかを検証する。

データ分析の旅はまだ始まったばかりです。ぜひこの記事を参考に、あなただけの最強の投資分析ツールを育ててみてください!

最後までお読みいただきありがとうございました。

Discussion