In this two-part tutorial, we explore how to build a Real-Time Stock Tracker and a complementary Stock Data Viewer using Python. These scripts utilize popular libraries like Tkinter, yfinance, SQLite, and Matplotlib, providing a seamless integration of real-time data monitoring and storage.
This project is ideal for beginners and intermediate developers who want to learn:
By following this tutorial, you’ll not only build a functional stock tracking system but also gain hands-on experience with essential Python libraries.
This script relies on several Python libraries for its functionality. Below is the detailed list with comments:
# Importing necessary libraries
import tkinter as tk
# Tkinter is used to create the graphical user interface (GUI) of the application
from tkinter import ttk
# ttk provides themed widgets for modern styling in the Tkinter application
import yfinance as yf
# yfinance is used to fetch real-time stock data from Yahoo Finance
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# Embeds Matplotlib graphs into the Tkinter GUI
import matplotlib.pyplot as plt
# Matplotlib is used for creating and customizing graphs
import threading
# Provides tools for creating and managing threads, enabling real-time data updates
import time
# Used to introduce delays for periodic updates without overloading the GUI or API
import sqlite3
# SQLite library is used for handling the database, including creating tables and storing stock data
from datetime import datetime
# datetime is used to fetch and format the current date and time for timestamps
import os
# os module ensures the SQLite database is created in the same directory as the script
This section initializes global variables for tracking stock prices and defines a dictionary of stock options with their corresponding tickers.
# Global variables
times = [] # To store time points for the graph
prices = [] # To store stock prices for the graph
stop_event = threading.Event() # Event to stop background threads
current_thread = None # Keep track of the current thread
# Stock list (popular Indian stocks + NSE/BSE indices)
stock_options = {
"Reliance Industries": "RELIANCE.NS",
"Tata Consultancy Services (TCS)": "TCS.NS",
"Infosys": "INFY.NS",
"HDFC Bank": "HDFCBANK.NS",
"ICICI Bank": "ICICIBANK.NS",
"State Bank of India (SBI)": "SBIN.NS",
"Bharti Airtel": "BHARTIARTL.NS",
"Adani Enterprises": "ADANIENT.NS",
"NSE Nifty 50 Index": "^NSEI",
"BSE Sensex Index": "^BSESN"
}
This function ensures the SQLite database and the required table are created if they don’t already exist. It uses the os
module to place the database in the same directory as the script.
# Path to the SQLite database
db_path = os.path.join(os.path.dirname(__file__), "stock_data.db")
# Function to create the SQLite database and table
def create_database():
"""Creates the SQLite database and the required table if they do not exist."""
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS stock_prices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stock_name TEXT,
price REAL,
timestamp TEXT
)
""")
conn.commit()
conn.close()
This function fetches the latest stock price using the yfinance API. It extracts the most recent closing price from the retrieved data.
# Function to fetch the current stock price
def fetch_stock_price(ticker):
"""Fetches the latest stock price using the yfinance API."""
try:
stock = yf.Ticker(ticker)
data = stock.history(period="1d", interval="1m")
price = data['Close'].iloc[-1]
return round(price, 2)
except Exception as e:
print("Error fetching data:", e)
return None
This function updates the graph in real time and stores the fetched stock data into the SQLite database. It uses a separate database connection for thread safety.
# Function to update the graph dynamically
def update_graph(ticker, stock_name):
global times, prices
conn = sqlite3.connect(db_path) # Separate connection for this thread
cursor = conn.cursor()
while not stop_event.is_set():
price = fetch_stock_price(ticker)
if price:
prices.append(price)
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
times.append(current_time)
save_to_database(cursor, stock_name, price, current_time)
conn.commit()
plot_graph(stock_name)
time.sleep(5) # Update every 5 seconds
conn.close()
The save_to_database
function inserts the stock price, name, and timestamp into the SQLite database.
# Function to save data to SQLite database
def save_to_database(cursor, stock_name, price, timestamp):
cursor.execute("INSERT INTO stock_prices (stock_name, price, timestamp) VALUES (?, ?, ?)",
(stock_name, price, timestamp))
This function plots the stock price graph using Matplotlib. It includes labels and formatting for better visualization.
# Function to plot the graph
def plot_graph(stock_name):
ax.clear()
ax.plot(times, prices, color="blue", label=f"{stock_name} Price")
ax.set_title(f"Real-Time Stock Price Graph ({stock_name})")
ax.set_xlabel("Time")
ax.set_ylabel("Price (INR)")
ax.legend(loc="upper left")
ax.grid()
ax.tick_params(axis="x", rotation=45)
canvas.draw()
This function starts tracking the selected stock in a new thread. It resets the graph data and handles thread management to ensure only one thread runs at a time.
# Function to start tracking a stock
def start_tracking():
"""Starts tracking the selected stock in a new thread."""
global current_thread, stop_event, times, prices
# Stop the previous thread if it's running
if current_thread and current_thread.is_alive()():
stop_event.set() # Signal the thread to stop
current_thread.join() # Wait for the thread to finish
# Reset the graph data
times = []
prices = []
# Clear the stop_event for the new thread
stop_event.clear()
# Start a new thread for the selected stock
selected_stock = stock_var.get()
ticker = stock_options[selected_stock]
current_thread = threading.Thread(target=update_graph, args=(ticker, selected_stock), daemon=True)
current_thread.start()
This function handles the application’s clean-up process when the window is closed. It ensures all threads are terminated gracefully and resources are released.
# Function to handle the window close event
def on_close():
"""Stops the background thread and closes the Tkinter window."""
global stop_event, current_thread
# Signal the background thread to stop
stop_event.set()
# Wait for the thread to finish if it's still running
if current_thread and current_thread.is_alive()():
current_thread.join()
# Close all Matplotlib resources
plt.close('all')
# Destroy the Tkinter window
root.destroy()
import tkinter as tk
from tkinter import ttk
import yfinance as yf
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import threading
import time
import sqlite3
from datetime import datetime
import os
# Global variables
times = [] # To store time points for the graph
prices = [] # To store stock prices for the graph
stop_event = threading.Event() # Event to stop background threads
current_thread = None # Keep track of the current thread for stock tracking
# Stock list (popular Indian stocks + NSE/BSE indices)
stock_options = {
"Reliance Industries": "RELIANCE.NS",
"Tata Consultancy Services (TCS)": "TCS.NS",
"Infosys": "INFY.NS",
"HDFC Bank": "HDFCBANK.NS",
"ICICI Bank": "ICICIBANK.NS",
"State Bank of India (SBI)": "SBIN.NS",
"Bharti Airtel": "BHARTIARTL.NS",
"Adani Enterprises": "ADANIENT.NS",
"NSE Nifty 50 Index": "^NSEI",
"BSE Sensex Index": "^BSESN"
}
# Path to the SQLite database (same directory as the script)
db_path = os.path.join(os.path.dirname(__file__), "stock_data.db")
# Function to create the SQLite database and table
def create_database():
"""Creates the SQLite database and the required table if they do not exist."""
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS stock_prices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stock_name TEXT,
price REAL,
timestamp TEXT
)
""")
conn.commit()
conn.close()
# Function to fetch the current stock price
def fetch_stock_price(ticker):
"""Fetches the latest stock price using the yfinance API."""
try:
stock = yf.Ticker(ticker)
data = stock.history(period="1d", interval="1m")
price = data['Close'].iloc[-1]
return round(price, 2)
except Exception as e:
print("Error fetching data:", e)
return None
# Function to update the graph dynamically
def update_graph(ticker, stock_name):
"""
Updates the graph with the stock price in real-time.
Stores the data in the database as well.
"""
global times, prices
conn = sqlite3.connect(db_path) # Separate connection for this thread
cursor = conn.cursor()
while not stop_event.is_set():
price = fetch_stock_price(ticker)
if price:
prices.append(price)
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
times.append(current_time)
save_to_database(cursor, stock_name, price, current_time)
conn.commit()
plot_graph(stock_name)
time.sleep(5) # Update every 5 seconds
conn.close()
# Function to save data to the SQLite database
def save_to_database(cursor, stock_name, price, timestamp):
"""Inserts the stock price data into the database."""
cursor.execute("INSERT INTO stock_prices (stock_name, price, timestamp) VALUES (?, ?, ?)",
(stock_name, price, timestamp))
# Function to plot the graph
def plot_graph(stock_name):
"""Plots the stock price graph using Matplotlib."""
ax.clear()
ax.plot(times, prices, color='blue', label=f"{stock_name} Price")
ax.set_title(f"Real-Time Stock Price Graph ({stock_name})")
ax.set_xlabel("Time")
ax.set_ylabel("Price (INR)")
ax.legend(loc="upper left")
ax.grid()
ax.tick_params(axis='x', rotation=45)
canvas.draw()
# Function to start tracking a stock
def start_tracking():
"""Starts tracking the selected stock in a new thread."""
global current_thread, stop_event, times, prices
# Stop the previous thread if it's running
if current_thread and current_thread.is_alive():
stop_event.set() # Signal the thread to stop
current_thread.join() # Wait for the thread to finish
# Reset the graph data
times = []
prices = []
# Clear the stop_event for the new thread
stop_event.clear()
# Start a new thread for the selected stock
selected_stock = stock_var.get()
ticker = stock_options[selected_stock]
current_thread = threading.Thread(target=update_graph, args=(ticker, selected_stock), daemon=True)
current_thread.start()
# Function to handle the window close event
def on_close():
"""Stops the background thread and closes the Tkinter window."""
global stop_event, current_thread
stop_event.set() # Signal the thread to stop
if current_thread and current_thread.is_alive():
current_thread.join() # Wait for the thread to finish
plt.close('all') # Close matplotlib resources
root.destroy() # Destroy the Tkinter window
# Tkinter window setup
root = tk.Tk()
root.title("plus2net.com Indian Stock Price Tracker")
root.geometry("800x600")
# Create the database (if it doesn't exist)
create_database()
# Bind the close event to the on_close function
root.protocol("WM_DELETE_WINDOW", on_close)
# Title label
title_label = tk.Label(root, text="Indian Stock Price Tracker", font=("Arial", 16, "bold"), fg="#007bff")
title_label.pack(pady=10)
# Frame for dropdown and button
selection_frame = tk.Frame(root)
selection_frame.pack(pady=10)
# Stock selection dropdown
stock_var = tk.StringVar(value="Reliance Industries")
stock_dropdown = ttk.Combobox(selection_frame, textvariable=stock_var, values=list(stock_options.keys()), state="readonly", font=("Arial", 12))
stock_dropdown.pack(side=tk.LEFT, padx=5)
# Start button next to the dropdown
start_button = ttk.Button(selection_frame, text="Start Tracking", command=start_tracking)
start_button.pack(side=tk.LEFT, padx=5)
# Matplotlib figure and canvas for the graph
fig, ax = plt.subplots()
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# Run the Tkinter event loop
root.mainloop()
This script uses Tkinter and SQLite to display stored stock data in a graphical interface. Below is the code broken into sections:
# Importing necessary libraries
import tkinter as tk
# Tkinter is used to create the graphical user interface (GUI)
from tkinter import ttk
# ttk provides themed widgets for better styling
import sqlite3
# SQLite library is used for database operations
import os
# os module ensures the database is created in the same directory as the script
# Path to the SQLite database
db_path = os.path.join(os.path.dirname(__file__), "stock_data.db")
The display_data
function fetches data for the selected stock from the SQLite database and displays it in a Treeview widget.
# Function to fetch and display data for the selected stock
def display_data():
"""
Fetches and displays data for the selected stock from the SQLite database.
Populates the Treeview with the fetched records.
"""
# Clear any existing data in the Treeview
for row in tree.get_children():
tree.delete(row)
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Get the selected stock from the dropdown
selected_stock = stock_var.get()
# Fetch data for the selected stock
cursor.execute("SELECT stock_name, price, timestamp FROM stock_prices WHERE stock_name = ? ORDER BY id DESC",
(selected_stock,))
records = cursor.fetchall()
conn.close()
# Populate the Treeview with fetched data
for record in records:
tree.insert("", tk.END, values=record)
The populate_dropdown
function populates the dropdown with unique stock names fetched from the database.
# Function to populate the dropdown with unique stock names
def populate_dropdown():
"""
Populates the stock selection dropdown with unique stock names
from the SQLite database.
"""
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Fetch unique stock names from the database
cursor.execute("SELECT DISTINCT stock_name FROM stock_prices")
stocks = cursor.fetchall()
conn.close()
# Update the dropdown with stock names
stock_names = [stock[0] for stock in stocks]
stock_var.set(stock_names[0] if stock_names else "No Data")
stock_dropdown['values'] = stock_names
This section sets up the Tkinter window and widgets, including the dropdown, button, and Treeview widget for displaying data.
# Tkinter window setup
root = tk.Tk()
root.title("View Stored Stock Data")
root.geometry("800x400")
# Title label
title_label = tk.Label(root, text="Stored Stock Data", font=("Arial", 16, "bold"), fg="#007bff")
title_label.pack(pady=10)
# Frame for dropdown and button
selection_frame = tk.Frame(root)
selection_frame.pack(pady=10)
# Dropdown to select stock
stock_var = tk.StringVar()
stock_dropdown = ttk.Combobox(selection_frame, textvariable=stock_var, state="readonly", font=("Arial", 12))
stock_dropdown.pack(side=tk.LEFT, padx=5)
# Button to fetch and display data
fetch_button = tk.Button(selection_frame, text="Load Data", command=display_data, font=("Arial", 12))
fetch_button.pack(side=tk.LEFT, padx=5)
# Treeview widget to display stored data
columns = ("Stock Name", "Price", "Timestamp")
tree = ttk.Treeview(root, columns=columns, show="headings")
tree.heading("Stock Name", text="Stock Name")
tree.heading("Price", text="Price")
tree.heading("Timestamp", text="Timestamp")
tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Set column widths
tree.column("Stock Name", width=200)
tree.column("Price", width=100)
tree.column("Timestamp", width=200)
# Populate the dropdown with stock names on startup
populate_dropdown()
# Run the Tkinter event loop
root.mainloop()
import tkinter as tk
from tkinter import ttk
import sqlite3
import os
# Path to the SQLite database (same directory as the script)
db_path = os.path.join(os.path.dirname(__file__), "stock_data.db")
# Function to fetch and display data for the selected stock
def display_data():
"""
Fetches and displays data for the selected stock from the SQLite database.
Populates the Treeview with the fetched records.
"""
# Clear any existing data in the Treeview
for row in tree.get_children():
tree.delete(row)
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Get the selected stock from the dropdown
selected_stock = stock_var.get()
# Fetch data for the selected stock
cursor.execute("SELECT stock_name, price, timestamp FROM stock_prices WHERE stock_name = ? ORDER BY id DESC", (selected_stock,))
records = cursor.fetchall()
conn.close()
# Populate the Treeview with fetched data
for record in records:
tree.insert("", tk.END, values=record)
# Function to populate the dropdown with unique stock names from the database
def populate_dropdown():
"""
Populates the stock selection dropdown with unique stock names
from the SQLite database.
"""
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Fetch unique stock names from the database
cursor.execute("SELECT DISTINCT stock_name FROM stock_prices")
stocks = cursor.fetchall()
conn.close()
# Update the dropdown with stock names
stock_names = [stock[0] for stock in stocks]
stock_var.set(stock_names[0] if stock_names else "No Data")
stock_dropdown['values'] = stock_names
# Tkinter window setup
root = tk.Tk()
root.title("plus2net.com View Stored Stock Data")
root.geometry("800x400")
# Title label
title_label = tk.Label(root, text="Stored Stock Data", font=("Arial", 16, "bold"), fg="#007bff")
title_label.pack(pady=10)
# Frame for dropdown and button
selection_frame = tk.Frame(root)
selection_frame.pack(pady=10)
# Dropdown to select stock
stock_var = tk.StringVar()
stock_dropdown = ttk.Combobox(selection_frame, textvariable=stock_var, state="readonly", font=("Arial", 12))
stock_dropdown.pack(side=tk.LEFT, padx=5)
# Button to fetch and display data
fetch_button = tk.Button(selection_frame, text="Load Data", command=display_data, font=("Arial", 12))
fetch_button.pack(side=tk.LEFT, padx=5)
# Treeview widget to display stored data
columns = ("Stock Name", "Price", "Timestamp")
tree = ttk.Treeview(root, columns=columns, show="headings")
tree.heading("Stock Name", text="Stock Name")
tree.heading("Price", text="Price")
tree.heading("Timestamp", text="Timestamp")
tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Set column widths
tree.column("Stock Name", width=200)
tree.column("Price", width=100)
tree.column("Timestamp", width=200)
# Populate the dropdown with stock names on startup
populate_dropdown()
# Run the Tkinter event loop
root.mainloop()
By combining the power of Tkinter, SQLite, and Matplotlib, this project demonstrates how to create a complete stock tracking and data viewing application. From fetching live stock prices with yfinance to storing and visualizing data dynamically, this tutorial equips you with practical skills to build data-driven desktop applications. With further customization, you can expand this project to track cryptocurrencies, commodities, or implement alert systems. Dive in, experiment, and make it your own!