Atif-67/yfi
1
1import streamlit as st
2import yfinance as yf
3import pandas as pd
4import datetime as dt
5import plotly.graph_objects as go
6from plotly.subplots import make_subplots
7import requests
8from requests.adapters import HTTPAdapter
9from urllib3.util.retry import Retry
10
11# Page Configuration
12st.set_page_config(
13 page_title="Global Markets Pro",
14 page_icon="๐",
15 layout="wide",
16 initial_sidebar_state="expanded"
17)
18
19# Custom CSS for professional styling
20# st.markdown("""
21# <style>
22# :root {
23# --primary-color: #2563eb;
24# --secondary-color: #1e40af;
25# --accent-color: #3b82f6;
26# --background-color: #f8fafc;
27# --surface-color: #ffffff;
28# --text-color: #1e293b;
29# --text-secondary: #64748b;
30# }
31
32# .main {
33# background-color: var(--background-color);
34# color: var(--text-color);
35# }
36
37# .stSelectbox div, .stTextInput div, .stDateInput div {
38# background-color: var(--surface-color) !important;
39# border-radius: 8px !important;
40# box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
41# }
42
43# .stButton>button {
44# background-color: var(--primary-color) !important;
45# color: white !important;
46# border-radius: 8px !important;
47# padding: 0.5rem 1rem !important;
48# font-weight: 500 !important;
49# transition: all 0.2s !important;
50# }
51
52# .stButton>button:hover {
53# background-color: var(--secondary-color) !important;
54# transform: translateY(-1px) !important;
55# box-shadow: 0 4px 6px rgba(0,0,0,0.1) !important;
56# }
57
58# .stMetric {
59# background-color: var(--surface-color) !important;
60# border-radius: 12px !important;
61# padding: 1.5rem !important;
62# box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
63# }
64
65# .stDataFrame {
66# border-radius: 12px !important;
67# box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
68# }
69
70# .stTabs [aria-selected="true"] {
71# background-color: var(--primary-color) !important;
72# color: white !important;
73# }
74
75# .sidebar .sidebar-content {
76# background: linear-gradient(180deg, #2563eb 0%, #1e40af 100%) !important;
77# color: white !important;
78# }
79
80# .sidebar .sidebar-content a {
81# color: white !important;
82# }
83
84# .sidebar .sidebar-content .stMarkdown h1,
85# .sidebar .sidebar-content .stMarkdown h2,
86# .sidebar .sidebar-content .stMarkdown h3 {
87# color: white !important;
88# }
89# </style>
90# """, unsafe_allow_html=True)
91
92#just change the css becuse the css is so bright and not professional
93# Custom CSS for dark theme
94st.markdown("""
95<style>
96 :root {
97 --primary-color: #1f2937; /* Dark Gray */
98 --secondary-color: #4b5563; /* Medium Gray */
99 --accent-color: #10b981; /* Emerald Green */
100 --background-color: #111827; /* Dark Background */
101 --surface-color: #1f2937; /* Surface Background */
102 --text-color: #f9fafb; /* Light Text */
103 --text-secondary: #9ca3af; /* Muted Text */
104 }
105
106 .main {
107 background-color: var(--background-color);
108 color: var(--text-color);
109 }
110
111 .stSelectbox div, .stTextInput div, .stDateInput div {
112 background-color: var(--surface-color) !important;
113 border-radius: 8px !important;
114 box-shadow: 0 1px 3px rgba(0,0,0,0.5) !important;
115 color: var(--text-color) !important;
116 }
117
118 .stButton>button {
119 background-color: var(--accent-color) !important;
120 color: white !important;
121 border-radius: 8px !important;
122 padding: 0.5rem 1rem !important;
123 font-weight: 500 !important;
124 transition: all 0.2s !important;
125 }
126
127 .stButton>button:hover {
128 background-color: #059669 !important; /* Darker Emerald */
129 transform: translateY(-1px) !important;
130 box-shadow: 0 4px 6px rgba(0,0,0,0.5) !important;
131 }
132
133 .stMetric {
134 background-color: var(--surface-color) !important;
135 border-radius: 12px !important;
136 padding: 1.5rem !important;
137 box-shadow: 0 1px 3px rgba(0,0,0,0.5) !important;
138 color: var(--text-color) !important;
139 }
140
141 .stDataFrame {
142 border-radius: 12px !important;
143 box-shadow: 0 1px 3px rgba(0,0,0,0.5) !important;
144 color: var(--text-color) !important;
145 }
146
147 .stTabs [aria-selected="true"] {
148 background-color: var(--accent-color) !important;
149 color: white !important;
150 }
151
152 .sidebar .sidebar-content {
153 background: linear-gradient(180deg, #1f2937 0%, #4b5563 100%) !important;
154 color: white !important;
155 }
156
157 .sidebar .sidebar-content a {
158 color: var(--accent-color) !important;
159 }
160
161 .sidebar .sidebar-content .stMarkdown h1,
162 .sidebar .sidebar-content .stMarkdown h2,
163 .sidebar .sidebar-content .stMarkdown h3 {
164 color: white !important;
165 }
166</style>
167""", unsafe_allow_html=True)
168
169# Title Section
170st.title("๐ Global Markets Pro")
171st.markdown("""
172<div style="color: var(--text-secondary); margin-bottom: 2rem;">
173 Professional-grade market data analysis for investors and traders
174</div>
175""", unsafe_allow_html=True)
176
177# Enhanced Ticker List (500+ global companies)
178GLOBAL_TICKERS = {
179 "Technology": [
180 "AAPL", "MSFT", "NVDA", "AVGO", "ASML", "TSM", "ADBE", "CSCO", "ACN", "CRM",
181 "ORCL", "SAP", "INTU", "AMD", "INTC", "QCOM", "TXN", "AMAT", "LRCX", "KLAC",
182 "SNOW", "PLTR", "U", "DDOG", "ZS", "CRWD", "NET", "MDB", "NOW", "TEAM"
183 ],
184 "Finance": [
185 "JPM", "BAC", "WFC", "C", "HSBC", "GS", "MS", "BLK", "SCHW", "AXP",
186 "V", "MA", "PYPL", "SQ", "COIN", "MUFG", "RY", "TD", "BNPQY", "ING"
187 ],
188 "Consumer": [
189 "AMZN", "WMT", "COST", "TGT", "HD", "LOW", "NKE", "MCD", "SBUX", "PEP",
190 "KO", "PG", "UL", "NSRGY", "EL", "LVMUY", "KHC", "PM", "MO", "BUD"
191 ],
192 "Healthcare": [
193 "JNJ", "PFE", "ABBV", "LLY", "MRK", "NVS", "AZN", "UNH", "DHR", "TMO",
194 "ISRG", "SYK", "BDX", "BSX", "MDT", "ZTS", "VRTX", "REGN", "GILD", "BMY"
195 ],
196 "Energy & Industrials": [
197 "XOM", "CVX", "SHEL", "TTE", "BP", "ENB", "COP", "EOG", "BHP", "RIO",
198 "CAT", "DE", "HON", "GE", "BA", "RTX", "LMT", "NOC", "GD", "MMM"
199 ],
200 "Emerging Markets": [
201 "BABA", "TCEHY", "JD", "PDD", "BIDU", "NTES", "TSM", "005930.KS", "000660.KS",
202 "0688.HK", "3690.HK", "601318.SS", "600519.SS", "601288.SS", "RELIANCE.NS",
203 "TATASTEEL.NS", "INFY", "HDB", "ICICIY", "ITUB"
204 ],
205 "Crypto & Blockchain": [
206 "COIN", "MARA", "RIOT", "MSTR", "HUT", "BITF", "CLSK", "BTBT", "MOGO", "SI"
207 ],
208 "EV & Clean Energy": [
209 "TSLA", "NIO", "LI", "XPEV", "RIVN", "LCID", "FSR", "PLUG", "FCEL", "BE",
210 "ENPH", "SEDG", "FSLR", "RUN", "SPWR", "NEE", "DQ", "JKS", "CSIQ"
211 ]
212}
213
214# Session State Management
215if 'stock_data' not in st.session_state:
216 st.session_state.stock_data = None
217if 'current_ticker' not in st.session_state:
218 st.session_state.current_ticker = None
219if 'comparison_tickers' not in st.session_state:
220 st.session_state.comparison_tickers = []
221
222# Custom Session with Retries
223def create_session():
224 session = requests.Session()
225 retry = Retry(
226 total=5,
227 backoff_factor=0.5,
228 status_forcelist=[500, 502, 503, 504],
229 )
230 adapter = HTTPAdapter(max_retries=retry)
231 session.mount('http://', adapter)
232 session.mount('https://', adapter)
233 session.headers.update({
234 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
235 })
236 return session
237
238# Enhanced Data Fetching Function
239@st.cache_data(ttl=3600) # Cache for 1 hour
240def fetch_stock_data(ticker, start_date, end_date, interval='1d'):
241 try:
242 ticker_obj = yf.Ticker(ticker)
243 data = ticker_obj.history(
244 start=start_date,
245 end=end_date,
246 interval=interval,
247 auto_adjust=False,
248 actions=True
249 )
250 if data is None or data.empty:
251 return None
252 # Calculate technical indicators
253 data['SMA_50'] = data['Close'].rolling(window=50).mean()
254 data['SMA_200'] = data['Close'].rolling(window=200).mean()
255 data['Daily_Return'] = data['Close'].pct_change()
256 # Format the data
257 data = data.rename(columns={
258 'Open': 'open',
259 'High': 'high',
260 'Low': 'low',
261 'Close': 'close',
262 'Adj Close': 'adj_close',
263 'Volume': 'volume'
264 })
265 data = data.reset_index().rename(columns={'Date': 'date'})
266 return data[['date', 'open', 'high', 'low', 'close', 'adj_close', 'volume',
267 'SMA_50', 'SMA_200', 'Daily_Return']]
268 except Exception as e:
269 st.error(f"Error fetching data for {ticker}: {str(e)}")
270 return None
271
272# Sidebar - Filters and Info
273with st.sidebar:
274 st.markdown("""
275 <div style="text-align: center; margin-bottom: 2rem;">
276 <h1 style="color: white;">Global Markets Pro</h1>
277 <p style="color: rgba(255,255,255,0.8);">Professional Market Analysis</p>
278 </div>
279 """, unsafe_allow_html=True)
280
281 # Sector Selection
282 selected_sector = st.selectbox(
283 "Select Sector",
284 list(GLOBAL_TICKERS.keys()),
285 index=0
286 )
287
288 # Ticker Selection
289 selected_ticker = st.selectbox(
290 "Select Ticker",
291 GLOBAL_TICKERS[selected_sector],
292 index=0
293 )
294
295 # Date Range
296 col1, col2 = st.columns(2)
297 with col1:
298 start_date = st.date_input(
299 "Start Date",
300 value=dt.date(2020, 1, 1),
301 min_value=dt.date(1980, 1, 1),
302 max_value=dt.date.today()
303 )
304 with col2:
305 end_date = st.date_input(
306 "End Date",
307 value=dt.date.today(),
308 min_value=dt.date(1980, 1, 1),
309 max_value=dt.date.today()
310 )
311
312 # Comparison Tickers
313 comparison_tickers = st.multiselect(
314 "Compare With (Max 4)",
315 [t for sector in GLOBAL_TICKERS.values() for t in sector],
316 default=[],
317 max_selections=4
318 )
319
320 # Interval Selection
321 interval = st.selectbox(
322 "Data Interval",
323 ["1d", "1wk", "1mo"],
324 index=0
325 )
326
327 st.markdown("---")
328
329 # Social Links
330 st.markdown("""
331 <div style="margin-top: 2rem;">
332 <h3 style="color: white;">Connect</h3>
333 <p>
334 <a href="mailto:muhammadatiflatif67@gmail.com" style="color: white; text-decoration: none;">
335 ๐ง Email
336 </a>
337 </p>
338 <p>
339 <a href="https://www.linkedin.com/in/muhammad-atif-latif-13a171318" style="color: white; text-decoration: none;">
340 ๐ LinkedIn
341 </a>
342 </p>
343 <p>
344 <a href="https://www.kaggle.com/muhammadatiflatif" style="color: white; text-decoration: none;">
345 ๐ Kaggle
346 </a>
347 </p>
348 <p>
349 <a href="https://x.com/mianatif5867" style="color: white; text-decoration: none;">
350 ๐ Twitter
351 </a>
352 </p>
353 <p>
354 <a href="https://github.com/M-Atif-Latif" style="color: white; text-decoration: none;">
355 ๐ป GitHub
356 </a>
357 </p>
358 </div>
359 """, unsafe_allow_html=True)
360
361# Main Content
362col1, col2 = st.columns([3, 1])
363with col1:
364 if st.button("๐ Fetch Market Data", use_container_width=True):
365 with st.spinner(f"Loading data for {selected_ticker}..."):
366 data = fetch_stock_data(selected_ticker, start_date, end_date, interval)
367 if data is not None:
368 st.session_state.stock_data = data
369 st.session_state.current_ticker = selected_ticker
370 st.session_state.comparison_tickers = comparison_tickers
371 st.success("Data loaded successfully!")
372with col2:
373 if st.button("๐ Clear Data", use_container_width=True, type="secondary"):
374 st.session_state.stock_data = None
375 st.session_state.current_ticker = None
376 st.session_state.comparison_tickers = []
377 st.rerun()
378
379# Display Data
380if st.session_state.stock_data is not None:
381 df = st.session_state.stock_data
382 ticker = st.session_state.current_ticker
383
384 # Metrics Row
385 st.markdown("---")
386 col1, col2, col3, col4 = st.columns(4)
387 with col1:
388 st.metric(
389 "Current Price",
390 f"${df.iloc[-1]['close']:,.2f}",
391 f"{df.iloc[-1]['close'] - df.iloc[-2]['close']:,.2f}",
392 delta_color="normal"
393 )
394 with col2:
395 st.metric(
396 "52 Week Range",
397 f"${df['close'].min():,.2f} - ${df['close'].max():,.2f}"
398 )
399 with col3:
400 daily_return = df.iloc[-1]['Daily_Return'] * 100
401 st.metric(
402 "Daily Return",
403 f"{daily_return:.2f}%",
404 delta_color="inverse" if daily_return < 0 else "normal"
405 )
406 with col4:
407 vol = df['volume'].mean() / 1_000_000
408 st.metric(
409 "Avg Volume",
410 f"{vol:,.1f}M"
411 )
412
413 # Interactive Chart
414 st.markdown("---")
415 st.markdown(f"### {ticker} Price Analysis")
416
417 fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
418 vertical_spacing=0.05, row_heights=[0.7, 0.3])
419
420 # Price and Moving Averages
421 fig.add_trace(
422 go.Candlestick(
423 x=df['date'],
424 open=df['open'],
425 high=df['high'],
426 low=df['low'],
427 close=df['close'],
428 name="Price",
429 increasing_line_color='#2ecc71',
430 decreasing_line_color='#e74c3c'
431 ),
432 row=1, col=1
433 )
434
435 fig.add_trace(
436 go.Scatter(
437 x=df['date'],
438 y=df['SMA_50'],
439 name="50-Day SMA",
440 line=dict(color='#3498db', width=2)
441 ),
442 row=1, col=1
443 )
444
445 fig.add_trace(
446 go.Scatter(
447 x=df['date'],
448 y=df['SMA_200'],
449 name="200-Day SMA",
450 line=dict(color='#f39c12', width=2)
451 ),
452 row=1, col=1
453 )
454
455 # Volume
456 fig.add_trace(
457 go.Bar(
458 x=df['date'],
459 y=df['volume'],
460 name="Volume",
461 marker_color='#7f8c8d'
462 ),
463 row=2, col=1
464 )
465
466 fig.update_layout(
467 height=800,
468 showlegend=True,
469 hovermode="x unified",
470 template="plotly_white",
471 margin=dict(l=20, r=20, t=40, b=20),
472 xaxis_rangeslider_visible=False
473 )
474
475 st.plotly_chart(fig, use_container_width=True)
476
477 # Comparison Charts
478 if st.session_state.comparison_tickers:
479 st.markdown("---")
480 st.markdown("### Performance Comparison")
481
482 comparison_data = {}
483 for comp_ticker in st.session_state.comparison_tickers:
484 comp_df = fetch_stock_data(comp_ticker, start_date, end_date, interval)
485 if comp_df is not None:
486 comparison_data[comp_ticker] = comp_df
487
488 if comparison_data:
489 fig = go.Figure()
490
491 # Normalize all prices to percentage change from start date
492 base_price = df.iloc[0]['close']
493 fig.add_trace(
494 go.Scatter(
495 x=df['date'],
496 y=(df['close'] / base_price - 1) * 100,
497 name=ticker,
498 line=dict(width=3)
499 )
500 )
501
502 for comp_ticker, comp_df in comparison_data.items():
503 comp_base = comp_df.iloc[0]['close']
504 fig.add_trace(
505 go.Scatter(
506 x=comp_df['date'],
507 y=(comp_df['close'] / comp_base - 1) * 100,
508 name=comp_ticker
509 )
510 )
511
512 fig.update_layout(
513 title="Normalized Performance Comparison",
514 yaxis_title="Percentage Change (%)",
515 hovermode="x unified",
516 height=500
517 )
518
519 st.plotly_chart(fig, use_container_width=True)
520
521 # Data Table and Export
522 st.markdown("---")
523 st.markdown("### Market Data Table")
524
525 # Show technical indicators in the table
526 display_cols = ['date', 'open', 'high', 'low', 'close', 'volume',
527 'SMA_50', 'SMA_200', 'Daily_Return']
528
529 st.dataframe(
530 df[display_cols].rename(columns={
531 'date': 'Date',
532 'open': 'Open',
533 'high': 'High',
534 'low': 'Low',
535 'close': 'Close',
536 'volume': 'Volume',
537 'SMA_50': '50-Day SMA',
538 'SMA_200': '200-Day SMA',
539 'Daily_Return': 'Daily Return'
540 }).style.format({
541 'Open': '{:,.2f}',
542 'High': '{:,.2f}',
543 'Low': '{:,.2f}',
544 'Close': '{:,.2f}',
545 'Volume': '{:,.0f}',
546 '50-Day SMA': '{:,.2f}',
547 '200-Day SMA': '{:,.2f}',
548 'Daily Return': '{:.2%}'
549 }),
550 height=400,
551 use_container_width=True
552 )
553
554 # Export Options
555 st.markdown("---")
556 st.markdown("### Export Data")
557 col1, col2 = st.columns(2)
558 with col1:
559 csv = df.to_csv(index=False)
560 st.download_button(
561 "๐ฅ Download CSV",
562 csv,
563 file_name=f"{ticker}_market_data_{start_date}_to_{end_date}.csv",
564 mime="text/csv",
565 use_container_width=True
566 )
567 with col2:
568 # Export Plotly chart as PNG
569 try:
570 chart_png = fig.to_image(format="png")
571 st.download_button(
572 "๐ Download Chart as PNG",
573 chart_png,
574 file_name=f"{ticker}_chart.png",
575 mime="image/png",
576 use_container_width=True
577 )
578 except Exception as e:
579 st.download_button(
580 "๐ Download Chart as PNG",
581 b"",
582 file_name=f"{ticker}_chart.png",
583 disabled=True,
584 help=f"PNG export failed: {str(e)}",
585 use_container_width=True
586 )
587
588# Footer
589st.markdown("---")
590st.markdown("""
591<div style="text-align: center; color: var(--text-secondary); padding: 1rem;">
592 <p>Global Markets Pro โข Professional Market Analysis Tool</p>
593 <p style="font-size: 0.8rem;">Data provided by Yahoo Finance โข Updated at {}</p>
594</div>
595""".format(dt.datetime.now().strftime("%Y-%m-%d %H:%M")), unsafe_allow_html=True)
596 