【自由研究】重回帰分析を用いて日経平均株価を予測する

日経平均株価を重回帰分析を用いて予測したいと思います。
###---構築環境---
・Mac Book Air 2018
・Python3.7

###---参考資料---
・NumPy】移動平均線と重回帰分析で株価予測
（https://algorithm.joho.info/programming/python/numpy-moving-average-regression-multiple/）
・scikit-learn で線形回帰 (単回帰分析・重回帰分析)
(https://pythondatascience.plavox.info/scikit-learn/線形回帰)

###---概要---
日経平均株価2014,2015を使用して2016を予測します。
説明変数として長短異なる４本の移動平均線を使用します。
どの移動平均線（単純移動平均線）が最適か調べるために、
以下の幅で全パターンで重回帰分析を実施します。
目的変数は、調整後終値です。


短期間移動平均線
1営業日〜５営業日
中期間移動平均線
２０営業日〜２５営業日
長期間移動平均線
４５営業日〜５５営業日
超長期間移動平均線
７５営業日〜百営業日

この期間設定は任意ですが、PCのスペックと処理時間に依存しますね。

###---ソースコード---

```python
import numpy as np
import pandas as pd
from sklearn import linear_model
import requests

def SMA(signal):
    k=0;SMA=[]
    for rp in range(signal):
        SMA.append(0)
    while True:
        sma=[]
        for r in range(signal):
            s=df.loc[k+r,4]
            sma.append(s)
        sma5=sum(sma)/len(sma)
        k+=1
        if k==len(df)-(signal-1):
            break
        SMA.append(sma5)
    return SMA

def Integer_checker(number):
    number=int(number)
    if number<=9:
        number='0'+str(number)
    else:
        number=str(number)
    return number

number=[]
correct=[];wrong=[]
ll=75
while True:
    l=45
    while True:
        m=20
        while True:
            s=1
            while True:
                df=pd.DataFrame();k=14
                while True:
                    ds=pd.read_csv('..//data//nikkei'+str(k)+'.csv',header=None,skiprows=1)
                    df=df.append(ds)
                    k+=1
                    if k==16:
                        break
                df=df.reset_index(drop=True)
                df['SMA_short']=SMA(s);df['SMA_middle']=SMA(m)
                df['SMA_long']=SMA(l);df['SMA_super_long']=SMA(ll)
                df=df.replace(0, np.nan);df=df.dropna(how='any')
                df=df.reset_index(drop=True)
                
                clf=linear_model.LinearRegression()
                x=df.drop([0,1,2,3,4,5], axis=1)
                X=x.as_matrix()
                Y=df[4].as_matrix()
                clf.fit(X, Y)
                
                Frame=pd.DataFrame({"Name":x.columns,
                   "Coefficients":np.abs(clf.coef_)}).sort_values(by='Coefficients')
                intercept=clf.intercept_
                
                df=pd.read_csv('..//data//nikkei16.csv',header=None,skiprows=1,usecols=[4])
                df['SMA_short']=SMA(s);df['SMA_middle']=SMA(m)
                df['SMA_long']=SMA(l);df['SMA_super_long']=SMA(ll)
                df=df.replace(0, np.nan);df=df.dropna(how='any')
                df=df.reset_index(drop=True)
                df['Model']=df['SMA_super_long']*Frame.loc[3,'Coefficients']+ \
                            df['SMA_long']*Frame.loc[2,'Coefficients']+ \
                            df['SMA_middle']*Frame.loc[1,'Coefficients']+ \
                            df['SMA_short']*Frame.loc[0,'Coefficients']+intercept
                #print(df)
                #df.to_csv('..//data//model.csv',header=False,index=False)
                df=df[[4,'Model']]
                df=df.rename(columns={4: 0,'Model':5})
                #print(df)
                
                k=0
                while True:
                    if df.loc[k+1,0]>df.loc[k,0]:
                        df.loc[k+1,1]='+'
                    elif df.loc[k+1,0]<df.loc[k,0]:
                        df.loc[k+1,1]='-'
                    k+=1
                    if len(df)-1<=k:
                        break
                k=0
                while True:
                    if df.loc[k+1,5]>df.loc[k,5]:
                        df.loc[k+1,2]='+'
                    elif df.loc[k+1,5]<df.loc[k,5]:
                        df.loc[k+1,2]='-'
                    k+=1
                    if len(df)-1<=k:
                        break
                
                k=1
                while True:
                    if df.loc[k,1]==df.loc[k,2]:
                        df.loc[k,3]='='
                    else:
                        df.loc[k,3]='≠'
                    k+=1
                    if len(df)<=k:
                        break
                df=df.dropna(how='any')
                df=df.reset_index(drop=True)
                
                plus=[];k=0
                while True:
                    if df.loc[k,3]=='=':
                        plus.append(df.loc[k,3])
                    k+=1
                    if len(df)<=k:
                        break
                ans1=(len(plus)/len(df))*100
                correct.append(ans1)
                ans2=((len(df)-len(plus))/len(df))*100
                wrong.append(ans2)
                
                numb=Integer_checker(ll)+Integer_checker(l)+Integer_checker(m)+Integer_checker(s)
                number.append(numb)
                s+=1
                #print(s)
                if s==6:#1~5
                    break
            m+=1
            #print('処理中...',s,m,l,ll)
            if m==26:#20~26
                break
        l+=1
        
        if l==55:#45~55
            break
    ll+=1
    if ll==100:#75~100
        break

#print(df)    
#print(Frame,intercept)
dy.to_csv('..//data//result_of_analytics.csv',header=False,index=False)
print(dy)
```


###---概説---
各移動平均線を一つずつ定めて所定のループ回数で全パターン調べています。
日経平均の2014年と2015年を学習に使用し、2016年を検証に使用します。
重回帰分析によって、求められた2016年の予測値と実値の各営業日ごとの増減を調べ、
増減が同方向に動いたときを正答率を算出します。
正答率を下記に記します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407666/87de13d4-5b17-22b3-f373-31b6c3a0d2fc.png)

各移動平均線のパラメーターの設定し、正答率は48~56%でした。
あまりいい結果になりませんでしたね。

改善点としては、
・重回帰分析ではなく機械学習や深層学習に置き換える。
・移動平均線の期間・種類を変える。
ですかね？