analitics

Pages

Thursday, October 8, 2026

News : Python 3.15 PEP's.

Python 3.15 brings significant improvements across performance, core features, and developer tools. The startup time is now much faster thanks to explicit lazy imports, and the experimental JIT compiler provides a 7 to 12 percent speed boost depending on your operating system. The update introduces new built-in types like frozendict and sentinel, and officially makes UTF-8 the default text encoding. For developers, the standard library now includes better error messages, more console colors, and a new high-frequency profiling tool called Tachyon to help measure and optimize code performance. The type hinting system is more flexible, and there are major updates to the C API. Most notably, it includes a stable ABI for free-threaded builds, which is a massive step forward for running efficient multi-threaded Python code without the Global Interpreter Lock. Additionally, official macOS installers now include free-threading support by default, Windows 64-bit binaries use a more optimized tail-calling interpreter, and frame pointers are enabled by default for easier system-level debugging. This specific Release Candidate 3 is a surprise extra release added to fix a few last-minute bugs related to the new lazy imports before the final version is launched.
  • PEP 810: Explicit lazy imports for faster startup times
  • PEP 814: Add frozendict built-in type
  • PEP 661: Add sentinel built-in type
  • PEP 798: Unpacking in comprehensions
  • PEP 686: Python now uses UTF-8 as the default encoding
  • PEP 829: Package startup configuration files
  • PEP 799: Tachyon: High frequency statistical sampling profiler / A dedicated profiling package
  • PEP 728: TypedDict with typed extra items
  • PEP 747: Annotating type forms with TypeForm
  • PEP 800: Disjoint bases in the type system
  • PEP 803, 820, 793: Stable ABI for free-threaded builds and related C API
  • PEP 782: A new PyBytesWriter C API to create a Python bytes object
  • PEP 788: Protection against finalization in the C API
  • PEP 831: Frame pointers are enabled by default for improved system-level observability
  • PEP 790: 3.15 release schedule

tkinter : analyze stock market data for a chosen ticker symbol

This Python script creates a mobile-friendly graphical application using Tkinter to analyze stock market data for a chosen ticker symbol, such as NVDA. When you launch the app, it presents a user interface with input fields to type a stock symbol and select a time frame, like one month, six months, or one year. Upon clicking the Load button, the script sends a direct web request to Yahoo Finance. It uses a custom user browser agent header to fetch accurate raw historical market price data, avoiding network blocking or API failures on mobile Python environments. Once the raw data is downloaded, the script converts the response into a structured Pandas dataframe containing daily open, high, low, close, and volume values. It then automatically computes several key technical market indicators. It calculates 20-day and 50-day Simple Moving Averages to show price trends over time. It computes Bollinger Bands to illustrate price volatility boundaries, and it calculates the Relative Strength Index over 14 days to identify overbought or oversold market conditions. At the top of the interface, the app displays text cards showing the latest stock price, current RSI value, and moving averages. Below these metrics, it renders two interactive charts using Matplotlib embedded directly into Tkinter. The upper chart plots the stock closing price alongside the moving averages and Bollinger Bands shading. The lower chart plots the RSI line with dashed horizontal benchmark lines at values 30 and 70. In short, this script serves as a lightweight, real-time stock dashboard that fetches financial market data, calculates essential technical indicators, and visualizes price action clearly on mobile screens.
Let's see the source code:
import tkinter as tk
from tkinter import ttk, messagebox
import pandas as pd
import numpy as np
import requests
from datetime import datetime, timedelta

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

class FinancialDashboardApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Market Indicators Dashboard")
        self.root.geometry("480x800")

        # --- Controls Frame (Top) ---
        control_frame = ttk.LabelFrame(root, text=" Parametrii Simbol ")
        control_frame.pack(fill="x", padx=10, pady=5)

        ttk.Label(control_frame, text="Ticker:").grid(row=0, column=0, padx=5, pady=5)
        self.ticker_entry = ttk.Entry(control_frame, width=8)
        self.ticker_entry.insert(0, "NVDA")
        self.ticker_entry.grid(row=0, column=1, padx=5, pady=5)

        ttk.Label(control_frame, text="Perioadă:").grid(row=0, column=2, padx=5, pady=5)
        self.period_cb = ttk.Combobox(control_frame, values=["1mo", "3mo", "6mo", "1y"], width=6)
        self.period_cb.set("6mo")
        self.period_cb.grid(row=0, column=3, padx=5, pady=5)

        fetch_btn = ttk.Button(control_frame, text="Încarcă", command=self.load_data)
        fetch_btn.grid(row=0, column=4, padx=5, pady=5)

        # --- Info Cards Frame (Middle) ---
        self.info_frame = ttk.LabelFrame(root, text=" Date & Indicatori ")
        self.info_frame.pack(fill="x", padx=10, pady=5)

        self.lbl_price = ttk.Label(self.info_frame, text="Preț: -", font=("Helvetica", 10, "bold"))
        self.lbl_price.grid(row=0, column=0, sticky="w", padx=10, pady=2)

        self.lbl_rsi = ttk.Label(self.info_frame, text="RSI (14): -")
        self.lbl_rsi.grid(row=0, column=1, sticky="w", padx=10, pady=2)

        self.lbl_sma20 = ttk.Label(self.info_frame, text="SMA 20: -")
        self.lbl_sma20.grid(row=1, column=0, sticky="w", padx=10, pady=2)

        self.lbl_sma50 = ttk.Label(self.info_frame, text="SMA 50: -")
        self.lbl_sma50.grid(row=1, column=1, sticky="w", padx=10, pady=2)

        # --- Matplotlib Canvas Frame (Bottom) ---
        self.plot_frame = ttk.Frame(root)
        self.plot_frame.pack(fill="both", expand=True, padx=10, pady=5)

        self.fig = Figure(figsize=(5, 6), dpi=90)
        self.ax1 = self.fig.add_subplot(211) # Subplot Preț + SMA / Bollinger
        self.ax2 = self.fig.add_subplot(212, sharex=self.ax1) # Subplot RSI

        self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame)
        self.canvas.get_tk_widget().pack(fill="both", expand=True)

        self.load_data()

    def fetch_yahoo_data(self, symbol, range_str):
        """Descarcă date brute din Yahoo v8 API simulând un browser desktop."""
        url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={range_str}&interval=1d"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        }
        
        response = requests.get(url, headers=headers, timeout=10)
        if response.status_code != 200:
            return pd.DataFrame()

        data = response.json()
        result = data['chart']['result'][0]
        timestamps = result['timestamp']
        quote = result['indicators']['quote'][0]

        df = pd.DataFrame({
            'Open': quote['open'],
            'High': quote['high'],
            'Low': quote['low'],
            'Close': quote['close'],
            'Volume': quote['volume']
        }, index=pd.to_datetime(timestamps, unit='s'))

        df.dropna(subset=['Close'], inplace=True)
        return df

    def calculate_indicators(self, df):
        # 1. Simple Moving Averages (SMA)
        df['SMA_20'] = df['Close'].rolling(window=20).mean()
        df['SMA_50'] = df['Close'].rolling(window=50).mean()

        # 2. Bollinger Bands
        std20 = df['Close'].rolling(window=20).std()
        df['BB_Upper'] = df['SMA_20'] + (std20 * 2)
        df['BB_Lower'] = df['SMA_20'] - (std20 * 2)

        # 3. RSI (14 zile)
        delta = df['Close'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
        rs = gain / loss
        df['RSI'] = 100 - (100 / (1 + rs))

        return df

    def load_data(self):
        ticker_symbol = self.ticker_entry.get().strip().upper()
        period = self.period_cb.get()

        if not ticker_symbol:
            messagebox.showerror("Eroare", "Introduceți un ticker valid.")
            return

        try:
            # Preluare date prin request HTTP direct
            df = self.fetch_yahoo_data(ticker_symbol, period)

            if df.empty:
                messagebox.showwarning("Atenție", f"Nu s-au găsit date pentru tickerul '{ticker_symbol}'. Verificați conexiunea la internet sau simbolul introduse.")
                return

            df = self.calculate_indicators(df)

            curr_price = df['Close'].iloc[-1]
            last_rsi = df['RSI'].iloc[-1] if not pd.isna(df['RSI'].iloc[-1]) else 0.0
            last_sma20 = df['SMA_20'].iloc[-1] if not pd.isna(df['SMA_20'].iloc[-1]) else 0.0
            last_sma50 = df['SMA_50'].iloc[-1] if not pd.isna(df['SMA_50'].iloc[-1]) else 0.0

            # Actualizare etichete UI
            self.lbl_price.config(text=f"Preț: {curr_price:.2f} USD")
            self.lbl_rsi.config(text=f"RSI (14): {last_rsi:.2f}")
            self.lbl_sma20.config(text=f"SMA 20: {last_sma20:.2f}")
            self.lbl_sma50.config(text=f"SMA 50: {last_sma50:.2f}")

            # Generare grafice
            self.plot_charts(df, ticker_symbol)

        except Exception as e:
            messagebox.showerror("Eroare", f"A apărut o eroare la procesare:\n{e}")

    def plot_charts(self, df, ticker_symbol):
        self.ax1.clear()
        self.ax2.clear()

        # Grafic 1: Preț, SMA 20, SMA 50 și Benzi Bollinger
        self.ax1.plot(df.index, df['Close'], label='Close', color='black', linewidth=1.2)
        self.ax1.plot(df.index, df['SMA_20'], label='SMA 20', color='blue', linestyle='--', alpha=0.7)
        self.ax1.plot(df.index, df['SMA_50'], label='SMA 50', color='orange', linestyle='--', alpha=0.7)
        self.ax1.plot(df.index, df['BB_Upper'], label='BB Upper', color='gray', linestyle=':', alpha=0.5)
        self.ax1.plot(df.index, df['BB_Lower'], label='BB Lower', color='gray', linestyle=':', alpha=0.5)
        self.ax1.fill_between(df.index, df['BB_Lower'], df['BB_Upper'], color='gray', alpha=0.1)

        self.ax1.set_title(f"{ticker_symbol} - Preț & Indicatori", fontsize=10)
        self.ax1.legend(loc="upper left", fontsize=7)
        self.ax1.grid(True, linestyle=':', alpha=0.6)

        # Grafic 2: RSI cu nivelurile 30 și 70
        self.ax2.plot(df.index, df['RSI'], label='RSI (14)', color='purple')
        self.ax2.axhline(70, color='red', linestyle='--', alpha=0.6)   # Overbought
        self.ax2.axhline(30, color='green', linestyle='--', alpha=0.6) # Oversold
        self.ax2.set_ylim(0, 100)
        self.ax2.set_title("RSI (14)", fontsize=9)
        self.ax2.grid(True, linestyle=':', alpha=0.6)

        self.fig.autofmt_xdate(rotation=30)
        self.fig.tight_layout()
        self.canvas.draw()

if __name__ == "__main__":
    root = tk.Tk()
    app = FinancialDashboardApp(root)
    root.mainloop()