Spaces:
Sleeping
Sleeping
| # %% | |
| import gradio as gr | |
| import pandas as pd | |
| import yfinance as yf | |
| from datetime import datetime | |
| import plotly.graph_objects as go | |
| import numpy as np | |
| # Functions for calculating indicators (SMA, RSI, etc.) and generating trading signals | |
| def calculate_sma(df, window): | |
| return df['Close'].rolling(window=window).mean() | |
| def calculate_ema(df, window): | |
| return df['Close'].ewm(span=window, adjust=False).mean() | |
| def calculate_macd(df): | |
| short_ema = df['Close'].ewm(span=12, adjust=False).mean() | |
| long_ema = df['Close'].ewm(span=26, adjust=False).mean() | |
| macd = short_ema - long_ema | |
| signal = macd.ewm(span=9, adjust=False).mean() | |
| return macd, signal | |
| def calculate_rsi(df): | |
| delta = df['Close'].diff() | |
| gain = (delta.where(delta > 0, 0)).rolling(window=14).mean() | |
| loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean() | |
| rs = gain / loss | |
| rsi = 100 - (100 / (1 + rs)) | |
| return rsi | |
| def calculate_bollinger_bands(df): | |
| middle_bb = df['Close'].rolling(window=20).mean() | |
| upper_bb = middle_bb + 2 * df['Close'].rolling(window=20).std() | |
| lower_bb = middle_bb - 2 * df['Close'].rolling(window=20).std() | |
| return middle_bb, upper_bb, lower_bb | |
| def calculate_stochastic_oscillator(df): | |
| lowest_low = df['Low'].rolling(window=14).min() | |
| highest_high = df['High'].rolling(window=14).max() | |
| slowk = ((df['Close'] - lowest_low) / (highest_high - lowest_low)) * 100 | |
| slowd = slowk.rolling(window=3).mean() | |
| return slowk, slowd | |
| def calculate_cmf(df, window=20): | |
| mfv = ((df['Close'] - df['Low']) - (df['High'] - df['Close'])) / (df['High'] - df['Low']) * df['Volume'] | |
| cmf = mfv.rolling(window=window).sum() / df['Volume'].rolling(window=window).sum() | |
| return cmf | |
| def calculate_cci(df, window=20): | |
| """Calculate Commodity Channel Index (CCI).""" | |
| typical_price = (df['High'] + df['Low'] + df['Close']) / 3 | |
| sma = typical_price.rolling(window=window).mean() | |
| mean_deviation = (typical_price - sma).abs().rolling(window=window).mean() | |
| cci = (typical_price - sma) / (0.015 * mean_deviation) | |
| return cci | |
| def generate_trading_signals(df): | |
| # Calculate various indicators | |
| df['SMA_30'] = calculate_sma(df, 30) | |
| df['SMA_100'] = calculate_sma(df, 100) | |
| df['EMA_12'] = calculate_ema(df, 12) | |
| df['EMA_26'] = calculate_ema(df, 26) | |
| df['RSI'] = calculate_rsi(df) | |
| df['MiddleBB'], df['UpperBB'], df['LowerBB'] = calculate_bollinger_bands(df) | |
| df['SlowK'], df['SlowD'] = calculate_stochastic_oscillator(df) | |
| df['CMF'] = calculate_cmf(df) | |
| df['CCI'] = calculate_cci(df) | |
| # Generate trading signals | |
| df['SMA_Signal'] = np.where(df['SMA_30'] > df['SMA_100'], 1, 0) | |
| macd, signal = calculate_macd(df) | |
| df['MACD_Signal'] = np.select([(macd > signal) & (macd.shift(1) <= signal.shift(1)), | |
| (macd < signal) & (macd.shift(1) >= signal.shift(1))],[1, -1], default=0) | |
| df['RSI_Signal'] = np.where(df['RSI'] < 15, 1, 0) | |
| df['RSI_Signal'] = np.where(df['RSI'] > 100, -1, df['RSI_Signal']) | |
| df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'], 0, 0) | |
| df['BB_Signal'] = np.where(df['Close'] > df['UpperBB'], -1, df['BB_Signal']) | |
| df['Stochastic_Signal'] = np.where((df['SlowK'] < 5) & (df['SlowD'] < 5), 1, 0) | |
| df['Stochastic_Signal'] = np.where((df['SlowK'] > 95) & (df['SlowD'] > 95), -1, df['Stochastic_Signal']) | |
| df['CMF_Signal'] = np.where(df['CMF'] > 0.5, -1, np.where(df['CMF'] < -0.5, 1, 0)) | |
| df['CCI_Signal'] = np.where(df['CCI'] < -250, 1, 0) | |
| df['CCI_Signal'] = np.where(df['CCI'] > 250, -1, df['CCI_Signal']) | |
| # Combined signal for stronger buy/sell points | |
| df['Combined_Signal'] = df[['RSI_Signal', 'BB_Signal', | |
| 'Stochastic_Signal', 'CMF_Signal', | |
| 'CCI_Signal']].sum(axis=1) | |
| return df | |
| # %% | |
| def plot_combined_signals(df, ticker): | |
| # Create a figure | |
| fig = go.Figure() | |
| # Add closing price trace | |
| fig.add_trace(go.Scatter( | |
| x=df.index, y=df['Close'], | |
| mode='lines', | |
| name='Closing Price', | |
| line=dict(color='lightcoral', width=2) | |
| )) | |
| # Add buy signals | |
| buy_signals = df[df['Combined_Signal'] >= 3] | |
| fig.add_trace(go.Scatter( | |
| x=buy_signals.index, y=buy_signals['Close'], | |
| mode='markers', | |
| marker=dict(symbol='triangle-up', size=10, color='lightgreen'), | |
| name='Buy Signal' | |
| )) | |
| # Add sell signals | |
| sell_signals = df[df['Combined_Signal'] <= -3] | |
| fig.add_trace(go.Scatter( | |
| x=sell_signals.index, y=sell_signals['Close'], | |
| mode='markers', | |
| marker=dict(symbol='triangle-down', size=10, color='lightsalmon'), | |
| name='Sell Signal' | |
| )) | |
| # Combined signal trace | |
| fig.add_trace(go.Scatter( | |
| x=df.index, y=df['Combined_Signal'], | |
| mode='lines', | |
| name='Combined Signal', | |
| line=dict(color='deepskyblue', width=2), | |
| yaxis='y2' | |
| )) | |
| # Update layout | |
| fig.update_layout( | |
| title=f'{ticker}: Stock Price and Combined Trading Signal (Last 60 Days)', | |
| xaxis=dict(title='Date'), | |
| yaxis=dict(title='Price', side='left'), | |
| yaxis2=dict(title='Combined Signal', overlaying='y', side='right', showgrid=False), | |
| plot_bgcolor='black', | |
| paper_bgcolor='black', | |
| font=dict(color='white') | |
| ) | |
| return fig | |
| # %% | |
| def stock_analysis(ticker, start_date, end_date): | |
| # Download stock data from Yahoo Finance | |
| df = yf.download(ticker, start=start_date, end=end_date) | |
| # Generate signals | |
| generate_trading_signals(df) | |
| # Last 60 days | |
| df_last_60 = df.tail(60) | |
| # Plot signals | |
| fig_signals = plot_combined_signals(df_last_60, ticker) | |
| return fig_signals | |
| # %% | |
| def plot_individual_signals(df, ticker): | |
| # Create a figure | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter( | |
| x=df.index, y=df['Close'], | |
| mode='lines', | |
| name='Closing Price', | |
| line=dict(color='lightcoral', width=2) | |
| )) | |
| # Add buy/sell signals for each indicator | |
| signal_names = ['RSI_Signal', 'BB_Signal', | |
| 'Stochastic_Signal', 'CMF_Signal', | |
| 'CCI_Signal'] | |
| for signal in signal_names: | |
| buy_signals = df[df[signal] == 1] | |
| sell_signals = df[df[signal] == -1] | |
| fig.add_trace(go.Scatter( | |
| x=buy_signals.index, y=buy_signals['Close'], | |
| mode='markers', | |
| marker=dict(symbol='triangle-up', size=10, color='lightgreen'), | |
| name=f'{signal} Buy Signal' | |
| )) | |
| fig.add_trace(go.Scatter( | |
| x=sell_signals.index, y=sell_signals['Close'], | |
| mode='markers', | |
| marker=dict(symbol='triangle-down', size=10, color='lightsalmon'), | |
| name=f'{signal} Sell Signal' | |
| )) | |
| fig.update_layout( | |
| title=f'{ticker}: Individual Trading Signals', | |
| xaxis=dict(title='Date'), | |
| yaxis=dict(title='Price', side='left'), | |
| plot_bgcolor='black', | |
| paper_bgcolor='black', | |
| font=dict(color='white') | |
| ) | |
| return fig | |
| def display_signals(df): | |
| # Create a signals DataFrame | |
| signals_df = df[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal', | |
| 'BB_Signal', 'Stochastic_Signal', | |
| 'CMF_Signal', 'CCI_Signal']].copy() | |
| # The Date is the index, so we don't need to add it as a column | |
| signals_df.index.name = 'Date' # Name the index for better readability | |
| # Replace signal values with 'Buy', 'Sell', or 'Hold' | |
| for column in signals_df.columns: | |
| signals_df[column] = signals_df[column].replace( | |
| {1: 'Buy', -1: 'Sell', 0: 'Hold'} | |
| ) | |
| return signals_df | |
| def stock_analysis(ticker, start_date, end_date): | |
| # Download stock data from Yahoo Finance | |
| df = yf.download(ticker, start=start_date, end=end_date) | |
| # Generate signals | |
| df = generate_trading_signals(df) | |
| # Last 60 days for plotting | |
| df_last_60 = df.tail(200) | |
| # Plot combined signals | |
| fig_signals = plot_combined_signals(df_last_60, ticker) | |
| # Plot individual signals | |
| fig_individual_signals = plot_individual_signals(df_last_60, ticker) | |
| # Display signals DataFrame | |
| signals_df = df_last_60[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal', | |
| 'Stochastic_Signal','CMF_Signal', | |
| 'CCI_Signal']] | |
| return fig_signals, fig_individual_signals | |
| # %% | |
| # Define Gradio interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## Stock Market Analysis App") | |
| ticker_input = gr.Textbox(label="Enter Stock Ticker (e.g., AAPL, NVDA)", value="NVDA") | |
| start_date_input = gr.Textbox(label="Start Date (YYYY-MM-DD)", value="2022-01-01") | |
| end_date_input = gr.Textbox(label="End Date (YYYY-MM-DD)", value="2025-01-01") | |
| # Create a submit button that runs the stock analysis function | |
| button = gr.Button("Analyze Stock") | |
| # Outputs: Display results, charts | |
| combined_signals_output = gr.Plot(label="Combined Trading Signals") | |
| individual_signals_output = gr.Plot(label="Individual Trading Signals") | |
| #signals_df_output = gr.Dataframe(label="Buy/Sell Signals") | |
| # Link button to function | |
| button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input], | |
| outputs=[combined_signals_output, individual_signals_output]) | |
| # Launch the interface | |
| demo.launch() | |