Logistic回帰を用いた株価が上昇するか下降するかの推定
Logistic回帰は推定結果が0になるか1になるかを推定するのに利用されるので、今回は2022年10月21日のデータをつかって翌日22日の株価が上がるか、下がるかを推定してみる。
ライブラリのインポート
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
from scipy import stats
stats.chisqprob = lambda chisq, df: stats.chi2.sf(chisq, df)
データの読み込み
株価データを読み込みます。
raw_data = pd.read_csv('technical_stock_20221021.csv')
#主市場や指数採用銘柄は関係なさそうなので除外
raw_data = raw_data.drop(['主市場','指数採用銘柄'],axis=1)
#株価の変動を計算します。
raw_data["株価変動"] = raw_data["翌日株価"] - raw_data["株価"]
raw_data.loc[raw_data["株価変動"] > 0 ,
"株価上下"] = 1
raw_data = raw_data.fillna({'株価上下': 0})
#翌日株価、株価変動は削除します。
raw_data = raw_data.drop(['翌日株価','株価変動'],axis=1)
#欠損値がある行は削除します
data = raw_data.dropna(axis=0)
#ダミー変数を作成します。
data_preprocessed = pd.get_dummies(data, drop_first=True)
data_preprocessed.head()
data_preprocessed.describe(include='all')
従属変数と独立変数の宣言
targets = data_preprocessed['株価上下']
inputs = data_preprocessed.drop(['株価上下'],axis=1)
inputs = inputs[['証券コード', '時価総額', '売買単位', '信用残-買', '信用残-売', '前週比-買', '前週比-売', 'PER', 'EPS', 'PBR','配当利回', 'ROE', 'ROA', '売上高', '売上高変化率-Y0Y', 'PSR','売上高営業利益率', '売上高経常利益率', '売上債権回転率', '経常利益', '経常利益変化率-YoY', '自己資本比率','前期最終損益', '有利子負債自己資本利率', 'EV/EBITDA倍率', '流動比率', '当座比率', 'PCFR','棚卸資産回転率', '信用残/売買高レシオ', '株価', '年初来安値からの上昇率', '年初来高値からの下落率','RSI', 'サイコロジカルライン', 'ノーマルストキャスティクス', 'スローストキャスティクス','ベータ(対TOPIX)', 'ベータ(対日経平均)', 'ベータ(対東証業種指数)', 'ゴールデンクロス', 'デッドクロス','一目均衡雲抜け上', '一目均衡雲抜け下', 'DMI-日足-買', 'DMI-日足-売', 'DMI-週足-買','DMI-週足-売', 'RCI-買', 'RCI-売', 'MACD-日足-買', 'MACD-日足-売','MACD-週足-買', 'MACD-週足-売', 'ノーマルストキャスティクス-買', 'ノーマルストキャスティクス-売','スローストキャスティクス-買', 'スローストキャスティクス-売']]
訓練データとテストデータの分割
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(inputs, targets, test_size=0.2, random_state=42)
ロジスティック回帰
x = sm.add_constant(x_train.astype(float))
reg_log = sm.Logit(y_train,x)
results_log = reg_log.fit()
# 回帰のまとめ表
results_log.summary()
表の見方は以下のとおりです。
Method: MLE
最尤推定法で有ることを示しています。最尤推定法は尤度関数の値が大きいほど、モデルが正確である確率が高いことを前提にモデル作成が行われます。尤度関数とは作成したモデルが実際の変数間の関係をどれくらい示す関数です。
Log-Likelihood: 対数尤度
基本的にマイナスになる。大きければ大きいほうが良い
LL-Null: 独立変数がない場合の対数尤度
モデルが説明力を持っているかを示す
LLR:対数尤度比
モデルが統計的にLL-Nullと異なるか。即ち意味がないモデルかどうかを確認するために使われる
LLR p-value: p値
今回の値ではp値が0.05よりも小さいの優位であることを示している。
Pseudo R-squ.: 疑似決定係数(McFadden’s決定係数)
0.2から0.4の間の価が良い
混同行列
def confusion_matrix(data,actual_values,model):
#Logitモデルを使って値を予測します
pred_values = model.predict(data)
# 階級を指定します
bins=np.array([0,0.5,1])
# ヒストグラムを作成します。ここで、値が0 と 0.5 の間であれば値は0とします
cm = np.histogram2d(actual_values, pred_values, bins=bins)[0]
# 正確性を計算します
accuracy = (cm[0,0]+cm[1,1])/cm.sum()
# 混同行列と正確性を返します
return cm, accuracy
confusion_matrix(x,y_train,results_log)
モデルのテスト
X_test = sm.add_constant(x_test.astype(float))
訓練用の結果と比較するために、テスト用データに基づく混同行列と正確性を求めます
confusion_matrix(X_test, y_test, results_log)
テストデータによる結果が59.02%で、訓練用データによる結果が60.26%となりました。
約60%の確率で株価の上下がわかることは悪くないですが、一日のデータを使って算出しているので、このモデルが別の日に適用できるかはもうちょっと精査したほうが良さそうですね。
ディスカッション
コメント一覧
まだ、コメントがありません