Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -15,7 +15,6 @@ def calculate_sma(df, window):
|
|
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()
|
@@ -23,7 +22,6 @@ def calculate_macd(df):
|
|
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()
|
@@ -68,8 +66,6 @@ def calculate_cci(df, window=20):
|
|
68 |
|
69 |
|
70 |
|
71 |
-
|
72 |
-
|
73 |
def generate_trading_signals(df):
|
74 |
# Calculate various indicators
|
75 |
df['SMA_30'] = calculate_sma(df, 30)
|
@@ -85,35 +81,34 @@ def generate_trading_signals(df):
|
|
85 |
|
86 |
|
87 |
|
|
|
88 |
# Generate trading signals
|
89 |
-
df['SMA_Signal'] = np.where(df['SMA_30'] > df['SMA_100'], 1, 0)
|
90 |
|
91 |
macd, signal = calculate_macd(df)
|
92 |
-
df['MACD_Signal'] = np.
|
93 |
-
(macd < signal) & (macd.shift(1) >= signal.shift(1))],[1, -1], default=0)
|
94 |
-
|
95 |
-
|
96 |
|
97 |
-
df['RSI_Signal'] = np.where(df['RSI'] <
|
98 |
-
df['RSI_Signal'] = np.where(df['RSI'] >
|
99 |
|
100 |
-
df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'],
|
101 |
df['BB_Signal'] = np.where(df['Close'] > df['UpperBB'], -1, df['BB_Signal'])
|
102 |
|
103 |
-
df['Stochastic_Signal'] = np.where((df['SlowK'] <
|
104 |
-
df['Stochastic_Signal'] = np.where((df['SlowK'] >
|
105 |
|
106 |
-
df['
|
|
|
107 |
|
108 |
|
109 |
-
df['CCI_Signal'] = np.where(df['CCI'] < -
|
110 |
df['CCI_Signal'] = np.where(df['CCI'] > 150, -1, df['CCI_Signal'])
|
111 |
|
112 |
|
113 |
|
114 |
# Combined signal for stronger buy/sell points
|
115 |
-
df['Combined_Signal'] = df[['RSI_Signal', 'BB_Signal',
|
116 |
-
'Stochastic_Signal', 'CMF_Signal',
|
117 |
'CCI_Signal']].sum(axis=1)
|
118 |
|
119 |
return df
|
@@ -192,94 +187,7 @@ def stock_analysis(ticker, start_date, end_date):
|
|
192 |
|
193 |
|
194 |
# %%
|
195 |
-
def plot_individual_signals(df, ticker):
|
196 |
-
# Create a figure
|
197 |
-
fig = go.Figure()
|
198 |
-
fig.add_trace(go.Scatter(
|
199 |
-
x=df.index, y=df['Close'],
|
200 |
-
mode='lines',
|
201 |
-
name='Closing Price',
|
202 |
-
line=dict(color='lightcoral', width=2)
|
203 |
-
))
|
204 |
-
|
205 |
-
# Add buy/sell signals for each indicator
|
206 |
-
signal_names = ['RSI_Signal', 'BB_Signal',
|
207 |
-
'Stochastic_Signal', 'CMF_Signal',
|
208 |
-
'CCI_Signal']
|
209 |
-
|
210 |
-
for signal in signal_names:
|
211 |
-
buy_signals = df[df[signal] == 1]
|
212 |
-
sell_signals = df[df[signal] == -1]
|
213 |
-
|
214 |
-
fig.add_trace(go.Scatter(
|
215 |
-
x=buy_signals.index, y=buy_signals['Close'],
|
216 |
-
mode='markers',
|
217 |
-
marker=dict(symbol='triangle-up', size=10, color='lightgreen'),
|
218 |
-
name=f'{signal} Buy Signal'
|
219 |
-
))
|
220 |
-
|
221 |
-
fig.add_trace(go.Scatter(
|
222 |
-
x=sell_signals.index, y=sell_signals['Close'],
|
223 |
-
mode='markers',
|
224 |
-
marker=dict(symbol='triangle-down', size=10, color='lightsalmon'),
|
225 |
-
name=f'{signal} Sell Signal'
|
226 |
-
))
|
227 |
-
|
228 |
-
fig.update_layout(
|
229 |
-
title=f'{ticker}: Individual Trading Signals',
|
230 |
-
xaxis=dict(title='Date'),
|
231 |
-
yaxis=dict(title='Price', side='left'),
|
232 |
-
plot_bgcolor='black',
|
233 |
-
paper_bgcolor='black',
|
234 |
-
font=dict(color='white')
|
235 |
-
)
|
236 |
|
237 |
-
return fig
|
238 |
-
|
239 |
-
|
240 |
-
def display_signals(df):
|
241 |
-
# Create a signals DataFrame
|
242 |
-
signals_df = df[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal',
|
243 |
-
'BB_Signal', 'Stochastic_Signal', 'ATR_Signal',
|
244 |
-
'CMF_Signal', 'CCI_Signal']].copy()
|
245 |
-
|
246 |
-
# The Date is the index, so we don't need to add it as a column
|
247 |
-
signals_df.index.name = 'Date' # Name the index for better readability
|
248 |
-
|
249 |
-
# Replace signal values with 'Buy', 'Sell', or 'Hold'
|
250 |
-
for column in signals_df.columns:
|
251 |
-
signals_df[column] = signals_df[column].replace(
|
252 |
-
{1: 'Buy', -1: 'Sell', 0: 'Hold'}
|
253 |
-
)
|
254 |
-
|
255 |
-
return signals_df
|
256 |
-
|
257 |
-
def stock_analysis(ticker, start_date, end_date):
|
258 |
-
# Download stock data from Yahoo Finance
|
259 |
-
df = yf.download(ticker, start=start_date, end=end_date)
|
260 |
-
|
261 |
-
# Generate signals
|
262 |
-
df = generate_trading_signals(df)
|
263 |
-
|
264 |
-
# Last 60 days for plotting
|
265 |
-
df_last_60 = df.tail(60)
|
266 |
-
|
267 |
-
# Plot combined signals
|
268 |
-
fig_signals = plot_combined_signals(df_last_60, ticker)
|
269 |
-
|
270 |
-
# Plot individual signals
|
271 |
-
fig_individual_signals = plot_individual_signals(df_last_60, ticker)
|
272 |
-
|
273 |
-
# Display signals DataFrame
|
274 |
-
signals_df = df_last_60[['Close', 'SMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal',
|
275 |
-
'Stochastic_Signal', 'ATR_Signal', 'CMF_Signal',
|
276 |
-
'CCI_Signal']]
|
277 |
-
|
278 |
-
return fig_signals, fig_individual_signals
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
# %%
|
283 |
# Define Gradio interface
|
284 |
with gr.Blocks() as demo:
|
285 |
gr.Markdown("## Stock Market Analysis App")
|
@@ -292,16 +200,14 @@ with gr.Blocks() as demo:
|
|
292 |
button = gr.Button("Analyze Stock")
|
293 |
|
294 |
# Outputs: Display results, charts
|
295 |
-
|
296 |
-
individual_signals_output = gr.Plot(label="Individual Trading Signals")
|
297 |
-
#signals_df_output = gr.Dataframe(label="Buy/Sell Signals")
|
298 |
|
299 |
# Link button to function
|
300 |
-
button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input],
|
301 |
-
outputs=[combined_signals_output, individual_signals_output])
|
302 |
|
303 |
# Launch the interface
|
304 |
demo.launch()
|
305 |
|
306 |
|
307 |
|
|
|
|
15 |
def calculate_ema(df, window):
|
16 |
return df['Close'].ewm(span=window, adjust=False).mean()
|
17 |
|
|
|
18 |
def calculate_macd(df):
|
19 |
short_ema = df['Close'].ewm(span=12, adjust=False).mean()
|
20 |
long_ema = df['Close'].ewm(span=26, adjust=False).mean()
|
|
|
22 |
signal = macd.ewm(span=9, adjust=False).mean()
|
23 |
return macd, signal
|
24 |
|
|
|
25 |
def calculate_rsi(df):
|
26 |
delta = df['Close'].diff()
|
27 |
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
|
|
|
66 |
|
67 |
|
68 |
|
|
|
|
|
69 |
def generate_trading_signals(df):
|
70 |
# Calculate various indicators
|
71 |
df['SMA_30'] = calculate_sma(df, 30)
|
|
|
81 |
|
82 |
|
83 |
|
84 |
+
|
85 |
# Generate trading signals
|
86 |
+
df['SMA_Signal'] = np.where(df['SMA_30'] > df['SMA_100']+3, 1, 0)
|
87 |
|
88 |
macd, signal = calculate_macd(df)
|
89 |
+
df['MACD_Signal'] = np.where((macd > signal.shift(1)) & (macd.shift(1) < signal), 1, 0)
|
|
|
|
|
|
|
90 |
|
91 |
+
df['RSI_Signal'] = np.where(df['RSI'] < 30, 1, 0)
|
92 |
+
df['RSI_Signal'] = np.where(df['RSI'] > 70, -1, df['RSI_Signal'])
|
93 |
|
94 |
+
df['BB_Signal'] = np.where(df['Close'] < df['LowerBB'], 1, 0)
|
95 |
df['BB_Signal'] = np.where(df['Close'] > df['UpperBB'], -1, df['BB_Signal'])
|
96 |
|
97 |
+
df['Stochastic_Signal'] = np.where((df['SlowK'] < 15) & (df['SlowD'] < 20), 1, 0)
|
98 |
+
df['Stochastic_Signal'] = np.where((df['SlowK'] > 80) & (df['SlowD'] > 80), -1, df['Stochastic_Signal'])
|
99 |
|
100 |
+
df['ATR_Signal'] = np.where(df['ATR'] > df['ATR'].rolling(window=20).mean(), 1, 0)
|
101 |
+
df['CMF_Signal'] = np.where(df['CMF'] > 0.05, 1, np.where(df['CMF'] < -0.05, -1, 0))
|
102 |
|
103 |
|
104 |
+
df['CCI_Signal'] = np.where(df['CCI'] < -150, 1, 0)
|
105 |
df['CCI_Signal'] = np.where(df['CCI'] > 150, -1, df['CCI_Signal'])
|
106 |
|
107 |
|
108 |
|
109 |
# Combined signal for stronger buy/sell points
|
110 |
+
df['Combined_Signal'] = df[['SMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal',
|
111 |
+
'Stochastic_Signal', 'ATR_Signal', 'CMF_Signal',
|
112 |
'CCI_Signal']].sum(axis=1)
|
113 |
|
114 |
return df
|
|
|
187 |
|
188 |
|
189 |
# %%
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
# Define Gradio interface
|
192 |
with gr.Blocks() as demo:
|
193 |
gr.Markdown("## Stock Market Analysis App")
|
|
|
200 |
button = gr.Button("Analyze Stock")
|
201 |
|
202 |
# Outputs: Display results, charts
|
203 |
+
signals_output = gr.Plot(label="Trading Signals")
|
|
|
|
|
204 |
|
205 |
# Link button to function
|
206 |
+
button.click(stock_analysis, inputs=[ticker_input, start_date_input, end_date_input], outputs=[signals_output])
|
|
|
207 |
|
208 |
# Launch the interface
|
209 |
demo.launch()
|
210 |
|
211 |
|
212 |
|
213 |
+
|