Implement real data from yahoo finance and the possibility to choose ticker 

import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from datetime import datetime, timedelta
import warnings

# Suppress the specific UserWarning if needed
warnings.filterwarnings("ignore", message="X does not have valid feature names")

# Generate synthetic financial data with technical indicators
def generate_data(num_days=200):
    np.random.seed(0)
    dates = [datetime.today() - timedelta(days=x) for x in range(num_days)][::-1]
    price = 100 + np.cumsum(np.random.randn(num_days)) + 50 * np.sin(np.linspace(0, 3 * np.pi, num_days))  # Added trend
    volume = np.random.randint(100, 1000, size=num_days)
    data = pd.DataFrame({
        'Date': dates,
        'Price': price,
        'Volume': volume
    })
    data = add_technical_indicators(data)
    return data

# Add technical indicators to the dataframe
def add_technical_indicators(data):
    # Simple Moving Averages
    data['SMA_10'] = data['Price'].rolling(window=10).mean()
    data['SMA_50'] = data['Price'].rolling(window=50).mean()
    
    # Exponential Moving Averages
    data['EMA_10'] = data['Price'].ewm(span=10, adjust=False).mean()
    data['EMA_50'] = data['Price'].ewm(span=50, adjust=False).mean()
    data['EMA_12'] = data['Price'].ewm(span=12, adjust=False).mean()
    data['EMA_26'] = data['Price'].ewm(span=26, adjust=False).mean()
    
    # Relative Strength Index
    delta = data['Price'].diff()
    up = delta.clip(lower=0)
    down = -1 * delta.clip(upper=0)
    ema_up = up.ewm(com=13, adjust=False).mean()
    ema_down = down.ewm(com=13, adjust=False).mean()
    rs = ema_up / ema_down
    data['RSI'] = 100 - (100 / (1 + rs))
    
    # Moving Average Convergence Divergence
    ema_12 = data['EMA_12']
    ema_26 = data['EMA_26']
    data['MACD'] = ema_12 - ema_26
    data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()
    
    # Initialize EMA_up and EMA_down for RSI calculation
    data['EMA_up'] = ema_up
    data['EMA_down'] = ema_down
    
    # Forward-fill and backward-fill missing values
    data = data.ffill().bfill()
    
    return data

# Prepare machine learning model for price prediction
def prepare_model(data):
    feature_cols = ['Price', 'Volume', 'SMA_10', 'SMA_50', 'EMA_10', 'EMA_50', 'RSI', 'MACD', 'Signal_Line']
    X = data[feature_cols]
    y = data['Price'].shift(-1)  # Predict the next day's price
    X = X[:-1]
    y = y[:-1]
    
    # Feature Scaling
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    # Initialize the model
    model = RandomForestRegressor(n_estimators=100, random_state=42)
    
    # Cross-validation
    cv_scores = cross_val_score(model, X_scaled, y, cv=5, scoring='neg_mean_squared_error')
    rmse_scores = np.sqrt(-cv_scores)
    print(f"Average CV RMSE Score: {np.mean(rmse_scores):.4f}")
    
    # Fit the model
    model.fit(X_scaled, y)
    
    return model, scaler, feature_cols

# Predict future prices
def predict_future(model, scaler, feature_cols, data, num_days=30):
    predictions = []
    dates = []
    new_rows = []  # Collect new rows here
    
    current_data = data.copy().reset_index(drop=True)
    
    # Initialize EMA_up and EMA_down if not present
    if 'EMA_up' not in current_data.columns:
        current_data['EMA_up'] = 0
    if 'EMA_down' not in current_data.columns:
        current_data['EMA_down'] = 0
    
    for _ in range(num_days):
        last_row = current_data.iloc[-1]
        X_new = last_row[feature_cols].values.reshape(1, -1)
        X_new_scaled = scaler.transform(X_new)
        pred_price = model.predict(X_new_scaled)[0]
        
        # Create new date
        new_date = last_row['Date'] + timedelta(days=1)
        
        # Generate random volume for the new day
        new_volume = np.random.randint(100, 1000)
        
        # Calculate new technical indicators
        new_sma_10 = (last_row['SMA_10'] * 9 + pred_price) / 10
        new_sma_50 = (last_row['SMA_50'] * 49 + pred_price) / 50
        new_ema_10 = (pred_price - last_row['EMA_10']) * (2 / (10 + 1)) + last_row['EMA_10']
        new_ema_50 = (pred_price - last_row['EMA_50']) * (2 / (50 + 1)) + last_row['EMA_50']
        new_ema_12 = (pred_price - last_row['EMA_12']) * (2 / (12 + 1)) + last_row['EMA_12']
        new_ema_26 = (pred_price - last_row['EMA_26']) * (2 / (26 + 1)) + last_row['EMA_26']
        
        # RSI calculation
        delta = pred_price - last_row['Price']
        gain = max(delta, 0)
        loss = max(-delta, 0)
        ema_up = (last_row['EMA_up'] * 13 + gain) / 14
        ema_down = (last_row['EMA_down'] * 13 + loss) / 14
        if ema_down == 0:
            rsi = 100
        else:
            rs = ema_up / ema_down
            rsi = 100 - (100 / (1 + rs))
        
        # MACD and Signal Line
        new_macd = new_ema_12 - new_ema_26
        new_signal_line = (last_row['Signal_Line'] * 8 + new_macd) / 9
        
        # Append the new data to list
        new_data = {
            'Date': new_date,
            'Price': pred_price,
            'Volume': new_volume,
            'SMA_10': new_sma_10,
            'SMA_50': new_sma_50,
            'EMA_10': new_ema_10,
            'EMA_50': new_ema_50,
            'EMA_12': new_ema_12,
            'EMA_26': new_ema_26,
            'RSI': rsi,
            'MACD': new_macd,
            'Signal_Line': new_signal_line,
            'EMA_up': ema_up,
            'EMA_down': ema_down
        }
        new_rows.append(new_data)
        predictions.append(pred_price)
        dates.append(new_date)
        
        # Update current_data with the new row for next iteration
        current_data = pd.concat([current_data, pd.DataFrame([new_data])], ignore_index=True)
    
    prediction_df = pd.DataFrame({
        'Date': dates,
        'Predicted_Price': predictions
    })
    return prediction_df

# Initialize Dash app
app = dash.Dash(__name__)
app.title = "AI-Powered Financial Analytics Dashboard"

# Prepare data
df = generate_data(num_days=200)

# Prepare machine learning model for price prediction
model, scaler, feature_cols = prepare_model(df)

# Predict future prices
prediction_df = predict_future(model, scaler, feature_cols, df)

# Layout of the dashboard
app.layout = html.Div([
    html.H1("AI-Powered Financial Analytics Dashboard", style={'textAlign': 'center'}),
    
    html.Div([
        dcc.Graph(
            id='price-chart',
            figure={
                'data': [
                    go.Scatter(
                        x=df['Date'],
                        y=df['Price'],
                        mode='lines',
                        name='Historical Price'
                    ),
                    go.Scatter(
                        x=prediction_df['Date'],
                        y=prediction_df['Predicted_Price'],
                        mode='lines',
                        name='Predicted Price',
                        line=dict(dash='dash')
                    ),
                    go.Scatter(
                        x=df['Date'],
                        y=df['SMA_10'],
                        mode='lines',
                        name='SMA 10',
                        line=dict(color='orange')
                    ),
                    go.Scatter(
                        x=df['Date'],
                        y=df['SMA_50'],
                        mode='lines',
                        name='SMA 50',
                        line=dict(color='magenta')
                    )
                ],
                'layout': go.Layout(
                    title='Stock Price Over Time',
                    xaxis={'title': 'Date'},
                    yaxis={'title': 'Price ($)'},
                    hovermode='closest',
                    legend=dict(x=0, y=1)
                )
            }
        )
    ], style={'width': '90%', 'margin': 'auto'}),
    
    html.Div([
        dcc.Graph(
            id='technical-indicators',
            figure={
                'data': [
                    go.Scatter(
                        x=df['Date'],
                        y=df['RSI'],
                        mode='lines',
                        name='RSI',
                        yaxis='y2'
                    ),
                    go.Scatter(
                        x=df['Date'],
                        y=df['MACD'],
                        mode='lines',
                        name='MACD',
                        yaxis='y3'
                    ),
                    go.Scatter(
                        x=df['Date'],
                        y=df['Signal_Line'],
                        mode='lines',
                        name='Signal Line',
                        yaxis='y3',
                        line=dict(dash='dash')
                    )
                ],
                'layout': go.Layout(
                    title='Technical Indicators',
                    xaxis={'title': 'Date'},
                    yaxis=dict(title='RSI', side='left'),
                    yaxis2=dict(title='MACD', overlaying='y', side='right'),
                    yaxis3=dict(title='Signal Line', overlaying='y', side='right', anchor='free', position=0.85),
                    hovermode='closest',
                    legend=dict(x=0, y=1)
                )
            }
        )
    ], style={'width': '90%', 'margin': 'auto', 'paddingTop': '50px'}),
    
    html.Div([
        dcc.Graph(
            id='volume-chart',
            figure={
                'data': [
                    go.Bar(
                        x=df['Date'],
                        y=df['Volume'],
                        name='Volume'
                    )
                ],
                'layout': go.Layout(
                    title='Trading Volume Over Time',
                    xaxis={'title': 'Date'},
                    yaxis={'title': 'Volume'},
                    hovermode='closest'
                )
            }
        )
    ], style={'width': '90%', 'margin': 'auto', 'paddingTop': '50px'}),
    
    html.Div([
        html.H3("Predictive Insights", style={'textAlign': 'center'}),
        html.P("The model now incorporates technical indicators such as Moving Averages, RSI, and MACD to enhance prediction accuracy. A Random Forest Regressor is used to capture complex patterns in the data. For further improvements, consider integrating real financial data, implementing backtesting strategies, and experimenting with more advanced machine learning models like Gradient Boosting or Neural Networks.")
    ], style={'width': '90%', 'margin': 'auto', 'paddingTop': '20px'})
])

# Run the Dash app
if __name__ == '__main__':
    app.run_server(debug=True)