ころがる狸

ころがる狸のデータ解析ブログ

【Streamlit】株価データのお手軽GUI分析

手元のデータを簡単に分析するためのツールが欲しいと思うことはありませんか?既存の解析ツールでは手の届かない細かい機能を簡単に実装できれば、ちょっとしたビジネスインテリジェンス(BI)ツールや株式運用ツールとして役立ちそうです。Pythonを使ったデータのインタラクティブな解析はBokehやPlotlyといったライブラリで容易に実装できますが、アプリケーションとして立ち上げるにはStreamlitがおススメです。今回の記事では、自前で取得した少数の株価データをさくっと可視化して分析するための簡単なアプリケーションをStreamlitを用いて作成しました。Streamlitは多くの技術ブログで取り上げられているので今更ですが、実際に作成した画面を表示しながら基本的な機能を確認してみたいと思います。

公式ドキュメントはこちら。これがStreamlitのすべてです。
Welcome to Streamlit — Streamlit 0.79.0 documentation

完成画面を先に見てみましょう。アメリカのセキュリティ系企業の情報を集めました。データ保存先フォルダやファイル名を指定したり、表示する銘柄を選択できるようにします。それと付属して各銘柄の配当やPSRといった基本情報や、株価の時系列データを並べて表示できるようにしました。また、時系列データの範囲をスライダーでインタラクティブに変更できるようにしています。これらは実に簡単に実装できます。
そう、Streamlitならね(誰だ)。

f:id:Dajiro:20210320160918p:plain
Streamlitで作成したアプリケーションの画面。

情報収集

アプリケーションを作成するための情報収集が必要です。今回はStreamlitを実装するために11企業のデータを集めました。

銘柄の配当や所属セクター等の最新情報はBloombergなどのサイトから収集することができます。
GOOGL:NASDAQ GS 株価 - アルファベット - Bloomberg Markets

また、銘柄の株価の時系列データはGoogleスプレッドシートから取得することが可能です。これに関しては以下の記事に詳しく記載されています。
GOOGLEFINANCE - ドキュメント エディタ ヘルプ
【Google Finance関数】Googleスプレッドシートで株価を取得する方法 – 米国株GAFAの場合 | UX BEAR【ゆえっくま】

インストール

インストール方法はなんてことはありません。pip installしましょう。必要に応じて仮想環境も作りましょう。

conda create -n stock python
pip install streamlit

各パーツの実装方法

画面を広くつかうか、それとも画面中央に寄せて使うかをプログラムの先頭で指定する必要があります。Streamlitに関する指定はすべてこの行の後に記載します。デフォルトでは中央寄せ設定です。

import streamlit as st
st.set_page_cinfig(layout = "wide")

入力ファイルの指定方法も極めて簡単です。以下を記載すると、変数名に選択したファイル名が代入されます。

path = st.text_input("Enter a stock directory path for security companies:", "../update/20210320_security/")

続いて、画面の分割方法です。ここではファイル選択をした後に画面を二分割して表示しています。これはPythonのwith構文を用いて対応します。2021月現在、分割した画面内でさらに画面分割というような実装には対応していない模様です。

col1, col2 = st.beta_columns(2)
with col1:
    左側画面内での処理の実装
with col2:
    右側画面内での処理の実装
f:id:Dajiro:20210320163755p:plain
画面分割法。

画面左右にデータフレームとMatplotlibの図を張りますが、表示する銘柄をあらかじめ定義しておいた範囲で取捨選択できるように設定します。

options = st.multiselect(f"Select constituent stocks of security companies", SectorInfo.security_lst, default = SectorInfo.security_lst)

ここで、SectorInfoは銘柄の名称を格納しているクラスです。登録する項目をリスト形式で取り出します。

pandasのデータフレームの表示と、表示期間を示すスライダーの表示方法は以下の通りです。表示する始点、終点及びデフォルト値と刻み幅を指定できます。

st.write(データフレームのパス)
syear = st.slider(f"Start year:security", 2010., 2022., 2016., 0.05)
eyear = st.slider(f"End year:security", 2010., 2022., 2016., 0.05)

最後に、Col2で図を表示します。Matplotlibのplt.figureをStreamlitのpyplotに渡します。

fig = plt.figure(figsize=(3, 3))

#作図処理開始
plt.plot(XXXX)
#作図処理終了

st.pyplot(fig)

以上です。拍子抜けするくらい簡単だと思いませんか?それでいて見栄えの良いGUIがサクッと構築できるわけですから、素晴らしいソフトウェアではないですか。

分析結果

さて、このようなGUIを作ったからには株価の分析も行いたいですよね。個人的に興味のあるセキュリティ企業に限って言えば、以下のことは言えそうです。

  • オクタ(OKTA)、パロアルト(PANW)、ドキュサイン(DOCU)、クラウドストライク(CRDW)等の比較的若い企業の株価は相関している模様。
  • 2020年2、3月のコロナショックで株価は暴落しているが、今年2月にも株価が急落している様子が目立つ。グロース株の利益確定売りが発生し、工業・エネルギー等のバリュー株が優先的に買われたことが原因と推測される。この背景には金利の上昇もある。
  • 配当金を出している企業は(この範囲では)マカフィーのみだが今後の株価が上昇するか疑問。グロース株の下落が底を打ち、上昇トレンドに乗ったらこれらの企業の成長を見込んで購入を検討する価値がある。

といったところでしょうか。このように同業企業の株価を重ねてみたり、時間幅を変えるといろいろな情報が見えてくるので大変面白いですね。

f:id:Dajiro:20210320170957p:plain
セキュリティ企業の株価(2019-2022)

プログラム(の一部)

参考まで、プログラムの全体も張っておきます。プロット用の関数は外部から読み込んでいますし、元データは提供していないのでこのままでは動きませんが悪しからず。しかしStreamlitに関する実装はすべてこの中に詰まっています。慣れればあっという間に実装できそうです。

import pandas as pd
import pickle 
import matplotlib.pyplot as plt
import streamlit as st
from util import plotSector, SectorInfo

st.header("Securty Companies")
path_sec = st.text_input("Enter a stock directory path for security companies:", "../update/20210320_security/")
path_sec_df = st.text_input("Enter a properties path for security companies:", "../properties/20210320_security_table.pkl")
with open(path_sec_df, "rb") as f:
    df_sec = pickle.load(f)

col1, col2 = st.beta_columns(2)
with col1:
    options = st.multiselect(f"Select constituent stocks of security companies", SectorInfo.security_lst, default = SectorInfo.security_lst)

    df_sec_sector = pd.concat([df_sec.iloc[getIndex(df_sec, ticker.replace(".p", ""))] for ticker in options], axis = 1).transpose()
    st.write(df_sec_sector)
    syear = st.slider(f"Start year:security", 2010., 2022., 2016., 0.05)
    eyear = st.slider(f"End year:security", 2010., 2022., 2022., 0.05)

with col2:
    fig = plotSector(path_sec, options, maxprice=False, syear=syear, eyear=eyear)
    st.pyplot(fig)