NeuSpaarX commited on
Commit
67f501e
·
verified ·
1 Parent(s): 33fd6a6

Delete main.py

Browse files
Files changed (1) hide show
  1. main.py +0 -544
main.py DELETED
@@ -1,544 +0,0 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import plotly.graph_objects as go
4
- import plotly.express as px
5
- from datetime import datetime, timedelta
6
- from phi.agent.agent import Agent
7
- from phi.model.groq import Groq
8
- from phi.tools.yfinance import YFinanceTools
9
- from phi.tools.duckduckgo import DuckDuckGo
10
- from phi.tools.googlesearch import GoogleSearch
11
- import yfinance as yf
12
-
13
- import os
14
- from dotenv import load_dotenv
15
-
16
- # Load environment variables from .env file
17
- load_dotenv()
18
-
19
- # Get API key from environment variables
20
- GROQ_API_KEY = os.getenv("GROQ_API_KEY")
21
-
22
- # Add error handling
23
- if not GROQ_API_KEY:
24
- st.error("GROQ_API_KEY not found. Please check your .env file.")
25
-
26
- # Enhanced stock symbol mappings
27
- COMMON_STOCKS = {
28
- # US Stocks
29
- 'NVIDIA': 'NVDA',
30
- 'APPLE': 'AAPL',
31
- 'GOOGLE': 'GOOGL',
32
- 'MICROSOFT': 'MSFT',
33
- 'TESLA': 'TSLA',
34
- 'AMAZON': 'AMZN',
35
- 'META': 'META',
36
- 'NETFLIX': 'NFLX',
37
- # Indian Stocks - NSE
38
- 'TCS': 'TCS.NS',
39
- 'RELIANCE': 'RELIANCE.NS',
40
- 'INFOSYS': 'INFY.NS',
41
- 'WIPRO': 'WIPRO.NS',
42
- 'HDFC': 'HDFCBANK.NS',
43
- 'TATAMOTORS': 'TATAMOTORS.NS',
44
- 'ICICIBANK': 'ICICIBANK.NS',
45
- 'SBIN': 'SBIN.NS',
46
- 'MARUTI': 'MARUTI.NS',
47
- 'BHARTIARTL': 'BHARTIARTL.NS',
48
- 'HCLTECH': 'HCLTECH.NS',
49
- 'ITC': 'ITC.NS',
50
- 'AXISBANK': 'AXISBANK.NS'
51
- }
52
-
53
- # Page configuration
54
- st.set_page_config(
55
- page_title="Advanced Stock Market Analysis",
56
- page_icon="📈",
57
- layout="wide",
58
- initial_sidebar_state="expanded"
59
- )
60
-
61
- # Custom CSS with improved styling
62
- st.markdown("""
63
- <style>
64
- .main {
65
- padding: 2rem;
66
- }
67
- .stApp {
68
- max-width: 1400px;
69
- margin: 0 auto;
70
- }
71
- .metric-card {
72
- background-color: #f8f9fa;
73
- border-radius: 10px;
74
- padding: 1rem;
75
- margin: 0.5rem 0;
76
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
77
- transition: transform 0.2s;
78
- }
79
- .metric-card:hover {
80
- transform: translateY(-2px);
81
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
82
- }
83
- .stock-header {
84
- font-size: 28px;
85
- font-weight: bold;
86
- margin-bottom: 20px;
87
- color: #f4e285;
88
- text-align: center;
89
- padding: 1rem;
90
- background: #1a1f36;
91
- border-radius: 10px;
92
- }
93
- .news-card {
94
- background-color: white;
95
- padding: 1rem;
96
- border-radius: 5px;
97
- margin: 10px 0;
98
- border-left: 4px solid #1f77b4;
99
- transition: transform 0.2s;
100
- }
101
- .news-card:hover {
102
- transform: translateX(5px);
103
- }
104
- .stButton>button {
105
- width: 100%;
106
- }
107
- .market-indicator {
108
- font-size: 16px;
109
- color: #666;
110
- text-align: center;
111
- margin-bottom: 1rem;
112
- }
113
- </style>
114
- """, unsafe_allow_html=True)
115
-
116
- # Initialize session state
117
- if 'agents_initialized' not in st.session_state:
118
- st.session_state.agents_initialized = False
119
- st.session_state.watchlist = set()
120
- st.session_state.analysis_history = []
121
- st.session_state.last_refresh = None
122
-
123
- def initialize_agents():
124
- """Initialize all agent instances with improved error handling"""
125
- if not st.session_state.agents_initialized:
126
- try:
127
- st.session_state.web_agent = Agent(
128
- name="Web Search Agent",
129
- role="Search the web for the information",
130
- model=Groq(api_key=GROQ_API_KEY,
131
- id="llama-3.3-70b-versatile"),
132
- tools=[
133
- GoogleSearch(fixed_language='english', fixed_max_results=5)
134
- # DuckDuckGo(fixed_max_results=1)
135
- ],
136
- instructions=['Always include sources and verification'],
137
- show_tool_calls=True,
138
- markdown=True
139
- )
140
-
141
- st.session_state.finance_agent = Agent(
142
- name="Financial AI Agent",
143
- role="Providing financial insights",
144
- model=Groq(api_key=GROQ_API_KEY,
145
- id="llama-3.3-70b-versatile"),
146
- tools=[
147
- YFinanceTools(
148
- stock_price=True,
149
- company_news=True,
150
- analyst_recommendations=True,
151
- historical_prices=True
152
- )
153
- ],
154
- instructions=["Provide detailed analysis with data visualization"],
155
- show_tool_calls=True,
156
- markdown=True
157
- )
158
-
159
- st.session_state.multi_ai_agent = Agent(
160
- name='A Stock Market Agent',
161
- role='A comprehensive assistant specializing in stock market analysis',
162
- model=Groq(api_key=GROQ_API_KEY,
163
- id="llama-3.3-70b-versatile"),
164
- team=[st.session_state.web_agent, st.session_state.finance_agent],
165
- instructions=["Provide comprehensive analysis with multiple data sources"],
166
- show_tool_calls=True,
167
- markdown=True
168
- )
169
-
170
- st.session_state.agents_initialized = True
171
- return True
172
- except Exception as e:
173
- st.error(f"Error initializing agents: {str(e)}")
174
- return False
175
-
176
- def get_symbol_from_name(stock_name):
177
- """Enhanced function to fetch stock symbol from full stock name"""
178
- try:
179
- # Clean up input
180
- stock_name = stock_name.strip().upper()
181
-
182
- # First check if it's in our common stocks dictionary
183
- if stock_name in COMMON_STOCKS:
184
- return COMMON_STOCKS[stock_name]
185
-
186
- # Check if it's already a valid symbol
187
- ticker = yf.Ticker(stock_name)
188
- try:
189
- info = ticker.info
190
- if info and 'symbol' in info:
191
- return stock_name
192
- except:
193
- pass
194
-
195
- # Try Indian stock market (NSE)
196
- try:
197
- indian_symbol = f"{stock_name}.NS"
198
- ticker = yf.Ticker(indian_symbol)
199
- info = ticker.info
200
- if info and 'symbol' in info:
201
- return indian_symbol
202
- except:
203
- # Try BSE
204
- try:
205
- bse_symbol = f"{stock_name}.BO"
206
- ticker = yf.Ticker(bse_symbol)
207
- info = ticker.info
208
- if info and 'symbol' in info:
209
- return bse_symbol
210
- except:
211
- pass
212
-
213
- st.error(f"Could not find valid symbol for {stock_name}")
214
- return None
215
- except Exception as e:
216
- st.error(f"Error processing {stock_name}: {str(e)}")
217
- return None
218
-
219
- def get_stock_data(symbol, period="1y"):
220
- """Enhanced function to fetch stock data with proper cache handling"""
221
- try:
222
- # Create a new ticker instance
223
- stock = yf.Ticker(symbol)
224
-
225
- # Fetch data with error handling
226
- try:
227
- info = stock.info
228
- if not info:
229
- raise ValueError("No data retrieved for symbol")
230
- except Exception as info_error:
231
- # If .NS suffix is missing for Indian stocks, try adding it
232
- if not symbol.endswith('.NS') and not symbol.endswith('.BO'):
233
- try:
234
- indian_symbol = f"{symbol}.NS"
235
- stock = yf.Ticker(indian_symbol)
236
- info = stock.info
237
- symbol = indian_symbol
238
- except:
239
- # Try Bombay Stock Exchange
240
- try:
241
- bse_symbol = f"{symbol}.BO"
242
- stock = yf.Ticker(bse_symbol)
243
- info = stock.info
244
- symbol = bse_symbol
245
- except:
246
- raise info_error
247
- else:
248
- raise info_error
249
-
250
- # Fetch historical data
251
- hist = stock.history(period=period, interval="1d", auto_adjust=True)
252
-
253
- if hist.empty:
254
- raise ValueError("No historical data available")
255
-
256
- return info, hist
257
- except Exception as e:
258
- st.error(f"Error fetching data for {symbol}: {str(e)}")
259
- return None, None
260
-
261
- def create_price_chart(hist_data, symbol):
262
- """Create an interactive price chart using plotly"""
263
- fig = go.Figure()
264
-
265
- # Add candlestick chart
266
- fig.add_trace(go.Candlestick(
267
- x=hist_data.index,
268
- open=hist_data['Open'],
269
- high=hist_data['High'],
270
- low=hist_data['Low'],
271
- close=hist_data['Close'],
272
- name='Price'
273
- ))
274
-
275
- # Add moving averages
276
- ma20 = hist_data['Close'].rolling(window=20).mean()
277
- ma50 = hist_data['Close'].rolling(window=50).mean()
278
-
279
- fig.add_trace(go.Scatter(x=hist_data.index, y=ma20, name='20 Day MA', line=dict(color='orange')))
280
- fig.add_trace(go.Scatter(x=hist_data.index, y=ma50, name='50 Day MA', line=dict(color='blue')))
281
-
282
- fig.update_layout(
283
- title=f'{symbol} Stock Price',
284
- yaxis_title='Price',
285
- template='plotly_white',
286
- xaxis_rangeslider_visible=False,
287
- height=600
288
- )
289
-
290
- return fig
291
-
292
- def create_volume_chart(hist_data):
293
- """Create enhanced volume chart using plotly"""
294
- # Calculate volume moving average
295
- volume_ma = hist_data['Volume'].rolling(window=20).mean()
296
-
297
- fig = go.Figure()
298
-
299
- # Add volume bars
300
- fig.add_trace(go.Bar(
301
- x=hist_data.index,
302
- y=hist_data['Volume'],
303
- name='Volume',
304
- marker_color='rgba(31, 119, 180, 0.3)'
305
- ))
306
-
307
- # Add volume moving average
308
- fig.add_trace(go.Scatter(
309
- x=hist_data.index,
310
- y=volume_ma,
311
- name='20 Day Volume MA',
312
- line=dict(color='red')
313
- ))
314
-
315
- fig.update_layout(
316
- title='Trading Volume Analysis',
317
- yaxis_title='Volume',
318
- template='plotly_white',
319
- height=400
320
- )
321
-
322
- return fig
323
-
324
- def format_large_number(number):
325
- """Format large numbers into readable format"""
326
- if number >= 1e12:
327
- return f"${number/1e12:.2f}T"
328
- elif number >= 1e9:
329
- return f"${number/1e9:.2f}B"
330
- elif number >= 1e6:
331
- return f"${number/1e6:.2f}M"
332
- else:
333
- return f"${number:,.2f}"
334
-
335
- def display_metrics(info):
336
- """Display enhanced key metrics in a grid"""
337
- col1, col2, col3, col4 = st.columns(4)
338
-
339
- with col1:
340
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
341
- market_cap = info.get('marketCap', 'N/A')
342
- if market_cap != 'N/A':
343
- market_cap = format_large_number(market_cap)
344
- st.metric("Market Cap", market_cap)
345
- st.markdown('</div>', unsafe_allow_html=True)
346
-
347
- with col2:
348
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
349
- pe_ratio = info.get('trailingPE', 'N/A')
350
- if pe_ratio != 'N/A':
351
- pe_ratio = f"{pe_ratio:.2f}"
352
- st.metric("P/E Ratio", pe_ratio)
353
- st.markdown('</div>', unsafe_allow_html=True)
354
-
355
- with col3:
356
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
357
- high = info.get('fiftyTwoWeekHigh', 'N/A')
358
- if high != 'N/A':
359
- high = f"${high:.2f}"
360
- st.metric("52 Week High", high)
361
- st.markdown('</div>', unsafe_allow_html=True)
362
-
363
- with col4:
364
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
365
- low = info.get('fiftyTwoWeekLow', 'N/A')
366
- if low != 'N/A':
367
- low = f"${low:.2f}"
368
- st.metric("52 Week Low", low)
369
- st.markdown('</div>', unsafe_allow_html=True)
370
-
371
- def main():
372
- # Sidebar
373
- with st.sidebar:
374
- st.header("📊 Analysis Options")
375
- analysis_type = st.selectbox(
376
- "Choose Analysis Type",
377
- ["Comprehensive Analysis", "Technical Analysis", "Fundamental Analysis",
378
- "News Analysis", "Sentiment Analysis"]
379
- )
380
-
381
- # Add market selection
382
- market = st.selectbox(
383
- "Select Market",
384
- ["US Market", "Indian Market (NSE)", "Indian Market (BSE)"]
385
- )
386
-
387
- st.markdown("---")
388
-
389
-
390
-
391
- # Main content
392
- st.markdown('<h1 class="stock-header">🤖 Advanced Stock Market Analysis By NeuSpaarX</h1>',
393
- unsafe_allow_html=True)
394
-
395
- # Search and Analysis Section
396
- col1, col2 = st.columns([2, 1])
397
- with col1:
398
- stock_input = st.text_input(
399
- "Enter Stock Name or Symbol",
400
- help="Enter company name (e.g., NVIDIA) or symbol (e.g., NVDA)"
401
- )
402
- with col2:
403
- date_range = st.selectbox(
404
- "Select Time Range",
405
- ["1 Month", "3 Months", "6 Months", "1 Year", "5 Years"], key="time_range"
406
- )
407
- # Convert selected range to yfinance period format
408
- period_map = {
409
- "1 Month": "1mo",
410
- "3 Months": "3mo",
411
- "6 Months": "6mo",
412
- "1 Year": "1y",
413
- "5 Years": "5y"
414
- }
415
- period = period_map[date_range]
416
-
417
- if st.button("Analyze", type="primary"):
418
- if not stock_input:
419
- st.error("Please enter a stock name or symbol.")
420
- return
421
-
422
- # Convert input to symbol
423
- stock_symbol = get_symbol_from_name(stock_input)
424
- if stock_symbol:
425
- try:
426
- # Initialize agents
427
- if initialize_agents():
428
- # Show loading spinner
429
- with st.spinner(f"Analyzing {stock_symbol}..."):
430
- # Fetch fresh stock data
431
- info, hist = get_stock_data(stock_symbol, period=period)
432
-
433
- if info and hist is not None:
434
- # Display market status
435
- market_status = "🟢 Market Open" if info.get('regularMarketOpen') else "🔴 Market Closed"
436
- st.markdown(f"<div class='market-indicator'>{market_status}</div>", unsafe_allow_html=True)
437
-
438
- # Create tabs for different sections
439
- overview_tab, charts_tab = st.tabs(["Overview", "Charts"])
440
-
441
- with overview_tab:
442
- # Display company info
443
- st.markdown("### Company Overview")
444
- st.write(info.get('longBusinessSummary', 'No description available.'))
445
-
446
- # Display key metrics
447
- st.markdown("### Key Metrics")
448
- display_metrics(info)
449
-
450
- # Additional company information
451
- col1, col2 = st.columns(2)
452
- with col1:
453
- st.markdown("### Company Details")
454
- st.write(f"Sector: {info.get('sector', 'N/A')}")
455
- st.write(f"Industry: {info.get('industry', 'N/A')}")
456
- st.write(f"Country: {info.get('country', 'N/A')}")
457
- st.write(f"Employees: {info.get('fullTimeEmployees', 'N/A'):,}")
458
-
459
- with col2:
460
- st.markdown("### Trading Information")
461
- st.write(f"Exchange: {info.get('exchange', 'N/A')}")
462
- st.write(f"Currency: {info.get('currency', 'N/A')}")
463
- st.write(f"Volume: {info.get('volume', 'N/A'):,}")
464
-
465
- with charts_tab:
466
- # Price chart
467
- st.markdown("### Price Analysis")
468
- price_chart = create_price_chart(hist, stock_symbol)
469
- st.plotly_chart(price_chart, use_container_width=True)
470
-
471
- # Volume chart
472
- volume_chart = create_volume_chart(hist)
473
- st.plotly_chart(volume_chart, use_container_width=True)
474
-
475
- # Technical indicators
476
- st.markdown("### Technical Indicators")
477
- col1, col2, col3 = st.columns(3)
478
-
479
- with col1:
480
- rsi = hist['Close'].diff()
481
- rsi_pos = rsi.copy()
482
- rsi_neg = rsi.copy()
483
- rsi_pos[rsi_pos < 0] = 0
484
- rsi_neg[rsi_neg > 0] = 0
485
- rsi_14_pos = rsi_pos.rolling(window=14).mean()
486
- rsi_14_neg = abs(rsi_neg.rolling(window=14).mean())
487
- rsi_14 = 100 - (100 / (1 + rsi_14_pos / rsi_14_neg))
488
- st.metric("RSI (14)", f"{rsi_14.iloc[-1]:.2f}")
489
-
490
- with col2:
491
- ma20 = hist['Close'].rolling(window=20).mean()
492
- ma50 = hist['Close'].rolling(window=50).mean()
493
- cross_signal = "Bullish" if ma20.iloc[-1] > ma50.iloc[-1] else "Bearish"
494
- st.metric("MA Cross Signal", cross_signal)
495
-
496
- with col3:
497
- volatility = hist['Close'].pct_change().std() * (252 ** 0.5) * 100
498
- st.metric("Annualized Volatility", f"{volatility:.2f}%")
499
-
500
-
501
- # Add refresh button
502
- if st.button("🔄 Refresh Data"):
503
- st.session_state.last_refresh = datetime.now()
504
- st.experimental_rerun()
505
-
506
- except Exception as e:
507
- st.error(f"An error occurred: {str(e)}")
508
-
509
- # Display analysis history
510
- if st.session_state.analysis_history:
511
- st.markdown("---")
512
- st.markdown("### Recent Analysis History")
513
- history_df = pd.DataFrame(st.session_state.analysis_history)
514
- history_df['timestamp'] = history_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
515
- st.dataframe(history_df, use_container_width=True)
516
-
517
- # Footer
518
- st.markdown("---")
519
- st.markdown("### About")
520
- st.markdown("""
521
- This advanced stock market analysis tool combines:
522
- - Real-time market data analysis
523
- - AI-powered insights and predictions
524
- - Technical and fundamental analysis
525
- - News and sentiment analysis
526
- - Interactive charts and visualizations
527
-
528
- Features:
529
- - Support for both US and Indian markets (NSE/BSE)
530
- - Company name and symbol resolution
531
- - Watchlist management
532
- - Multiple timeframe analysis
533
- - Technical indicators
534
-
535
- Use the sidebar to configure your analysis preferences and manage your watchlist.
536
- """)
537
-
538
- # Display last refresh time if available
539
- if st.session_state.last_refresh:
540
- st.markdown(f"<div class='market-indicator'>Last refreshed: {st.session_state.last_refresh.strftime('%Y-%m-%d %H:%M:%S')}</div>",
541
- unsafe_allow_html=True)
542
-
543
- if __name__ == "__main__":
544
- main()