import plotly.graph_objects as go import plotly.express as px import pandas as pd import logging import matplotlib.pyplot as plt from plotly.subplots import make_subplots import numpy as np logging.basicConfig(level=logging.INFO) def plot_indicators(df, ticker): try: fig = make_subplots( rows=7, cols=1, shared_xaxes=True, vertical_spacing=0.03, subplot_titles=( 'Price & Moving Averages', 'Volume', 'MACD & RSI', 'Stochastic & Williams %R', 'ADX & DI', 'ATR & CCI', 'Signal Strength' ), row_heights=[0.4, 0.1, 0.15, 0.15, 0.15, 0.15, 0.15] ) # Price and Moving Averages fig.add_trace( go.Candlestick( x=df.index, open=df['Open'], high=df['High'], low=df['Low'], close=df['value'], name='Price', increasing_line_color='#00CC96', decreasing_line_color='#EF553B' ), row=1, col=1 ) for ma in ['sma_10', 'sma_20', 'sma_50', 'ema_12', 'ema_26', 'ema_50']: if ma in df: fig.add_trace( go.Scatter(x=df.index, y=df[ma], name=ma.upper(), line=dict(width=1.5)), row=1, col=1 ) if 'bbu_20_2' in df: fig.add_trace( go.Scatter(x=df.index, y=df['bbu_20_2'], name='BB Upper', line=dict(color='gray', dash='dot')), row=1, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df['bbm_20_2'], name='BB Middle', line=dict(color='gray')), row=1, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df["bbl_20_2"], name="BB Lower", line=dict(color="gray", dash="dot")), row=1, col=1 ) # Position Size and Risk Annotation if 'atr_14' in df: atr = df['atr_14'].iloc[-1] stop_distance = atr * 2 position_size = (10000 * 0.01) / stop_distance fig.add_annotation( text=f"Position Size: {position_size:.0f} shares (1% risk, ATR {atr:.2f})", xref="paper", yref="paper", x=0.05, y=0.95, showarrow=False, font=dict(color="black", size=12) ) # Volume fig.add_trace( go.Bar(x=df.index, y=df["Volume"], name="Volume", marker_color="blue", opacity=0.5), row=2, col=1 ) # MACD & RSI if 'macd_12_26_9' in df: fig.add_trace( go.Scatter(x=df.index, y=df['macd_12_26_9'], name='MACD', line=dict(color='blue')), row=3, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df["macds_12_26_9"], name="MACD Signal", line=dict(color="orange")), row=3, col=1 ) fig.add_trace( go.Bar(x=df.index, y=df["macdhist_12_26_9"], name="MACD Hist", marker_color="gray"), row=3, col=1 ) if 'rsi_14' in df: fig.add_trace( go.Scatter(x=df.index, y=df["rsi_14"], name="RSI 14", line=dict(color="purple")), row=3, col=1 ) fig.add_hline(y=70, line_dash="dash", line_color="red", row=3, col=1) fig.add_hline(y=30, line_dash="dash", line_color="green", row=3, col=1) if 'rsi_21' in df: fig.add_trace( go.Scatter(x=df.index, y=df["rsi_21"], name="RSI 21", line=dict(color="magenta", dash="dash")), row=3, col=1 ) if 'rsi_50' in df: fig.add_trace( go.Scatter(x=df.index, y=df["rsi_50"], name="RSI 50", line=dict(color="cyan", dash="dot")), row=3, col=1 ) # Stochastic & Williams %R if 'stochk_14_3_3' in df: fig.add_trace( go.Scatter(x=df.index, y=df["stochk_14_3_3"], name="Stoch %K", line=dict(color="blue")), row=4, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df["stochd_14_3_3"], name="Stoch %D", line=dict(color="orange")), row=4, col=1 ) fig.add_hline(y=80, line_dash="dash", line_color="red", row=4, col=1) fig.add_hline(y=20, line_dash="dash", line_color="green", row=4, col=1) if 'willr_14' in df: fig.add_trace( go.Scatter(x=df.index, y=df["willr_14"], name="Williams %R", line=dict(color="green")), row=4, col=1 ) fig.add_hline(y=-20, line_dash="dash", line_color="red", row=4, col=1) fig.add_hline(y=-80, line_dash="dash", line_color="green", row=4, col=1) # ADX & DI if 'adx_14' in df: fig.add_trace( go.Scatter(x=df.index, y=df['adx_14'], name='ADX', line=dict(color='blue')), row=5, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df.get('pdi_14'), name='+DI', line=dict(color='green')), row=5, col=1 ) fig.add_trace( go.Scatter(x=df.index, y=df.get('mdi_14'), name='-DI', line=dict(color='red')), row=5, col=1 ) fig.add_hline(y=25, line_dash="dash", line_color="black", row=5, col=1) # ATR & CCI if 'atr_14' in df: fig.add_trace( go.Scatter(x=df.index, y=df["atr_14"], name="ATR", line=dict(color="orange")), row=6, col=1 ) if 'cci_20' in df: fig.add_trace( go.Scatter(x=df.index, y=df["cci_20"], name="CCI", line=dict(color="purple")), row=6, col=1 ) fig.add_hline(y=100, line_dash="dash", line_color="red", row=6, col=1) fig.add_hline(y=-100, line_dash="dash", line_color="green", row=6, col=1) # Signal Strength Plot if all(col in df for col in ['RSI_Signal', 'MACD_Signal', 'ADX_Signal', 'Sentiment_Signal', 'Model_Signal']): signal_strength = ( df['RSI_Signal'].abs() + df['MACD_Signal'].abs() + df['ADX_Signal'].abs() + df['Sentiment_Signal'].abs() + df['Model_Signal'].abs() ) fig.add_trace( go.Scatter( x=df.index, y=signal_strength, name='Signal Strength', line=dict(color='teal'), fill='tozeroy' ), row=7, col=1 ) fig.add_hline(y=3, line_dash="dash", line_color="orange", row=7, col=1, annotation_text="Strong Signal Threshold") fig.update_layout( title=f"{ticker} Price and Technical Indicators", template="plotly_white", height=2400, width=1400, showlegend=True, xaxis_rangeslider_visible=False, margin=dict(l=50, r=50, t=100, b=50), xaxis=dict(tickformat="%Y-%m-%d", minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white", hovermode="x unified" ) return fig except Exception as e: logging.error(f"Plot indicators error: {e}") return None def plot_future_forecast(df, result, indicators): fig, ax = plt.subplots(figsize=(10, 6)) ax.plot(df.index, df["value"], label="Historical Value", color="blue", linewidth=2) for ind in indicators: if ind in df.columns: ax.plot(df.index, df[ind], label=ind, linestyle='--') if "latest_prediction" in result: last_date = df.index[-1] horizon = len(result["latest_prediction"]) future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=horizon, freq='B') ax.plot(future_dates, result["latest_prediction"], label="Forecast Value", color="orange", linestyle="--", linewidth=2) for i, val in enumerate(result["latest_prediction"]): ax.text(future_dates[i], val, f"{val:.2f}", color="orange") ax.legend() ax.set_title("Historical Data, Indicators, and Future Forecast") ax.set_xlabel("Date") ax.set_ylabel("Value") ax.grid(True) plt.tight_layout() return fig # Other plotting functions remain unchanged def plot_forecast(result, df): try: actual = result.get("actual", []) forecast = result.get("forecast", []) if not actual or not forecast: return None dates = df.index[-len(actual):] fig = go.Figure() fig.add_trace(go.Scatter(x=dates, y=actual, name='Actual', line=dict(color='blue'))) fig.add_trace(go.Scatter(x=dates, y=forecast, name='Forecast', line=dict(color='orange'))) fig.update_layout( title="Backtest: Actual vs Forecast", template="plotly_white", height=600, xaxis_title="Date", yaxis_title="Price", xaxis=dict(tickformat="%Y-%m-%d", minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot forecast error: {e}") return None # ... (other plotting functions like plot_future_forecast, plot_metrics_r2, etc., remain as provided) def plot_metrics_r2(result): try: metrics = result.get("metrics", {}) if not metrics: return None fig = go.Figure() fig.add_trace(go.Bar( x=['R²', 'MAPE'], y=[metrics.get('R2', 0), metrics.get('MAPE', 0)], marker_color=['#1E90FF', '#FF6347'] )) fig.update_layout( title="R² and MAPE Metrics", template="plotly_white", height=600, xaxis_title="Metric", yaxis_title="Value", xaxis=dict(minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot R2 error: {e}") return None def plot_metrics_errors(result): try: metrics = result.get("metrics", {}) if not metrics: return None fig = go.Figure() fig.add_trace(go.Bar( x=['RMSE', 'MAE'], y=[metrics.get('RMSE', 0), metrics.get('MAE', 0)], marker_color=['#32CD32', '#9370DB'] )) fig.update_layout( title="Error Metrics", template="plotly_white", height=600, xaxis_title="Metric", yaxis_title="Value", xaxis=dict(minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot metrics errors: {e}") return None def plot_metrics_precision_recall(result): try: metrics = result.get("metrics", {}) if not metrics: return None fig = go.Figure() fig.add_trace(go.Bar( x=['Precision', 'Recall'], y=[metrics.get('Precision', 0), metrics.get('Recall', 0)], marker_color=['#1E90FF', '#FF6347'] )) fig.update_layout( title="Precision and Recall Metrics", template="plotly_white", height=600, xaxis_title="Metric", yaxis_title="Value", xaxis=dict(minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot precision recall error: {e}") return None def plot_metrics_risk(result): try: metrics = result.get("metrics", {}) if not metrics: return None fig = go.Figure() fig.add_trace(go.Bar( x=['MASE', 'Sharpe', 'Volatility'], y=[metrics.get('MASE', 0), metrics.get('Sharpe', 0), metrics.get('Volatility', 0)], marker_color=['#32CD32', '#9370DB', '#FFD700'] )) fig.update_layout( title="Risk Metrics", template="plotly_white", height=600, xaxis_title="Metric", yaxis_title="Value", xaxis=dict(minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot risk metrics error: {e}") return None def plot_loss_curve(result): try: train_loss = result.get("train_loss", []) val_loss = result.get("val_loss", []) if not train_loss: return None epochs = list(range(1, len(train_loss) + 1)) fig = go.Figure() fig.add_trace(go.Scatter(x=epochs, y=train_loss, mode='lines', name='Train Loss', line=dict(color='#00CC96'))) fig.add_trace(go.Scatter(x=epochs, y=val_loss, mode='lines', name='Validation Loss', line=dict(color='#EF553B'))) fig.update_layout( title="Training and Validation Loss", template="plotly_white", height=600, xaxis_title="Epoch", yaxis_title="Loss", xaxis=dict(minor=dict(ticks="inside", showgrid=True), gridcolor="lightgrey"), yaxis=dict(gridcolor="lightgrey"), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot loss curve error: {e}") return None def plot_model_architecture(result): try: summary_text = result.get("model_summary", "No model summary available.") if not summary_text or summary_text == "No model summary available.": summary_text = "Model architecture summary could not be generated." fig = go.Figure() fig.add_annotation( text=summary_text.replace('\n', '
'), xref="paper", yref="paper", x=0, y=1, showarrow=False, font=dict(size=14, family="Courier New", color="#1E90FF"), align="left", bgcolor="white", bordercolor="black", borderwidth=1, width=600, height=400 ) fig.update_layout( title="Model Architecture", template="plotly_white", height=600, showlegend=False, xaxis=dict(visible=False), yaxis=dict(visible=False), plot_bgcolor="white", paper_bgcolor="white" ) return fig except Exception as e: logging.error(f"Plot model architecture error: {e}") return None def plot_signals(signals_df, ticker): try: fig = go.Figure() fig.add_trace(go.Scatter( x=signals_df.index, y=signals_df['Price'], mode='lines', name='Price' )) buy_signals = signals_df[signals_df['Signal'] == 'Buy'] sell_signals = signals_df[signals_df['Signal'] == 'Sell'] fig.add_trace(go.Scatter( x=buy_signals.index, y=buy_signals['Price'], mode='markers', marker=dict(symbol='triangle-up', size=10, color='green'), name='Buy Signal' )) fig.add_trace(go.Scatter( x=sell_signals.index, y=sell_signals['Price'], mode='markers', marker=dict(symbol='triangle-down', size=10, color='red'), name='Sell Signal' )) fig.update_layout( title=f'{ticker} Trading Signals', xaxis_title='Date', yaxis_title='Price', template="plotly_white", xaxis_rangeslider_visible=False ) return fig except Exception as e: logging.error(f"Plot signals error: {e}") return None def plot_backtest(equity_df, trades_df, ticker): try: fig = go.Figure() fig.add_trace(go.Scatter( x=equity_df.index, y=equity_df['Equity'], mode='lines', name='Equity Curve' )) buy_trades = trades_df[trades_df['Type'] == 'Buy'] sell_trades = trades_df[trades_df['Type'] == 'Sell'] exit_trades = trades_df[trades_df['Type'] == 'Exit'] fig.add_trace(go.Scatter( x=buy_trades['Date'], y=buy_trades['Price'], mode='markers', marker=dict(symbol='triangle-up', size=10, color='green'), name='Buy Trades' )) fig.add_trace(go.Scatter( x=sell_trades['Date'], y=sell_trades['Price'], mode='markers', marker=dict(symbol='triangle-down', size=10, color='red'), name='Sell Trades' )) fig.add_trace(go.Scatter( x=exit_trades['Date'], y=exit_trades['Price'], mode='markers', marker=dict(symbol='circle', size=8, color='blue'), name='Exit Trades' )) fig.update_layout( title=f'{ticker} Backtest Equity Curve and Trades', xaxis_title='Date', yaxis_title='Equity / Price', template="plotly_white", xaxis_rangeslider_visible=False ) return fig except Exception as e: logging.error(f"Plot backtest error: {e}") return None