File size: 5,619 Bytes
007ca59
 
 
aa14fca
007ca59
 
aa14fca
007ca59
 
 
 
aa14fca
007ca59
 
 
 
aa14fca
007ca59
 
 
 
 
aa14fca
007ca59
aa14fca
 
 
 
 
 
 
 
 
007ca59
aa14fca
 
007ca59
aa14fca
 
 
007ca59
aa14fca
 
 
 
007ca59
 
aa14fca
007ca59
aa14fca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
007ca59
 
 
aa14fca
 
007ca59
aa14fca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
007ca59
aa14fca
007ca59
 
aa14fca
007ca59
aa14fca
 
 
007ca59
aa14fca
 
 
 
 
007ca59
 
 
aa14fca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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 = "<h3>Market News & Sentiment</h3>"
    for item in news:
        news_html += f"""
        <div style="margin-bottom: 15px; padding: 10px; border: 1px solid #eee; border-radius: 5px;">
            <b>{item['title']}</b><br>
            Sentiment: {item['sentiment']} ({item['score']:.2f})<br>
            <a href="{item['link']}" target="_blank" style="color: #007bff;">Read more</a>
        </div>
        """

    # Generate recommendation
    recommendation = f"""
    <div style="padding: 20px; background: {'#d4edda' if macd_signal == 'Bullish' else '#f8d7da'}; border-radius: 5px;">
        <h4>Recommendation for {ticker}</h4>
        <p>RSI: {latest['RSI']:.2f} ({rsi_signal})</p>
        <p>MACD: {macd_signal}</p>
        <p>50-Day MA: {latest['MA50']:.2f}</p>
        <p>200-Day MA: {latest['MA200']:.2f}</p>
        <h4 style="color: {'green' if macd_signal == 'Bullish' else 'red'};">{'Consider Buying' if macd_signal == 'Bullish' else 'Consider Selling'}</h4>
    </div>
    """

    return recommendation, fig.to_html(), news_html

# ------------------- App Configuration -------------------
iface = gr.Interface(
    fn=analyze_stock,
    inputs=gr.Textbox(label="Enter PSX Ticker (e.g., HBL, LUCK, OGDC)"),
    outputs=[
        gr.HTML(label="Recommendation"),
        gr.HTML(label="Technical Analysis"),
        gr.HTML(label="Market News")
    ],
    title="πŸš€ PSX Smart Trading Assistant",
    description="Real-time Pakistan Stock Exchange Analysis with AI-powered Insights",
    examples=[["HBL"], ["LUCK"], ["OGDC"]],
    allow_flagging="never",
    theme=gr.themes.Soft()
)

if __name__ == "__main__":
    iface.launch(server_name="0.0.0.0", server_port=7860)