pythonでGUIを作ってみる。

# はじめに
どうも。久しぶりに記事を投稿します。和麿です。最近事情があり、スクレイピングを隠れてやっております。昔は、スクレイピングと聞いて、『は？それが何？』っと思っていたのですが、今はスクレイピングしなければいけないという強い思いに駆られています。本当に人の考えは立場により、そして時代によって変わっていくんだなと感じております。
さてさて、そういうことで、すっかりおさらばしたプログラムを最近チビチビ進めている状況です。今更ながら、カプセル化とか、学びながらコードを誰に咎められることもなく書いています。
プログラムはあくまで道具だと言われます。だから目的がなければ書く意味もない。学ぶ必要もないわけです。そこで、狂人は無理やり目的を作り出す。そういう道理になっているわけです。
ということで今回は、pythonを使ってGUIを作っていきたいと思います。具体的には、会社コードと指定した期間を入力したら、その間の株価の推移を表示してくれるアプリ（というのははばかられる）のコードを書いていきたいと思います。

#環境
環境を以下に示します。
・windows10
・python3(anaconda)
開発は主にjupyter-labで行いました。

#コードの中身の概略
一応コードの中身をざっくり解説します。
結果だけが欲しかったら、最後の『最終的なコード』を参照していただければいいと思います。

##必要なライブラリ
今回使用したライブラリを以下に示します。

```python

from pandas_datareader import data
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
%matplotlib inline

```
主に以下のような感じ。
・pandas:データ処理用
・matplotlib:グラフ表示用(%matplotlib inlineはjupyter系でグラフを表示するときに使用する。)
・numpy：計算用
・tkinter：GUI作成用。（たくさん種類があるが、tkinterはanacondaにデフォルトで入っているため使いやすいため使用。）

こんな感じでオーソドックスなライブラリを使用しています。

##関数の定義
今回関数をいくつか定義しました。
大きく2つ。
・株価データを取得する関数
・ボタンを押したときにグラフを計算し、表示する関数

###株価データを取得する関数
会社コードから株価データを取得後、5,25,50日平均を計算し、データに追加して、返す関数を定義しました。
これは[kinocode](https://youtu.be/0-fZ47QudYo)の丸パクリです。

```python

def company_stock(start,end,company_code):
    df = data.DataReader(company_code,'stooq')
    df = df[(df.index <=end)&(df.index >=start)]

    date=df.index
    price=df['Close']

    span01 = 5
    span02 = 25
    span03 = 50

    df['sma01'] = price.rolling(window=span01).mean()
    df['sma02'] = price.rolling(window=span02).mean()
    df['sma03'] = price.rolling(window=span03).mean()
    
    return df
```

###ボタンを押したときにグラフを計算し、表示する関数
ボタンを押した時のイベントを関数として定義しています。
テキストから値を取得し、株価データを取得し、グラフを設定したGUIに表示する関数を定義しています。

```python

## clickイベント
def btn_click():
    company_code = txtBox.get()
    start = txtBox2.get()
    end = txtBox3.get()

    df = company_stock(start,end,company_code)
    date=df.index
    price=df['Close']
    
    #plt.figure(figsize=(20,10))
    
    fig = Figure(figsize=(6,6), dpi=100)
    plt = fig.add_subplot(2,1,1)
    plt.plot(date,price,label=company_code)
    plt.plot(date,df['sma01'],label='sma01')
    plt.plot(date,df['sma02'],label='sma02')
    plt.plot(date,df['sma03'],label='sma03')
    
    plt.set_title(company_code)
    plt.set_xlabel('date')
    plt.set_ylabel('price')
    #plt.title(company_code)
    #plt.xlabel('date')
    #plt.ylabel('price')
    plt.legend()

    plt = fig.add_subplot(2,1,2)
    plt.bar(date,df['Volume'],label='Volume',color='grey')
    plt.legend()


    canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
    canvas.draw()
    canvas.get_tk_widget().place(x=10, y=120)
```

##GUIの設定
GUIを設定するコードです。
配置や画面は試行錯誤して作っていきます。
ボタンのイベントは"command=btn_click"と関数と紐づけて設定します。
（結構書いていったら何となくわかる感じだと思いました。）

```python
# Figure instance
fig = plt.Figure(figsize=(6,6), dpi=100)

root = tk.Tk()
root.title("stock analsis")
root.geometry("620x740")

#テキストを書く
label = tk.Label(root, text="会社コード")
label.place(x=10, y=10)

label2 = tk.Label(root, text="開始日")
label2.place(x=120, y=10)

label3 = tk.Label(root, text="終了日")
label3.place(x=230, y=10)

#ボタンを書く
txtBox = tk.Entry()
txtBox.configure(state='normal', width=15)
txtBox.place(x=10, y=40)

txtBox2 = tk.Entry()
txtBox2.configure(state='normal', width=15)
txtBox2.place(x=120, y=40)

txtBox3 = tk.Entry()
txtBox3.configure(state='normal', width=15)
txtBox3.place(x=230, y=40)

#ボタンを設置する
button = tk.Button(text='株価表示', width=20, command=btn_click)
button.place(x=10, y=80)


#グラフを書く
canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
canvas.draw()
canvas.get_tk_widget().place(x=10, y=120)

root.mainloop()

```

#最終的なコード
最終的には以下のようなコードになります。
（上からコードを繋げただけ。）
とりあえず、これをコピペすれば多分動く！

```stock_analysis.py

from pandas_datareader import data
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
%matplotlib inline

def company_stock(start,end,company_code):
    df = data.DataReader(company_code,'stooq')
    df = df[(df.index <=end)&(df.index >=start)]

    date=df.index
    price=df['Close']

    span01 = 5
    span02 = 25
    span03 = 50

    df['sma01'] = price.rolling(window=span01).mean()
    df['sma02'] = price.rolling(window=span02).mean()
    df['sma03'] = price.rolling(window=span03).mean()
    
    return df

# clickイベント
def btn_click():
    company_code = txtBox.get()
    start = txtBox2.get()
    end = txtBox3.get()

    df = company_stock(start,end,company_code)
    date=df.index
    price=df['Close']
    
    #plt.figure(figsize=(20,10))
    
    fig = Figure(figsize=(6,6), dpi=100)
    plt = fig.add_subplot(2,1,1)
    plt.plot(date,price,label=company_code)
    plt.plot(date,df['sma01'],label='sma01')
    plt.plot(date,df['sma02'],label='sma02')
    plt.plot(date,df['sma03'],label='sma03')
    
    plt.set_title(company_code)
    plt.set_xlabel('date')
    plt.set_ylabel('price')
    #plt.title(company_code)
    #plt.xlabel('date')
    #plt.ylabel('price')
    plt.legend()

    plt = fig.add_subplot(2,1,2)
    plt.bar(date,df['Volume'],label='Volume',color='grey')
    plt.legend()


    canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
    canvas.draw()
    canvas.get_tk_widget().place(x=10, y=120)

# Figure instance
fig = plt.Figure(figsize=(6,6), dpi=100)

root = tk.Tk()
root.title("stock analsis")
root.geometry("620x740")

#テキストを書く
label = tk.Label(root, text="会社コード")
label.place(x=10, y=10)

label2 = tk.Label(root, text="開始日")
label2.place(x=120, y=10)

label3 = tk.Label(root, text="終了日")
label3.place(x=230, y=10)

#ボタンを書く
txtBox = tk.Entry()
txtBox.configure(state='normal', width=15)
txtBox.place(x=10, y=40)

txtBox2 = tk.Entry()
txtBox2.configure(state='normal', width=15)
txtBox2.place(x=120, y=40)

txtBox3 = tk.Entry()
txtBox3.configure(state='normal', width=15)
txtBox3.place(x=230, y=40)

#ボタンを設置する
button = tk.Button(text='株価表示', width=20, command=btn_click)
button.place(x=10, y=80)


#グラフを書く
canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
canvas.draw()
canvas.get_tk_widget().place(x=10, y=120)

root.mainloop()

```

会社コードは[証券取引所のサイト](https://quote.jpx.co.jp/jpx/template/quote.cgi?F=tmp/stock_search)から以下図の様に取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297798/1954a0cb-ce52-afaa-2625-797b2a9deebe.png)

これをもとに条件を記入すると以下のような結果を得ることが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297798/2b17b9e6-4826-0f00-f490-b270a9637b63.png)

#おわりに
とりあえずグラフをGUIに表示する方法が分かったので、グラフを表示して検討っていうのがやりやすくなったなって思いました。また賢くなった。でも、忘れないようにしていきたい。（最近無茶苦茶苦労したLAN外SSHのやり方を忘れて、人の記憶力のはかなさを感じました。）