Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import mplfinance as mpf | |
| from data_processor import DataProcessor | |
| from sentiment_analyzer import SentimentAnalyzer | |
| from model_handler import ModelHandler | |
| from trading_logic import TradingLogic | |
| import io | |
| import base64 | |
| # Global instances | |
| data_processor = DataProcessor() | |
| sentiment_analyzer = SentimentAnalyzer() | |
| model_handler = ModelHandler() | |
| trading_logic = TradingLogic() | |
| # Asset mapping | |
| asset_map = { | |
| "Gold Futures (GC=F)": "GC=F", | |
| "Bitcoin USD (BTC-USD)": "BTC-USD" | |
| } | |
| def create_chart_analysis(interval, asset_name): | |
| """Create chart with technical indicators using mplfinance""" | |
| try: | |
| ticker = asset_map[asset_name] | |
| df = data_processor.get_asset_data(ticker, interval) | |
| if df.empty: | |
| # Return error plot instead of string | |
| fig, ax = plt.subplots(figsize=(12, 8), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| ax.text(0.5, 0.5, f'No data available for {asset_name}\nPlease try a different interval', | |
| ha='center', va='center', transform=ax.transAxes, fontsize=14, color='red') | |
| ax.set_title('Data Error', color='black') | |
| ax.axis('off') | |
| pred_fig = plt.figure(figsize=(10, 4), facecolor='white') | |
| pred_fig.patch.set_facecolor('white') | |
| return fig, {}, pred_fig | |
| # Calculate indicators | |
| df = data_processor.calculate_indicators(df) | |
| # Create main candlestick chart with mplfinance | |
| # Prepare additional plots for indicators | |
| ap = [] | |
| # Add moving averages (last 100 data points) | |
| if 'SMA_20' in df.columns: | |
| ap.append(mpf.make_addplot(df['SMA_20'].iloc[-100:], color='#FFA500', width=1.5, label='SMA 20')) | |
| if 'SMA_50' in df.columns: | |
| ap.append(mpf.make_addplot(df['SMA_50'].iloc[-100:], color='#FF4500', width=1.5, label='SMA 50')) | |
| # Add Bollinger Bands | |
| if 'BB_upper' in df.columns and 'BB_lower' in df.columns: | |
| ap.append(mpf.make_addplot(df['BB_upper'].iloc[-100:], color='#4169E1', width=1, linestyle='dashed', label='BB Upper')) | |
| ap.append(mpf.make_addplot(df['BB_lower'].iloc[-100:], color='#4169E1', width=1, linestyle='dashed', label='BB Lower')) | |
| # Create figure | |
| try: | |
| fig, axes = mpf.plot( | |
| df[-100:], # Show last 100 candles | |
| type='candle', | |
| style='yahoo', | |
| title=f'{asset_name} - {interval}', | |
| ylabel='Price (USD)', | |
| volume=True, | |
| addplot=ap, | |
| figsize=(12, 8), | |
| returnfig=True, | |
| warn_too_much_data=200, | |
| tight_layout=True | |
| ) | |
| # Adjust layout | |
| fig.patch.set_facecolor('white') | |
| if axes: | |
| axes[0].set_facecolor('white') | |
| axes[0].grid(True, alpha=0.3) | |
| except Exception as plot_error: | |
| print(f"Mplfinance plot error: {plot_error}") | |
| fig, axes = plt.subplots(figsize=(12, 8), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| axes.text(0.5, 0.5, f'Chart Plot Error: {str(plot_error)}', ha='center', va='center', | |
| transform=axes.transAxes, fontsize=14, color='red') | |
| axes.set_title('Plot Generation Error', color='black') | |
| axes.axis('off') | |
| # Prepare data for Chronos | |
| prepared_data = data_processor.prepare_for_chronos(df) | |
| # Generate predictions | |
| predictions = model_handler.predict(prepared_data, horizon=10) | |
| current_price = df['Close'].iloc[-1] | |
| # Get signal | |
| signal, confidence = trading_logic.generate_signal( | |
| predictions, current_price, df | |
| ) | |
| # Calculate TP/SL | |
| tp, sl = trading_logic.calculate_tp_sl( | |
| current_price, df['ATR'].iloc[-1] if 'ATR' in df.columns else 10, signal | |
| ) | |
| # Create metrics display | |
| metrics = { | |
| "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}" if 'RSI' in df.columns else "N/A", | |
| "MACD": f"{df['MACD'].iloc[-1]:.4f}" if 'MACD' in df.columns else "N/A", | |
| "Volume": f"{df['Volume'].iloc[-1]:,.0f}" if 'Volume' in df.columns else "N/A" | |
| } | |
| # Create prediction chart using matplotlib | |
| pred_fig, ax = plt.subplots(figsize=(10, 4), facecolor='white') | |
| pred_fig.patch.set_facecolor('white') | |
| # Plot historical prices (last 30 points) | |
| hist_data = df['Close'].iloc[-30:] | |
| hist_dates = df.index[-30:] | |
| ax.plot(hist_dates, hist_data, color='#4169E1', linewidth=2, label='Historical') | |
| # Plot predictions | |
| if predictions.any() and len(predictions) > 0: | |
| future_dates = pd.date_range( | |
| start=df.index[-1], periods=len(predictions), freq='D' | |
| ) | |
| ax.plot(future_dates, predictions, color='#FF6600', linewidth=2, | |
| marker='o', markersize=4, label='Predictions') | |
| # Connect historical to prediction | |
| ax.plot([hist_dates[-1], future_dates[0]], | |
| [hist_data.iloc[-1], predictions[0]], | |
| color='#FF6600', linewidth=1, linestyle='--') | |
| ax.set_title('Price Prediction (Next 10 Periods)', fontsize=12, color='black') | |
| ax.set_xlabel('Date', color='black') | |
| ax.set_ylabel('Price (USD)', color='black') | |
| ax.legend() | |
| ax.grid(True, alpha=0.3) | |
| ax.tick_params(colors='black') | |
| return fig, metrics, pred_fig | |
| except Exception as e: | |
| # Return error plot instead of string | |
| fig, ax = plt.subplots(figsize=(12, 8), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| ax.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center', | |
| transform=ax.transAxes, fontsize=14, color='red') | |
| ax.set_title('Chart Generation Error', color='black') | |
| ax.axis('off') | |
| pred_fig = plt.figure(figsize=(10, 4), facecolor='white') | |
| pred_fig.patch.set_facecolor('white') | |
| return fig, {}, pred_fig | |
| def analyze_sentiment(asset_name): | |
| """Analyze market sentiment for selected asset""" | |
| try: | |
| sentiment_score, news_summary = sentiment_analyzer.analyze_sentiment(asset_name) | |
| # Create sentiment gauge using matplotlib | |
| fig, ax = plt.subplots(figsize=(6, 4), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| # Create gauge | |
| ax.set_xlim(-1.5, 1.5) | |
| ax.set_ylim(0, 1) | |
| ax.set_aspect('equal') | |
| # Draw gauge background | |
| theta = np.linspace(np.pi, 0, 100) | |
| ax.plot(np.cos(theta), np.sin(theta), color='lightgray', linewidth=10) | |
| # Draw colored regions | |
| ax.fill_between(np.cos(theta[50:]), np.sin(theta[50:]), 0, | |
| where=np.cos(theta[50:])<0, color='red', alpha=0.3) | |
| ax.fill_between(np.cos(theta[25:75]), np.sin(theta[25:75]), 0, | |
| color='gray', alpha=0.3) | |
| ax.fill_between(np.cos(theta[:50]), np.sin(theta[:50]), 0, | |
| where=np.cos(theta[:50])>0, color='green', alpha=0.3) | |
| # Draw needle | |
| needle_angle = np.pi * (1 - (sentiment_score + 1) / 2) | |
| ax.plot([0, 0.8*np.cos(needle_angle)], [0, 0.8*np.sin(needle_angle)], | |
| color='gold', linewidth=4) | |
| # Add score text | |
| ax.text(0, -0.2, f"{sentiment_score:.2f}", ha='center', va='center', | |
| fontsize=16, color='black', weight='bold') | |
| ax.set_title(f'{asset_name} Market Sentiment', color='black') | |
| # Remove axes | |
| ax.axis('off') | |
| return fig, news_summary | |
| except Exception as e: | |
| # Return error plot | |
| fig, ax = plt.subplots(figsize=(6, 4), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| ax.text(0.5, 0.5, f'Sentiment Error: {str(e)}', ha='center', va='center', | |
| transform=ax.transAxes, fontsize=12, color='red') | |
| ax.axis('off') | |
| return fig, f"<p>Error analyzing sentiment: {str(e)}</p>" | |
| def get_fundamentals(asset_name): | |
| """Get fundamental analysis data""" | |
| try: | |
| ticker = asset_map[asset_name] | |
| fundamentals = data_processor.get_fundamental_data(ticker) | |
| # Create fundamentals table | |
| table_data = [] | |
| for key, value in fundamentals.items(): | |
| table_data.append([key, value]) | |
| df = pd.DataFrame(table_data, columns=['Metric', 'Value']) | |
| # Create fundamentals gauge chart | |
| fig, ax = plt.subplots(figsize=(6, 4), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| strength_index = fundamentals.get('Strength Index', 50) | |
| # Create horizontal bar gauge | |
| ax.barh([0], [strength_index], height=0.3, color='gold', alpha=0.7) | |
| ax.set_xlim(0, 100) | |
| ax.set_ylim(-0.5, 0.5) | |
| ax.set_title(f'{asset_name} Strength Index', color='black') | |
| ax.set_xlabel('Index Value', color='black') | |
| ax.text(strength_index, 0, f'{strength_index:.1f}', | |
| ha='left', va='center', fontsize=12, color='black', weight='bold') | |
| ax.grid(True, alpha=0.3) | |
| ax.tick_params(colors='black') | |
| return fig, df | |
| except Exception as e: | |
| # Return error plot | |
| fig, ax = plt.subplots(figsize=(6, 4), facecolor='white') | |
| fig.patch.set_facecolor('white') | |
| ax.text(0.5, 0.5, f'Fundamentals Error: {str(e)}', ha='center', va='center', | |
| transform=ax.transAxes, fontsize=12, color='red') | |
| ax.axis('off') | |
| return fig, pd.DataFrame() | |
| # Create Gradio interface | |
| with gr.Blocks( | |
| theme=gr.themes.Default(primary_hue="blue", secondary_hue="blue"), | |
| title="Trading Analysis & Prediction", | |
| css=""" | |
| .gradio-container {background-color: #FFFFFF !important; color: #000000 !important} | |
| .gr-button-primary {background-color: #4169E1 !important; color: #FFFFFF !important} | |
| .gr-button-secondary {border-color: #4169E1 !important; color: #4169E1 !important} | |
| .gr-tab button {color: #000000 !important} | |
| .gr-tab button.selected {background-color: #4169E1 !important; color: #FFFFFF !important} | |
| .gr-highlighted {background-color: #F0F0F0 !important} | |
| .anycoder-link {color: #4169E1 !important; text-decoration: none; font-weight: bold} | |
| .gr-json {background-color: #FFFFFF !important; color: #000000 !important} | |
| .gr-json label {color: #000000 !important} | |
| .gr-textbox, .gr-dropdown, .gr-number {background-color: #FFFFFF !important; color: #000000 !important} | |
| """ | |
| ) as demo: | |
| # Header with anycoder link | |
| gr.HTML(""" | |
| <div style="text-align: center; padding: 20px;"> | |
| <h1 style="color: #4169E1;">Trading Analysis & Prediction</h1> | |
| <p>Advanced AI-powered analysis for Gold and Bitcoin</p> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| asset_dropdown = gr.Dropdown( | |
| choices=list(asset_map.keys()), | |
| value="Gold Futures (GC=F)", | |
| label="Select Asset", | |
| info="Choose trading pair" | |
| ) | |
| with gr.Column(scale=1): | |
| interval_dropdown = gr.Dropdown( | |
| choices=[ | |
| "5m", "15m", "30m", "1h", "1d", "1wk", "1mo", "3mo" | |
| ], | |
| value="1d", | |
| label="Time Interval", | |
| info="Select analysis timeframe" | |
| ) | |
| with gr.Column(scale=1): | |
| refresh_btn = gr.Button("Refresh Data", variant="primary") | |
| with gr.Tabs(): | |
| with gr.TabItem("Chart Analysis"): | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| chart_plot = gr.Plot(label="Price Chart") | |
| with gr.Column(scale=1): | |
| metrics_output = gr.JSON(label="Trading Metrics") | |
| with gr.Row(): | |
| pred_plot = gr.Plot(label="Price Predictions") | |
| with gr.TabItem("Sentiment Analysis"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| sentiment_gauge = gr.Plot(label="Sentiment Score") | |
| with gr.Column(scale=1): | |
| news_display = gr.HTML(label="Market News") | |
| with gr.TabItem("Fundamentals"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| fundamentals_gauge = gr.Plot(label="Strength Index") | |
| with gr.Column(scale=1): | |
| fundamentals_table = gr.Dataframe( | |
| headers=["Metric", "Value"], | |
| label="Key Fundamentals", | |
| interactive=False | |
| ) | |
| # Event handlers | |
| def update_all(interval, asset): | |
| chart, metrics, pred = create_chart_analysis(interval, asset) | |
| sentiment, news = analyze_sentiment(asset) | |
| fund_gauge, fund_table = get_fundamentals(asset) | |
| return chart, metrics, pred, sentiment, news, fund_gauge, fund_table | |
| refresh_btn.click( | |
| fn=update_all, | |
| inputs=[interval_dropdown, asset_dropdown], | |
| outputs=[ | |
| chart_plot, metrics_output, pred_plot, | |
| sentiment_gauge, news_display, | |
| fundamentals_gauge, fundamentals_table | |
| ] | |
| ) | |
| demo.load( | |
| fn=update_all, | |
| inputs=[interval_dropdown, asset_dropdown], | |
| outputs=[ | |
| chart_plot, metrics_output, pred_plot, | |
| 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 | |
| ) |