Setup
First we import the necessary libraries, including yfinance for fetching the stock data.
import reflex as rx
from reflex_ag_grid import ag_grid
import yfinance as yf
from datetime import datetime, timedelta
import pandas as pd
Fetching and transforming data
Next, we define the State class, which contains the application’s state and logic. The fetch_stock_data
function fetches stock data for the specified companies and transforms it into a format suitable for display in AG Grid. We call this function when clicking on a button, by linking the on_click
trigger of the button to this state function.
We define state variables, any fields in your app that may change over time (A State Var is directly rendered into the frontend of the app).
The data
state variable stores the raw stock data fetched from Yahoo Finance. We transform this data to round the values and store it as a list of dictionaries, which is the format that AG Grid expects. The transformed data is sorted by date and ticker in descending order and stored in the dict_data
state variable.
The datetime_now
state variable stores the current datetime when the data was fetched.
# The list of companies to fetch data for
companies = ["AAPL", "MSFT", "GOOGL", "AMZN", "META"]class State(rx.State):
# The data fetched from Yahoo Finance
data: pd.DataFrame
# The data to be displayed in the AG Grid
dict_data: list[dict] = [\{}]
# The datetime of the current fetched data
datetime_now: datetime = datetime.now()
def fetch_stock_data(self):
self.datetime_now = datetime.now()
start_date = self.datetime_now - timedelta(days=180)
# Fetch data for all tickers in a single download
self.data = yf.download(companies, start=start_date, end=self.datetime_now, group_by='ticker')
rows = []
for ticker in companies:
# Check if the DataFrame has a multi-level column index (for multiple tickers)
if isinstance(self.data.columns, pd.MultiIndex):
ticker_data = self.data[ticker] # Select the data for the current ticker
else:
ticker_data = self.data # If only one ticker, no multi-level index exists
for date, row in ticker_data.iterrows():
rows.append({
"ticker": ticker,
"date": date.strftime("%Y-%m-%d"),
"open": round(row["Open"], 2),
"high": round(row["High"], 2),
"mid": round((row["High"] + row["Low"]) / 2, 2),
"low": round(row["Low"], 2),
"close": round(row["Close"], 2),
"volume": int(row["Volume"]),
})
self.dict_data = sorted(rows, key=lambda x: (x["date"], x["ticker"]), reverse=True)
rx.button(
"Fetch Latest Data",
on_click=State.fetch_stock_data,
)