Logistic回帰を用いた株価が上昇するか下降するかの推定

Logistic回帰は推定結果が0になるか1になるかを推定するのに利用されるので、今回は2022年10月21日のデータをつかって翌日22日の株価が上がるか、下がるかを推定してみる。

ライブラリのインポート

In [1]:
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)

データの読み込み

株価データを読み込みます。

In [2]:
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()
Out[2]:
証券コード 時価総額 売買単位 信用残-買 信用残-売 前週比-買 前週比-売 PER PER変化率-1年前 PER変化率-3年前 … 業種_輸送用機器 業種_通信業 業種_金属製品 業種_鉄鋼 業種_鉱業 業種_陸運業 業種_電気機器 業種_電気・ガス業 業種_非鉄金属 業種_食料品
80 1301 32894000000 100 12300.0 4400.0 200.0 -3700.0 8.43 -1.47 -19.83 … 0 0 0 0 0 0 0 0 0 0
99 1352 7759000000 100 13800.0 200.0 0.0 -100.0 9.71 -8.23 -52.80 … 0 0 0 0 0 0 0 0 0 0
109 1376 17412000000 100 5100.0 300.0 -500.0 300.0 12.02 0.20 -2.71 … 0 0 0 0 0 0 0 0 0 0
110 1377 162382000000 100 55000.0 90900.0 -700.0 -1100.0 20.00 -7.81 -7.46 … 0 0 0 0 0 0 0 0 0 0
111 1379 64750000000 100 43000.0 42700.0 1200.0 -500.0 15.07 -7.00 -21.55 … 0 0 0 0 0 0 0 0 0 0

5 rows × 121 columns

In [3]:
data_preprocessed.describe(include='all')
Out[3]:
証券コード 時価総額 売買単位 信用残-買 信用残-売 前週比-買 前週比-売 PER PER変化率-1年前 PER変化率-3年前 … 業種_輸送用機器 業種_通信業 業種_金属製品 業種_鉄鋼 業種_鉱業 業種_陸運業 業種_電気機器 業種_電気・ガス業 業種_非鉄金属 業種_食料品
count 1523.000000 1.523000e+03 1523.0 1.523000e+03 1.523000e+03 1.523000e+03 1.523000e+03 1523.000000 1523.000000 1523.000000 … 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000 1523.000000
unique NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN … NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
top NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN … NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
freq NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN … NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
mean 5657.988181 1.629514e+11 100.0 2.561689e+05 5.850401e+04 3.235916e+03 -8.540775e+03 24.345069 4.008109 67.091169 … 0.019041 0.108339 0.029547 0.014445 0.001313 0.011819 0.073539 0.010506 0.008536 0.042022
std 2432.407552 6.641912e+11 0.0 5.774443e+05 2.730431e+05 7.093146e+04 5.002839e+05 36.290122 23.445367 309.449914 … 0.136715 0.310910 0.169389 0.119356 0.036226 0.108105 0.261105 0.101990 0.092024 0.200706
min 1301.000000 1.272000e+09 100.0 0.000000e+00 0.000000e+00 -9.422000e+05 -1.921990e+07 1.390000 -55.110000 -98.990000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
25% 3539.500000 1.216750e+10 100.0 2.800000e+04 2.000000e+02 -2.850000e+03 -9.500000e+02 10.565000 -8.730000 -17.035000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
50% 5903.000000 3.139600e+10 100.0 9.020000e+04 6.300000e+03 1.000000e+02 0.000000e+00 15.160000 -0.700000 17.190000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
75% 7714.000000 9.715450e+10 100.0 2.461000e+05 4.740000e+04 3.600000e+03 2.500000e+02 25.505000 10.090000 72.155000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
max 9997.000000 1.635572e+13 100.0 8.833600e+06 6.529200e+06 1.738600e+06 2.960900e+06 780.520000 187.860000 8919.010000 … 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000

11 rows × 121 columns

従属変数と独立変数の宣言

In [4]:
targets = data_preprocessed['株価上下']
inputs = data_preprocessed.drop(['株価上下'],axis=1)
In [5]:
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-週足-売', 'ノーマルストキャスティクス-買', 'ノーマルストキャスティクス-売','スローストキャスティクス-買', 'スローストキャスティクス-売']]

訓練データとテストデータの分割

In [6]:
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)

ロジスティック回帰

In [7]:
x = sm.add_constant(x_train.astype(float))
reg_log = sm.Logit(y_train,x)
results_log = reg_log.fit()
# 回帰のまとめ表
results_log.summary()
Optimization terminated successfully.
         Current function value: 0.645485
         Iterations 7
Out[7]:
Logit Regression Results
Dep. Variable: 株価上下 No. Observations: 1218
Model: Logit Df Residuals: 1160
Method: MLE Df Model: 57
Date: Thu, 28 Oct 2021 Pseudo R-squ.: 0.06724
Time: 04:06:53 Log-Likelihood: -786.20
converged: True LL-Null: -842.87
Covariance Type: nonrobust LLR p-value: 1.328e-05
coef std err z P>|z| [0.025 0.975]
証券コード 3.927e-05 2.61e-05 1.503 0.133 -1.19e-05 9.05e-05
時価総額 3.587e-13 2.53e-13 1.417 0.157 -1.38e-13 8.55e-13
売買単位 0.0035 0.007 0.505 0.614 -0.010 0.017
信用残-買 -2.821e-07 1.67e-07 -1.694 0.090 -6.09e-07 4.43e-08
信用残-売 8.409e-07 5.18e-07 1.622 0.105 -1.75e-07 1.86e-06
前週比-買 -5.125e-07 1.35e-06 -0.380 0.704 -3.16e-06 2.13e-06
前週比-売 -5.107e-07 1.38e-06 -0.370 0.711 -3.22e-06 2.2e-06
PER -7.196e-05 0.002 -0.032 0.975 -0.005 0.004
EPS 0.0009 0.001 1.307 0.191 -0.000 0.002
PBR 0.0999 0.062 1.623 0.105 -0.021 0.221
配当利回 0.0655 0.065 1.003 0.316 -0.062 0.194
ROE -0.0168 0.025 -0.670 0.503 -0.066 0.032
ROA 0.0126 0.034 0.372 0.710 -0.054 0.079
売上高 -5.179e-14 3.28e-13 -0.158 0.875 -6.95e-13 5.92e-13
売上高変化率-Y0Y 0.0011 0.006 0.196 0.845 -0.010 0.012
PSR -0.1478 0.076 -1.949 0.051 -0.296 0.001
売上高営業利益率 -0.0875 0.052 -1.692 0.091 -0.189 0.014
売上高経常利益率 0.1041 0.053 1.954 0.051 -0.000 0.209
売上債権回転率 0.0002 0.000 0.938 0.348 -0.000 0.001
経常利益 -4.35e-11 2.02e-11 -2.157 0.031 -8.3e-11 -3.98e-12
経常利益変化率-YoY 6.183e-05 0.000 0.272 0.785 -0.000 0.001
自己資本比率 -0.0054 0.008 -0.718 0.473 -0.020 0.009
前期最終損益 4.118e-11 2.63e-11 1.564 0.118 -1.04e-11 9.28e-11
有利子負債自己資本利率 -0.0016 0.001 -1.158 0.247 -0.004 0.001
EV/EBITDA倍率 0.0019 0.003 0.672 0.501 -0.004 0.008
流動比率 -0.0007 0.001 -0.696 0.487 -0.003 0.001
当座比率 0.0007 0.001 0.644 0.520 -0.001 0.003
PCFR 0.0084 0.011 0.745 0.457 -0.014 0.031
棚卸資産回転率 -0.0004 0.000 -1.731 0.083 -0.001 4.63e-05
信用残/売買高レシオ 0.0027 0.004 0.714 0.476 -0.005 0.010
株価 4.262e-07 3.58e-05 0.012 0.990 -6.97e-05 7.06e-05
年初来安値からの上昇率 -0.0002 0.003 -0.080 0.936 -0.006 0.005
年初来高値からの下落率 0.0102 0.008 1.277 0.202 -0.005 0.026
RSI -0.0160 0.010 -1.673 0.094 -0.035 0.003
サイコロジカルライン 0.0004 0.007 0.055 0.956 -0.014 0.014
ノーマルストキャスティクス -0.0211 0.008 -2.700 0.007 -0.036 -0.006
スローストキャスティクス 0.0244 0.008 2.930 0.003 0.008 0.041
ベータ(対TOPIX) -1.5302 0.977 -1.566 0.117 -3.445 0.385
ベータ(対日経平均) 2.4135 1.052 2.295 0.022 0.352 4.475
ベータ(対東証業種指数) -0.5878 0.489 -1.203 0.229 -1.546 0.370
ゴールデンクロス -0.0751 0.260 -0.289 0.772 -0.584 0.434
デッドクロス -1.0177 0.747 -1.361 0.173 -2.483 0.447
一目均衡雲抜け上 0.0550 0.171 0.322 0.748 -0.280 0.390
一目均衡雲抜け下 0.0142 0.175 0.081 0.935 -0.328 0.357
DMI-日足-買 0.0964 0.533 0.181 0.857 -0.948 1.141
DMI-日足-売 0.4955 0.265 1.873 0.061 -0.023 1.014
DMI-週足-買 0.7410 0.375 1.974 0.048 0.005 1.477
DMI-週足-売 0.4226 0.329 1.284 0.199 -0.222 1.068
RCI-買 -0.0450 0.340 -0.132 0.895 -0.711 0.621
RCI-売 0.3172 0.253 1.255 0.210 -0.178 0.813
MACD-日足-買 -1.1286 0.460 -2.455 0.014 -2.030 -0.228
MACD-日足-売 -0.2100 0.285 -0.736 0.462 -0.769 0.349
MACD-週足-買 -0.2217 0.389 -0.570 0.568 -0.984 0.540
MACD-週足-売 0.1757 0.241 0.728 0.467 -0.298 0.649
ノーマルストキャスティクス-買 -0.1480 0.270 -0.548 0.583 -0.677 0.381
ノーマルストキャスティクス-売 0.1974 0.287 0.687 0.492 -0.366 0.761
スローストキャスティクス-買 -0.0825 0.307 -0.268 0.788 -0.685 0.520
スローストキャスティクス-売 -0.0059 0.238 -0.025 0.980 -0.472 0.460

表の見方は以下のとおりです。

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の間の価が良い

混同行列

In [8]:
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
In [9]:
confusion_matrix(x,y_train,results_log)
Out[9]:
(array([[427., 211.],
        [273., 307.]]),
 0.6026272577996716)

モデルのテスト

In [10]:
X_test = sm.add_constant(x_test.astype(float))

訓練用の結果と比較するために、テスト用データに基づく混同行列と正確性を求めます

In [11]:
confusion_matrix(X_test, y_test, results_log)
Out[11]:
(array([[94., 54.],
        [71., 86.]]),
 0.5901639344262295)

テストデータによる結果が59.02%で、訓練用データによる結果が60.26%となりました。

約60%の確率で株価の上下がわかることは悪くないですが、一日のデータを使って算出しているので、このモデルが別の日に適用できるかはもうちょっと精査したほうが良さそうですね。

Follow me!