TiDB CloudとStreamlitでインタラクティブなウェブアプリを構築
※このブログは2023年5月10日に公開された英語ブログ「Building an Interactive Web App with TiDB Cloud and Streamlit」の拙訳です。
今日のようなデータドリブンの世界では、大規模なデータセットを迅速かつ簡単に分析することが不可欠です。TiDB CloudやStreamlitのような強力なツールを使えば、開発者はデータの分析や可視化を容易にするインタラクティブなUIを構築することができます。
TiDB Cloudは、先進的なオープンソースの分散型SQLデータベースであるTiDBのフルマネージドサービスであり、低レイテンシーと水平スケーラビリティでトランザクションデータへのリアルタイムなアクセスを実現します。Streamlitと組み合わせることで、TiDB Cloudは金融データへのリアルタイムアクセスを提供し、ユーザーがリアルタイムでデータを分析・可視化することを可能にします。
一方のStreamlitはオープンソースであるPythonフレームワークで、ウェブアプリケーションの構築プロセスを簡素化するものです。開発者が最小限の労力で強力なデータ・アプリケーションを作成できる、直観的なAPIを提供しています。
この投稿では、TiDB CloudとStreamlitを使ってインタラクティブな株式データ用のウェブアプリケーションを構築する方法を紹介します。一部のアプリケーションの構成要素は、コードを順に追いながら説明します。まずTiDB Cloudに接続し、次にYahoo Finance APIからデータを取得し、最後にPlotlyを使ってデータを視覚化する方法を学びます。このチュートリアルが終わるころには、データ分析と可視化のワークフローを合理化する同様のアプリケーションを構築する強力なツールの活用方法について理解を深めていることでしょう。
前提条件
作業を始める前に、以下の設定が必要となります。
- TiDB CloudアカウントとTiDB Cloud上の無料のTiDB Serverlessクラスタ。詳細はTiDB Cloudクイックスタートをご覧ください。
- Python 3
- Git
初期設定
ストック・データ・プロジェクトのセットアップ
1. TiDB CloudとStreamlitの結合サンプルコードリポジトリをクローンします。ターミナルまたはコマンドプロンプト (Windowsユーザー) から、以下のコマンドを実行します。
git clone https://github.com/tidbcloud/streamlit-stockdata-analysis.git
2. プロジェクトのルート・ディレクトリ “streamlit-stockdata-analysis” に移動し、以下を入力します。
cd streamlit-stockdata-analysis
3. requirements.txtに記載されているproject dependenciesをインストールします。ターミナル・ウィンドウで以下を入力します。
python3 -m pip install -r requirements.txt
データベース・シークレットの保存
TiDB Cloudクラスタの接続情報を格納するsecretsファイルを作成します。Streamlitアプリはこのファイルを参照して、TiDBデータベースとの接続を行います。StreamlitアプリとTiDBとの接続の詳細については、Streamlitチュートリアル「Connect Streamlit to TiDB (英語) 」を参照してください。
1. プロジェクトのルートディレクトリに、.streamlit/secrets.tomlという名前のファイルを作成します。
2. プレースホルダーの値をTiDB Cloudクラスタの情報に置き換えて、以下の内容をファイルに追加します。
#.streamlit/secrets.toml [tidb] host = "<TiDB_cluster_host>" port = 4000 database = "test" user = "<TiDB_cluster_user>" password = "<TiDB_cluster_password>" ssl_ca = "<path_to_CA_store>"
認証局 (CA) の保存パスはオペレーティングシステムによって異なります。このパスはTiDB CloudクラスタのConnectionタブで確認できます。たとえば、macOSの場合のパスは/etc/ssl/cert.pem
になります。
TiDBとStreamlitアプリの接続について、詳細はStreamlitのドキュメント (英語) を参照してください。
株式データを保存するTiDBテーブルの作成
ティッカーシンボルの日次ヒストリカルデータをTiDBに保存するには、以下の手順に従います。
1. TiDB Consoleにログインし、クラスタの概要ページに移動します。

2. 左側のナビゲーションペインでChat2Queryを選択し、以下のSQLスクリプトを実行します。スクリプトはtestデータベース内に ”stock_price_history” テーブルを作成します。このテーブルには、株式の取引量、配当金、始値と終値などの情報が格納されます。
SQL CREATE TABLE test.stock_price_history ( id int PRIMARY KEY AUTO_INCREMENT, Opening_Price DOUBLE, High DOUBLE, Low DOUBLE, Closing_Price DOUBLE, Volume BIGINT, Dividends DOUBLE, Market_Date DATE, Ticker VARCHAR(10) );
株式データプロジェクトの動き
初期設定が完了したら、いよいよプロジェクトを実行に移しましょう。このチュートリアルでは、マイクロソフト (MSFT) とグーグル (GOOGL) の10年分の株価ヒストリカルデータを収集し、分析します。他の銘柄を追跡したい場合は、お好きなティッカーシンボルに置き換えてください。このアプリケーションはYahoo Finance APIからデータを取得し、TiDB Cloudに保存し、Plotlyの3Dチャートを使って可視化します。
1. ローカルマシンでプロジェクトを実行します。ターミナルまたはコマンドプロンプト (Windowsユーザー) から、streamlit run stocks.py
と入力してください。
2. ウェブブラウザ (http://localhost:8502) でアプリケーションを起動します。
3. デフォルトのメニューで、Collect Trade Dataを選択し、分析したい銘柄のティッカーシンボル (この場合はMSFT) を入力します。
4. 開始日と終了日をデフォルト値のままにしてGet Dataをクリックすると、選択した銘柄の10年分のヒストリカルデータを取得できます。

5. Save Dataをクリックすると、取得した銘柄データがTiDB Cloudに保存されます。

6. Googleのデータを取得するには、ティッカーシンボルGOOGLを使い、手順3~5を繰り返します。
7. データを分析するには、Visualize Trade Dataをクリックし、対応するティッカーシンボルを入力し、日付はデフォルトのままにして、Visualizeをクリックします。

この操作により、TiDB上で分析クエリを実行し、その結果を3Dチャートで表示し、Google株とMicrosoft株の配当金支払総額と取引高を長期間で比較することができます。

コードのチュートリアル
このセクションでは、株式データプロジェクトの重要な要素となるコードについて説明します。アプリケーションのコンポーネントと、それらがどのように相互作用して過去の株式データを収集、分析、視覚化しているかを探ります。また、使用されている様々なパッケージと、それらがアプリケーションの全体的な機能にどのように貢献しているかについても説明します。
使用するパッケージ
import streamlit as st import yfinance as yf import pandas as pd import plotly.express as px import pymysql
パッケージ | 説明 |
streamlit |
データサイエンスおよび機械学習プロジェクトのためのウェブアプリケーション構築 |
yfinance |
Yahoo Financeから過去の株価データを取得・分析 |
pandas |
データ操作と分析 |
plotly.express |
インタラクティブなビジュアライゼーション |
pymysql |
TiDBとの相互作用 |
こうしたパッケージとTiDBを組み合わせることで、データを分析、視覚化、保存するインタラクティブなウェブページを構築するための強力なツールキットとなります。
TiDBへのアクセス
TiDBと連動する関数によって、プロジェクトの分析・可視化機能の基盤が提供されます。
データベースへの接続
init_connection()
関数は、Streamlit Secrets Manager (英語) に保存されているクレデンシャルを使用してTiDBデータベースに接続します。この関数は、データの取得と保存に使用する接続オブジェクトを返します。
def init_connection(): config = st.secrets["tidb"] return pymysql.connect( host=config["host"], port=config["port"], user=config["user"], password=config["password"], database=config["database"], ssl_verify_cert=True, ssl_verify_identity=True, ssl_ca= config["ssl_ca"] ) conn = init_connection()
データの保存
get_ticker_data()
関数は、指定されたティッカーシンボル、開始日、終了日の過去の株式データを取得します。Yahoo Financeのyfinance
ライブラリを使用し、この関数は株価の始値、高値、安値、終値、出来高、配当を含むpandas.DataFrame
を返します。
def get_ticker_data(symbol, start_date, end_date): ticker = yf.Ticker(symbol) data = ticker.history(start=start_date, end=end_date) return data
save_data()
関数は、pymysql
ライブラリのバルクインサートメソッドexecutemany
を使用してTiDBデータベースに株式データを挿入します。この関数はpandas.DataFrame
とティッカーシンボルを入力として受取り、データを整形してデータベースに挿入します。
def save_data(data, symbol): data["Date"] = data.index data["Ticker"] = symbol data.reset_index(drop=True, inplace=True) df = data.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume', 'Dividends', 'Date', 'Ticker']] cur = conn.cursor() data = [tuple(row) for row in df.itertuples(index=False)] query = 'INSERT INTO stock_price_history (Opening_Price, High, Low, Closing_Price,Volume, Dividends , Market_Date, Ticker) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s);' cur.executemany(query, data) rows_upserted = cur.rowcount # commit the changes conn.commit() cur.close() conn.close() st.success( str(rows_upserted) + " data saved successfully!")
データの取得
fetch_data()
関数は、TiDBのHybrid Transactional & Analytical Processing (HTAP) 機能を活用してSQLクエリを実行し、集約された株式データ情報を取得します。
この関数は、2つの銘柄ティッカーシンボルと日付範囲を受け取り、ティッカーシンボル、年、総配当、平均取引量を含むpandas.DataFrame
を返します。
def fetch_data(symbol1, symbol2, start_date, end_date): cursor = conn.cursor() query = f""" SELECT Ticker, YEAR(Market_Date) AS Year, ROUND(SUM(Dividends), 2) AS Total_Dividends, CAST(ROUND(AVG(Volume), 2) AS DOUBLE) AS Avg_Volume FROM stock_price_history WHERE Ticker IN ('{symbol1}', '{symbol2}') AND Market_Date BETWEEN '{start_date}' AND '{end_date}' GROUP BY Ticker, YEAR(Market_Date) ORDER BY Ticker, YEAR(Market_Date) ASC; """ cursor.execute(query) data = cursor.fetchall() cols = ['Ticker', 'Year', 'Total_Dividends', 'Avg_Volume'] df = pd.DataFrame(data, columns=cols) return df
ウェブアプリケーション
このウェブアプリケーションでは、過去の株式取引データを収集、視覚化することができます。
取引データの収集
取引データの収集ページでは、ユーザーは銘柄ティッカーシンボル、開始日、終了日を入力します。ユーザーがGet Dataをクリックすると、アプリは指定された日付範囲内の指定された銘柄の過去の取引データを取得し、テーブルに表示します。このデータは、ユーザーが保存するかページを離れるまで、セッションに保存されます。
# Define the inputs symbol = st.text_input("Ticker Symbol").upper() start_date = st.date_input("Start Date", value=pd.to_datetime("today").floor("D") - pd.offsets.DateOffset(years=10)) end_date = st.date_input("End Date", value=pd.to_datetime("today").floor("D")) # Define the button to retrieve the data if st.button("Get Data"): data = get_ticker_data(symbol, start_date, end_date) st.write(data) # store data in session st.session_state.data = data
Save Dataボタンをクリックすると、TiDBにデータが追加され、セッションがクリアされます。
# Define the button to save the data to TiDB if st.button("Save Data"): if st.session_state.get("data") is None: st.write("No data to save.") return data = st.session_state.data save_data(data, symbol) del st.session_state['data']
取引データの可視化
取引データの可視化ページでは、ユーザーは2つの銘柄ティッカーシンボル、開始日、終了日を入力します。Visualizeをクリックすると、指定された日付範囲内で特定の銘柄について過去の取引データが取得され、各銘柄の取引量に対する支払配当金の3D折れ線グラフが表示されます。
# Create two text boxes for entering the stock symbols symbol1 = st.text_input("Enter Ticker Symbol").upper() symbol2 = st.text_input("Enter Ticker Symbol to Compare").upper() # Create two date pickers for selecting the start and end dates start_date = st.date_input("Start Date", value=pd.to_datetime("today").floor("D") - pd.offsets.DateOffset(years=10)) end_date = st.date_input("End Date", value=pd.to_datetime("today").floor("D")) if st.button("Visualize"): # Fetch data from the database data = fetch_data(symbol1, symbol2, start_date, end_date) if data.empty: st.warning('No data found for the selected criteria. Please adjust the inputs.') else: # Display the chart plot_3d_line(data)
プロット3Dチャート
plot_3d_line関数は、Plotlyライブラリを使用して3D折れ線グラフを作成します。このライブラリは、データをより意味のあるものにする様々なインタラクティブな可視化ツールを提供します。各銘柄ティッカーの配当支払額、売買高、年の相関関係を視覚化することで、ユーザーは銘柄の長期的なパフォーマンスに関する洞察を深めて、より多くの情報に基づいた投資判断を行うことが可能になります。
def plot_3d_line(data): fig = px.line_3d(data, x='Year', y='Total_Dividends', z='Avg_Volume', color='Ticker') fig.update_layout(title=f"Dividend Paid Vs Volume Traded", height=600, width=800, scene=dict(xaxis_title="Year", yaxis_title="Dividends Paid", zaxis_title="Volume Traded")) st.plotly_chart(fig)
まとめ
PythonとStreamlitを使い株式データ分析アプリを構築すれば、金融データを可視化し分析するための強力なツールとなります。さらに、バックエンドデータベースとしてTiDBを使用することで、アプリケーションに水平スケーラビリティと高可用性を提供することができます。
TiDBを体験するには、コミュニティエディションまたはTiDB Cloud無料トライアルをお試しください。日本語ドキュメントのTiDBクイックスタートガイド、またはTiDB Cloudワークショップガイドのご利用をお勧めします。ご不明な点などございましたら、お問い合わせフォームよりご連絡ください。また、GitHubにて問題を報告することもできます。