Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | @@ -24,7 +24,7 @@ def analyze_stock(symbol, prediction_days=30): | |
| 24 | 
             
                        symbol = symbol.upper() + ".JK"
         | 
| 25 |  | 
| 26 | 
             
                    stock = yf.Ticker(symbol)
         | 
| 27 | 
            -
                    data = stock.history(period=" | 
| 28 |  | 
| 29 | 
             
                    if data.empty:
         | 
| 30 | 
             
                        raise ValueError("No price data available for this stock.")
         | 
| @@ -38,6 +38,7 @@ def analyze_stock(symbol, prediction_days=30): | |
| 38 | 
             
                    fig_technical = create_technical_chart(data, indicators)
         | 
| 39 | 
             
                    fig_prediction = create_prediction_chart(data, predictions)
         | 
| 40 |  | 
|  | |
| 41 | 
             
                    last_price = data['Close'].iloc[-1]
         | 
| 42 | 
             
                    tp1 = last_price * (1 + (predictions.get("change_pct", 0) / 200))
         | 
| 43 | 
             
                    tp2 = last_price * (1 + (predictions.get("change_pct", 0) / 100))
         | 
| @@ -56,10 +57,7 @@ def analyze_stock(symbol, prediction_days=30): | |
| 56 | 
             
                        "high_30d": 0,
         | 
| 57 | 
             
                        "low_30d": 0,
         | 
| 58 | 
             
                        "change_pct": 0,
         | 
| 59 | 
            -
                        "summary":  | 
| 60 | 
            -
                        "tp1": 0,
         | 
| 61 | 
            -
                        "tp2": 0,
         | 
| 62 | 
            -
                        "sl": 0,
         | 
| 63 | 
             
                    }
         | 
| 64 | 
             
                    return {}, {}, {}, empty_fig, empty_fig, empty_fig, empty_predictions
         | 
| 65 |  | 
| @@ -75,146 +73,112 @@ def update_analysis(symbol, prediction_days): | |
| 75 | 
             
                    predictions,
         | 
| 76 | 
             
                ) = analyze_stock(symbol, prediction_days)
         | 
| 77 |  | 
| 78 | 
            -
                if not fundamental_info | 
| 79 | 
            -
                    error_msg = f"**ERROR:** {predictions.get('summary')}"
         | 
| 80 | 
             
                    return (
         | 
| 81 | 
            -
                         | 
| 82 | 
            -
                        gr.Markdown.update(value=error_msg),
         | 
| 83 | 
            -
                        gr.Markdown.update(value=error_msg),
         | 
| 84 | 
             
                        gr.Plot.update(value=None),
         | 
| 85 | 
             
                        gr.Plot.update(value=None),
         | 
| 86 | 
             
                        gr.Plot.update(value=None),
         | 
| 87 | 
             
                    )
         | 
| 88 |  | 
| 89 | 
            -
                 | 
| 90 | 
            -
                 | 
| 91 | 
            -
                 | 
| 92 | 
            -
                 | 
| 93 | 
            -
                 | 
| 94 | 
            -
                 | 
| 95 | 
            -
                 | 
| 96 | 
            -
                 | 
| 97 | 
             
                """
         | 
| 98 |  | 
| 99 | 
             
                details_list = "".join(
         | 
| 100 | 
             
                    [f"<li>{line.strip()}</li>" for line in signals.get("details", "").split("\n") if line.strip()]
         | 
| 101 | 
             
                )
         | 
| 102 |  | 
| 103 | 
            -
                 | 
| 104 | 
            -
                 | 
| 105 | 
            -
                 | 
| 106 | 
            -
                 | 
| 107 | 
            -
                 | 
| 108 | 
            -
                 | 
| 109 | 
            -
                 | 
| 110 | 
            -
             | 
| 111 | 
            -
                #### Detailed Signals:
         | 
| 112 | 
             
                <ul style="margin-top: 8px; padding-left: 20px; line-height: 1.6;">
         | 
| 113 | 
             
                {details_list}
         | 
| 114 | 
             
                </ul>
         | 
| 115 | 
             
                """
         | 
| 116 |  | 
| 117 | 
            -
                 | 
| 118 | 
            -
                 | 
| 119 | 
            -
                 | 
| 120 | 
            -
                 | 
| 121 | 
            -
                 | 
| 122 | 
            -
             | 
| 123 | 
            -
                 | 
| 124 | 
            -
                 | 
| 125 | 
            -
                 | 
| 126 | 
            -
                - **Stop Loss:** Rp{predictions.get('sl', 0):,.2f}
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                #### Model Insight
         | 
| 129 | 
            -
                > {predictions.get('summary', 'No analysis available')}
         | 
| 130 | 
             
                """
         | 
| 131 |  | 
|  | |
|  | |
| 132 | 
             
                return (
         | 
| 133 | 
            -
                     | 
| 134 | 
            -
                     | 
| 135 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
| 136 | 
             
                    fig_price,
         | 
| 137 | 
             
                    fig_technical,
         | 
| 138 | 
             
                    fig_prediction,
         | 
| 139 | 
             
                )
         | 
| 140 |  | 
| 141 |  | 
|  | |
| 142 | 
             
            with gr.Blocks(
         | 
| 143 | 
            -
                title="REXPRO FINANCIAL AI DASHBOARD" | 
|  | |
| 144 | 
             
            ) as app:
         | 
| 145 | 
             
                gr.Markdown("# REXPRO FINANCIAL AI DASHBOARD")
         | 
| 146 | 
             
                gr.Markdown(
         | 
| 147 | 
            -
                    " | 
| 148 | 
             
                )
         | 
| 149 | 
            -
                
         | 
| 150 | 
            -
                with gr.Row(variant="panel"):
         | 
| 151 | 
            -
                    with gr.Column(scale=1):
         | 
| 152 | 
            -
                        symbol = gr.Textbox(
         | 
| 153 | 
            -
                            label="MASUKKAN SIMBOL SAHAM (IDX)",
         | 
| 154 | 
            -
                            value="BBCA",
         | 
| 155 | 
            -
                            placeholder="Contoh: BBCA, TLKM, ADRO, BMRI",
         | 
| 156 | 
            -
                            interactive=True,
         | 
| 157 | 
            -
                            show_label=True
         | 
| 158 | 
            -
                        )
         | 
| 159 | 
            -
                    with gr.Column(scale=1):
         | 
| 160 | 
            -
                        prediction_days = gr.Slider(
         | 
| 161 | 
            -
                            label="PERIODE PERAMALAN (HARI)",
         | 
| 162 | 
            -
                            minimum=5,
         | 
| 163 | 
            -
                            maximum=60,
         | 
| 164 | 
            -
                            step=5,
         | 
| 165 | 
            -
                            value=30,
         | 
| 166 | 
            -
                            interactive=True,
         | 
| 167 | 
            -
                            show_label=True
         | 
| 168 | 
            -
                        )
         | 
| 169 | 
            -
                    with gr.Column(min_width=150, scale=0):
         | 
| 170 | 
            -
                        analyze_button = gr.Button("RUN ANALYSIS", size="lg")
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                with gr.Tabs():
         | 
| 173 | 
            -
                    with gr.TabItem("RINGKASAN & TARGET"):
         | 
| 174 | 
            -
                        with gr.Row():
         | 
| 175 | 
            -
                            with gr.Group():
         | 
| 176 | 
            -
                                fundamentals_output = gr.Markdown(
         | 
| 177 | 
            -
                                    "Hasil Fundamental akan muncul di sini.", 
         | 
| 178 | 
            -
                                    elem_classes=["card"]
         | 
| 179 | 
            -
                                )
         | 
| 180 | 
            -
                            with gr.Group():
         | 
| 181 | 
            -
                                trading_signal_output = gr.Markdown(
         | 
| 182 | 
            -
                                    "Ringkasan Sinyal Teknikal akan muncul di sini.",
         | 
| 183 | 
            -
                                    elem_classes=["card"]
         | 
| 184 | 
            -
                                )
         | 
| 185 | 
            -
                            with gr.Group():
         | 
| 186 | 
            -
                                prediction_output = gr.Markdown(
         | 
| 187 | 
            -
                                    "Hasil Peramalan AI & Target Trading akan muncul di sini.",
         | 
| 188 | 
            -
                                    elem_classes=["card"]
         | 
| 189 | 
            -
                                )
         | 
| 190 | 
            -
                    
         | 
| 191 | 
            -
                    with gr.TabItem("VISUALISASI GRAFIK"):
         | 
| 192 | 
            -
                        gr.Markdown("## Grafik Analisis Saham")
         | 
| 193 | 
            -
                        
         | 
| 194 | 
            -
                        with gr.Row():
         | 
| 195 | 
            -
                            with gr.Column(scale=1):
         | 
| 196 | 
            -
                                price_chart = gr.Plot(label="1. HARGA & RATA-RATA BERGERAK (MA)")
         | 
| 197 | 
            -
                            
         | 
| 198 | 
            -
                            with gr.Column(scale=1):
         | 
| 199 | 
            -
                                technical_chart = gr.Plot(label="2. INDIKATOR TEKNIKAL UTAMA (RSI/MACD)")
         | 
| 200 | 
            -
                        
         | 
| 201 | 
            -
                        gr.Markdown("---")
         | 
| 202 | 
            -
                        
         | 
| 203 | 
            -
                        with gr.Row():
         | 
| 204 | 
            -
                            prediction_chart = gr.Plot(label="3. PROYEKSI PERAMALAN AI") 
         | 
| 205 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 206 |  | 
| 207 | 
             
                analyze_button.click(
         | 
| 208 | 
             
                    fn=update_analysis,
         | 
| 209 | 
             
                    inputs=[symbol, prediction_days],
         | 
| 210 | 
            -
                    outputs=[
         | 
| 211 | 
            -
                        fundamentals_output,
         | 
| 212 | 
            -
                        trading_signal_output,
         | 
| 213 | 
            -
                        prediction_output,
         | 
| 214 | 
            -
                        price_chart,
         | 
| 215 | 
            -
                        technical_chart,
         | 
| 216 | 
            -
                        prediction_chart,
         | 
| 217 | 
            -
                    ],
         | 
| 218 | 
             
                )
         | 
| 219 |  | 
| 220 | 
             
            if __name__ == "__main__":
         | 
|  | |
| 24 | 
             
                        symbol = symbol.upper() + ".JK"
         | 
| 25 |  | 
| 26 | 
             
                    stock = yf.Ticker(symbol)
         | 
| 27 | 
            +
                    data = stock.history(period="6mo", interval="1d")
         | 
| 28 |  | 
| 29 | 
             
                    if data.empty:
         | 
| 30 | 
             
                        raise ValueError("No price data available for this stock.")
         | 
|  | |
| 38 | 
             
                    fig_technical = create_technical_chart(data, indicators)
         | 
| 39 | 
             
                    fig_prediction = create_prediction_chart(data, predictions)
         | 
| 40 |  | 
| 41 | 
            +
                    # kalkulasi TP1, TP2, SL
         | 
| 42 | 
             
                    last_price = data['Close'].iloc[-1]
         | 
| 43 | 
             
                    tp1 = last_price * (1 + (predictions.get("change_pct", 0) / 200))
         | 
| 44 | 
             
                    tp2 = last_price * (1 + (predictions.get("change_pct", 0) / 100))
         | 
|  | |
| 57 | 
             
                        "high_30d": 0,
         | 
| 58 | 
             
                        "low_30d": 0,
         | 
| 59 | 
             
                        "change_pct": 0,
         | 
| 60 | 
            +
                        "summary": "Prediction unavailable.",
         | 
|  | |
|  | |
|  | |
| 61 | 
             
                    }
         | 
| 62 | 
             
                    return {}, {}, {}, empty_fig, empty_fig, empty_fig, empty_predictions
         | 
| 63 |  | 
|  | |
| 73 | 
             
                    predictions,
         | 
| 74 | 
             
                ) = analyze_stock(symbol, prediction_days)
         | 
| 75 |  | 
| 76 | 
            +
                if not fundamental_info:
         | 
|  | |
| 77 | 
             
                    return (
         | 
| 78 | 
            +
                        "Unable to fetch stock data.",
         | 
|  | |
|  | |
| 79 | 
             
                        gr.Plot.update(value=None),
         | 
| 80 | 
             
                        gr.Plot.update(value=None),
         | 
| 81 | 
             
                        gr.Plot.update(value=None),
         | 
| 82 | 
             
                    )
         | 
| 83 |  | 
| 84 | 
            +
                fundamentals = f"""
         | 
| 85 | 
            +
                <h4>COMPANY FUNDAMENTALS</h4>
         | 
| 86 | 
            +
                <b>Name:</b> {fundamental_info.get('name', 'N/A')} ({symbol.upper()})<br>
         | 
| 87 | 
            +
                <b>Current Price:</b> Rp{fundamental_info.get('current_price', 0):,.2f}<br>
         | 
| 88 | 
            +
                <b>Market Cap:</b> {fundamental_info.get('market_cap', 0):,}<br>
         | 
| 89 | 
            +
                <b>P/E Ratio:</b> {fundamental_info.get('pe_ratio', 0):.2f}<br>
         | 
| 90 | 
            +
                <b>Dividend Yield:</b> {fundamental_info.get('dividend_yield', 0):.2f}%<br>
         | 
| 91 | 
            +
                <b>Volume:</b> {fundamental_info.get('volume', 0):,}<br>
         | 
| 92 | 
             
                """
         | 
| 93 |  | 
| 94 | 
             
                details_list = "".join(
         | 
| 95 | 
             
                    [f"<li>{line.strip()}</li>" for line in signals.get("details", "").split("\n") if line.strip()]
         | 
| 96 | 
             
                )
         | 
| 97 |  | 
| 98 | 
            +
                trading_signal = f"""
         | 
| 99 | 
            +
                <h4>TECHNICAL SIGNAL SUMMARY</h4>
         | 
| 100 | 
            +
                <b>Overall Trend:</b> {signals.get('overall', 'N/A')}<br>
         | 
| 101 | 
            +
                <b>Signal Strength:</b> {signals.get('strength', 0):.2f}%<br>
         | 
| 102 | 
            +
                <b>Support:</b> Rp{signals.get('support', 0):,.2f}<br>
         | 
| 103 | 
            +
                <b>Resistance:</b> Rp{signals.get('resistance', 0):,.2f}<br>
         | 
| 104 | 
            +
                <b>Stop Loss:</b> Rp{signals.get('stop_loss', 0):,.2f}<br><br>
         | 
| 105 | 
            +
                <b>Detailed Signals:</b>
         | 
|  | |
| 106 | 
             
                <ul style="margin-top: 8px; padding-left: 20px; line-height: 1.6;">
         | 
| 107 | 
             
                {details_list}
         | 
| 108 | 
             
                </ul>
         | 
| 109 | 
             
                """
         | 
| 110 |  | 
| 111 | 
            +
                prediction = f"""
         | 
| 112 | 
            +
                <h4>30-DAY AI FORECAST (CHRONOS-BOLT)</h4>
         | 
| 113 | 
            +
                <b>Predicted High:</b> Rp{predictions.get('high_30d', 0):,.2f}<br>
         | 
| 114 | 
            +
                <b>Predicted Low:</b> Rp{predictions.get('low_30d', 0):,.2f}<br>
         | 
| 115 | 
            +
                <b>Expected Change:</b> {predictions.get('change_pct', 0):.2f}%<br><br>
         | 
| 116 | 
            +
                <b>TP1:</b> Rp{predictions.get('tp1', 0):,.2f}<br>
         | 
| 117 | 
            +
                <b>TP2:</b> Rp{predictions.get('tp2', 0):,.2f}<br>
         | 
| 118 | 
            +
                <b>Stop Loss:</b> Rp{predictions.get('sl', 0):,.2f}<br><br>
         | 
| 119 | 
            +
                <b>Model Insight:</b><br>{predictions.get('summary', 'No analysis available')}
         | 
|  | |
|  | |
|  | |
|  | |
| 120 | 
             
                """
         | 
| 121 |  | 
| 122 | 
            +
                # Karena custom CSS dihapus, kita akan menggunakan div sederhana tanpa class 'panel-box' dan 'triple-panel'
         | 
| 123 | 
            +
                # Gradio secara otomatis akan menata elemen-elemen ini dengan lebih standar
         | 
| 124 | 
             
                return (
         | 
| 125 | 
            +
                    f"""
         | 
| 126 | 
            +
                    <div style="display: flex; flex-direction: row; gap: 16px;">
         | 
| 127 | 
            +
                        <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{fundamentals}</div>
         | 
| 128 | 
            +
                        <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{trading_signal}</div>
         | 
| 129 | 
            +
                        <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{prediction}</div>
         | 
| 130 | 
            +
                    </div>
         | 
| 131 | 
            +
                    """,
         | 
| 132 | 
             
                    fig_price,
         | 
| 133 | 
             
                    fig_technical,
         | 
| 134 | 
             
                    fig_prediction,
         | 
| 135 | 
             
                )
         | 
| 136 |  | 
| 137 |  | 
| 138 | 
            +
            # --- Perubahan utama di sini ---
         | 
| 139 | 
             
            with gr.Blocks(
         | 
| 140 | 
            +
                title="REXPRO FINANCIAL AI DASHBOARD"
         | 
| 141 | 
            +
                # Parameter theme dan css dihapus untuk kembali ke default Gradio
         | 
| 142 | 
             
            ) as app:
         | 
| 143 | 
             
                gr.Markdown("# REXPRO FINANCIAL AI DASHBOARD")
         | 
| 144 | 
             
                gr.Markdown(
         | 
| 145 | 
            +
                    "Comprehensive stock analytics powered by **AI forecasting and technical analysis.**"
         | 
| 146 | 
             
                )
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 147 |  | 
| 148 | 
            +
                with gr.Row():
         | 
| 149 | 
            +
                    symbol = gr.Textbox(
         | 
| 150 | 
            +
                        label="STOCK SYMBOL (IDX)",
         | 
| 151 | 
            +
                        value="BBCA",
         | 
| 152 | 
            +
                        placeholder="Example: BBCA, TLKM, ADRO, BMRI",
         | 
| 153 | 
            +
                        interactive=True,
         | 
| 154 | 
            +
                    )
         | 
| 155 | 
            +
                    prediction_days = gr.Slider(
         | 
| 156 | 
            +
                        label="FORECAST PERIOD (DAYS)",
         | 
| 157 | 
            +
                        minimum=5,
         | 
| 158 | 
            +
                        maximum=60,
         | 
| 159 | 
            +
                        step=5,
         | 
| 160 | 
            +
                        value=30,
         | 
| 161 | 
            +
                        interactive=True,
         | 
| 162 | 
            +
                    )
         | 
| 163 | 
            +
                    analyze_button = gr.Button("RUN ANALYSIS")
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                gr.Markdown("---")
         | 
| 166 | 
            +
                # Bagian report_section diubah agar lebih kompatibel dengan tema default,
         | 
| 167 | 
            +
                # menggunakan sedikit inline CSS untuk meniru tata letak tiga kolom dasar.
         | 
| 168 | 
            +
                report_section = gr.HTML() 
         | 
| 169 | 
            +
                gr.Markdown("---")
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                with gr.Tab("MARKET CHARTS"):
         | 
| 172 | 
            +
                    with gr.Row():
         | 
| 173 | 
            +
                        price_chart = gr.Plot(label="PRICE & MOVING AVERAGES")
         | 
| 174 | 
            +
                        technical_chart = gr.Plot(label="TECHNICAL INDICATORS OVERVIEW")
         | 
| 175 | 
            +
                    gr.Markdown("---")
         | 
| 176 | 
            +
                    prediction_chart = gr.Plot(label="AI FORECAST PROJECTION")
         | 
| 177 |  | 
| 178 | 
             
                analyze_button.click(
         | 
| 179 | 
             
                    fn=update_analysis,
         | 
| 180 | 
             
                    inputs=[symbol, prediction_days],
         | 
| 181 | 
            +
                    outputs=[report_section, price_chart, technical_chart, prediction_chart],
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 182 | 
             
                )
         | 
| 183 |  | 
| 184 | 
             
            if __name__ == "__main__":
         | 
