arjunanand13 commited on
Commit
973f2b8
·
verified ·
1 Parent(s): fc09205

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -74
app.py CHANGED
@@ -8,6 +8,7 @@ from datetime import datetime, timedelta
8
  import warnings
9
  warnings.filterwarnings('ignore')
10
 
 
11
  COMPANIES = {
12
  'Apple (AAPL)': 'AAPL',
13
  'Microsoft (MSFT)': 'MSFT',
@@ -31,15 +32,16 @@ COMPANIES = {
31
  'Netflix (NFLX)': 'NFLX'
32
  }
33
 
34
- def calculate_metrics(df: pd.DataFrame) -> pd.DataFrame:
 
35
  data = df.copy()
36
 
37
- # Calculate basic metrics
38
  data['Returns'] = data['Close'].pct_change()
39
  data['SMA_20'] = data['Close'].rolling(window=20).mean()
40
  data['SMA_50'] = data['Close'].rolling(window=50).mean()
41
 
42
- # Calculate RSI
43
  delta = data['Close'].diff()
44
  gain = delta.clip(lower=0)
45
  loss = -delta.clip(upper=0)
@@ -48,23 +50,25 @@ def calculate_metrics(df: pd.DataFrame) -> pd.DataFrame:
48
  rs = avg_gain / avg_loss
49
  data['RSI'] = 100 - (100 / (1 + rs))
50
 
51
- # Calculate Bollinger Bands
52
- rolling_mean = data['Close'].rolling(window=20).mean()
53
- rolling_std = data['Close'].rolling(window=20).std()
54
- data['BB_middle'] = rolling_mean
55
- data['BB_upper'] = rolling_mean + (rolling_std * 2)
56
- data['BB_lower'] = rolling_mean - (rolling_std * 2)
57
 
58
  return data
59
 
60
- def create_analysis_plots(data: pd.DataFrame) -> list:
 
61
  # Price and Volume Plot
62
- fig1 = make_subplots(rows=2, cols=1, shared_xaxes=True,
63
- subplot_titles=('Price and Moving Averages', 'Volume'),
64
- row_heights=[0.7, 0.3],
65
- vertical_spacing=0.1)
66
-
67
- # Price and SMAs
 
 
68
  fig1.add_trace(
69
  go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
70
  row=1, col=1
@@ -78,20 +82,22 @@ def create_analysis_plots(data: pd.DataFrame) -> list:
78
  row=1, col=1
79
  )
80
 
81
- # Volume
82
  fig1.add_trace(
83
  go.Bar(x=data.index, y=data['Volume'], name='Volume', marker_color='lightblue'),
84
  row=2, col=1
85
  )
86
 
87
  fig1.update_layout(height=600, title_text="Price Analysis")
88
-
89
- # Technical Indicators Plot
90
- fig2 = make_subplots(rows=2, cols=1, shared_xaxes=True,
91
- subplot_titles=('RSI', 'Bollinger Bands'),
92
- row_heights=[0.5, 0.5],
93
- vertical_spacing=0.1)
94
-
 
 
 
95
  # RSI
96
  fig2.add_trace(
97
  go.Scatter(x=data.index, y=data['RSI'], name='RSI', line=dict(color='purple')),
@@ -105,53 +111,52 @@ def create_analysis_plots(data: pd.DataFrame) -> list:
105
  go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
106
  row=2, col=1
107
  )
108
- fig2.add_trace(
109
- go.Scatter(x=data.index, y=data['BB_upper'], name='Upper BB',
110
- line=dict(color='gray', dash='dash')),
111
- row=2, col=1
112
- )
113
- fig2.add_trace(
114
- go.Scatter(x=data.index, y=data['BB_middle'], name='Middle BB',
115
- line=dict(color='red', dash='dash')),
116
- row=2, col=1
117
- )
118
- fig2.add_trace(
119
- go.Scatter(x=data.index, y=data['BB_lower'], name='Lower BB',
120
- line=dict(color='gray', dash='dash')),
121
- row=2, col=1
122
- )
123
 
124
  fig2.update_layout(height=600, title_text="Technical Analysis")
125
 
126
  return [fig1, fig2]
127
 
128
- def generate_summary(data: pd.DataFrame, symbol: str) -> str:
129
- current_price = data['Close'].iloc[-1]
130
- prev_price = data['Close'].iloc[-2]
131
- daily_return = ((current_price - prev_price) / prev_price) * 100
132
-
133
- rsi = data['RSI'].iloc[-1]
134
- sma_20 = data['SMA_20'].iloc[-1]
135
- sma_50 = data['SMA_50'].iloc[-1]
136
-
137
- summary = f"""Analysis Summary for {symbol}:
138
-
 
 
 
 
 
 
 
 
 
139
  • Current Price: ${current_price:.2f}
140
  • Daily Change: {daily_return:+.2f}%
141
- • Trend: {'Bullish' if sma_20 > sma_50 else 'Bearish'} (20-day MA vs 50-day MA)
142
- • RSI: {rsi:.2f} ({'Overbought' if rsi > 70 else 'Oversold' if rsi < 30 else 'Neutral'})
143
- • Volume: {data['Volume'].iloc[-1]:,.0f}
144
 
145
  Technical Signals:
146
- • Moving Averages: Price is {'above' if current_price > sma_20 else 'below'} 20-day MA
147
- • Bollinger Bands: Price is {
148
- 'near upper band (potential resistance)' if current_price > data['BB_upper'].iloc[-1] * 0.95
149
- else 'near lower band (potential support)' if current_price < data['BB_lower'].iloc[-1] * 1.05
150
- else 'in middle range'}
151
  """
152
- return summary
 
 
153
 
154
- def analyze_stock(company: str, lookback_days: int = 180) -> tuple:
 
155
  try:
156
  symbol = COMPANIES[company]
157
  end_date = datetime.now()
@@ -159,26 +164,21 @@ def analyze_stock(company: str, lookback_days: int = 180) -> tuple:
159
 
160
  # Download data
161
  data = yf.download(symbol, start=start_date, end=end_date)
162
-
163
  if len(data) == 0:
164
  return "No data available for the selected period.", None, None
165
 
166
- # Calculate metrics
167
  data = calculate_metrics(data)
168
-
169
- # Generate analysis
170
  summary = generate_summary(data, symbol)
171
- plots = create_analysis_plots(data)
172
 
173
  return summary, plots[0], plots[1]
174
-
175
  except Exception as e:
176
  return f"Error analyzing stock: {str(e)}", None, None
177
 
178
- def refresh_analysis(company, lookback_days):
179
- return analyze_stock(company, lookback_days)
180
-
181
- def create_gradio_interface():
182
  with gr.Blocks() as interface:
183
  gr.Markdown("# Stock Market Analysis Dashboard")
184
 
@@ -199,23 +199,24 @@ def create_gradio_interface():
199
 
200
  with gr.Row():
201
  summary = gr.Textbox(label="Analysis Summary", lines=10)
202
-
203
  with gr.Row():
204
  plot1 = gr.Plot(label="Price Analysis")
205
  plot2 = gr.Plot(label="Technical Analysis")
206
 
 
207
  refresh_btn.click(
208
- fn=refresh_analysis,
209
  inputs=[company, lookback],
210
  outputs=[summary, plot1, plot2]
211
  )
212
 
213
- # Auto-update on selection changes
214
  company.change(
215
  fn=analyze_stock,
216
  inputs=[company, lookback],
217
  outputs=[summary, plot1, plot2]
218
  )
 
219
  lookback.release(
220
  fn=analyze_stock,
221
  inputs=[company, lookback],
@@ -225,5 +226,5 @@ def create_gradio_interface():
225
  return interface
226
 
227
  if __name__ == "__main__":
228
- interface = create_gradio_interface()
229
  interface.launch(share=True)
 
8
  import warnings
9
  warnings.filterwarnings('ignore')
10
 
11
+ # List of companies with their symbols
12
  COMPANIES = {
13
  'Apple (AAPL)': 'AAPL',
14
  'Microsoft (MSFT)': 'MSFT',
 
32
  'Netflix (NFLX)': 'NFLX'
33
  }
34
 
35
+ def calculate_metrics(df):
36
+ """Calculate technical indicators"""
37
  data = df.copy()
38
 
39
+ # Basic metrics
40
  data['Returns'] = data['Close'].pct_change()
41
  data['SMA_20'] = data['Close'].rolling(window=20).mean()
42
  data['SMA_50'] = data['Close'].rolling(window=50).mean()
43
 
44
+ # RSI
45
  delta = data['Close'].diff()
46
  gain = delta.clip(lower=0)
47
  loss = -delta.clip(upper=0)
 
50
  rs = avg_gain / avg_loss
51
  data['RSI'] = 100 - (100 / (1 + rs))
52
 
53
+ # Bollinger Bands
54
+ data['BB_middle'] = data['Close'].rolling(window=20).mean()
55
+ bb_std = data['Close'].rolling(window=20).std()
56
+ data['BB_upper'] = data['BB_middle'] + (2 * bb_std)
57
+ data['BB_lower'] = data['BB_middle'] - (2 * bb_std)
 
58
 
59
  return data
60
 
61
+ def create_plots(data):
62
+ """Create analysis plots"""
63
  # Price and Volume Plot
64
+ fig1 = make_subplots(
65
+ rows=2, cols=1,
66
+ shared_xaxes=True,
67
+ vertical_spacing=0.1,
68
+ subplot_titles=('Price and Moving Averages', 'Volume'),
69
+ row_heights=[0.7, 0.3]
70
+ )
71
+
72
  fig1.add_trace(
73
  go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
74
  row=1, col=1
 
82
  row=1, col=1
83
  )
84
 
 
85
  fig1.add_trace(
86
  go.Bar(x=data.index, y=data['Volume'], name='Volume', marker_color='lightblue'),
87
  row=2, col=1
88
  )
89
 
90
  fig1.update_layout(height=600, title_text="Price Analysis")
91
+
92
+ # Technical Analysis Plot
93
+ fig2 = make_subplots(
94
+ rows=2, cols=1,
95
+ shared_xaxes=True,
96
+ vertical_spacing=0.1,
97
+ subplot_titles=('RSI', 'Bollinger Bands'),
98
+ row_heights=[0.5, 0.5]
99
+ )
100
+
101
  # RSI
102
  fig2.add_trace(
103
  go.Scatter(x=data.index, y=data['RSI'], name='RSI', line=dict(color='purple')),
 
111
  go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
112
  row=2, col=1
113
  )
114
+ for band, color in [('BB_upper', 'gray'), ('BB_middle', 'red'), ('BB_lower', 'gray')]:
115
+ fig2.add_trace(
116
+ go.Scatter(x=data.index, y=data[band], name=band, line=dict(color=color, dash='dash')),
117
+ row=2, col=1
118
+ )
 
 
 
 
 
 
 
 
 
 
119
 
120
  fig2.update_layout(height=600, title_text="Technical Analysis")
121
 
122
  return [fig1, fig2]
123
 
124
+ def generate_summary(data, symbol):
125
+ """Generate analysis summary"""
126
+ try:
127
+ current_price = float(data['Close'].iloc[-1])
128
+ prev_price = float(data['Close'].iloc[-2])
129
+ daily_return = ((current_price - prev_price) / prev_price) * 100
130
+
131
+ rsi = float(data['RSI'].iloc[-1])
132
+ sma_20 = float(data['SMA_20'].iloc[-1])
133
+ sma_50 = float(data['SMA_50'].iloc[-1])
134
+ volume = float(data['Volume'].iloc[-1])
135
+
136
+ bb_position = "in middle range"
137
+ if current_price > float(data['BB_upper'].iloc[-1] * 0.95):
138
+ bb_position = "near upper band (potential resistance)"
139
+ elif current_price < float(data['BB_lower'].iloc[-1] * 1.05):
140
+ bb_position = "near lower band (potential support)"
141
+
142
+ summary = f"""Analysis Summary for {symbol}:
143
+
144
  • Current Price: ${current_price:.2f}
145
  • Daily Change: {daily_return:+.2f}%
146
+ • Trend: {"Bullish" if sma_20 > sma_50 else "Bearish"} (20-day MA vs 50-day MA)
147
+ • RSI: {rsi:.2f} ({"Overbought" if rsi > 70 else "Oversold" if rsi < 30 else "Neutral"})
148
+ • Volume: {volume:,.0f}
149
 
150
  Technical Signals:
151
+ • Moving Averages: Price is {"above" if current_price > sma_20 else "below"} 20-day MA
152
+ • Bollinger Bands: Price is {bb_position}
 
 
 
153
  """
154
+ return summary
155
+ except Exception as e:
156
+ return f"Error generating summary: {str(e)}"
157
 
158
+ def analyze_stock(company, lookback_days=180):
159
+ """Main analysis function"""
160
  try:
161
  symbol = COMPANIES[company]
162
  end_date = datetime.now()
 
164
 
165
  # Download data
166
  data = yf.download(symbol, start=start_date, end=end_date)
 
167
  if len(data) == 0:
168
  return "No data available for the selected period.", None, None
169
 
170
+ # Calculate metrics and create analysis
171
  data = calculate_metrics(data)
 
 
172
  summary = generate_summary(data, symbol)
173
+ plots = create_plots(data)
174
 
175
  return summary, plots[0], plots[1]
176
+
177
  except Exception as e:
178
  return f"Error analyzing stock: {str(e)}", None, None
179
 
180
+ def create_interface():
181
+ """Create Gradio interface"""
 
 
182
  with gr.Blocks() as interface:
183
  gr.Markdown("# Stock Market Analysis Dashboard")
184
 
 
199
 
200
  with gr.Row():
201
  summary = gr.Textbox(label="Analysis Summary", lines=10)
202
+
203
  with gr.Row():
204
  plot1 = gr.Plot(label="Price Analysis")
205
  plot2 = gr.Plot(label="Technical Analysis")
206
 
207
+ # Event handlers
208
  refresh_btn.click(
209
+ fn=analyze_stock,
210
  inputs=[company, lookback],
211
  outputs=[summary, plot1, plot2]
212
  )
213
 
 
214
  company.change(
215
  fn=analyze_stock,
216
  inputs=[company, lookback],
217
  outputs=[summary, plot1, plot2]
218
  )
219
+
220
  lookback.release(
221
  fn=analyze_stock,
222
  inputs=[company, lookback],
 
226
  return interface
227
 
228
  if __name__ == "__main__":
229
+ interface = create_interface()
230
  interface.launch(share=True)