import gradio as gr import pandas as pd import yfinance as yf from utils import ( calculate_technical_indicators, generate_trading_signals, get_fundamental_data, predict_prices, create_price_chart, create_technical_chart, create_prediction_chart, ) import warnings warnings.filterwarnings("ignore") def analyze_stock(symbol, prediction_days=30): try: if not symbol.strip(): raise ValueError("Please enter a valid stock symbol.") if not symbol.endswith(".JK"): symbol = symbol.upper() + ".JK" stock = yf.Ticker(symbol) data = stock.history(period="6mo", interval="1d") if data.empty: raise ValueError("No price data available for this stock.") indicators = calculate_technical_indicators(data) signals = generate_trading_signals(data, indicators) fundamental_info = get_fundamental_data(stock) predictions = predict_prices(data, prediction_days=prediction_days) fig_price = create_price_chart(data, indicators) fig_technical = create_technical_chart(data, indicators) fig_prediction = create_prediction_chart(data, predictions) return fundamental_info, indicators, signals, fig_price, fig_technical, fig_prediction, predictions except Exception as e: print(f"Error analyzing {symbol}: {e}") empty_fig = gr.Plot.update(value=None) empty_predictions = { 'high_30d': 0, 'low_30d': 0, 'change_pct': 0, 'summary': 'Prediction unavailable.' } return {}, {}, {}, empty_fig, empty_fig, empty_fig, empty_predictions def update_analysis(symbol, prediction_days): ( fundamental_info, indicators, signals, fig_price, fig_technical, fig_prediction, predictions, ) = analyze_stock(symbol, prediction_days) if not fundamental_info: return ( "❌ Unable to fetch stock data.", gr.Plot.update(value=None), gr.Plot.update(value=None), gr.Plot.update(value=None), "", "0", "0", "0", "" ) summary_text = f""" ### 🏢 {fundamental_info.get('name', 'N/A')} ({symbol.upper()}) **Current Price:** Rp{fundamental_info.get('current_price', 0):,.2f} **Market Cap:** {fundamental_info.get('market_cap', 0):,} **P/E Ratio:** {fundamental_info.get('pe_ratio', 0):.2f} **Dividend Yield:** {fundamental_info.get('dividend_yield', 0):.2f}% **Volume:** {fundamental_info.get('volume', 0):,} """ signal_text = f""" ### 📈 Technical Trading Signal **Overall Signal:** {signals.get('overall', 'N/A')} **Strength:** {signals.get('strength', 0):.2f}% **Support:** {signals.get('support', 0):,.2f} **Resistance:** {signals.get('resistance', 0):,.2f} **Stop Loss:** {signals.get('stop_loss', 0):,.2f} **Signal Details:** {signals.get('details', '')} """ prediction_text = f""" ### 🤖 AI Forecast (Amazon Chronos-Bolt) **Predicted High (30d):** Rp{predictions.get('high_30d', 0):,.2f} **Predicted Low (30d):** Rp{predictions.get('low_30d', 0):,.2f} **Expected Change:** {predictions.get('change_pct', 0):.2f}% 🧠 **Model Insight:** {predictions.get('summary', 'No analysis available')} """ return ( summary_text, fig_price, fig_technical, fig_prediction, signal_text, f"{predictions.get('high_30d', 0):,.2f}", f"{predictions.get('low_30d', 0):,.2f}", f"{predictions.get('change_pct', 0):.2f}%", prediction_text, ) with gr.Blocks( title="AI Stock Forecast Dashboard", theme=gr.themes.Soft(primary_hue="blue", secondary_hue="gray"), css=""" #dashboard {padding: 20px; max-width: 1300px; margin: auto;} .gradio-container {font-family: 'Inter', sans-serif;} h1, h2, h3 {color: #1e293b;} .gr-button {font-weight: 600; border-radius: 8px;} .gr-markdown {background: #f8fafc; border-radius: 10px; padding: 15px;} """ ) as app: gr.Markdown("# ⚡ AI Stock Analysis Dashboard — Chronos-Bolt Edition", elem_id="dashboard") gr.Markdown("Enter any **Indonesian stock ticker** (e.g., `BBCA`, `ADRO`, `TLKM`, `BMRI`) to get live market insights and AI-based 30-day forecasts.", elem_id="dashboard") with gr.Row(): symbol = gr.Textbox( label="Stock Symbol", value="BBCA", placeholder="Type e.g. BBCA, ADRO, TLKM ...", interactive=True, lines=1 ) prediction_days = gr.Slider( label="Prediction Period (Days)", minimum=5, maximum=60, step=5, value=30, interactive=True, ) analyze_button = gr.Button("🚀 Analyze Stock") gr.Markdown("---") with gr.Row(): with gr.Column(): fundamentals_output = gr.Markdown(label="Fundamentals") with gr.Column(): signal_output = gr.Markdown(label="Trading Signals") gr.Markdown("---") with gr.Tab("📊 Charts Overview"): with gr.Row(): price_chart = gr.Plot(label="Price & Moving Averages") technical_chart = gr.Plot(label="Technical Indicators") gr.Markdown("---") prediction_chart = gr.Plot(label="AI Forecast Projection") with gr.Tab("🤖 AI Forecast Results"): with gr.Row(): predicted_high = gr.Textbox(label="Predicted High (30d)") predicted_low = gr.Textbox(label="Predicted Low (30d)") predicted_change = gr.Textbox(label="Expected Change (%)") gr.Markdown("---") prediction_summary = gr.Markdown(label="Prediction Analysis") analyze_button.click( fn=update_analysis, inputs=[symbol, prediction_days], outputs=[ fundamentals_output, price_chart, technical_chart, prediction_chart, signal_output, predicted_high, predicted_low, predicted_change, prediction_summary, ], ) if __name__ == "__main__": app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)