株価の推移データから分析用の指標を抽出するサンプルコード

プログラミング
  • URLをコピーしました!
目次

はじめに

ある企業の株価の変動を予測する際の分析に、テクニカル分析が挙げられます。値動きのデータを集めることができたら、トレンド分析につなげるための各種指標を集めていくことになります。株価の動きを予測するために使われるテクニカル指標。これがわかると、まるでシャーロック・ホームズが犯人を特定するように、相場の流れを見抜けるようになります。今回は、アニメや映画のエピソードを例にしながら、移動平均、ボリンジャーバンド、RSI、MACDといった指標を解説していきます!

移動平均線 – 『スラムダンク』の湘北の成長曲線?

移動平均線とは、一定期間の株価の平均を取ることで、相場のトレンドをつかむ指標です。短期(5日)、中期(20日)、長期(50日)といったスパンで計算し、相場の方向性を探ります。

これはまるで『スラムダンク』の湘北高校の成長曲線みたいなもの。序盤は桜木花道の個人プレーが目立ち、チームとしての力は不安定。しかし、三井寿が復帰し、安定感が増していくと、チームの平均パフォーマンス(=移動平均線)は上昇傾向に。最終的に全国大会で王者・山王工業を破るまでに成長しました。

株価も同じで、短期的な上下動に惑わされず、移動平均線の流れを読むことで、上昇トレンドか下降トレンドかを見極めることができます。移動平均を使えば、長期的な株価の傾向を確認でき、投資判断の大きな指標となります。
株価のデータについて、日足のデータはデータベースとして集めているとします。まずは移動平均を計算してみます。
移動平均(MA: Moving Average): これは一定期間の平均株価で、株価のトレンドを把握するのに役立ちます。短期的な移動平均(例えば5日間)と長期的な移動平均(例えば50日間または200日間)を比較することで、買い時と売り時を見つけることができます。

import pandas as pd
import sqlite3

# データベースへの接続
conn = sqlite3.connect('stock_data.db')

# データの取得
query = "SELECT * FROM stock_price"
df = pd.read_sql_query(query, conn)

# 日付をdatetime型に変換
df['date'] = pd.to_datetime(df['date'])

# 銘柄ごとに処理
tickers = df['ticker'].unique()
df_ma = pd.DataFrame()

for ticker in tickers:
    df_temp = df[df['ticker'] == ticker].copy()
    df_temp.set_index('date', inplace=True)

    # 移動平均の計算
    df_temp['ma_5'] = df_temp['close'].rolling(window=5).mean()
    df_temp['ma_10'] = df_temp['close'].rolling(window=10).mean()
    df_temp['ma_20'] = df_temp['close'].rolling(window=20).mean()

    df_ma = df_ma.append(df_temp.reset_index())

# テーブルへ保存
df_ma.to_sql('stock_price_ma', conn, if_exists='replace', index=False)

# 接続を閉じる
conn.close()

このスクリプトでは5日、10日、20日の移動平均を計算していますが、必要に応じてスパンを変更できます。

ボリンジャーバンド – 『新世紀エヴァンゲリオン』のA.T.フィールド?

続いてそのまま求めた移動平均を使ってボリンジャーバンドも求めます。ボリンジャーバンドは、移動平均に加えて価格のブレ幅(標準偏差)を利用し、相場の変動範囲を予測する指標です。価格が一定の範囲内で推移しているか、急変動しているかを判断するのに役立ちます。

これはまるで『エヴァンゲリオン』のA.T.フィールドのようなものです。エヴァの機体を守るバリアのように、価格の上限・下限が設定されます。もし価格がボリンジャーバンドの上限を超えたら、それは「買われすぎ」、逆に下限を割ったら「売られすぎ」を示唆します。

市場の価格変動がボリンジャーバンドの範囲内に収まっているかどうかを確認することで、エントリーやエグジットのタイミングを見極めるのに有効です。

import pandas as pd
import sqlite3

# データベースへの接続
conn = sqlite3.connect('stock_data.db')

# データの取得
query = "SELECT * FROM stock_price"
df = pd.read_sql_query(query, conn)

# 日付をdatetime型に変換
df['date'] = pd.to_datetime(df['date'])

# 銘柄ごとに処理
tickers = df['ticker'].unique()
df_ma = pd.DataFrame()

for ticker in tickers:
    df_temp = df[df['ticker'] == ticker].copy()
    df_temp.set_index('date', inplace=True)

    # 移動平均の計算
    df_temp['ma_20'] = df_temp['close'].rolling(window=20).mean()
    
    # ボリンジャーバンドの計算
    df_temp['std_20'] = df_temp['close'].rolling(window=20).std()
    df_temp['upper_band'] = df_temp['ma_20'] + (df_temp['std_20'] * 2)
    df_temp['lower_band'] = df_temp['ma_20'] - (df_temp['std_20'] * 2)

    df_ma = df_ma.append(df_temp.reset_index())

# テーブルへ保存
df_ma.to_sql('stock_price_ma_bb', conn, if_exists='replace', index=False)

# 接続を閉じる
conn.close()

このスクリプトでは、20日間の移動平均と標準偏差を計算し、それを用いてボリンジャーバンド(上帯と下帯)を計算しています。ボリンジャーバンドの上帯は移動平均に2倍の標準偏差を加えたもの、下帯は移動平均から2倍の標準偏差を引いたものとなります。

RSI(相対力指数) – 『ドラゴンボール』のスカウター?

次にRSIも求めます。RSI(Relative Strength Index)は、一定期間の価格の上昇幅と下降幅を比較して、相場が「買われすぎ」か「売られすぎ」かを測る指標です。0〜100の数値で表され、一般的に70を超えると「買われすぎ」、30を下回ると「売られすぎ」と判断されます。

これはまさに『ドラゴンボール』のスカウターのようなもの。フリーザ軍が戦闘力を測るとき、スカウターが「戦闘力3万以上だと!」と爆発するように、RSIが70を超えると「市場は加熱しすぎている」と判断できます。

逆に、悟空がナメック星で回復カプセルに入った後、一気に戦闘力が上がるように、RSIが30を下回ったときは「そろそろ買い場かも?」というサインになります。市場の過熱感や売られすぎの状況を判断することで、適切なタイミングでの売買判断が可能となります。

import pandas as pd
import sqlite3

# データベースへの接続
conn = sqlite3.connect('stock_data.db')

# データの取得
query = "SELECT * FROM stock_price"
df = pd.read_sql_query(query, conn)

# 日付をdatetime型に変換
df['date'] = pd.to_datetime(df['date'])

# 銘柄ごとに処理
tickers = df['ticker'].unique()
df_ma = pd.DataFrame()

for ticker in tickers:
    df_temp = df[df['ticker'] == ticker].copy()
    df_temp.set_index('date', inplace=True)

    # 移動平均の計算
    df_temp['ma_20'] = df_temp['close'].rolling(window=20).mean()
    
    # ボリンジャーバンドの計算
    df_temp['std_20'] = df_temp['close'].rolling(window=20).std()
    df_temp['upper_band'] = df_temp['ma_20'] + (df_temp['std_20'] * 2)
    df_temp['lower_band'] = df_temp['ma_20'] - (df_temp['std_20'] * 2)

    # RSIの計算
    delta = df_temp['close'].diff()
    up, down = delta.copy(), delta.copy()
    up[up < 0] = 0
    down[down > 0] = 0

    average_gain = up.rolling(window=14).mean()
    average_loss = abs(down.rolling(window=14).mean())

    rs = average_gain / average_loss
    df_temp['rsi'] = 100 - (100 / (1 + rs))

    df_ma = df_ma.append(df_temp.reset_index())

# テーブルへ保存
df_ma.to_sql('stock_price_ma_bb_rsi', conn, if_exists='replace', index=False)

# 接続を閉じる
conn.close()

このスクリプトでは、まず価格の変化量(delta)を計算し、それを利益(up)と損失(down)に分けます。次に、14日間の平均利益(average_gain)と平均損失(average_loss)を計算し、その比率(rs)を求めます。最後に、RSIの公式を用いてRSIを計算します。

なお、上記のコードではシンプルなRSIの計算方法を用いていますが、より正確なRSIを求めるためには平滑化されたRSI(SMMA: Smoothed Moving Averageを使用)を計算する方法もあります。

MACD – 『スター・ウォーズ』のジェダイのフォース?

そのままMACDも求めます。MACD(Moving Average Convergence Divergence)は、短期(12日)と長期(26日)の移動平均を組み合わせ、トレンドの勢いを測る指標です。短期と長期の移動平均の差を取ることで、相場の勢いを把握できます。

これはまるで『スター・ウォーズ』におけるフォースの流れ。ルーク・スカイウォーカーが「フォースを感じろ」と言われたように、MACDは市場の流れ(トレンド)がどの方向に向かっているかを示します。

もし短期移動平均線(フォースの光側)が長期移動平均線(ダークサイド)を上回れば、上昇トレンドのサイン。逆に短期線が長期線を下回れば、下降トレンドのサインとなります。

ジェダイがフォースを使って未来を予測するように、MACDを活用することで、今後の株価の動きを推測する手がかりを得ることができます。市場のトレンドを見極めるうえで、MACDは非常に有効な指標となります。

import pandas as pd
import sqlite3

# データベースへの接続
conn = sqlite3.connect('stock_data.db')

# データの取得
query = "SELECT * FROM stock_price"
df = pd.read_sql_query(query, conn)

# 日付をdatetime型に変換
df['date'] = pd.to_datetime(df['date'])

# 銘柄ごとに処理
tickers = df['ticker'].unique()
df_ma = pd.DataFrame()

for ticker in tickers:
    df_temp = df[df['ticker'] == ticker].copy()
    df_temp.set_index('date', inplace=True)

    # 移動平均の計算
    df_temp['ma_20'] = df_temp['close'].rolling(window=20).mean()
    
    # ボリンジャーバンドの計算
    df_temp['std_20'] = df_temp['close'].rolling(window=20).std()
    df_temp['upper_band'] = df_temp['ma_20'] + (df_temp['std_20'] * 2)
    df_temp['lower_band'] = df_temp['ma_20'] - (df_temp['std_20'] * 2)

    # RSIの計算
    delta = df_temp['close'].diff()
    up, down = delta.copy(), delta.copy()
    up[up < 0] = 0
    down[down > 0] = 0

    average_gain = up.rolling(window=14).mean()
    average_loss = abs(down.rolling(window=14).mean())

    rs = average_gain / average_loss
    df_temp['rsi'] = 100 - (100 / (1 + rs))

    # MACDの計算
    exp12 = df_temp['close'].ewm(span=12, adjust=False).mean()
    exp26 = df_temp['close'].ewm(span=26, adjust=False).mean()
    df_temp['macd'] = exp12 - exp26
    df_temp['signal'] = df_temp['macd'].ewm(span=9, adjust=False).mean()
    df_temp['histogram'] = df_temp['macd'] - df_temp['signal']

    df_ma = df_ma.append(df_temp.reset_index())

# テーブルへ保存
df_ma.to_sql('stock_price_ma_bb_rsi_macd', conn, if_exists='replace', index=False)

# 接続を閉じる
conn.close()

このスクリプトでは、まず12日と26日のEMA(exp12exp26)を計算し、その差(macd)を求めます。次に、macdの9日EMA(signal)を計算します。最後に、macdsignalの差(histogram)を求めます。これがMACDのヒストグラムになります。

まとめ

テクニカル分析の代表的な4種の指標を取り出しました。
移動平均線 → 湘北高校の成長曲線
ボリンジャーバンド → エヴァのA.T.フィールド
RSI → ドラゴンボールのスカウター
MACD → スター・ウォーズのフォース
分析のためのデータを収集した後は、これらを組み合わせて戦略を立て、トレンド分析を行うことになります。本記事では指標の収集までの実装を行いました。

バーマン
プロダクトマネージャー
ソフトウェア開発に長く従事しています。
・機械学習のサンプルコード作成
・生成型AIから調べたことのまとめ
・これまでのビジネスで経験したことのまとめ
を記事として作成させていただいています。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次