JayLacoma's picture
Update app.py
ba4126d verified
raw
history blame
6.96 kB
# %%
# %%
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_atr(df, window=14):
high_low = df['High'] - df['Low']
high_close = np.abs(df['High'] - df['Close'].shift())
low_close = np.abs(df['Low'] - df['Close'].shift())
tr = high_low.combine(high_close, max).combine(low_close, max)
atr = tr.rolling(window=window).mean()
return atr
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['ATR'] = calculate_atr(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']+3, 1, 0)
macd, signal = calculate_macd(df)
df['MACD_Signal'] = np.where((macd > signal.shift(1)) & (macd.shift(1) < signal), 1, 0)
df['RSI_Signal'] = np.where(df['RSI'] < 30, 1, 0)
df['RSI_Signal'] = np.where(df['RSI'] > 70, -1, df['RSI_Signal'])
df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'], 1, 0)
df['BB_Signal'] = np.where(df['Close'] > df['UpperBB'], -1, df['BB_Signal'])
df['Stochastic_Signal'] = np.where((df['SlowK'] < 15) & (df['SlowD'] < 20), 1, 0)
df['Stochastic_Signal'] = np.where((df['SlowK'] > 80) & (df['SlowD'] > 80), -1, df['Stochastic_Signal'])
df['ATR_Signal'] = np.where(df['ATR'] > df['ATR'].rolling(window=20).mean(), 1, 0)
df['CMF_Signal'] = np.where(df['CMF'] > 0.05, 1, np.where(df['CMF'] < -0.05, -1, 0))
df['CCI_Signal'] = np.where(df['CCI'] < -150, 1, 0)
df['CCI_Signal'] = np.where(df['CCI'] > 150, -1, df['CCI_Signal'])
# Combined signal for stronger buy/sell points
df['Combined_Signal'] = df[['SMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal',
'Stochastic_Signal', 'ATR_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
# %%
# 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
signals_output = gr.Plot(label="Trading Signals")
# Link button to function
button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input], outputs=[signals_output])
# Launch the interface
demo.launch()