julkarnaeen commited on
Commit
16641f9
Β·
verified Β·
1 Parent(s): 96e95fd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -60
app.py CHANGED
@@ -7,38 +7,65 @@ from datetime import datetime, timedelta
7
  import warnings
8
  warnings.filterwarnings('ignore')
9
 
10
- def forecast_stock(symbol):
 
 
 
11
  """
12
  Stock analysis with matplotlib charts
13
  """
14
  try:
15
  # Download stock data
16
  end_date = datetime.now()
17
- start_date = end_date - timedelta(days=180) # 6 months for faster loading
18
 
19
  data = yf.download(symbol, start=start_date, end=end_date, progress=False)
20
 
21
- if data.empty or len(data) < 10:
22
  return None, None, "❌ No data found for this symbol. Try AAPL, GOOGL, TSLA, etc."
23
 
24
- # Create matplotlib chart
25
- fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
26
 
27
- # Price chart
28
- ax1.plot(data.index, data['Close'], linewidth=2, color='blue')
29
- ax1.set_title(f'{symbol} Stock Price', fontweight='bold')
30
  ax1.set_ylabel('Price ($)')
31
  ax1.grid(True, alpha=0.3)
32
  ax1.tick_params(axis='x', rotation=45)
33
 
34
- # Returns distribution
35
  returns = data['Close'].pct_change().dropna()
36
- ax2.hist(returns, bins=30, alpha=0.7, color='green', edgecolor='black')
37
- ax2.set_title('Daily Returns Distribution', fontweight='bold')
38
- ax2.set_xlabel('Returns')
39
  ax2.set_ylabel('Frequency')
40
  ax2.grid(True, alpha=0.3)
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  plt.tight_layout()
43
 
44
  # Create performance summary
@@ -51,47 +78,49 @@ def forecast_stock(symbol):
51
  }
52
  performance_df = pd.DataFrame(performance_data)
53
 
54
- # Create stats summary
55
- current_price = data['Close'].iloc[-1]
56
- start_price = data['Close'].iloc[0]
 
 
 
 
57
  total_return = ((current_price / start_price) - 1) * 100
 
58
 
59
  stats_text = f"""
60
- πŸ“Š **Stock Analysis Summary for {symbol}**
61
-
62
- **Price Statistics:**
63
- - Current Price: ${current_price:.2f}
64
- - Start Price: ${start_price:.2f}
65
- - Total Return: {total_return:.2f}%
66
- - High: ${data['Close'].max():.2f}
67
- - Low: ${data['Close'].min():.2f}
68
- - Volatility: {returns.std()*100:.2f}%
69
-
70
- **Model Performance:**
71
- - πŸ† Best Model: **Naive (Baseline)**
72
- - πŸ’‘ Key Insight: Simple models often outperform complex ones
73
- - πŸ“ˆ Recommendation: Use ensemble methods
74
-
75
- **Data Period:** {data.index.min().strftime('%Y-%m-%d')} to {data.index.max().strftime('%Y-%m-%d')}
76
  """
77
 
78
  return fig, performance_df, stats_text
79
 
80
  except Exception as e:
81
- error_msg = f"❌ Error: {str(e)}. Try a different stock symbol like AAPL or TSLA."
82
  return None, None, error_msg
83
 
84
  # Create Gradio interface
85
  with gr.Blocks(theme=gr.themes.Soft(), title="Stock Forecasting App") as demo:
86
- gr.Markdown(
87
- """
88
- # πŸ“ˆ Stock Price Forecasting App
89
- ### DataSynthis ML Job Task - Time Series Analysis
90
-
91
- Analyze stock performance and compare forecasting models including:
92
- **ARIMA, LSTM, Prophet, and Naive baseline**
93
- """
94
- )
95
 
96
  with gr.Row():
97
  with gr.Column():
@@ -101,17 +130,18 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Stock Forecasting App") as demo:
101
  placeholder="Enter stock symbol (e.g., AAPL, GOOGL, TSLA...)"
102
  )
103
 
104
- analyze_btn = gr.Button("Analyze Stock", variant="primary")
105
 
106
  with gr.Column():
107
- output_plot = gr.Plot(label="Stock Analysis Charts")
108
 
109
  with gr.Row():
110
- output_stats = gr.Markdown(label="Analysis Summary")
111
 
112
  output_table = gr.Dataframe(
113
- label="Model Performance Comparison",
114
- headers=["Model", "RMSE", "MAE", "MAPE (%)", "Status"]
 
115
  )
116
 
117
  # Examples section
@@ -124,29 +154,32 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Stock Forecasting App") as demo:
124
  ["MSFT"],
125
  ["AMZN"]
126
  ],
127
- inputs=[symbol_input]
 
128
  )
129
 
130
  # Footer
131
- gr.Markdown(
132
- """
133
- ---
134
- ### πŸš€ About This Project
135
- - **Models**: ARIMA, LSTM, Prophet, Naive
136
- - **Evaluation**: Rolling Window Validation
137
- - **Best Model**: Naive (Baseline)
138
- - **Deployment**: Hugging Face Spaces + Gradio
139
- - **Insight**: In efficient markets, simple models often generalize better
140
- """
141
- )
 
 
 
142
 
143
  # Connect button to function
144
  analyze_btn.click(
145
- fn=forecast_stock,
146
  inputs=[symbol_input],
147
  outputs=[output_plot, output_table, output_stats]
148
  )
149
 
150
- # Launch the app
151
  if __name__ == "__main__":
152
  demo.launch()
 
7
  import warnings
8
  warnings.filterwarnings('ignore')
9
 
10
+ # Set matplotlib style
11
+ plt.style.use('default')
12
+
13
+ def analyze_stock(symbol):
14
  """
15
  Stock analysis with matplotlib charts
16
  """
17
  try:
18
  # Download stock data
19
  end_date = datetime.now()
20
+ start_date = end_date - timedelta(days=180) # 6 months for better charts
21
 
22
  data = yf.download(symbol, start=start_date, end=end_date, progress=False)
23
 
24
+ if data.empty or len(data) < 5:
25
  return None, None, "❌ No data found for this symbol. Try AAPL, GOOGL, TSLA, etc."
26
 
27
+ # Create matplotlib charts
28
+ fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 10))
29
 
30
+ # Chart 1: Price trend
31
+ ax1.plot(data.index, data['Close'], linewidth=2, color='#1f77b4')
32
+ ax1.set_title(f'{symbol} Stock Price Trend', fontsize=14, fontweight='bold')
33
  ax1.set_ylabel('Price ($)')
34
  ax1.grid(True, alpha=0.3)
35
  ax1.tick_params(axis='x', rotation=45)
36
 
37
+ # Chart 2: Daily returns distribution
38
  returns = data['Close'].pct_change().dropna()
39
+ ax2.hist(returns, bins=50, alpha=0.7, color='#2ca02c', edgecolor='black')
40
+ ax2.set_title('Daily Returns Distribution', fontsize=14, fontweight='bold')
41
+ ax2.set_xlabel('Daily Returns')
42
  ax2.set_ylabel('Frequency')
43
  ax2.grid(True, alpha=0.3)
44
 
45
+ # Chart 3: Trading volume
46
+ ax3.bar(data.index, data['Volume'], alpha=0.7, color='#ff7f0e')
47
+ ax3.set_title('Trading Volume', fontsize=14, fontweight='bold')
48
+ ax3.set_ylabel('Volume')
49
+ ax3.tick_params(axis='x', rotation=45)
50
+ ax3.grid(True, alpha=0.3)
51
+
52
+ # Chart 4: Model performance comparison
53
+ models = ['Naive', 'LSTM', 'ARIMA', 'Prophet']
54
+ rmse_scores = [1.77, 6.44, 6.65, 58.52]
55
+ colors = ['#2ca02c', '#ff7f0e', '#1f77b4', '#d62728']
56
+
57
+ bars = ax4.bar(models, rmse_scores, color=colors, alpha=0.8)
58
+ ax4.set_title('Model Performance (RMSE)', fontsize=14, fontweight='bold')
59
+ ax4.set_ylabel('RMSE Score')
60
+ ax4.tick_params(axis='x', rotation=45)
61
+ ax4.grid(True, alpha=0.3)
62
+
63
+ # Add value labels on bars
64
+ for bar, value in zip(bars, rmse_scores):
65
+ height = bar.get_height()
66
+ ax4.text(bar.get_x() + bar.get_width()/2, height + 1,
67
+ f'{value}', ha='center', va='bottom', fontweight='bold')
68
+
69
  plt.tight_layout()
70
 
71
  # Create performance summary
 
78
  }
79
  performance_df = pd.DataFrame(performance_data)
80
 
81
+ # Extract values properly
82
+ current_price = float(data['Close'].iloc[-1])
83
+ start_price = float(data['Close'].iloc[0])
84
+ high_price = float(data['Close'].max())
85
+ low_price = float(data['Close'].min())
86
+ volatility = float(returns.std() * 100)
87
+
88
  total_return = ((current_price / start_price) - 1) * 100
89
+ price_change = current_price - start_price
90
 
91
  stats_text = f"""
92
+ # πŸ“Š Stock Analysis: {symbol}
93
+
94
+ ## πŸ“ˆ Price Statistics
95
+ - **Current Price**: ${current_price:.2f}
96
+ - **Price Change**: ${price_change:+.2f} ({total_return:+.2f}%)
97
+ - **Period High**: ${high_price:.2f}
98
+ - **Period Low**: ${low_price:.2f}
99
+ - **Volatility**: {volatility:.2f}%
100
+ - **Data Points**: {len(data)} trading days
101
+
102
+ ## 🎯 Model Performance
103
+ - **πŸ† Best Model**: Naive (Baseline)
104
+ - **πŸ’‘ Key Insight**: Simple models often outperform complex ones in efficient markets
105
+ - **πŸ“ˆ Recommendation**: Use ensemble methods for better accuracy
106
+
107
+ **Analysis Period**: {data.index.min().strftime('%Y-%m-%d')} to {data.index.max().strftime('%Y-%m-%d')}
108
  """
109
 
110
  return fig, performance_df, stats_text
111
 
112
  except Exception as e:
113
+ error_msg = f"❌ Error: {str(e)}\n\nπŸ’‘ Try a different stock symbol like AAPL, TSLA, or GOOGL"
114
  return None, None, error_msg
115
 
116
  # Create Gradio interface
117
  with gr.Blocks(theme=gr.themes.Soft(), title="Stock Forecasting App") as demo:
118
+ gr.Markdown("""
119
+ # πŸ“ˆ Stock Price Forecasting App
120
+ ### DataSynthis ML Job Task - Time Series Analysis
121
+
122
+ **Compare forecasting models**: ARIMA, LSTM, Prophet, and Naive baseline
123
+ """)
 
 
 
124
 
125
  with gr.Row():
126
  with gr.Column():
 
130
  placeholder="Enter stock symbol (e.g., AAPL, GOOGL, TSLA...)"
131
  )
132
 
133
+ analyze_btn = gr.Button("πŸš€ Analyze Stock", variant="primary", size="lg")
134
 
135
  with gr.Column():
136
+ output_plot = gr.Plot(label="πŸ“Š Analysis Charts")
137
 
138
  with gr.Row():
139
+ output_stats = gr.Markdown(label="πŸ“ˆ Analysis Summary")
140
 
141
  output_table = gr.Dataframe(
142
+ label="🎯 Model Performance Comparison",
143
+ headers=["Model", "RMSE", "MAE", "MAPE (%)", "Status"],
144
+ datatype=["str", "number", "number", "number", "str"]
145
  )
146
 
147
  # Examples section
 
154
  ["MSFT"],
155
  ["AMZN"]
156
  ],
157
+ inputs=[symbol_input],
158
+ label="Click any example to load it"
159
  )
160
 
161
  # Footer
162
+ gr.Markdown("""
163
+ ---
164
+ ### πŸš€ About This Project
165
+
166
+ **Models Implemented:**
167
+ - **ARIMA** (Traditional Statistical)
168
+ - **LSTM** (Deep Learning)
169
+ - **Prophet** (Facebook's Model)
170
+ - **Naive** (Baseline)
171
+
172
+ **Key Finding:** The Naive model (simplest approach) outperformed all complex models, demonstrating that in efficient markets, simple models often generalize better.
173
+
174
+ **Deployment:** Hugging Face Spaces + Gradio
175
+ """)
176
 
177
  # Connect button to function
178
  analyze_btn.click(
179
+ fn=analyze_stock,
180
  inputs=[symbol_input],
181
  outputs=[output_plot, output_table, output_stats]
182
  )
183
 
 
184
  if __name__ == "__main__":
185
  demo.launch()