x2004-成果物:株価の時系列予測


はじめに

 2023年12月中旬から、Aidemy Premiumにて「データ分析コース6ヶ月」を受講しました。その上で、成果物課題として「株価の時系列予測」をテーマとした課題の作成を行いました。
 Aidemy Premiumの受講を決めたのは、前職で売上管理などをした際に「管理だけでなく分析を行えれば、より質の高い管理・業務改善が出来るのではないか」と思いRを独学で勉強しましたが独学の壁が高く挫折してしまった経験から、Aidemy Premiumを活用して「データ分析」の基礎を身に付けたいと思った事がキッカケです。
 今回の成果物課題を通じて感じたことは、Pythonの奥深さと思い描いたように扱う事の難しさ、合わせてPythonで分析したものをこのような形で整理・発信していく事の面白さでした。
 未熟な点も散見されると思いますが、一読いただけますと幸いです。

1.目的

ⅰ)時系列予測を用いて、株価の予測値と実測値の乖離について分析を行う事
ⅱ)乖離があった場合、乖離の理由/根拠について考察を行う事
ⅲ)乖離の理由/根拠について考察に対し、今後の課題(対策)を考える事

2.用いた手法、予測に使用した銘柄の紹介

1)手法の紹介

・GoogleColaboratoryにてPython3を使用
・時系列予測を用いて、終値ベースで一定期間の株価を予測し、同じ期間の 
 実測値と比較をした。その上で、予測値と実測値の乖離がどの程度あるか
 を検証し、検証結果に対して考察を行った。

2)銘柄の紹介

・カバー株式会社【5253】
・Vtuber事務所『ホロライブプロダクション』を運営。
 動画配信やライブイベント、グッズ販売、ライセンスなどによる収益が
 メインの会社。

3.コードの解説

1)株価データを取得するためのプログラム作成

「株価の時系列予測」を行うために、「yahoofinance」から株価データを引用するためのコードを入力。これを土台として、今後のコードを組み立てていく。

#1)株価データを取得するためのプログラム作成

!pip install mplfinance japanize-matplotlib

2)ローソク足チャートの設定

時系列予測をグラフとして可視化した上で予測値と実測値の乖離について調べたいので、ここではグラフを出力・設定をするためのコードを作成した。
まずはyahoofinanceを引用するためのコードを作成し、次にグラフを表示した際の設定についてコードを作成した。

#2)ローソク足チャートの出力・設定
# yfinanceの導入(株データ取得のプログラム)
import yfinance as yf
from datetime import datetime
df = yf.download("5253.T").dropna()

import mplfinance as mpf
import japanize_matplotlib

import pandas as pd
import itertools

# グラフの設定(銘柄名の表示,ローソク足チャートを設定)
symbols=5253
name="カバー"

mpf.plot(df, title=name+"_日足チャート", type="candle", mav=(25, 50, 75), datetime_format="%Y/%m/%d", tight_layout=False, volume=True, figratio=(19,9),  savefig=str(symbols)+"_daily.png")

3)移動平均線の計算、チャートグラフの出力

前節でグラフを出力・設定するためのコードを作成したので、この節ではチャートグラフで価格の推移の指標として使用する「移動平均線の計算」と、実際にチャートグラフをグラフを出力するコードを作成した。
ここまでが、時系列予測を行うための事前準備となり、次の4節ではこの出力したデータをもとに、時系列予測を行う。

#3)移動平均線の計算、チャートグラフの出力
# 対象期間は、2023/10/2∼2024/2/14
# 移動平均線の計算
df["SMA25"] = df["Close"].rolling(window=25).mean()
df["SMA50"] = df["Close"].rolling(window=50).mean()
df["SMA75"] = df["Close"].rolling(window=75).mean()

# チャートグラフの出力
import matplotlib
%matplotlib inline

# チャートグラフの表示設定
df_start = df.loc[datetime(2023,10,2).strftime("%Y-%m-%d"):]

mpf.plot(df_start, title=name+"_日足チャート", type="candle", mav=(25, 50, 75), datetime_format="%Y/%m/%d", tight_layout=False, volume=True, figratio=(19,9), style="yahoo")
mpf.plot(df_start, title=name+"_日足チャート", type="candle", mav=(25, 50, 75), datetime_format="%Y/%m/%d", tight_layout=False, volume=True, figratio=(19,9), style="yahoo")

add_day_ave = [
                  mpf.make_addplot(df_start["SMA25"], panel=0, color="b", width=1, alpha=0.7),
                  mpf.make_addplot(df_start["SMA50"], panel=0, color="g", width=1, alpha=0.7),
                  mpf.make_addplot(df_start["SMA75"], panel=0, color="r", width=1, alpha=0.7)
               ]
mpf.plot(df_start, type='candle',datetime_format='%m/%d',xrotation=360, tight_layout=False, volume=True, figratio=(19,9),  style='yahoo')
mpf.plot(df_start, type='candle',datetime_format='%m/%d',xrotation=360, tight_layout=False, volume=True, figratio=(19,9),  style='yahoo')

df.loc[datetime(2023,10,2).strftime("%Y-%m-%d"):]


3)の工程で出力したチャートグラフ(2/16まで)
3)の工程で出力した株価、出来高、移動平均線の値一覧(2/16まで)

4)時系列予測

この節では、実際に時系列予測を行った。今回については、自分の時系列予測に対する理解が浅い事を理由として、時系列予測を6段階に分けて、整理した。

4-1: 時系列予測を設定
予測のためのコードを入力、実際に予測をする範囲を設定した。
(予測範囲は、2024/2/1~2/14で設定)

#4-1:時系列予測を設定
# 時系列予測のコード
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from pandas import datetime

# 予測範囲を設定(日付はISO formatで指定)
pred_index = pd.date_range("2024-02-01", "2024-02-14")

4-2: 予測範囲を出力
前段階を踏まえて、予測範囲の出力した。
時系列で予測する営業日は10日で設定(休日/祝日は市場が動かないため)。

4-2:予測範囲を出力(予測する営業日は10日で設定)
df.tail(10)
4-2) 株価一覧(2/14まで)

4-3: 終値でdfを作成
終値を基準として、dataframeを作成。
基準を終値とした理由は、移動平均線が終値をベースとした指標であるため、移動平均線に沿った形で比較・検討がしやすい終値を基準とした。

#4-3:終値でdfを作成
df['Close'].index

4-4: 1/31までの終値を整理
2024/2/1~2/14を予測するための準備として、2024/1/31までのデータを整理するコードを作成した。休日/祝日については、市場が動かないことを考慮して市場が動いた最終日と同じ価格が表示されるように設定した。

#4-4:1/31までの終値を整理
# 終値で1/31まで出力
stock_price_close = df['Close'].loc[:"2024-01-31"].copy().asfreq('D')
stock_price_close.tail(15)

# 休日,祝日などの取引が行われなかった日は前日の終値を表示(価格が動いていないと考える)
stock_price_close = stock_price_close.ffill()
stock_price_close.tail(15)


4-4) 1/31までの終値の整理一覧

4-5: SARIMAモデル導入の前段階
ここは、Aidemyの時系列予測の添削課題のコードを流用した。
周期パラメータについては、添削課題と異なったため7日(1週間)で設定。

#4-5:SARIMAモデル導入の前段階
# orderの最適化関数(添削課題のコードを流用,アレンジ)
def selectparameter(DATA, s):
    p = d = q = range(0, 2)
    pdq = list(itertools.product(p, d, q))
    seasonal_pdq = [(x[0], x[1], x[2], s) for x in list(itertools.product(p, d, q))]
    parameters = []
    BICs = np.array([])
    for param in pdq:
        for param_seasonal in seasonal_pdq:
            try:
                mod = sm.tsa.statespace.SARIMAX(DATA,
                                                order=param,
                                                seasonal_order=param_seasonal)
                results = mod.fit()
                parameters.append([param, param_seasonal, results.bic])
                BICs = np.append(BICs, results.bic)
            except:
                continue
    return parameters[np.argmin(BICs)]

# 周期パラメータは取引所の営業日を考慮して7日に設定
best_params = selectparameter(stock_price_close, 7)

4-6: SARIMAモデルを導入,予測を実行, 実測値と予測値をグラフに反映
SARIMAモデルを使って予測を実行した。その上で、実測値(青線)と予測値(赤線)をグラフに反映し乖離について分析を行った。

#4-6:SARIMAモデルを導入,予測を実行, 実測値と予測値をグラフに反映
# SARIMAモデルを導入
SARIMA_yfinace_model = sm.tsa.statespace.SARIMAX(stock_price_close, order=best_params[0],
                                             seasonal_order=best_params[1],
                                             enforce_stationarity=False, enforce_invertibility=False).fit()
# 予測を実行
pred = SARIMA_yfinace_model.predict('2024-02-01', '2024-02-14')

# 実測値と予測値をグラフに反映
plt.plot(stock_price_close)
plt.plot(df['Close'].loc["2024-02-01":], "b")
plt.plot(pred, "r")
plt.show()


4-6) 予測値(赤線)と実測値(青線)のグラフ

4.予測結果

ⅰ)予測では、2/1以降の終値は上昇をする傾向にあると予想された。
 しかし、実測値は予測に反し、2/1以降の終値は徐々に下落していった。
 ⇒予測値と実測値が相反する動きを見せる形となった。

ⅱ)予測値と実測値が相反する要因については、次節で説明を行う。

5.予測結果に対する考察

予測結果と実測値が相反する動きになったことに対して、以下の要因が関係されるのではないかと考察する。

1)2/9の第3四半期決算に対する、投資家の「予測」のベクトルと「実績」への反応による影響があったのではないか

 ⅰ)決算前の投資家の「予測」ベクトルに対する考察
 ・第3四半期決算前の「予測」は2通り考えられた
  a.第3四半期の目安 : 75%を超える場合…決算前の価格より上昇が期待
    #→株価の動きとしては、大きな下落を伴う価格変動は取りにくい
       b.第3四半期の目安 : 75%を下回る場合…決算前の価格より下落が予想
   #→株価の動きとしては、大きな上昇を伴う価格変動は取りにくい
 ・2月に入ってからの価格変動は、下落が続いていた
  →この動きから「実績は目安より悪い」と予測した人が多かったのでは
   ないかと予想ができる(株価の動きなどでは実証が出来ない事が問題)

 ⅱ)第3四半期決算の「実績」への対応
 ・第3四半期決算の「実績」:計画に対する経常利益の進捗率 : 約67%
     ⇒第3四半期の目安 : 75%を低い水準のため「失望売り」が多くなった。
   それに伴い、株価は大きな下落をした。
 ・「失望売り」を踏まえた、投資家の取れる戦略
  a.期末決算の目安である経常利益の進捗率 : 100%超を想定する場合…
   →「失望売り」による下落を継続し、下落が落ち着くのを待つ。
     その上で安い時に多くの株を購入し期末決算後に売る準備を行う。
  b.期末決算の目安である経常利益の進捗率 : 100%を下回る想定の場合…
   →「失望売り」による下落を継続。
    来期見通しが良い場合は購入を検討し、悪い場合は損切りを行う。
       ※2/15現在は、a.とb.どちらにも対応が出来る形で価格が動いている。
   (「a.とb.どちらの動きを考えている人が多いか」は分からず)

2)参加している投資家の特徴/投資スパン/投資基準による違い

ⅰ)個人投資家/機関投資家の特徴/戦略の違い
   市場に参加する投資家は、2つのタイプに大別できる
  ①個人投資家…個人の資産を使って、投資を行う投資家。
         (機関投資家と比べて)使える資産が少ない事、
         それに伴い株の保有数や1回あたりの取引で得られる
         利益が少なく、取れる戦略も限られている事が特徴。
  ②機関投資家…銀行や証券会社に勤めていて、投資を行う投資家。
         (機関投資家と比べて)資産が多い事、保有できる株の数
         も個人投資家より多く、1回あたりの取引で得られる
         利益も多く、多彩な戦略が取れる事が特徴。
  ③取れる戦略の違い
  ・個人投資家…資産が少なく保有数に比例した株価への影響力が小さい
  ・機関投資家…資産が多く保有数に比例した株価への影響は小さくない
  →保有数と保有スパン、得られる収益に大きな差が生じやすい。
   「投資の目的/利益確定の目標値」も違う場合が多く、株価に影響が
   及ぶ場合がある。
ⅱ)投資基準の違い
 個人投資家も機関投資家共に「収益を上げる」という目的は一致するが、
 銘柄選びの基準については、各個人/企業によって異なる。
 以下は代表的な例となる)
  ・ファンダメンタル(経常利益などの見込み)が良い
  ・テクニカル指標(統計学に基づいた指標)での売買タイミングである
  ・個人的に応援している会社
  ・配当金や株主優待を主目的として投資をするetc

3)日経平均や外国銘柄などの影響を考慮して予測する事が難しい

ⅰ)日経平均や外国銘柄などの影響について
・日経平均の上昇に伴い、日本銘柄が上昇しやすい地場になることはある。
・外国銘柄の上昇に伴い、関連する日本銘柄も上昇する事がある
  例)2024年の1~2月:半導体銘柄、2020年前半:医療・製薬関連など

ⅱ)日経平均や外国銘柄などへの、機関投資家/個人投資家の共通する考え方
・機関投資家/個人投資家には2つの共通する考え方がある
 ①共通する考えとして「より収益性の高い銘柄」に投資を行う傾向がある
  (これは「収益性」を重視する投資家が取る傾向が強い動きである)
 ②機関投資家/個人投資家共に、程度の差はあれ使える資産に限界がある
  =より効率的/効果的に「収益を上げる」戦略をとるケースが散見される
   例)外国銘柄が収益を上げ易い場合→日本銘柄を売り、外国銘柄を買う
     結果:日本銘柄の株価は下がり、外国銘柄の株価は上がる

ⅲ)買いすぎ/売られ過ぎの判断が行われる問題
・機関投資家/個人投資家問わず、原則として「買った銘柄を売る」といった
 利益を確定する判断(行動)をしないと資産は増えない。
・そのため、一定の価格(価格帯)を超えたら、利益確定の動きが取られる。
 ただし、機関投資家/個人投資家の利益確定の基準が異なる場合も多く、
 これにより株価の動き(時系列の動き)が歪なものになる場合がある。

4)事業のイベント/トラブル等による影響を考慮する事が難しい

ⅰ)イベントの発表、それに伴う売上などへの影響を考慮すること
・カバー株式会社を例に考えた場合、この会社はエンターテインメントを事
 業とする会社であるため、所属アイドルなどがテレビや雑誌等で紹介され 
 る、季節性のあるイベント等に参加することにより知名度がアップする事
 で、結果として売上上昇が考慮できる場合が少なからずある。
・この場合、市場参加者がイベント参加をどの程度ポジティブ/ネガティブに
 捉えたら株価に影響があるのかは、実際にイベントが実施されないと分か
 らない事が多いため、こういった事象を予測するには、時系列予測のよう
 な取り組み方ではなく機械学習(回帰)のようなアプローチが必要であり、
 且つ緻密にデータ収集を行う必要が出てくる。
・これらを短期で行う、ないしは個人レベルで行う事は、ハードルが高い。

ⅱ)所属タレントの退所等のトラブルに伴う売上への影響を考慮すること
・例としては、2024年1月にカバー株式会社に所属するアイドル1期生が、機 
 密情報の漏洩により2月末にYoutubeチャンネルとメンバーシップの解除が
 発表された。
・このようなトラブルがどの上場会社でも発生するものだが、発生したトラ
 ブルに対して、市場参加者の中でポジティブ/ネガティブに考えた割合は
 どちらが多いか、トラブルの影響を考えた上でどのような戦略を取るのが
 効果的と考えるかは、株価や出来高だけでは正確に予測が難しい
 (=実証が出来ないため、個人の考えの域を出ない)。

5)上記の考察に対し、客観的に考察する指標の作成が困難である     

 上記の考察については、客観的な指標とするための「数値化」「データ化」を図ることが難しい内容になる。このため、時系列予測だけでは実測値に近い値で株価予測を行うのは、株価予測に対して予測案の1つとしては機能するが、「株取引をして収益を得る」ことを目的として時系列予測を用いるのは「有用性がある」とは言い難い面がある。
 #また、仮に上記の考察が出来たとして、個人が株取引をする上で予測の「有用性」と「費用対効果」を考えた場合、恐らく実用性のある予測モデルが完成するまでに時間がかかる事、株価がアップダウンを繰り返すものである事を考慮すると、個人が1つの銘柄に対して実用性のある予測モデルを作成し取引で収益を上げ続けるには「費用対効果」の面で効果が薄いように感じる。

6.今後の課題

ⅰ)時系列予測+αで予測精度を上げていく
・時系列予測だけでは予測精度が出ないことが分かったので、次回は機械学
 習(回帰)などの他の要素を加えて予測精度を上げていく必要がある。

ⅱ)「”市場参加者の思惑”の指標化」について検討をする。
・銘柄に対して投資を行っている参加者が、「どの出来事に対して、どのよ
 うに反応をするか」をデータ化していけば、恐らく予測精度は上がる。
・今回の銘柄では、エンターテインメントを事業とする会社ということもあ 
 り、良いイベント関連のニュース等をキッカケとして市場の注目を集め、 
 決算成績の見通し・結果を踏まえて株価の変動が起こる傾向が見られるの
 ではないかと考えている。
・このため、この銘柄(ないしは似た銘柄)に限定する形になってしまうが、
   ①発生したニュースとそれに伴う株価のアップダウンを記録すること
   ②記録をもとに相関性などの関連を調べること
   ③上記の活動を長期に渡り継続し、分析が出来る状態にすること
 以上を行うことで、実測値との乖離が少ない予測に近づくのではないか。
 




この記事が気に入ったらサポートをしてみませんか?