Spaces:
Build error
Build error
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| from data_processor import DataProcessor | |
| from sentiment_analyzer import SentimentAnalyzer | |
| from model_handler import ModelHandler | |
| from trading_logic import TradingLogic | |
| from plotter import create_mplfinance_chart | |
| import plotly.graph_objects as go | |
| # Global instances | |
| data_processor = DataProcessor() | |
| sentiment_analyzer = SentimentAnalyzer() | |
| model_handler = ModelHandler() | |
| trading_logic = TradingLogic() | |
| def create_chart_analysis(ticker, interval): | |
| """Create chart with technical indicators and predictions""" | |
| try: | |
| df = data_processor.get_market_data(ticker, interval) | |
| if df.empty: | |
| return "No data available", None | |
| # Hitung indikator | |
| df = data_processor.calculate_indicators(df) | |
| # Prepare data for Chronos | |
| prepared_data = data_processor.prepare_for_chronos(df) | |
| # Generate predictions (Chronos-2 atau Fallback) | |
| predictions = model_handler.predict(prepared_data, horizon=10) | |
| current_price = df['Close'].iloc[-1] | |
| # Buat chart menggunakan MPLFINANCE (dikembalikan sebagai HTML) | |
| chart_html = create_mplfinance_chart( | |
| df, | |
| ticker=f'{ticker} ({interval})', | |
| predictions=predictions | |
| ) | |
| # Hasilkan sinyal trading | |
| signal, confidence = trading_logic.generate_signal( | |
| predictions, current_price, df | |
| ) | |
| # Hitung TP/SL | |
| tp, sl = trading_logic.calculate_tp_sl( | |
| current_price, df['ATR'].iloc[-1], signal | |
| ) | |
| # Create metrics display | |
| metrics = { | |
| "Ticker": ticker, | |
| "Current Price": f"${current_price:.2f}", | |
| "Signal": signal.upper(), | |
| "Confidence": f"{confidence:.1%}", | |
| "Take Profit": f"${tp:.2f}" if tp else "N/A", | |
| "Stop Loss": f"${sl:.2f}" if sl else "N/A", | |
| "RSI": f"{df['RSI'].iloc[-1]:.1f}", | |
| "MACD": f"{df['MACD'].iloc[-1]:.4f}", | |
| "Volume": f"{df['Volume'].iloc[-1]:,.0f}" | |
| } | |
| return chart_html, metrics | |
| except Exception as e: | |
| return f"Error creating chart: {str(e)}", None | |
| def analyze_sentiment(ticker): | |
| """Analyze gold/crypto market sentiment""" | |
| # KOREKSI: Panggil fungsi yang diperbarui dan kirim ticker | |
| sentiment_score, news_summary = sentiment_analyzer.analyze_market_sentiment(ticker) | |
| # Gunakan template terang untuk Plotly | |
| fig = go.Figure(go.Indicator( | |
| mode="gauge+number+delta", | |
| value=sentiment_score, | |
| domain={'x': [0, 1], 'y': [0, 1]}, | |
| title={'text': f"{ticker} Market Sentiment (Simulated)"}, | |
| delta={'reference': 0}, | |
| gauge={ | |
| 'axis': {'range': [-1, 1]}, | |
| 'bar': {'color': "#FFD700"}, | |
| 'steps': [ | |
| {'range': [-1, -0.5], 'color': "rgba(255,0,0,0.5)"}, | |
| {'range': [-0.5, 0.5], 'color': "rgba(100,100,100,0.3)"}, | |
| {'range': [0.5, 1], 'color': "rgba(0,255,0,0.5)"} | |
| ], | |
| 'threshold': { | |
| 'line': {'color': "black", 'width': 4}, | |
| 'thickness': 0.75, | |
| 'value': 0 | |
| } | |
| } | |
| )) | |
| fig.update_layout( | |
| template='plotly_white', | |
| height=300, | |
| paper_bgcolor='#f0f4f9', | |
| plot_bgcolor='#f0f4f9', | |
| font=dict(color='black') | |
| ) | |
| return fig, news_summary | |
| def get_fundamentals(ticker): | |
| """Get fundamental analysis data""" | |
| try: | |
| fundamentals = data_processor.get_fundamental_data(ticker) | |
| # Buat fundamentals table | |
| table_data = [] | |
| for key, value in fundamentals.items(): | |
| table_data.append([key, value]) | |
| df = pd.DataFrame(table_data, columns=['Metric', 'Value']) | |
| # Ambil nilai kunci untuk gauge | |
| if ticker == "BTC-USD": | |
| gauge_title = "Crypto Volatility Index" | |
| gauge_value = fundamentals.get(gauge_title, 100) | |
| gauge_range = [0, 200] | |
| else: | |
| gauge_title = "Gold Strength Index" | |
| gauge_value = fundamentals.get(gauge_title, 50) | |
| gauge_range = [0, 100] | |
| # Create fundamentals gauge chart | |
| fig = go.Figure(go.Indicator( | |
| mode="gauge+number", | |
| value=gauge_value, | |
| title={'text': gauge_title}, | |
| gauge={ | |
| 'axis': {'range': gauge_range}, | |
| 'bar': {'color': "#FFD700"}, | |
| 'steps': [ | |
| {'range': [gauge_range[0], gauge_range[1] * 0.3], 'color': "rgba(255,0,0,0.5)"}, | |
| {'range': [gauge_range[1] * 0.3, gauge_range[1] * 0.7], 'color': "rgba(100,100,100,0.3)"}, | |
| {'range': [gauge_range[1] * 0.7, gauge_range[1]], 'color': "rgba(0,255,0,0.5)"} | |
| ] | |
| } | |
| )) | |
| fig.update_layout( | |
| template='plotly_white', | |
| height=300, | |
| paper_bgcolor='#f0f4f9', | |
| plot_bgcolor='#f0f4f9', | |
| font=dict(color='black') | |
| ) | |
| return fig, df | |
| except Exception as e: | |
| return str(e), None | |
| # Create Gradio interface | |
| with gr.Blocks( | |
| theme=gr.themes.Default(primary_hue="yellow", secondary_hue="yellow"), | |
| title="Ultimate Market Analysis & Prediction", | |
| css=""" | |
| .gradio-container {background-color: #f0f4f9; color: black} | |
| .gr-button-primary {background-color: #FFD700 !important; color: #000000 !important} | |
| .gr-button-secondary {border-color: #FFD700 !important; color: #000000 !important} | |
| .gr-tab button {color: black !important} | |
| .gr-tab button.selected {background-color: #FFD700 !important; color: #000000 !important} | |
| .gr-highlighted {background-color: #CCCCCC !important} | |
| .anycoder-link {color: #FFD700 !important; text-decoration: none; font-weight: bold} | |
| .mpl-chart-container { | |
| border: 1px solid #CCCCCC; | |
| border-radius: 5px; | |
| overflow: hidden; | |
| background: white; | |
| width: 100%; | |
| } | |
| .chart-title {color: black !important;} | |
| .metric-label {color: black !important;} | |
| """ | |
| ) as demo: | |
| gr.HTML(""" | |
| <div style="text-align: center; padding: 20px;"> | |
| <h1 style="color: black;">Ultimate Market Analysis & Prediction (Chronos-2)</h1> | |
| <p style="color: black;">AI-powered analysis for Gold Futures (GC=F) and Bitcoin (BTC-USD)</p> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| ticker_dropdown = gr.Dropdown( | |
| choices=["GC=F", "BTC-USD"], | |
| value="GC=F", | |
| label="Market Ticker", | |
| info="Select asset for analysis" | |
| ) | |
| # KOREKSI: Mengembalikan semua opsi interval waktu | |
| interval_dropdown = gr.Dropdown( | |
| choices=[ | |
| "5m", "15m", "30m", "1h", "4h", "1d", "1wk", "1mo", "3mo" | |
| ], | |
| value="1d", | |
| label="Time Interval", | |
| info="Select analysis timeframe" | |
| ) | |
| refresh_btn = gr.Button("売 Refresh Data & Predict", variant="primary") | |
| with gr.Tabs(): | |
| with gr.TabItem("投 Chart Analysis"): | |
| # Chart MPLFinance lebar penuh | |
| chart_html = gr.HTML(label="Price Chart & Indicators", elem_classes=["mpl-chart-container"]) | |
| with gr.Row(): | |
| metrics_output = gr.JSON(label="Trading Metrics") | |
| with gr.TabItem("堂 Sentiment Analysis"): | |
| with gr.Row(): | |
| sentiment_gauge = gr.Plot(label="Sentiment Score") | |
| news_display = gr.HTML(label="Market News") | |
| with gr.TabItem("嶋 Fundamentals"): | |
| with gr.Row(): | |
| fundamentals_gauge = gr.Plot(label="Strength Index Gauge") | |
| fundamentals_table = gr.Dataframe( | |
| headers=["Metric", "Value"], | |
| label="Key Fundamentals", | |
| interactive=False | |
| ) | |
| # Event handlers | |
| def update_all(ticker, interval): | |
| # FIX: create_chart_analysis sekarang hanya mengembalikan 2 output | |
| chart, metrics = create_chart_analysis(ticker, interval) | |
| # FIX: Panggil fungsi yang sudah diperbarui dan kirim ticker | |
| sentiment_gauge, news_display = analyze_sentiment(ticker) | |
| fund_gauge, fund_table = get_fundamentals(ticker) | |
| # Total 5 outputs Gradio components | |
| return chart, metrics, sentiment_gauge, news_display, fund_gauge, fund_table | |
| refresh_btn.click( | |
| fn=update_all, | |
| inputs=[ticker_dropdown, interval_dropdown], | |
| outputs=[ | |
| chart_html, metrics_output, | |
| sentiment_gauge, news_display, | |
| fundamentals_gauge, fundamentals_table | |
| ] | |
| ) | |
| demo.load( | |
| fn=update_all, | |
| inputs=[ticker_dropdown, interval_dropdown], | |
| outputs=[ | |
| chart_html, metrics_output, | |
| sentiment_gauge, news_display, | |
| fundamentals_gauge, fundamentals_table | |
| ] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| show_api=True | |
| ) |