import gradio as gr import yfinance as yf import pandas as pd import numpy as np import plotly.graph_objects as go from transformers import pipeline from datetime import datetime import requests from bs4 import BeautifulSoup import feedparser # ------------------- Initialize Models ------------------- sentiment_analyzer = pipeline("text-classification", model="ProsusAI/finbert") news_summarizer = pipeline("summarization", model="facebook/bart-large-cnn") translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ur-en") # ------------------- Technical Analysis Functions ------------------- def calculate_rsi(data, window=14): delta = data['Close'].diff() gain = (delta.where(delta > 0, 0)).rolling(window=window).mean() loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean() rs = gain / loss return 100 - (100 / (1 + rs)) def calculate_macd(data, slow=26, fast=12, signal=9): exp1 = data['Close'].ewm(span=fast, adjust=False).mean() exp2 = data['Close'].ewm(span=slow, adjust=False).mean() macd = exp1 - exp2 signal_line = macd.ewm(span=signal, adjust=False).mean() return macd, signal_line # ------------------- Data Fetching & Processing ------------------- def get_psx_data(ticker): try: stock = yf.Ticker(f"{ticker}.KA") data = stock.history(period="1y") if data.empty: return None, "Invalid ticker or no data available" # Calculate indicators data['RSI'] = calculate_rsi(data) data['MACD'], data['Signal'] = calculate_macd(data) data['MA50'] = data['Close'].rolling(window=50).mean() data['MA200'] = data['Close'].rolling(window=200).mean() return data, None except Exception as e: return None, str(e) # ------------------- News & Sentiment Analysis ------------------- def analyze_psx_news(): news_items = [] try: feed = feedparser.parse("https://www.dawn.com/feeds/pakistan") for entry in feed.entries[:5]: # Limit to 5 articles try: # Translate Urdu content to English if any(char in entry.title for char in ['\u0600', '\u0800']): # Detect Urdu characters translated = translator(entry.title)[0]['translation_text'] title = f"[URDU] {translated}" else: title = entry.title # Analyze sentiment sentiment = sentiment_analyzer(title)[0] news_items.append({ 'title': title, 'sentiment': sentiment['label'], 'score': sentiment['score'], 'link': entry.link }) except: continue except: pass return news_items # ------------------- Gradio Interface ------------------- def analyze_stock(ticker): # Get stock data data, error = get_psx_data(ticker) if error: return error, None, None, None # Create price chart fig = go.Figure() fig.add_trace(go.Candlestick(x=data.index, open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], name='Price')) fig.add_trace(go.Scatter(x=data.index, y=data['MA50'], line=dict(color='orange', width=1), name='MA50')) fig.add_trace(go.Scatter(x=data.index, y=data['MA200'], line=dict(color='blue', width=1), name='MA200')) fig.update_layout(title=f"{ticker} Technical Analysis", xaxis_rangeslider_visible=False) # Generate signals latest = data.iloc[-1] rsi_signal = "Oversold" if latest['RSI'] < 30 else "Overbought" if latest['RSI'] > 70 else "Neutral" macd_signal = "Bullish" if latest['MACD'] > latest['Signal'] else "Bearish" # News analysis news = analyze_psx_news() news_html = "
RSI: {latest['RSI']:.2f} ({rsi_signal})
MACD: {macd_signal}
50-Day MA: {latest['MA50']:.2f}
200-Day MA: {latest['MA200']:.2f}