""" Main Streamlit Application for AI Stock Trading with Sharia Compliance """ import streamlit as st import pandas as pd import os from dotenv import load_dotenv # Import our custom tools from tools.fetching import stock_fetcher, get_available_stocks from tools.analysis import stock_analyzer from tools.trading_decisions import trading_engine from tools.sharia_compliance import sharia_checker from tools.charting import chart_generator # Import new modular components from core.data_service import data_service from core.ai_assistant import ai_assistant from components.chat_interface import ChatInterface # Load environment variables load_dotenv() # Page configuration st.set_page_config( page_title="AI Stock Trading & Sharia Compliance", page_icon="πŸ“ˆ", layout="wide", initial_sidebar_state="expanded" ) class StockTradingApp: def __init__(self): self.initialize_session_state() self.setup_sidebar() def initialize_session_state(self): if 'selected_country' not in st.session_state: st.session_state.selected_country = 'USA' if 'selected_stock' not in st.session_state: st.session_state.selected_stock = None if 'stock_data' not in st.session_state: st.session_state.stock_data = {} if 'chat_history' not in st.session_state: st.session_state.chat_history = [] if 'current_page' not in st.session_state: st.session_state.current_page = 'home' def setup_sidebar(self): with st.sidebar: st.title("πŸ›οΈ Navigation") page = st.radio( "Select Page:", ["🏠 Home", "πŸ’¬ Chat Interface", "πŸ“Š Dashboard"], key="page_selector" ) page_mapping = { "🏠 Home": "home", "πŸ’¬ Chat Interface": "chat", "πŸ“Š Dashboard": "dashboard" } st.session_state.current_page = page_mapping[page] st.divider() self.render_stock_selector() st.divider() self.show_api_status() def render_stock_selector(self): st.subheader("🌍 Stock Selection") countries = ['USA', 'Egypt'] selected_country = st.selectbox( "Select Country:", countries, index=countries.index(st.session_state.selected_country), key="country_selector" ) if selected_country != st.session_state.selected_country: st.session_state.selected_country = selected_country st.session_state.selected_stock = None available_stocks = get_available_stocks(selected_country) if available_stocks: stock_names = list(available_stocks.keys()) current_index = 0 if st.session_state.selected_stock: current_symbol = st.session_state.selected_stock for i, (name, symbol) in enumerate(available_stocks.items()): if symbol == current_symbol: current_index = i break selected_stock_name = st.selectbox( "Select Stock:", stock_names, index=current_index, key="stock_selector" ) selected_symbol = available_stocks[selected_stock_name] if selected_symbol != st.session_state.selected_stock: st.session_state.selected_stock = selected_symbol st.session_state.stock_data = {} st.session_state.chat_history = [] if st.session_state.selected_stock: st.success(f"Selected: {selected_stock_name} ({selected_symbol})") else: st.error(f"No stocks available for {selected_country}") def show_api_status(self): st.subheader("API Used") openai_key = os.getenv('OPENAI_API_KEY') if openai_key: st.success("βœ… OpenAI Connected") else: st.error("❌ Not Connected") def run(self): st.title("πŸ€– AI Stock Trading") st.markdown("*Intelligent stock analysis with Islamic finance compliance*") if st.session_state.current_page == 'home': self.render_home_page() elif st.session_state.current_page == 'chat': self.render_chat_page() elif st.session_state.current_page == 'dashboard': self.render_dashboard_page() def render_home_page(self): st.header("🏠 Welcome to AI Stock Trading Platform") st.markdown(""" Get intelligent stock analysis with Islamic finance compliance checking. Select a country and stock from the sidebar to begin. **Key Features:** - πŸ“Š Real-time stock analysis with advanced indicators - πŸ€– AI-powered trading recommendations - β˜ͺ️ Sharia compliance assessment - πŸ’¬ Natural language chat interface **Supported Markets:** πŸ‡ΊπŸ‡Έ USA | πŸ‡ͺπŸ‡¬ Egypt *Disclaimer: For educational purposes only. Not financial advice.* """) if st.session_state.selected_stock: st.divider() st.subheader(f"πŸ“Š Quick Analysis: {st.session_state.selected_stock}") with st.spinner("Loading quick analysis..."): self.show_quick_analysis() def show_quick_analysis(self): symbol = st.session_state.selected_stock country = st.session_state.selected_country try: data = stock_fetcher.fetch_stock_data(symbol, period="1mo") stock_info = stock_fetcher.get_stock_info(symbol, country) if not data.empty: col1, col2, col3, col4 = st.columns(4) current_price = data['Close'].iloc[-1] price_change = data['Close'].iloc[-1] - data['Close'].iloc[-2] if len(data) > 1 else 0 price_change_pct = (price_change / data['Close'].iloc[-2] * 100) if len(data) > 1 else 0 with col1: formatted_price = stock_fetcher.format_price_with_currency(current_price, country) price_change_str = f"{price_change:+.2f} ({price_change_pct:+.1f}%)" st.metric("Current Price", formatted_price, price_change_str) with col2: high_52w = stock_info.get('fifty_two_week_high', 0) formatted_high = stock_fetcher.format_price_with_currency(high_52w, country) st.metric("52W High", formatted_high) with col3: low_52w = stock_info.get('fifty_two_week_low', 0) formatted_low = stock_fetcher.format_price_with_currency(low_52w, country) st.metric("52W Low", formatted_low) with col4: market_cap = stock_info.get('market_cap', 0) currency = stock_fetcher.get_market_currency(country) if market_cap > 1e9: if currency == 'EGP': market_cap_str = f"{market_cap/1e9:.1f}B EGP" else: market_cap_str = f"${market_cap/1e9:.1f}B" elif market_cap > 1e6: if currency == 'EGP': market_cap_str = f"{market_cap/1e6:.1f}M EGP" else: market_cap_str = f"${market_cap/1e6:.1f}M" else: if currency == 'EGP': market_cap_str = f"{market_cap:,.0f} EGP" else: market_cap_str = f"${market_cap:,.0f}" st.metric("Market Cap", market_cap_str) st.info(f"**{stock_info.get('company_name', 'N/A')}** | " f"Sector: {stock_info.get('sector', 'N/A')} | " f"Industry: {stock_info.get('industry', 'N/A')}") except Exception as e: st.error(f"Error loading quick analysis: {str(e)}") def load_stock_analysis(self, symbol: str): """Load complete analysis using data service""" country = st.session_state.selected_country # Pre-load all analysis components data_service.get_analysis(symbol) data_service.get_trading_recommendation(symbol, country) data_service.get_sharia_compliance(symbol, country) def render_chat_page(self): st.header("πŸ’¬ AI Stock Analysis Chat") symbol = st.session_state.selected_stock country = st.session_state.selected_country ChatInterface.render(symbol, country) def render_dashboard_page(self): st.header("πŸ“Š Dashboard") if not st.session_state.selected_stock: st.warning("⚠️ Please select a stock from the sidebar.") return symbol = st.session_state.selected_stock country = st.session_state.selected_country # Load data using new data service with st.spinner("Loading dashboard data..."): basic_info = data_service.get_basic_info(symbol, country) data = data_service.get_price_data(symbol, "1y") analysis = data_service.get_analysis(symbol, "1y") trading_decision = data_service.get_trading_recommendation(symbol, country) sharia_compliance = data_service.get_sharia_compliance(symbol, country) # Check if data loaded successfully if data is None or analysis.get('error') or trading_decision.get('error'): st.error("Failed to load dashboard data. Please try again.") return # KPIs at the top col1, col2, col3, col4, col5 = st.columns(5) with col1: if data is not None and hasattr(data, 'iloc') and len(data) > 0: current_price = data['Close'].iloc[-1] formatted_price = stock_fetcher.format_price_with_currency(current_price, country) st.metric("πŸ’° Current Price", formatted_price) else: st.metric("πŸ’° Current Price", "N/A") with col2: total_return = analysis.get('total_return_pct', 0) st.metric("Total Return", f"{total_return:.2f}%") with col3: rec = trading_decision.get('recommendation', 'HOLD') conf = trading_decision.get('confidence', 0.5) if conf <= 1.0: conf_pct = conf * 100 else: conf_pct = conf st.metric("Recommendation", rec, f"{conf_pct:.0f}% confidence") with col4: ruling = sharia_compliance.get('ruling', 'UNCERTAIN') sharia_conf = sharia_compliance.get('confidence', 0.5) if sharia_conf <= 1.0: sharia_conf_pct = sharia_conf * 100 else: sharia_conf_pct = sharia_conf st.metric("Sharia Status", ruling, f"{sharia_conf_pct:.0f}% confidence") with col5: volatility = analysis.get('volatility_annualized', 0) st.metric("Volatility", f"{volatility:.1f}%") # Charts section (only if data is available) if data is not None and hasattr(data, 'iloc') and len(data) > 0: st.divider() # First row: Risk Analysis and Trading Signals col1, col2 = st.columns(2) with col1: try: risk_fig = chart_generator.create_risk_analysis_chart(analysis, symbol) st.plotly_chart(risk_fig, use_container_width=True) except Exception as e: st.error(f"Risk chart error: {str(e)}") with col2: try: signals_fig = chart_generator.create_trading_signals_chart(data, analysis, trading_decision, symbol) st.plotly_chart(signals_fig, use_container_width=True) except Exception as e: st.error(f"Signals chart error: {str(e)}") # Second row: Price Chart (full width) try: price_fig = chart_generator.create_price_chart(data, symbol, analysis) st.plotly_chart(price_fig, use_container_width=True) except Exception as e: st.error(f"Price chart error: {str(e)}") else: st.warning("πŸ“Š Charts unavailable - no price data loaded.") def main(): app = StockTradingApp() app.run() if __name__ == "__main__": main()