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"
Error analyzing sentiment: {str(e)}
" 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(""" """) 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 )