Python tkinter 株価グラフを表示するGUIアプリを作成した【全銘柄対応】

まくまく
まくまく
株価をローソク足チャートで表示するGUIアプリを作成しました。

証券コード、調べたい期間をGUIアプリ上で設定するとグラフが作成されます。

株価チャートを表示するGUIアプリ


プログラムを実行するとこのようなウインドウが立ち上がります。左側に設定値、右側の広いエリアがグラフ表示、右下は銘柄名を表示するようになってます。


左側に証券コード、期間を入力して決定ボタンを押します。


右側に株価グラフが表示されました。日足のローソク足、5日移動平均線、25日移動平均線、出来高を表示しています。グラフの下には取得した銘柄名も表示されています。こちらは2021年1月1日から2021年12月1日までをグラフにしてみました。


期間を半年にしてみました。これくらいの方がローソク足の動きが分かりやすいですね。


2015年1月から2021年12月までの6年間ではこんな感じです。これくらい長い期間を設定すると、

「WARNING: YOU ARE PLOTTING SO MUCH DATA THAT IT MAY NOT BE POSSIBLE TO SEE DETAILS」という警告がでますが、気にしないでおきましょう。


もちろん他の銘柄にも対応しています。8035を入力して「東京エレクトロン」を表示してみました。



サンプルプログラム

Pythonは勉強中のため未熟なコードになっているところもあると思います。グラフの書き換え方法や、グラフの配置、存在しない証券コードを入力したときの表示だとか、自分でも気になっているところが多々あります。グラフはstooqから、銘柄名はJPXからっていうのもスマートじゃない感じですよね。完成度はそこそこなので、そのあたりはご了承いただければと思います。環境によってはうまく動作しないかもしれません。

#ライブラリのインポート
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import pandas as pd
import datetime as dt
from datetime import datetime
import pandas_datareader.data as web
import mplfinance as mpf
import requests
from matplotlib.figure import Figure

def stock2graph():
    global canvas
    s_code = (en_code.get()+".JP")
    fy = int(f_year.get())
    fm = int(f_month.get())
    fd = int(f_day.get())
    ty = int(t_year.get())
    tm = int(t_month.get())
    td = int(t_day.get())
    start = dt.date(fy,fm,fd)
    end = dt.date(ty,tm,td)
    df = web.DataReader(s_code,'stooq',start, end)
    d_ohlcv = {'Open': 'first',
               'High': 'max',
               'Low': 'min',
               'Close': 'last',
               'Volume': 'sum'}
    df_w = df.resample('W-MON', closed='left', label='left').agg(d_ohlcv)
    df = df.sort_index()
    #print(df)
    df_w = df_w.sort_index()
    clear()
    fig, axes = mpf.plot(df, title="\n"+s_code, type='candle', mav=(5, 25),volume=True, style='mike', returnfig=True, figsize=(10, 5))
    canvas = FigureCanvasTkAgg(fig, frame_graph)
    canvas.draw()
    canvas.get_tk_widget().pack()

def clear():
    canvas.get_tk_widget().destroy()
  
def load_data():
    global df_c
    url = "https://www.jpx.co.jp/markets/statistics-equities/misc/tvdivq0000001vg2-att/data_j.xls"
    r = requests.get(url)
    with open('data_j.xls', 'wb') as output:
        output.write(r.content)
    df_c = pd.read_excel("./data_j.xls", index_col=1)

def code2name():
    en_name.delete('0','end')
    code = en_code.get()
    if (int(code) in df_c.index.values) == True:
        s_name = df_c.at[int(code), '銘柄名']
        en_name.insert(0, str(s_name))
    else:
        en_name.insert(0, '銘柄はありません')
        
#ウインドウの作成
root = tk.Tk()
#ウインドウのタイトル
root.title("株価チャートを表示するGUIアプリ")
#ウインドウサイズと位置指定 幅,高さ,x座標,y座標 
root.geometry("1200x550+50+50")

#フレームの作成
frame = tk.Frame(root, width=1200, height=550, padx=10, pady=10, bg="#011a27")
frame.place(x=0, y=0)

frame_menu = tk.Frame(frame, relief=tk.FLAT, bg="#063852", bd=2)
frame_menu.place(x=10, y=10, width=150, height=520)

frame_name = tk.Frame(frame, relief=tk.FLAT, bg="#063852", bd=2)
frame_name.place(x=170, y=500, width=990, height=30)

frame_graph = tk.Frame(frame, relief=tk.FLAT, bg="#063852", padx=5, pady=5,bd=2)
frame_graph.place(x=170, y=10, width=990, height=480)

#ラベル作成
l_code = tk.Label(frame_menu,text="証券コード", relief="flat", fg="white", bg="#063852")
l_code.grid(row=0, column=0, sticky = tk.W)
#証券コード入力ボックス
en_code = tk.Entry(frame_menu, width = 6, relief="solid")
en_code.grid(row=0, column=1, sticky = tk.W, pady=20)

#日付
l_from = tk.Label(frame_menu,text="期間を入力", relief="flat", fg="white", bg="#063852")
l_from.grid(row=2, column=0, sticky = tk.W)
l_fy = tk.Label(frame_menu,text="from year", relief="flat", fg="white", bg="#063852")
l_fy.grid(row=3, column=0, sticky = tk.W)
f_year = tk.Entry(frame_menu, width = 6 ,relief="solid")
f_year.grid(row=3, column=1, sticky = tk.W)
l_fm = tk.Label(frame_menu,text="from month", relief="flat", fg="white", bg="#063852")
l_fm.grid(row=4, column=0, sticky = tk.W)
f_month = tk.Entry(frame_menu, width = 6,relief="solid")
f_month.grid(row=4, column=1, sticky = tk.W)
l_fd = tk.Label(frame_menu,text="from day", relief="flat", fg="white", bg="#063852")
l_fd.grid(row=5, column=0, sticky = tk.W)
f_day = tk.Entry(frame_menu, width = 6, relief="solid")
f_day.grid(row=5, column=1, sticky = tk.W)
l_ty = tk.Label(frame_menu,text="to year", relief="flat", fg="white", bg="#063852")
l_ty.grid(row=6, column=0, sticky = tk.W)
t_year = tk.Entry(frame_menu, width = 6, relief="solid")
t_year.grid(row=6, column=1, sticky = tk.W)
l_tm = tk.Label(frame_menu,text="to month", relief="flat", fg="white", bg="#063852")
l_tm.grid(row=7, column=0, sticky = tk.W)
t_month = tk.Entry(frame_menu, width = 6, relief="solid")
t_month.grid(row=7, column=1, sticky = tk.W)
l_td = tk.Label(frame_menu,text="to day", relief="flat", fg="white", bg="#063852")
l_td.grid(row=8, column=0, sticky = tk.W)
t_day = tk.Entry(frame_menu, width = 6, relief="solid")
t_day.grid(row=8, column=1, sticky = tk.W)

#銘柄名出力用
en_name = tk.Entry(frame_name, width = 50, relief="solid")
en_name.pack()

#データフレーム読み込み
load_data()
    
#ボタン作成
button = tk.Button(frame_menu, text="決定", command=lambda:[code2name(), stock2graph()])
button.grid(row=10, column=1, sticky = tk.W, padx=5, pady=30)

#グラフ用キャンバス
fig = Figure(figsize=(10, 5))
canvas = FigureCanvasTkAgg(fig, frame_graph)
canvas.get_tk_widget().pack()

#イベントループ
root.mainloop()
タイトルとURLをコピーしました