JayLacoma commited on
Commit
1f6ac5b
·
verified ·
1 Parent(s): 6e80415

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +211 -88
app.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import yfinance as yf
@@ -5,50 +7,47 @@ from datetime import datetime
5
  import plotly.graph_objects as go
6
  import numpy as np
7
 
8
- # Improved Indicator Calculation Functions
 
9
  def calculate_sma(df, window):
10
- """Calculate Simple Moving Average (SMA)."""
11
  return df['Close'].rolling(window=window).mean()
12
 
13
  def calculate_ema(df, window):
14
- """Calculate Exponential Moving Average (EMA)."""
15
  return df['Close'].ewm(span=window, adjust=False).mean()
16
 
 
17
  def calculate_macd(df):
18
- """Calculate MACD and its Signal Line."""
19
  short_ema = df['Close'].ewm(span=12, adjust=False).mean()
20
  long_ema = df['Close'].ewm(span=26, adjust=False).mean()
21
  macd = short_ema - long_ema
22
  signal = macd.ewm(span=9, adjust=False).mean()
23
  return macd, signal
24
 
25
- def calculate_rsi(df, window=14):
26
- """Calculate Relative Strength Index (RSI)."""
27
  delta = df['Close'].diff()
28
- gain = delta.where(delta > 0, 0).rolling(window=window).mean()
29
- loss = -delta.where(delta < 0, 0).rolling(window=window).mean()
30
  rs = gain / loss
31
  rsi = 100 - (100 / (1 + rs))
32
  return rsi
33
 
34
- def calculate_bollinger_bands(df, window=20):
35
- """Calculate Bollinger Bands."""
36
- middle_bb = df['Close'].rolling(window=window).mean()
37
- std_dev = df['Close'].rolling(window=window).std()
38
- upper_bb = middle_bb + (2 * std_dev)
39
- lower_bb = middle_bb - (2 * std_dev)
40
  return middle_bb, upper_bb, lower_bb
41
 
42
- def calculate_stochastic_oscillator(df, window=14):
43
- """Calculate Stochastic Oscillator (%K and %D)."""
44
- lowest_low = df['Low'].rolling(window=window).min()
45
- highest_high = df['High'].rolling(window=window).max()
46
  slowk = ((df['Close'] - lowest_low) / (highest_high - lowest_low)) * 100
47
  slowd = slowk.rolling(window=3).mean()
48
  return slowk, slowd
49
 
 
 
50
  def calculate_cmf(df, window=20):
51
- """Calculate Chaikin Money Flow (CMF)."""
52
  mfv = ((df['Close'] - df['Low']) - (df['High'] - df['Close'])) / (df['High'] - df['Low']) * df['Volume']
53
  cmf = mfv.rolling(window=window).sum() / df['Volume'].rolling(window=window).sum()
54
  return cmf
@@ -61,8 +60,10 @@ def calculate_cci(df, window=20):
61
  cci = (typical_price - sma) / (0.015 * mean_deviation)
62
  return cci
63
 
 
 
64
  def generate_trading_signals(df):
65
- """Generate trading signals based on indicators."""
66
  df['SMA_30'] = calculate_sma(df, 30)
67
  df['SMA_100'] = calculate_sma(df, 100)
68
  df['EMA_12'] = calculate_ema(df, 12)
@@ -73,102 +74,224 @@ def generate_trading_signals(df):
73
  df['CMF'] = calculate_cmf(df)
74
  df['CCI'] = calculate_cci(df)
75
 
76
- # Trading Signals
 
 
 
 
77
  macd, signal = calculate_macd(df)
78
  df['MACD_Signal'] = np.select([(macd > signal) & (macd.shift(1) <= signal.shift(1)),
79
- (macd < signal) & (macd.shift(1) >= signal.shift(1))],
80
- [1, -1], default=0)
81
-
82
- # Stricter thresholds for signals
83
- df['RSI_Signal'] = np.where(df['RSI'] < 5, 1, np.where(df['RSI'] > 95, -1, 0))
84
- df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'] - 2 * df['Close'].rolling(window=20).std(), 1,
85
- np.where(df['Close'] > df['UpperBB'] + 2 * df['Close'].rolling(window=20).std(), -1, 0))
86
- df['Stochastic_Signal'] = np.where((df['SlowK'] < 5) & (df['SlowD'] < 5), 1,
87
- np.where((df['SlowK'] > 95) & (df['SlowD'] > 95), -1, 0))
88
- df['CMF_Signal'] = np.where(df['CMF'] > 0.4, -1, np.where(df['CMF'] < -0.4, 1, 0))
89
- df['CCI_Signal'] = np.where(df['CCI'] < -200, 1, np.where(df['CCI'] > 200, -1, 0))
90
 
91
- # Combined signal for stronger buy/sell points
92
- df['Combined_Signal'] = df[['RSI_Signal', 'BB_Signal',
93
- 'Stochastic_Signal', 'CMF_Signal',
94
- 'CCI_Signal']].sum(axis=1)
95
 
96
- # Stricter combined signal threshold
97
- df['Buy_Signal'] = df['Combined_Signal'] >= 2
98
- df['Sell_Signal'] = df['Combined_Signal'] <= -2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  return df
101
 
102
 
103
- # Plot Functions
104
  def plot_combined_signals(df, ticker):
105
- """Plot combined signals and stock price."""
106
  fig = go.Figure()
107
- fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Closing Price',
108
- line=dict(color='lightcoral', width=2)))
109
 
110
- buy_signals = df[df['Combined_Signal'] >= 2]
111
- sell_signals = df[df['Combined_Signal'] <= -2]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- fig.add_trace(go.Scatter(x=buy_signals.index, y=buy_signals['Close'], mode='markers',
114
- marker=dict(symbol='triangle-up', size=10, color='lightgreen'), name='Buy Signal'))
115
- fig.add_trace(go.Scatter(x=sell_signals.index, y=sell_signals['Close'], mode='markers',
116
- marker=dict(symbol='triangle-down', size=10, color='lightsalmon'), name='Sell Signal'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
- fig.update_layout(title=f'{ticker}: Combined Trading Signals',
119
- xaxis=dict(title='Date'), yaxis=dict(title='Price'),
120
- plot_bgcolor='black', paper_bgcolor='black', font=dict(color='white'))
121
  return fig
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  def plot_individual_signals(df, ticker):
124
- """Plot individual signals for indicators."""
125
  fig = go.Figure()
126
- fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Closing Price',
127
- line=dict(color='lightcoral', width=2)))
128
-
129
- indicators = ['RSI_Signal', 'BB_Signal', 'Stochastic_Signal', 'CMF_Signal', 'CCI_Signal']
130
- for signal in indicators:
131
- buy = df[df[signal] == 1]
132
- sell = df[df[signal] == -1]
133
- fig.add_trace(go.Scatter(x=buy.index, y=buy['Close'], mode='markers',
134
- marker=dict(symbol='triangle-up', size=10, color='lightgreen'), name=f'{signal} Buy'))
135
- fig.add_trace(go.Scatter(x=sell.index, y=sell['Close'], mode='markers',
136
- marker=dict(symbol='triangle-down', size=10, color='lightsalmon'), name=f'{signal} Sell'))
137
-
138
- fig.update_layout(title=f'{ticker}: Individual Trading Signals',
139
- xaxis=dict(title='Date'), yaxis=dict(title='Price'),
140
- plot_bgcolor='black', paper_bgcolor='black', font=dict(color='white'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  return fig
142
 
143
- # Gradio Interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  def stock_analysis(ticker, start_date, end_date):
145
- """Main function to analyze stocks."""
146
- try:
147
- df = yf.download(ticker, start=start_date, end=end_date)
148
- df = generate_trading_signals(df)
149
- df_last_90 = df.tail(360)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
- combined_fig = plot_combined_signals(df_last_90, ticker)
152
- individual_fig = plot_individual_signals(df_last_90, ticker)
153
 
154
- return combined_fig, individual_fig
155
- except Exception as e:
156
- return f"Error: {str(e)}", None
157
 
158
- # Gradio UI
159
- with gr.Blocks() as app:
 
160
  gr.Markdown("## Stock Market Analysis App")
161
 
162
- ticker_input = gr.Textbox(label="Stock Ticker", value="AAPL")
163
  start_date_input = gr.Textbox(label="Start Date (YYYY-MM-DD)", value="2022-01-01")
164
  end_date_input = gr.Textbox(label="End Date (YYYY-MM-DD)", value="2026-01-01")
165
 
166
- analyze_button = gr.Button("Analyze Stock")
 
 
 
 
 
 
167
 
168
- combined_output = gr.Plot(label="Combined Signals")
169
- individual_output = gr.Plot(label="Individual Signals")
 
170
 
171
- analyze_button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input],
172
- outputs=[combined_output, individual_output])
173
 
174
- app.launch()
 
1
+ # %%
2
+ # %%
3
  import gradio as gr
4
  import pandas as pd
5
  import yfinance as yf
 
7
  import plotly.graph_objects as go
8
  import numpy as np
9
 
10
+ # Functions for calculating indicators (SMA, RSI, etc.) and generating trading signals
11
+
12
  def calculate_sma(df, window):
 
13
  return df['Close'].rolling(window=window).mean()
14
 
15
  def calculate_ema(df, window):
 
16
  return df['Close'].ewm(span=window, adjust=False).mean()
17
 
18
+
19
  def calculate_macd(df):
 
20
  short_ema = df['Close'].ewm(span=12, adjust=False).mean()
21
  long_ema = df['Close'].ewm(span=26, adjust=False).mean()
22
  macd = short_ema - long_ema
23
  signal = macd.ewm(span=9, adjust=False).mean()
24
  return macd, signal
25
 
26
+
27
+ def calculate_rsi(df):
28
  delta = df['Close'].diff()
29
+ gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
30
+ loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
31
  rs = gain / loss
32
  rsi = 100 - (100 / (1 + rs))
33
  return rsi
34
 
35
+ def calculate_bollinger_bands(df):
36
+ middle_bb = df['Close'].rolling(window=20).mean()
37
+ upper_bb = middle_bb + 2 * df['Close'].rolling(window=20).std()
38
+ lower_bb = middle_bb - 2 * df['Close'].rolling(window=20).std()
 
 
39
  return middle_bb, upper_bb, lower_bb
40
 
41
+ def calculate_stochastic_oscillator(df):
42
+ lowest_low = df['Low'].rolling(window=14).min()
43
+ highest_high = df['High'].rolling(window=14).max()
 
44
  slowk = ((df['Close'] - lowest_low) / (highest_high - lowest_low)) * 100
45
  slowd = slowk.rolling(window=3).mean()
46
  return slowk, slowd
47
 
48
+
49
+
50
  def calculate_cmf(df, window=20):
 
51
  mfv = ((df['Close'] - df['Low']) - (df['High'] - df['Close'])) / (df['High'] - df['Low']) * df['Volume']
52
  cmf = mfv.rolling(window=window).sum() / df['Volume'].rolling(window=window).sum()
53
  return cmf
 
60
  cci = (typical_price - sma) / (0.015 * mean_deviation)
61
  return cci
62
 
63
+
64
+
65
  def generate_trading_signals(df):
66
+ # Calculate various indicators
67
  df['SMA_30'] = calculate_sma(df, 30)
68
  df['SMA_100'] = calculate_sma(df, 100)
69
  df['EMA_12'] = calculate_ema(df, 12)
 
74
  df['CMF'] = calculate_cmf(df)
75
  df['CCI'] = calculate_cci(df)
76
 
77
+
78
+
79
+ # Generate trading signals
80
+ df['SMA_Signal'] = np.where(df['SMA_30'] > df['SMA_100'], 1, 0)
81
+
82
  macd, signal = calculate_macd(df)
83
  df['MACD_Signal'] = np.select([(macd > signal) & (macd.shift(1) <= signal.shift(1)),
84
+ (macd < signal) & (macd.shift(1) >= signal.shift(1))],[1, -1], default=0)
 
 
 
 
 
 
 
 
 
 
85
 
 
 
 
 
86
 
87
+
88
+ df['RSI_Signal'] = np.where(df['RSI'] < 20, 1, 0)
89
+ df['RSI_Signal'] = np.where(df['RSI'] > 90, -1, df['RSI_Signal'])
90
+
91
+ df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'], 0, 0)
92
+ df['BB_Signal'] = np.where(df['Close'] > df['UpperBB'], -1, df['BB_Signal'])
93
+
94
+ df['Stochastic_Signal'] = np.where((df['SlowK'] < 10) & (df['SlowD'] < 15), 1, 0)
95
+ df['Stochastic_Signal'] = np.where((df['SlowK'] > 90) & (df['SlowD'] > 85), -1, df['Stochastic_Signal'])
96
+
97
+
98
+ df['CMF_Signal'] = np.where(df['CMF'] > 0.3, -1, np.where(df['CMF'] < -0.3, 1, 0))
99
+
100
+
101
+ df['CCI_Signal'] = np.where(df['CCI'] < -180, 1, 0)
102
+ df['CCI_Signal'] = np.where(df['CCI'] > 150, -1, df['CCI_Signal'])
103
+
104
+
105
+
106
+ # Combined signal for stronger buy/sell points
107
+ df['Combined_Signal'] = df[['RSI_Signal', 'BB_Signal',
108
+ 'Stochastic_Signal', 'CMF_Signal',
109
+ 'CCI_Signal']].sum(axis=1)
110
 
111
  return df
112
 
113
 
114
+ # %%
115
  def plot_combined_signals(df, ticker):
116
+ # Create a figure
117
  fig = go.Figure()
 
 
118
 
119
+ # Add closing price trace
120
+ fig.add_trace(go.Scatter(
121
+ x=df.index, y=df['Close'],
122
+ mode='lines',
123
+ name='Closing Price',
124
+ line=dict(color='lightcoral', width=2)
125
+ ))
126
+
127
+ # Add buy signals
128
+ buy_signals = df[df['Combined_Signal'] >= 3]
129
+ fig.add_trace(go.Scatter(
130
+ x=buy_signals.index, y=buy_signals['Close'],
131
+ mode='markers',
132
+ marker=dict(symbol='triangle-up', size=10, color='lightgreen'),
133
+ name='Buy Signal'
134
+ ))
135
 
136
+ # Add sell signals
137
+ sell_signals = df[df['Combined_Signal'] <= -3]
138
+ fig.add_trace(go.Scatter(
139
+ x=sell_signals.index, y=sell_signals['Close'],
140
+ mode='markers',
141
+ marker=dict(symbol='triangle-down', size=10, color='lightsalmon'),
142
+ name='Sell Signal'
143
+ ))
144
+
145
+ # Combined signal trace
146
+ fig.add_trace(go.Scatter(
147
+ x=df.index, y=df['Combined_Signal'],
148
+ mode='lines',
149
+ name='Combined Signal',
150
+ line=dict(color='deepskyblue', width=2),
151
+ yaxis='y2'
152
+ ))
153
+
154
+ # Update layout
155
+ fig.update_layout(
156
+ title=f'{ticker}: 360 Stock Price and Combined Trading Signal',
157
+ xaxis=dict(title='Date'),
158
+ yaxis=dict(title='Price', side='left'),
159
+ yaxis2=dict(title='Combined Signal', overlaying='y', side='right', showgrid=False),
160
+ plot_bgcolor='black',
161
+ paper_bgcolor='black',
162
+ font=dict(color='white')
163
+ )
164
 
 
 
 
165
  return fig
166
 
167
+ # %%
168
+ def stock_analysis(ticker, start_date, end_date):
169
+ # Download stock data from Yahoo Finance
170
+ df = yf.download(ticker, start=start_date, end=end_date)
171
+
172
+ # Generate signals
173
+ generate_trading_signals(df)
174
+
175
+ # Last 60 days
176
+ df_last_60 = df.tail(120)
177
+
178
+ # Plot signals
179
+ fig_signals = plot_combined_signals(df_last_60, ticker)
180
+
181
+ return fig_signals
182
+
183
+
184
+
185
+
186
+ # %%
187
  def plot_individual_signals(df, ticker):
188
+ # Create a figure
189
  fig = go.Figure()
190
+ fig.add_trace(go.Scatter(
191
+ x=df.index, y=df['Close'],
192
+ mode='lines',
193
+ name='Closing Price',
194
+ line=dict(color='lightcoral', width=2)
195
+ ))
196
+
197
+ # Add buy/sell signals for each indicator
198
+ signal_names = ['RSI_Signal', 'BB_Signal',
199
+ 'Stochastic_Signal', 'CMF_Signal',
200
+ 'CCI_Signal']
201
+
202
+ for signal in signal_names:
203
+ buy_signals = df[df[signal] == 1]
204
+ sell_signals = df[df[signal] == -1]
205
+
206
+ fig.add_trace(go.Scatter(
207
+ x=buy_signals.index, y=buy_signals['Close'],
208
+ mode='markers',
209
+ marker=dict(symbol='triangle-up', size=10, color='lightgreen'),
210
+ name=f'{signal} Buy Signal'
211
+ ))
212
+
213
+ fig.add_trace(go.Scatter(
214
+ x=sell_signals.index, y=sell_signals['Close'],
215
+ mode='markers',
216
+ marker=dict(symbol='triangle-down', size=10, color='lightsalmon'),
217
+ name=f'{signal} Sell Signal'
218
+ ))
219
+
220
+ fig.update_layout(
221
+ title=f'{ticker}: Individual Trading Signals',
222
+ xaxis=dict(title='Date'),
223
+ yaxis=dict(title='Price', side='left'),
224
+ plot_bgcolor='black',
225
+ paper_bgcolor='black',
226
+ font=dict(color='white')
227
+ )
228
+
229
  return fig
230
 
231
+
232
+ def display_signals(df):
233
+ # Create a signals DataFrame
234
+ signals_df = df[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal',
235
+ 'BB_Signal', 'Stochastic_Signal',
236
+ 'CMF_Signal', 'CCI_Signal']].copy()
237
+
238
+ # The Date is the index, so we don't need to add it as a column
239
+ signals_df.index.name = 'Date' # Name the index for better readability
240
+
241
+ # Replace signal values with 'Buy', 'Sell', or 'Hold'
242
+ for column in signals_df.columns:
243
+ signals_df[column] = signals_df[column].replace(
244
+ {1: 'Buy', -1: 'Sell', 0: 'Hold'}
245
+ )
246
+
247
+ return signals_df
248
+
249
  def stock_analysis(ticker, start_date, end_date):
250
+ # Download stock data from Yahoo Finance
251
+ df = yf.download(ticker, start=start_date, end=end_date)
252
+
253
+ # Generate signals
254
+ df = generate_trading_signals(df)
255
+
256
+ # Last 60 days for plotting
257
+ df_last_60 = df.tail(360)
258
+
259
+ # Plot combined signals
260
+ fig_signals = plot_combined_signals(df_last_60, ticker)
261
+
262
+ # Plot individual signals
263
+ fig_individual_signals = plot_individual_signals(df_last_60, ticker)
264
+
265
+ # Display signals DataFrame
266
+ signals_df = df_last_60[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal',
267
+ 'Stochastic_Signal','CMF_Signal',
268
+ 'CCI_Signal']]
269
+
270
+ return fig_signals, fig_individual_signals
271
 
 
 
272
 
 
 
 
273
 
274
+ # %%
275
+ # Define Gradio interface
276
+ with gr.Blocks() as demo:
277
  gr.Markdown("## Stock Market Analysis App")
278
 
279
+ ticker_input = gr.Textbox(label="Enter Stock Ticker (e.g., AAPL, NVDA)", value="NVDA")
280
  start_date_input = gr.Textbox(label="Start Date (YYYY-MM-DD)", value="2022-01-01")
281
  end_date_input = gr.Textbox(label="End Date (YYYY-MM-DD)", value="2026-01-01")
282
 
283
+ # Create a submit button that runs the stock analysis function
284
+ button = gr.Button("Analyze Stock")
285
+
286
+ # Outputs: Display results, charts
287
+ combined_signals_output = gr.Plot(label="Combined Trading Signals")
288
+ individual_signals_output = gr.Plot(label="Individual Trading Signals")
289
+ #signals_df_output = gr.Dataframe(label="Buy/Sell Signals")
290
 
291
+ # Link button to function
292
+ button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input],
293
+ outputs=[combined_signals_output, individual_signals_output])
294
 
295
+ # Launch the interface
296
+ demo.launch()
297