{"id":52026,"date":"2022-08-06T00:00:00","date_gmt":"2022-08-06T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/"},"modified":"2022-08-06T00:00:00","modified_gmt":"2022-08-06T07:00:00","slug":"building-an-sp-500-dashboard-using-streamlit-and-griddb","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/","title":{"rendered":"Building an S&#038;P 500 Dashboard using Streamlit and GridDB"},"content":{"rendered":"<p>A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of performance and \u2018drill-down\u2019 to see more details. The function of a dashboard is to provide reliable results by aggregating and extracting value from all the data collected in your data warehouse, otherwise known as your key performance indicators (KPIs). This way, it becomes easy for users to understand data, even non-technical users. We will use streamlit and GridDB to help us built the dashboard webapp. Streamlit lets you turn data scripts into sharable web apps in minutes.<\/p>\n<p>As a first step, we will create a simple we scraper of S&amp;P500 data. After retrieving the ticker symbols, the resulting list will be used to fetch the stock price data from the yfinance library in Python. In the end, we will create the web app combining both functions.<\/p>\n<p>The outline of the tutorial is as follows:<\/p>\n<ol>\n<li>Prerequisites and Environment setup<\/li>\n<li>Dataset overview<\/li>\n<li>Importing required libraries <\/li>\n<li>Loading datasets<\/li>\n<li>Building the dashboard<\/li>\n<li>Conclusion<\/li>\n<\/ol>\n<h2>Prerequisites and Environment setup<\/h2>\n<p>For this project, we will need to install Streamlit and have GridDB installed along with its Python Client. The following packages need to be installed before you continue with the tutorial \u2013<\/p>\n<ol>\n<li>\n<p>Pandas<\/p>\n<\/li>\n<li>\n<p>matplotlib<\/p>\n<\/li>\n<li>\n<p>griddb_python<\/p>\n<\/li>\n<li>\n<p>Streamlit<\/p>\n<\/li>\n<li>\n<p>seaborn<\/p>\n<\/li>\n<li>\n<p>numpy<\/p>\n<\/li>\n<li>\n<p>yfinance<\/p>\n<\/li>\n<\/ol>\n<p>You can install these packages in Conda\u2019s virtual environment using <code>conda install package-name<\/code>. In case you are using Python directly via terminal\/command prompt, <code>pip install package-name<\/code> will do the work.<\/p>\n<h3>GridDB installation<\/h3>\n<p>While loading the dataset, this tutorial will cover two methods \u2013 Using GridDB as well as Using Pandas. To access GridDB using Python, the following packages also need to be installed beforehand:<\/p>\n<ol>\n<li><a href=\"https:\/\/github.com\/griddb\/c_client\">GridDB C-client<\/a><\/li>\n<li>SWIG (Simplified Wrapper and Interface Generator)<\/li>\n<li><a href=\"https:\/\/github.com\/griddb\/python_client\">GridDB Python Client<\/a><\/li>\n<\/ol>\n<h2>Dataset Overview<\/h2>\n<p>The S&amp;P 500 stock market index is maintained by S&amp;P Dow Jones Indices. It comprises 504 common stocks which are issued by 500 large-cap companies traded on American stock exchanges. Although called the S&amp;P 500, the index contains 505 stocks because it includes two share classes of stock from 5 of its component companies.<\/p>\n<p>The data used are available using these two links (<code>https:\/\/en.wikipedia.org\/wiki\/List_of_S%26P_500_companies<\/code>) and (<code>https:\/\/pypi.org\/project\/yfinance\/<\/code>).<\/p>\n<h2>Importing Required Libraries and the datasets<\/h2>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">import griddb_python as griddb\nimport streamlit as st\nimport pandas as pd\nimport base64\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport numpy as np\nimport yfinance as yf\nst.set_option('deprecation.showPyplotGlobalUse', False)<\/code><\/pre>\n<\/div>\n<pre><code>2022-04-25 14:04:27.637 INFO    numexpr.utils: Note: NumExpr detected 12 cores but \"NUMEXPR_MAX_THREADS\" not set, so enforcing safe limit of 8.\n2022-04-25 14:04:27.663 INFO    numexpr.utils: NumExpr defaulting to 8 threads.\n<\/code><\/pre>\n<h2>Loading the Dataset<\/h2>\n<p>We should now load the data into the GridDB server. Although it is possible to read the data directly from the CSV file, we can take advantage of GridDB\u2019s hybrid in-memory architecture to increase the speed of the application. We will also be able to load the necessary data into dataframes, boosting the performance of our queries.<\/p>\n<h3>Using GridDB<\/h3>\n<p>Toshiba GridDB\u2122 is a highly scalable NoSQL database best suited for IoT and Big Data. The foundation of GridDB\u2019s principles is based upon offering a versatile data store that is optimized for IoT, provides high scalability, tuned for high performance, and ensures high reliability.<\/p>\n<p>To store large amounts of data, a CSV file can be cumbersome. GridDB serves as a perfect alternative as it in open-source and a highly scalable database. GridDB is a scalable, in-memory, No SQL database which makes it easier for you to store large amounts of data. If you are new to GridDB, a tutorial on <a href=\"https:\/\/griddb.net\/en\/blog\/using-pandas-dataframes-with-griddb\/\">reading and writing to GridDB<\/a> can be useful.<\/p>\n<p>To start, we will load all of the data (in CSV form) into our GridDB server. Though we could easily load the data directly from CSV into dataframes objects, loading them into our database first will significantly increase the speed of the application because of GridDB\u2019s hybrid in-memory architecture.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">factory = griddb.StoreFactory.get_instance()\n\n# Initialize the GridDB container (enter your database credentials)\ntry:\n    gridstore = factory.get_store(host=host_name, port=your_port, \n            cluster_name=cluster_name, username=admin, \n            password=admin)\n\n    info = griddb.ContainerInfo(\"S&P500\",\n                    [[\"Symbol\", griddb.Type.STRING],[\"Security\", griddb.Type.STRING],[\" SEC filings\", griddb.Type.STRING],\n                     [\"GICS Sector\", griddb.Type.STRING],[\"GICS Sub-Industry\", griddb.Type.STRING],\n                     [\"Headquarters Location\", griddb.Type.STRING],[\"Date first added\", griddb.Type.TIMESTAMP]\n                     [\"CIK\",griddb.Type.INTEGER]], [\"Founded\",griddb.Type.INTEGER]],\n                    griddb.ContainerType.COLLECTION, True)\n    cont = gridstore.put_container(info) \n\n\nsql_statement = ('SELECT * FROM S&P500')\ndataset = pd.read_sql_query(sql_statement, cont)<\/code><\/pre>\n<\/div>\n<p>Note that the <code>cont<\/code> variable has the container information where our data is stored. Replace the <code>S&amp;P500<\/code> with the name of your container. More info can be found in this tutorial <a href=\"https:\/\/griddb.net\/en\/blog\/using-pandas-dataframes-with-griddb\/\">reading and writing to GridDB<\/a>.<\/p>\n<p>When it comes to IoT and Big Data use cases, GridDB clearly stands out among other databases in the Relational and NoSQL space. Overall, GridDB offers multiple reliability features for mission-critical applications that require high availability and data retention.<\/p>\n<h3>Using pandas to read_html<\/h3>\n<p>In Python you need to give access to a file by opening it. You can do it by using the open() function. Open returns a file object, which has methods and attributes for getting information about and manipulating the opened file. After loading the data we download the file in csv format.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># @st.cache\ndef load_data():\n    url = 'https:\/\/en.wikipedia.org\/wiki\/List_of_S%26P_500_companies'\n    html = pd.read_html(url, header = 0)\n    df = html[0]\n    return df\n\ndf = load_data()\nsector = df.groupby('GICS Sector')<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># Sidebar - Sector selection\nsorted_sector_unique = sorted( df['GICS Sector'].unique() )\nselected_sector = st.sidebar.multiselect('Sector', sorted_sector_unique, sorted_sector_unique)\n\n# Filtering data\ndf_selected_sector = df[ (df['GICS Sector'].isin(selected_sector)) ]<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># Download S&P500 data\n# https:\/\/discuss.streamlit.io\/t\/how-to-download-file-in-streamlit\/1806\ndef filedownload(df):\n    csv = df.to_csv(index=False)\n    b64 = base64.b64encode(csv.encode()).decode()  # strings &lt;-> bytes conversions\n    href = f'&lt;a href=\"data:file\/csv;base64,{b64}\" download=\"SP500.csv\">Download CSV File&lt;\/a>'\n    return href\n\nst.markdown(filedownload(df_selected_sector), unsafe_allow_html=True)<\/code><\/pre>\n<\/div>\n<pre><code>DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)\n<\/code><\/pre>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># https:\/\/pypi.org\/project\/yfinance\/\n\ndata = yf.download(\n        tickers = list(df_selected_sector[:10].Symbol),\n        period = \"ytd\",\n        interval = \"1d\",\n        group_by = 'ticker',\n        auto_adjust = True,\n        prepost = True,\n        threads = True,\n        proxy = None\n    )<\/code><\/pre>\n<\/div>\n<pre><code>[*********************100%***********************]  10 of 10 completed\n<\/code><\/pre>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">df.head()<\/code><\/pre>\n<\/div>\n<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }<\/p>\n<p>    .dataframe tbody tr th {\n        vertical-align: top;\n    }<\/p>\n<p>    .dataframe thead th {\n        text-align: right;\n    }\n  <\/style>\n<table border=\"1\" class=\"dataframe\">\n<thead>\n<tr style=\"text-align: right;\">\n<th>\n        <\/th>\n<th>\n          Symbol\n        <\/th>\n<th>\n          Security\n        <\/th>\n<th>\n          SEC filings\n        <\/th>\n<th>\n          GICS Sector\n        <\/th>\n<th>\n          GICS Sub-Industry\n        <\/th>\n<th>\n          Headquarters Location\n        <\/th>\n<th>\n          Date first added\n        <\/th>\n<th>\n          CIK\n        <\/th>\n<th>\n          Founded\n        <\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>\n          0\n        <\/th>\n<td>\n          MMM\n        <\/td>\n<td>\n          3M\n        <\/td>\n<td>\n          reports\n        <\/td>\n<td>\n          Industrials\n        <\/td>\n<td>\n          Industrial Conglomerates\n        <\/td>\n<td>\n          Saint Paul, Minnesota\n        <\/td>\n<td>\n          1976-08-09\n        <\/td>\n<td>\n          66740\n        <\/td>\n<td>\n          1902\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          1\n        <\/th>\n<td>\n          AOS\n        <\/td>\n<td>\n          A. O. Smith\n        <\/td>\n<td>\n          reports\n        <\/td>\n<td>\n          Industrials\n        <\/td>\n<td>\n          Building Products\n        <\/td>\n<td>\n          Milwaukee, Wisconsin\n        <\/td>\n<td>\n          2017-07-26\n        <\/td>\n<td>\n          91142\n        <\/td>\n<td>\n          1916\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          2\n        <\/th>\n<td>\n          ABT\n        <\/td>\n<td>\n          Abbott\n        <\/td>\n<td>\n          reports\n        <\/td>\n<td>\n          Health Care\n        <\/td>\n<td>\n          Health Care Equipment\n        <\/td>\n<td>\n          North Chicago, Illinois\n        <\/td>\n<td>\n          1964-03-31\n        <\/td>\n<td>\n          1800\n        <\/td>\n<td>\n          1888\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          3\n        <\/th>\n<td>\n          ABBV\n        <\/td>\n<td>\n          AbbVie\n        <\/td>\n<td>\n          reports\n        <\/td>\n<td>\n          Health Care\n        <\/td>\n<td>\n          Pharmaceuticals\n        <\/td>\n<td>\n          North Chicago, Illinois\n        <\/td>\n<td>\n          2012-12-31\n        <\/td>\n<td>\n          1551152\n        <\/td>\n<td>\n          2013 (1888)\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          4\n        <\/th>\n<td>\n          ABMD\n        <\/td>\n<td>\n          Abiomed\n        <\/td>\n<td>\n          reports\n        <\/td>\n<td>\n          Health Care\n        <\/td>\n<td>\n          Health Care Equipment\n        <\/td>\n<td>\n          Danvers, Massachusetts\n        <\/td>\n<td>\n          2018-05-31\n        <\/td>\n<td>\n          815094\n        <\/td>\n<td>\n          1981\n        <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Once the dataset is loaded, let us now explore the dataset. We&#8217;ll print the first 5 rows of this dataset using head() function.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">data.head()<\/code><\/pre>\n<\/div>\n<div style=\"overflow-x: scroll;overflow-y: hidden;\">\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }<\/p>\n<p>    .dataframe tbody tr th {\n        vertical-align: top;\n    }<\/p>\n<p>    .dataframe thead tr th {\n        text-align: left;\n    }<\/p>\n<p>    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n  <\/style>\n<table border=\"1\" class=\"dataframe\">\n<thead>\n<tr>\n<th>\n        <\/th>\n<th colspan=\"5\" halign=\"left\">\n          MMM\n        <\/th>\n<th colspan=\"5\" halign=\"left\">\n          ATVI\n        <\/th>\n<th>\n          &#8230;\n        <\/th>\n<th colspan=\"5\" halign=\"left\">\n          ABMD\n        <\/th>\n<th colspan=\"5\" halign=\"left\">\n          ADM\n        <\/th>\n<\/tr>\n<tr>\n<th>\n        <\/th>\n<th>\n          Open\n        <\/th>\n<th>\n          High\n        <\/th>\n<th>\n          Low\n        <\/th>\n<th>\n          Close\n        <\/th>\n<th>\n          Volume\n        <\/th>\n<th>\n          Open\n        <\/th>\n<th>\n          High\n        <\/th>\n<th>\n          Low\n        <\/th>\n<th>\n          Close\n        <\/th>\n<th>\n          Volume\n        <\/th>\n<th>\n          &#8230;\n        <\/th>\n<th>\n          Open\n        <\/th>\n<th>\n          High\n        <\/th>\n<th>\n          Low\n        <\/th>\n<th>\n          Close\n        <\/th>\n<th>\n          Volume\n        <\/th>\n<th>\n          Open\n        <\/th>\n<th>\n          High\n        <\/th>\n<th>\n          Low\n        <\/th>\n<th>\n          Close\n        <\/th>\n<th>\n          Volume\n        <\/th>\n<\/tr>\n<tr>\n<th>\n          Date\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<th>\n        <\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>\n          2022-01-03\n        <\/th>\n<td>\n          176.612779\n        <\/td>\n<td>\n          177.375396\n        <\/td>\n<td>\n          174.156512\n        <\/td>\n<td>\n          176.038330\n        <\/td>\n<td>\n          1930700\n        <\/td>\n<td>\n          66.047409\n        <\/td>\n<td>\n          67.270137\n        <\/td>\n<td>\n          65.411191\n        <\/td>\n<td>\n          67.021614\n        <\/td>\n<td>\n          13208100\n        <\/td>\n<td>\n          &#8230;\n        <\/td>\n<td>\n          358.000000\n        <\/td>\n<td>\n          366.320007\n        <\/td>\n<td>\n          353.320007\n        <\/td>\n<td>\n          366.290009\n        <\/td>\n<td>\n          240000\n        <\/td>\n<td>\n          67.242850\n        <\/td>\n<td>\n          67.799896\n        <\/td>\n<td>\n          67.014069\n        <\/td>\n<td>\n          67.531319\n        <\/td>\n<td>\n          2134200\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          2022-01-04\n        <\/th>\n<td>\n          176.771225\n        <\/td>\n<td>\n          179.524608\n        <\/td>\n<td>\n          176.325537\n        <\/td>\n<td>\n          178.504471\n        <\/td>\n<td>\n          2522200\n        <\/td>\n<td>\n          67.439135\n        <\/td>\n<td>\n          67.608136\n        <\/td>\n<td>\n          66.534516\n        <\/td>\n<td>\n          66.802917\n        <\/td>\n<td>\n          9464000\n        <\/td>\n<td>\n          &#8230;\n        <\/td>\n<td>\n          366.290009\n        <\/td>\n<td>\n          368.970001\n        <\/td>\n<td>\n          355.450012\n        <\/td>\n<td>\n          361.589996\n        <\/td>\n<td>\n          316200\n        <\/td>\n<td>\n          68.197774\n        <\/td>\n<td>\n          69.321808\n        <\/td>\n<td>\n          68.018724\n        <\/td>\n<td>\n          68.784660\n        <\/td>\n<td>\n          2898800\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          2022-01-05\n        <\/th>\n<td>\n          175.434170\n        <\/td>\n<td>\n          180.039645\n        <\/td>\n<td>\n          175.305410\n        <\/td>\n<td>\n          177.771576\n        <\/td>\n<td>\n          2952400\n        <\/td>\n<td>\n          66.802911\n        <\/td>\n<td>\n          67.459015\n        <\/td>\n<td>\n          65.868471\n        <\/td>\n<td>\n          65.898293\n        <\/td>\n<td>\n          14988200\n        <\/td>\n<td>\n          &#8230;\n        <\/td>\n<td>\n          359.429993\n        <\/td>\n<td>\n          364.109985\n        <\/td>\n<td>\n          337.480011\n        <\/td>\n<td>\n          338.200012\n        <\/td>\n<td>\n          359200\n        <\/td>\n<td>\n          68.844341\n        <\/td>\n<td>\n          69.301910\n        <\/td>\n<td>\n          68.207723\n        <\/td>\n<td>\n          68.247513\n        <\/td>\n<td>\n          2665400\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          2022-01-06\n        <\/th>\n<td>\n          179.148254\n        <\/td>\n<td>\n          179.544418\n        <\/td>\n<td>\n          175.840220\n        <\/td>\n<td>\n          176.295822\n        <\/td>\n<td>\n          2505400\n        <\/td>\n<td>\n          65.769067\n        <\/td>\n<td>\n          65.868475\n        <\/td>\n<td>\n          63.333540\n        <\/td>\n<td>\n          63.442890\n        <\/td>\n<td>\n          15071100\n        <\/td>\n<td>\n          &#8230;\n        <\/td>\n<td>\n          337.529999\n        <\/td>\n<td>\n          343.359985\n        <\/td>\n<td>\n          326.000000\n        <\/td>\n<td>\n          336.440002\n        <\/td>\n<td>\n          245600\n        <\/td>\n<td>\n          68.675245\n        <\/td>\n<td>\n          69.301913\n        <\/td>\n<td>\n          68.446456\n        <\/td>\n<td>\n          68.854294\n        <\/td>\n<td>\n          1920000\n        <\/td>\n<\/tr>\n<tr>\n<th>\n          2022-01-07\n        <\/th>\n<td>\n          176.424590\n        <\/td>\n<td>\n          178.761996\n        <\/td>\n<td>\n          175.523299\n        <\/td>\n<td>\n          178.227158\n        <\/td>\n<td>\n          2800200\n        <\/td>\n<td>\n          63.611887\n        <\/td>\n<td>\n          64.516509\n        <\/td>\n<td>\n          62.955787\n        <\/td>\n<td>\n          63.661591\n        <\/td>\n<td>\n          21467900\n        <\/td>\n<td>\n          &#8230;\n        <\/td>\n<td>\n          334.790009\n        <\/td>\n<td>\n          336.029999\n        <\/td>\n<td>\n          319.040009\n        <\/td>\n<td>\n          319.279999\n        <\/td>\n<td>\n          434200\n        <\/td>\n<td>\n          68.973652\n        <\/td>\n<td>\n          69.490909\n        <\/td>\n<td>\n          68.585713\n        <\/td>\n<td>\n          69.441170\n        <\/td>\n<td>\n          2029200\n        <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\n    5 rows \u00d7 50 columns\n  <\/p>\n<\/div>\n<h2>Building the dashboard<\/h2>\n<p>You can add text to your app in a number of ways with Streamlit. Here&#8217;s an example. In our dashboard, we will also add small paragraphs and write-ups using Markdown<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># Dashboard Title and paragraphs\nst.title('S&P 500 Dashboard | Streamlit & GridDB')\n\nst.markdown(\"\"\"\nThis Streamlit App made using the power of GridDB retrieves the list of the **S&P 500** and its corresponding **stock closing price**.\n* **Data source:** [Wikipedia](https:\/\/en.wikipedia.org\/wiki\/List_of_S%26P_500_companies) and [Yahoo finance library] (https:\/\/pypi.org\/project\/yfinance\/).\n\"\"\")<\/code><\/pre>\n<\/div>\n<p>For dropdown we use <code>st.selectbox<\/code> to choose from a series. You can write in the options you want, or pass through an array or data frame column.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">st.header('Display Companies in Selected Sector')\nst.write('Data Dimension: ' + str(df_selected_sector.shape[0]) + ' rows and ' + str(df_selected_sector.shape[1]) + ' columns.')\nst.dataframe(df_selected_sector)<\/code><\/pre>\n<\/div>\n<p>There are several popular data charting libraries supported by Streamlit, such as Matplotlib, Altair, and Plotly. For our dashboard, we will use Matplotlib.<\/p>\n<p>There is also a sidebar that gives streamlit a cleaner look and keeps your app to the left of the page, while all widgets can be moved there. Let&#8217;s create a widget for the state sidebar and a dropdown filter using <code>st.sidebar<\/code>.<\/p>\n<p>Below is the code for lineplots necessary to give us a good view of the stocks closing price data.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># Plot Closing Price of Query Symbol\ndef price_plot(symbol):\n  df = pd.DataFrame(data[symbol].Close)\n  df['Date'] = df.index\n  plt.fill_between(df.Date, df.Close, color='red', alpha=0.3)\n  plt.plot(df.Date, df.Close, color='red', alpha=0.8 )\n  plt.xticks(rotation=45)\n  plt.title(symbol, fontweight='normal')\n  plt.xlabel('Date', fontweight='normal')\n  plt.ylabel('Closing Price', fontweight='normal')\n  return st.pyplot()\n\nnum_company = st.sidebar.slider('Number of Companies', 1, 5)\n\nif st.button('Show Plots'):\n    st.header('Stock Closing Price')\n    for i in list(df_selected_sector.Symbol)[:num_company]:\n        price_plot(i)<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/08\/2.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/08\/2.png\" alt=\"\" width=\"3835\" height=\"1747\" class=\"aligncenter size-full wp-image-28683\" srcset=\"\/wp-content\/uploads\/2022\/08\/2.png 3835w, \/wp-content\/uploads\/2022\/08\/2-300x137.png 300w, \/wp-content\/uploads\/2022\/08\/2-1024x466.png 1024w, \/wp-content\/uploads\/2022\/08\/2-768x350.png 768w, \/wp-content\/uploads\/2022\/08\/2-1536x700.png 1536w, \/wp-content\/uploads\/2022\/08\/2-2048x933.png 2048w, \/wp-content\/uploads\/2022\/08\/2-600x273.png 600w\" sizes=\"(max-width: 3835px) 100vw, 3835px\" \/><\/a><\/p>\n<p>Now that we are finished with the code. Open a terminal and navigate to the path where main.py is located and start the streamlit web server by typing this in command line.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">streamlit run main.py<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/08\/3.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/08\/3.png\" alt=\"\" width=\"1285\" height=\"222\" class=\"aligncenter size-full wp-image-28684\" srcset=\"\/wp-content\/uploads\/2022\/08\/3.png 1285w, \/wp-content\/uploads\/2022\/08\/3-300x52.png 300w, \/wp-content\/uploads\/2022\/08\/3-1024x177.png 1024w, \/wp-content\/uploads\/2022\/08\/3-768x133.png 768w, \/wp-content\/uploads\/2022\/08\/3-600x104.png 600w, \/wp-content\/uploads\/2022\/08\/3-1280x222.png 1280w\" sizes=\"(max-width: 1285px) 100vw, 1285px\" \/><\/a><\/p>\n<p>By default it will be running on port 8501. Open your browser and and hit this url http:\/\/localhost:8501 to see your dashboard in the browser<\/p>\n<h2>Conclusion<\/h2>\n<p>In this tutorial, we\u2019ve built an amazing dashboard using the power of GridDB and streamlit. We examined two ways to import our data, using (1) GridDB and (2) pandas read_csv. For large datasets, GridDB provides an excellent alternative to import data in your notebook as it is open-source and highly scalable.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of performance and \u2018drill-down\u2019 to see more details. The function of a dashboard is to provide reliable results by aggregating and extracting value from all the data collected in your data [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":52027,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-52026","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building an S&amp;P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building an S&amp;P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-06T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2025\/12\/1-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1180\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Building an S&#038;P 500 Dashboard using Streamlit and GridDB\",\"datePublished\":\"2022-08-06T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\"},\"wordCount\":1111,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2025\/12\/1-scaled.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\",\"name\":\"Building an S&P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2025\/12\/1-scaled.png\",\"datePublished\":\"2022-08-06T07:00:00+00:00\",\"description\":\"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2025\/12\/1-scaled.png\",\"contentUrl\":\"\/wp-content\/uploads\/2025\/12\/1-scaled.png\",\"width\":2560,\"height\":1180},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building an S&P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT","description":"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/","og_locale":"en_US","og_type":"article","og_title":"Building an S&P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT","og_description":"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of","og_url":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2022-08-06T07:00:00+00:00","og_image":[{"width":2560,"height":1180,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2025\/12\/1-scaled.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Building an S&#038;P 500 Dashboard using Streamlit and GridDB","datePublished":"2022-08-06T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/"},"wordCount":1111,"commentCount":0,"publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2025\/12\/1-scaled.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/","url":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/","name":"Building an S&P 500 Dashboard using Streamlit and GridDB | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2025\/12\/1-scaled.png","datePublished":"2022-08-06T07:00:00+00:00","description":"A dashboard is a comprehensive snapshot of your company\u2019s performance. Because the nature of a dashboard is dynamic, one can click on any area of","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/building-an-sp-500-dashboard-using-streamlit-and-griddb\/#primaryimage","url":"\/wp-content\/uploads\/2025\/12\/1-scaled.png","contentUrl":"\/wp-content\/uploads\/2025\/12\/1-scaled.png","width":2560,"height":1180},{"@type":"WebSite","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/52026","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=52026"}],"version-history":[{"count":0,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/52026\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/52027"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=52026"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=52026"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=52026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}