データ分析で株価

##　序論
株価の分析を自分の手でしてみたいな思って、本プロダクトを作りました。普通に株価のチャートとどのくらい似たものができるのか、世間一般の株価分析ツールがどうなっているのか気にしながら作っていきたいと思います。

#内容
###流れ
具体的にどのようなことをやっていくかというと、
１．データを収集する
　　・ライブラリ＝Pandas_datareade pandas

２．データを整形する
　　・sort、rest_index
　　・Columnsを再命名
３．基本統計量を出してみる
　　・describe()→（参考）
　　・変化率
　　・グラフ書いてみる
　　・終値の変化
　　・ボラティリティ

４。将来を予想してみる
　　・prophet
　　・グラフ　→見方、拡大方法
　　・グラフトレンド→これいらないな

という流れで作っていきます。

###（使用するライブラリ）
・mathplotlib→グラフを書く
・pandas,numpy→データ整形用
・pystan→分析用
・fbporphet→機械学習用
・pandas_datareader→株価取得用
・datetime→日付取得用
・cross_validation→検証用

最初にインポートしていきましょう。

```python:stock.py
import matplotlib.pyplot as plt
import pandas as pd 
import pystan
from fbprophet import Prophet
from pandas_datareader import data
from datetime import datetime 
```

##コードの詳細
ではコードの中身を書いていきます。
###①データを収集する


```python:stock.py
plt.style.use('fivethirtyeight')
start_date="2011-04-01"
today=datetime.today().strftime("%Y-%m-%d")
print(f'{start_date}から{today}までの株価を取得します')
ticker_symbol = "GOOG"#取得したい株価のコー土
```


まず最初にここで、株価を所得する期間、所得する株の種類を指定します。


```python:stock.py	
#データを所得する関数を定義
def getMyStock(stock=ticker_symbol,start=start_date,end=today):
  df=data.DataReader(stock,'stooq',start,end)
  # print(df)
  df.sort_index(inplace=True)#並べ替え
  df.reset_index(inplace=True)#インデックスリセット
  df2=df.rename(columns={'Date':'ds','Close':"y"})
  return df2
my_stock=getMyStock()
print(my_stock)
 ````

ここでデータを所得する一連の流れを、一気にやるために関数(getMystock)を定義します。どのような処理をするのかというと、
まず、（2行目）の

```
data.DataReader(stock,"stocq",start,end)
```
ここでは、dataと名前をつけたpandas_datareaderをつかって株価を所得します。
参考→[Pandas_datareader公式ドキュメント](https://pandas-datareader.readthedocs.io/en/latest/remote_data.html)、[Pandas_datareaderを使ってデータ所得を試してみる](https://dev.classmethod.jp/articles/pandas_datareader-python/)

それから（3-6行目）で所得したデータを整形します。

```
 df.sort_index(inplace=True)#並べ替え
  df.reset_index(inplace=True)#インデックスリセット
  df2=df.rename(columns={'Date':'ds','Close':"y"})
```

株価は所得してきた時点で降順になんでいるので、sort 関数を使って、株価を昇順に並び替えます。
それから、並べ替えた時にインデックスも一緒に変わってしまうのでreset_indexでインデックスをリセットして連番をつけます。
最後に、
関数を定義したので、関数を実行して実行結果を変数my_stockに代入します。print(my_stock)でどういうデータが入っているか確認します。

```python:stock.py
my_stock=getMyStock()
print(my_stock)
```
出力結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/0720b9f4-93aa-d224-554c-4c6616bb727f.png)

ここまでで、指定した株の指定の期間の株価を取ってくることができました！簡単だね！ライブラリって便利ですね！

###②統計量を出してみる
####基本統計量
では株価のデータも取得できたので基本統計量を出してみましょう。基本統計量とは、平均値中央値などを指します。

```
（データ）.describe()
```

で出すことができるので↓のコードで出してみましょう！

```python:stock.py
my_stock.describe() #基本統計量
```

出力結果↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/8dc58e92-1a58-dcae-0faa-693251c3821e.png)


####その他統計量、グラフ
　　・変化率
　　・グラフ書いてみる
　　・終値の変化
　　・ボラティリティ
について出してみましょう。

```python:stock.py
daily_rate_change=(my_stock["y"].pct_change(1))#一日あたりの変化率 pct_change ボラティリティ
print(daily_rate_change)
print(f"変化率の標準偏差stdは、\n{daily_rate_change.std()}")
```

pct_change()を使うこと、で一つ前のデータとの変化率をとることができます。

```
daily_rate_change=(my_stock["y"].pct_change(1))#
```

↑はmy_stockのｙ列(終値)の変化率を取って変数daily_rate_changeに代入しています。ちなみにdaily_rate_changeに入っているデータは株価の変動＝ボラティリティと呼ばれます。
それから、daily_rate_changeで標準偏差を求めています。
変な”ｆ"があるのは、ｆストリングスを使っているからです。[ｆストリングスについて](https://note.nkmk.me/python-f-strings/)

####グラフ①終値の変動
では、日経２２５とかでよく見る株価変動みたいなあれ、あれについて今回所得したデータでグラフ書いてみましょう。簡単です。一行でおわります。

```python:stock.py
#グラフ
my_stock["y"].plot()#終値の変化、

```

my.stockの列の名前がYの列をとりだして、それを描写しているコードになります。
my.stockのデータ型はPandasDataframeなので、データの取り出し方は[こちら](https://pythondatascience.plavox.info/pandas/%E8%A1%8C%E3%83%BB%E5%88%97%E3%81%AE%E6%8A%BD%E5%87%BA)を参考にして下さい。

ここまでで、
・株価の基本統計量
・終値の一日あたりの変化率＝株価のボラティリティ
・変化率の標準偏差＝株価の変動の大きさ
をだすことができました。

####グラフ②（ボラティリティの視覚化）
次に、株価のボラティリティ（終値の一日あたりの変化率）もせっかく出したで、株価がどれぐらい変化しているか視覚化してみましょう！
 
```python:stock.py
plt.figure(figsize=(18,8))
plt.plot(daily_rate_change.index,daily_rate_change,lw=2)
plt.title("volatility")
plt.xlabel(f"{ticker_symbol}_data",fontsize=16)
plt.ylabel("Daily_volatility")
plt.legend(loc="upper right",fontsize=16)
plt.show()
```


 

###③株価の未来を予測してみましょう！
 
株価の未来を予測するためには、機械学習を使います。
いま所得した株価のデータを機械学習モデルに学習させて、未来の株価を予測します。今回使用するのはFaceBook様が出しているProphetというモデルになります。
機械学習に詳しくなくても、このモデルを使えばある程度の予測はできるの初心者におすすめです。

```python:stock.py
model=Prophet()   #モデルを作る
model.fit(my_stock)   #モデルに学習させる
future = model.make_future_dataframe(periods=365,freq='d')#モデルに365日分のデータフレーム作らせて、、future変数に入れる
forecast = model.predict(future)#予想させる
```

まず１行目ではprophetというインスタンスを作成して、変数modelに入れます。は？？？？インスタンス？？？？となると思いますが、ここでは機械学習モデルを呼び出して、変数Modelに入れていると理解していれば大丈夫です。
２行目では、先程所得してきた株価（my_stock）をモデルに学習させています。
３行目では、これから予想する未来の株価を入れるためのデータフレーム（箱）を作ります。
最後に４行目では、学習したモデルが、さっき作成したデータフレーム（箱）分だけ、未来を予測し、その結果をforcastに代入しています。
 
では、予測した株価がどうなっているのかグラフを書いてみましょう。

```python:stock.py
model.plot(forecast)
model.plot(forecast)#モデル全体をPLOT
```
出力結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/44536ca2-afa4-b523-5df8-2c7c376ae1dc.png)

結果は上のようになります。
黒点が実測値，青線の実線が予測値，そして薄い青の塗りつぶしが80%信頼区間1を示します。
見にくい２０２１以降のものを拡大して見てみましょう。

```python:stock.py
plt.xlim(future.ds.iloc[-365-30], future.ds.iloc[-1])#位置区間を取り出してプロット
plt.xlabel('Date')
plt.ylabel('Average')
```
 plt.xlimでｘ軸の区間を指定しています。
plt.xlim（始点、終点）という書き方で、future.ds.iloc[-365-30]というのは予測したデータが入っているfutureのds列のうしろから[-365－30（=-395）]日分のデータをとってきてという意味になります。

出力結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/6f8a5d66-54b9-dc13-9da9-5837c8e154a5.png)
１期間だけ指定して、グラフを書くことができましたね！
####トレンドについて（ちょい難）
ここから少し専門的な内容に入りますが、株価がどのような周期で動いているのか調べるために、トレンド分析をしてみましょう！
Prophetのモデルには、自前でトレンド分析をしてくれるツールがあるので超うれしいです。
トレンド（周期性）というのは、アイス業界の季節トレンドが一番わかり易いです。寒い時期（１０月から５月）は売上が下がって、暑い時期（６－９月）で売上が上がりますよね。株にもいろいろな業界があるので、株価のトレンド（周期）があります。
それでは調べてみましょう。

```python:stock.py
model.plot_components(forecast)#トレンド分析、周期性
```
出力結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/ae1d2a21-0cb1-41a3-9116-198f2b1c977d.png)

このような結果になります。
一番上の図が株価全期で見たトレンド、今回の場合だと２０２０年以降株価が上がり続けているトレンドがありますね。
二番目の図は、週のトレンドです。今回の場合は平日（MONDAYーFriday）の株価が下がり、週末は上がっているトレンドです。
三番目の図は月のトレンドです。どのように解釈できますか？８月が株上昇のピークで１０月に下落が来るトレンドになります。

 
####検証
最後にこの推計がどのぐらい合ってるか、検証値を出していきましょう。cross_validationを使うことで図ることができます。
 
 ```python:stock.py
from fbprophet.diagnostics import cross_validation
df_cv = cross_validation(model, initial='730 days', period='180 days', horizon = '365 days')
df_cv
```

検証に使うライブラリをまず最初にインポートします。
それからcroos_valiationを用いて予測値がどれぐらい、実際の値とずれる可能性があるか、上限と下限を出します。
initialは訓練期間の初期値、horizonは予測する期間を表します。そしてperiodで指定した日数分ずつ、学習期間が延ばすことをデータがなくなるまで繰り返すといおう意味です。
出力結果は次のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1895390/d95869b2-1475-a080-c939-22dec3af96cd.png)

yは実際の値、yhatは予測値、yhat_upperは予測上限、yhat_lowerは予測下限です。予測の誤差がわかるようになります！

以上で推計は終わりになります！

#コード全体

<details><summary>コード全文になります。</summary>
<div>

```python:stock.py
import matplotlib.pyplot as plt
import pandas as pd 
import pystan
from fbprophet import Prophet
from pandas_datareader import data
from datetime import datetime 

#基本情報　ここで入力を変える
plt.style.use('fivethirtyeight')
start_date="2011-04-01"
#end="2021-09-30" って終わる日を指定してもいいけど
today=datetime.today().strftime("%Y-%m-%d")
print(f'{start_date}から{today}までの株価を取得します')
ticker_symbol = "GOOG"#取得したい株価のコー土

#データを所得する関数を定義
def getMyStock(stock=ticker_symbol,start=start_date,end=today):
  df=data.DataReader(stock,'stooq',start,end)
  # print(df)
  df.sort_index(inplace=True)#並べ替え
  df.reset_index(inplace=True)#インデックスリセット
  df2=df.rename(columns={'Date':'ds','Close':"y"})
  return df2

my_stock=getMyStock()
print(my_stock)

my_stock.describe() #基本統計量

daily_rate_change=(my_stock["y"].pct_change(1))#一日あたりの変化率 pct_change ボラティリティ
print(daily_rate_change)
print(f"変化率の標準偏差stdは、\n{daily_rate_change.std()}")

#グラフ
my_stock["y"].plot()#終値の変化、PANDASの行の取り出し方

#ボラリティの視覚化
plt.figure(figsize=(18,8))
plt.plot(daily_rate_change.index,daily_rate_change,lw=2)
plt.title("volatility")
plt.xlabel(f"{ticker_symbol}_data",fontsize=16)
plt.ylabel("Daily_volatility")
plt.legend(loc="upper right",fontsize=16)
plt.show()

#未来の株価を予想してみる

model=Prophet()   #モデルを作る
model.fit(my_stock)   #モデルに学習させる
future = model.make_future_dataframe(periods=365,freq='d')#モデルに365日分のデータフレーム作らせて、、future変数に入れる
forecast = model.predict(future)#予想させる

model.plot(forecast)
model.plot(forecast)#モデル全体をPLOT
plt.xlim(future.ds.iloc[-365-30], future.ds.iloc[-1])#位置区間を取り出してプロット
plt.xlabel('Date')
plt.ylabel('Average')

model.plot_components(forecast)#トレンド分析、周期性

from fbprophet.diagnostics import cross_validation
df_cv = cross_validation(model, initial='730 days', period='180 days', horizon = '365 days')
# initialは訓練期間の初期値、horizonは予測する期間を表します。そしてperiodで指定した日数分ずつ、学習期間が延ばすことをデータがなくなるまで繰り返します。
df_cv


```
</div>
</details>

##感想
最初の初期値だけ変えれば、いろんな株のデータを分析することができます。また、データを株価からGDPや人口などの経済指標に変えることでレポートや卒論にも使えるなと思いました。



###参考文献
・[pythonでGAFAの株価を分析してみよう！](https://www.youtube.com/watch?v=kNZMmxR27Vw)
・[機械学習　株価分析](https://defilabo.io/python_kabukayosoku/)
・[pythonで需要予測がしたい人がはじめに見る動画](https://www.youtube.com/watch?v=uKq_dgEUVfA)
・[pythonで株価分析](https://www.youtube.com/watch?v=0-fZ47QudYo&t=1050s)
・[matplotlibのめっちゃまとめ](https://qiita.com/nkay/items/d1eb91e33b9d6469ef51)
・[相関性、相関係数とは？株価のデータをpythonで考察してみた](https://manareki.com/stock_correlation)
・[【Python入門】datetimeで日付や時刻を扱う方法を解説！](https://www.sejuku.net/blog/23606)

作成　geeksalon　たかぱん