Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import datetime
- import tkinter as tk
- from tkinter import messagebox, ttk
- import matplotlib.pyplot as plt
- import numpy as np
- import pandas as pd
- import yfinance as yf
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
- from sklearn.ensemble import RandomForestRegressor
- from sklearn.metrics import mean_squared_error
- from sklearn.model_selection import train_test_split
- class StockPredictorApp:
- def __init__(self, root):
- self.root = root
- self.root.title("Real-Time Stock Predictor & Analytics AI")
- self.root.geometry("1100x700")
- self.root.configure(bg="#2c3e50")
- # Layout Setup
- self.create_widgets()
- def create_widgets(self):
- # --- Top Control Panel ---
- control_frame = tk.Frame(self.root, bg="#34495e", bd=2, relief=tk.RIDGE)
- control_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=10)
- # Ticker Input
- tk.Label(
- control_frame,
- text="Stock Ticker (e.g., AAPL, SPY):",
- fg="white",
- bg="#34495e",
- font=("Arial", 11, "bold"),
- ).grid(row=0, column=0, padx=10, pady=10, sticky="w")
- self.ticker_entry = tk.Entry(control_frame, font=("Arial", 11), width=10)
- self.ticker_entry.insert(0, "AAPL")
- self.ticker_entry.grid(row=0, column=1, padx=5, pady=10)
- # Date Range inputs
- tk.Label(
- control_frame,
- text="Start Date (YYYY-MM-DD):",
- fg="white",
- bg="#34495e",
- font=("Arial", 11),
- ).grid(row=0, column=2, padx=10, pady=10)
- self.start_entry = tk.Entry(control_frame, font=("Arial", 11), width=12)
- self.start_entry.insert(0, "2020-01-01")
- self.start_entry.grid(row=0, column=3, padx=5, pady=10)
- tk.Label(
- control_frame,
- text="End Date (YYYY-MM-DD):",
- fg="white",
- bg="#34495e",
- font=("Arial", 11),
- ).grid(row=0, column=4, padx=10, pady=10)
- self.end_entry = tk.Entry(control_frame, font=("Arial", 11), width=12)
- self.end_entry.insert(0, datetime.datetime.now().strftime("%Y-%m-%d"))
- self.end_entry.grid(row=0, column=5, padx=5, pady=10)
- # Action Button
- self.predict_btn = tk.Button(
- control_frame,
- text="Run Prediction Model",
- command=self.process_stock_data,
- bg="#2ecc71",
- fg="white",
- font=("Arial", 11, "bold"),
- relief=tk.RAISED,
- cursor="hand2",
- )
- self.predict_btn.grid(row=0, column=6, padx=20, pady=10)
- # --- Dashboard Metrics Layout ---
- self.metrics_frame = tk.Frame(self.root, bg="#2c3e50")
- self.metrics_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.last_close_label = self.create_metric_box(
- self.metrics_frame, "Last Close Price", "N/A", "#2980b9", 0
- )
- self.predicted_label = self.create_metric_box(
- self.metrics_frame, "Next Day Prediction", "N/A", "#d35400", 1
- )
- self.mse_label = self.create_metric_box(
- self.metrics_frame, "Model Error (MSE)", "N/A", "#7f8c8d", 2
- )
- # --- Data Plot Frame ---
- self.plot_frame = tk.Frame(self.root, bg="white", bd=2, relief=tk.SUNKEN)
- self.plot_frame.pack(
- side=tk.BOTTOM, fill=tk.BOTH, expand=True, padx=10, pady=10
- )
- def create_metric_box(self, parent, title, initial_val, color, col_idx):
- box = tk.Frame(parent, bg=color, bd=2, relief=tk.GROOVE, width=250, height=80)
- box.grid(row=0, column=col_idx, padx=15, pady=5)
- box.grid_propagate(False)
- title_lbl = tk.Label(
- box, text=title, fg="#ecf0f1", bg=color, font=("Arial", 10, "italic")
- )
- title_lbl.pack(pady=2)
- val_lbl = tk.Label(
- box, text=initial_val, fg="white", bg=color, font=("Arial", 16, "bold")
- )
- val_lbl.pack(pady=5)
- return val_lbl
- def process_stock_data(self):
- ticker = self.ticker_entry.get().strip().upper()
- start_date = self.start_entry.get().strip()
- end_date = self.end_entry.get().strip()
- if not ticker:
- messagebox.showerror("Error", "Please enter a valid stock ticker.")
- return
- self.predict_btn.config(text="Processing...", state=tk.DISABLED)
- self.root.update_idletasks()
- try:
- # 1. Fetching Data safely
- df = yf.download(ticker, start=start_date, end=end_date)
- if df.empty:
- raise ValueError("No data returned. Check ticker name or dates.")
- # Flatten multi-level columns if returned by newer yfinance versions
- if isinstance(df.columns, pd.MultiIndex):
- if ticker in df.columns.levels[1]:
- df = df.xs(ticker, axis=1, level=1)
- else:
- df.columns = df.columns.get_level_values(0)
- # 2. Feature Engineering
- df["MA10"] = df["Close"].rolling(window=10).mean()
- df["MA50"] = df["Close"].rolling(window=50).mean()
- df["Returns"] = df["Close"].pct_change()
- df["Volatility"] = df["Returns"].rolling(window=10).std()
- # Target variable: Next day's closing price
- df["Target"] = df["Close"].shift(-1)
- # Clean up missing rows caused by rolling calculations
- df.dropna(inplace=True)
- if len(df) < 60:
- raise ValueError(
- "Not enough data days within range to train the ML model safely."
- )
- # Define Features & Target arrays
- feature_cols = ["Close", "MA10", "MA50", "Volatility"]
- X = df[feature_cols].values
- y = df["Target"].values
- # 3. Machine Learning Model Setup
- # FIXED: 'test_size=0.2' replaces the old typo parameter
- X_train, X_test, y_train, y_test = train_test_split(
- X, y, test_size=0.2, shuffle=False
- )
- model = RandomForestRegressor(n_estimators=100, random_state=42)
- model.fit(X_train, y_train)
- # Evaluate Test Performance
- test_preds = model.predict(X_test)
- mse = mean_squared_error(y_test, test_preds)
- # Predict Future (Next Day)
- latest_features = X[-1].reshape(1, -1)
- next_day_pred = model.predict(latest_features)[0]
- last_actual_close = float(df["Close"].iloc[-1])
- # Update Metrics UI
- self.last_close_label.config(text=f"${last_actual_close:.2f}")
- self.predicted_label.config(text=f"${next_day_pred:.2f}")
- self.mse_label.config(text=f"{mse:.4f}")
- # 4. Clear Old Charts & Render New Graphic
- for widget in self.plot_frame.winfo_children():
- widget.destroy()
- self.update_chart(df, y_test, test_preds, ticker)
- except Exception as e:
- messagebox.showerror("Execution Error", f"An error occurred:\n{str(e)}")
- finally:
- self.predict_btn.config(text="Run Prediction Model", state=tk.NORMAL)
- def update_chart(self, df, y_test, test_preds, ticker):
- fig, ax = plt.subplots(figsize=(10, 4.5), dpi=100)
- ax.set_facecolor("#f8f9fa")
- # Sync test split timelines
- test_dates = df.index[-len(y_test) :]
- ax.plot(
- df.index,
- df["Close"],
- label="Historical Full Trend",
- color="#7f8c8d",
- alpha=0.5,
- )
- ax.plot(
- test_dates,
- y_test,
- label="Actual Test Split Price",
- color="#2ecc71",
- linewidth=1.5,
- )
- ax.plot(
- test_dates,
- test_preds,
- label="AI Predicted Path",
- color="#e74c3c",
- linestyle="--",
- linewidth=1.5,
- )
- ax.set_title(
- f"{ticker} - Actual vs AI Model Backtest Tracking",
- fontsize=12,
- fontweight="bold",
- color="#2c3e50",
- )
- ax.set_xlabel("Timeline", fontsize=10)
- ax.set_ylabel("Price (USD)", fontsize=10)
- ax.legend(loc="upper left")
- ax.grid(True, linestyle=":", alpha=0.6)
- fig.tight_layout()
- canvas = FigureCanvasTkAgg(fig, master=self.plot_frame)
- canvas.draw()
- canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
- if __name__ == "__main__":
- root = tk.Tk()
- app = StockPredictorApp(root)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment