File size: 9,723 Bytes
c317182
8a40047
1ee6e16
45474bc
12a207c
1ee6e16
c317182
12a207c
c2091ec
c317182
5627ab5
12a207c
 
 
4f9f923
 
 
12a207c
4f9f923
 
 
 
 
12a207c
 
4f9f923
 
12a207c
4f9f923
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ee6e16
45474bc
4f9f923
 
 
 
 
12a207c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4f9f923
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2091ec
4f9f923
 
 
 
 
1ee6e16
4f9f923
 
1ee6e16
4f9f923
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ee6e16
 
4f9f923
 
 
c317182
4f9f923
c317182
4f9f923
 
c317182
12a207c
 
c317182
12a207c
 
 
 
 
 
c317182
12a207c
 
 
 
 
 
 
 
 
75b661f
12a207c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c317182
4f9f923
12a207c
 
4f9f923
 
c317182
 
4f9f923
c317182
 
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import streamlit as st
import plotly
import yfinance as yf
import pandas as pd
import plotly.graph_objs as plt
from groq import Groq
import os
from dotenv import load_dotenv
from duckduckgo_search import DDGS

# Lad environment variables from .env file
load_dotenv()

# Streamlit App Configuration
st.set_page_config(
    page_title="Financial Analysis AI Agent",
    page_icon="πŸ’Ή",
    layout="wide"
)

# Initialize Groq Client
def get_groq_client():
    try:
        # Try to get API key from environment variables
        groq_api_key = os.getenv("GROQ_API_KEY")
        
        if not groq_api_key:
            st.error("Groq API Key is missing. Please set GROQ_API_KEY in your .env file.")
            return None
        
        return Groq(api_key=groq_api_key)
    except Exception as e:
        st.error(f"Error initializing Groq client: {e}")
        return None

# Fetch Stock Information
def get_stock_info(symbol):
    try:
        stock = yf.Ticker(symbol)
        
        # Fetch key information
        info = stock.info
        
        # Create a structured dictionary of key financial metrics
        stock_data = {
            "Company Name": info.get('longName', 'N/A'),
            "Current Price": f"${info.get('currentPrice', 'N/A'):.2f}",
            "Market Cap": f"${info.get('marketCap', 'N/A'):,}",
            "PE Ratio": info.get('trailingPE', 'N/A'),
            "Dividend Yield": f"{info.get('dividendYield', 'N/A'):.2%}",
            "52 Week High": f"${info.get('fiftyTwoWeekHigh', 'N/A'):.2f}",
            "52 Week Low": f"${info.get('fiftyTwoWeekLow', 'N/A'):.2f}",
            "Sector": info.get('sector', 'N/A'),
            "Industry": info.get('industry', 'N/A')
        }
        
        return stock_data
    except Exception as e:
        st.error(f"Error fetching stock information: {e}")
        return None

# Fetch Historical Stock Data and Calculate Volatility
def get_stock_volatility(symbol, period='1y'):
    try:
        # Download historical stock data
        stock_data = yf.download(symbol, period=period)
        
        if stock_data.empty:
            st.error(f"No historical data found for {symbol}")
            return None
        
        # Calculate daily returns
        stock_data['Daily Returns'] = stock_data['Close'].pct_change()
        
        # Calculate rolling volatility (30-day standard deviation of returns)
        stock_data['Rolling Volatility'] = stock_data['Daily Returns'].rolling(window=30).std() * (252 ** 0.5)  # Annualized
        
        return stock_data
    except Exception as e:
        st.error(f"Error fetching historical stock data: {e}")
        return None

# Create Volatility Visualization
def create_volatility_chart(stock_data):
    try:
        # Create figure with two y-axes
        fig = plt.Figure()
        
        # Price line
        fig.add_trace(
            plt.Scatter(
                x=stock_data.index, 
                y=stock_data['Close'], 
                name='Stock Price', 
                line=dict(color='blue'),
                yaxis='y1'
            )
        )
        
        # Volatility line
        fig.add_trace(
            plt.Scatter(
                x=stock_data.index, 
                y=stock_data['Rolling Volatility'], 
                name='30-Day Volatility', 
                line=dict(color='red'),
                yaxis='y2'
            )
        )
        
        # Layout configuration
        fig.update_layout(
            title=f'Stock Price and Volatility',
            xaxis_title='Date',
            yaxis_title='Stock Price',
            yaxis2=dict(
                title='Annualized Volatility',
                overlaying='y',
                side='right'
            ),
            height=600,
            legend=dict(x=0, y=1.1, orientation='h')
        )
        
        return fig
    except Exception as e:
        st.error(f"Error creating volatility chart: {e}")
        return None

# Fetch News Using DuckDuckGo
def get_duckduckgo_news(symbol, limit=5):
    try:
        with DDGS() as ddgs:
            # Search for recent news about the stock
            news_results = list(ddgs.news(f"{symbol} stock recent news", max_results=limit))
            
            # Transform results to a consistent format
            formatted_news = [
                {
                    "title": result.get('title', 'N/A'),
                    "link": result.get('url', ''),
                    "publisher": result.get('source', 'N/A'),
                    "source": "DuckDuckGo"
                } for result in news_results
            ]
            
            return formatted_news
    except Exception as e:
        st.warning(f"DuckDuckGo news search error: {e}")
        return []

# Generate AI Analysis
def generate_ai_analysis(stock_info, news, query_type):
    client = get_groq_client()
    if not client:
        return "Unable to generate AI analysis due to client initialization error."
    
    try:
        # Prepare context for AI
        stock_context = "\n".join([f"{k}: {v}" for k, v in stock_info.items()])
        
        # Prepare news context
        news_context = "Recent News:\n" + "\n".join([
            f"- {news['title']} (Source: {news['publisher']})"
            for news in news
        ])
        
        # Full context
        full_context = f"{stock_context}\n\n{news_context}"
        
        # Generate prompt based on query type
        if query_type == "Analyst Recommendations":
            prompt = f"Provide a comprehensive analysis of analyst recommendations for this stock. Consider the following details:\n{full_context}\n\nFocus on: current analyst ratings, price targets, and recent sentiment changes."
        elif query_type == "Latest News Analysis":
            prompt = f"Analyze the latest news and its potential impact on the stock. Consider these details:\n{full_context}\n\nProvide insights on how recent news might affect the stock's performance."
        elif query_type == "Comprehensive Analysis":
            prompt = f"Provide a holistic analysis of the stock, integrating financial metrics and recent news:\n{full_context}\n\nOffer a balanced perspective on investment potential."
        else:
            prompt = f"Generate a detailed financial and news-based analysis:\n{full_context}"
        
        # Generate response using Groq
        response = client.chat.completions.create(
            model="llama3-70b-8192",
            messages=[
                {"role": "system", "content": "You are a professional financial analyst providing nuanced stock insights."},
                {"role": "user", "content": prompt}
            ]
        )
        
        return response.choices[0].message.content
    except Exception as e:
        return f"Error generating AI analysis: {e}"

# Main Streamlit App
def main():
    st.title("πŸš€ Advanced Financial Insight AI")
    st.markdown("Comprehensive stock analysis with DuckDuckGo news search")

    # Sidebar Configuration
    st.sidebar.header("πŸ” Stock Analysis")
    
    # Stock Symbol Input
    stock_symbol = st.sidebar.text_input(
        "Enter Stock Symbol", 
        value="NVDA", 
        help="Enter a valid stock ticker (e.g., AAPL, GOOGL)"
    )

    # Analysis Type Selection
    query_type = st.sidebar.selectbox(
        "Select Analysis Type",
        [
            "Comprehensive Analysis",
            "Analyst Recommendations",
            "Latest News Analysis"
        ]
    )

    # Generate Analysis Button
    if st.sidebar.button("Generate Analysis"):
        with st.spinner("Fetching and analyzing stock data..."):
            try:
                # Fetch Stock Information
                stock_info = get_stock_info(stock_symbol)
                
                if stock_info:
                    # Display Stock Information
                    st.subheader(f"Financial Snapshot: {stock_symbol}")
                    info_df = pd.DataFrame.from_dict(stock_info, orient='index', columns=['Value'])
                    st.table(info_df)
                
                # Fetch and Display Volatility Chart
                volatility_data = get_stock_volatility(stock_symbol)
                if volatility_data is not None:
                    # Create and Display Volatility Chart
                    st.subheader("πŸ“Š Stock Price and Volatility")
                    volatility_chart = create_volatility_chart(volatility_data)
                    st.plotly_chart(volatility_chart, use_container_width=True)
                
                # Fetch News via DuckDuckGo
                real_time_news = get_duckduckgo_news(stock_symbol)
                
                # Display News
                st.subheader("πŸ“° Latest News")
                for news in real_time_news:
                    st.markdown(f"**{news['title']}**")
                    st.markdown(f"*Source: {news['publisher']}*")
                    st.markdown(f"[Read more]({news['link']})")
                    st.markdown("---")
                
                # Generate AI Analysis
                ai_analysis = generate_ai_analysis(stock_info, real_time_news, query_type)
                
                # Display AI Analysis
                st.subheader("πŸ€– AI-Powered Insights")
                st.write(ai_analysis)
                
            except Exception as e:
                st.error(f"An error occurred: {e}")

    # Disclaimer
    st.sidebar.markdown("---")
    st.sidebar.warning(
        "🚨 Disclaimer: This is an AI-generated analysis. "
        "Always consult with a financial advisor before making investment decisions."
    )

# Run the Streamlit app
if __name__ == "__main__":
    main()