KYTHY commited on
Commit
fb9ddf4
·
verified ·
1 Parent(s): 440f8bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -55
app.py CHANGED
@@ -55,9 +55,10 @@ def analyze_text(text):
55
  with torch.no_grad():
56
  outputs = model(**inputs)
57
  logits = outputs.logits
58
- probs = torch.softmax(logits, dim=1).numpy()[0] # FinBERT = [negative, neutral, positive]
 
59
  score = (-1 * probs[0]) + (0 * probs[1]) + (1 * probs[2])
60
- return float(score)
61
 
62
  def summarize_themes(news_texts):
63
  """สรุปธีมข่าวด้วย Zero-shot classification"""
@@ -166,8 +167,10 @@ def main():
166
  st.markdown("วิเคราะห์แนวโน้มอารมณ์ของข่าวย้อนหลัง 7 วัน พร้อมราคาหุ้น")
167
 
168
  # Sidebar
169
- keyword = st.text_input("ค้นหา Stock Symbol (เช่น AAPL, TSLA):", "")
170
- analyze_btn = st.button("วิเคราะห์เลย")
 
 
171
  if not analyze_btn:
172
  st.info("กรอกคำค้นแล้วกด 'วิเคราะห์เลย'")
173
  return
@@ -175,6 +178,7 @@ def main():
175
  # ดึงข่าว
176
  st.info(f"กำลังดึงข่าวย้อนหลัง 7 วันสำหรับ '{keyword}'...")
177
  news_df = fetch_financial_news(keyword)
 
178
  if news_df.empty:
179
  st.warning("ไม่พบบทความข่าว")
180
  return
@@ -188,18 +192,23 @@ def main():
188
  avg_sentiment = news_df["sentiment"].mean()
189
  pos_pct = (news_df["sentiment"] > 0.1).mean() * 100
190
  neg_pct = (news_df["sentiment"] < -0.1).mean() * 100
 
191
  col1, col2, col3 = st.columns(3)
192
  col1.metric("ค่าเฉลี่ยอารมณ์ข่าว", f"{avg_sentiment:.2f}")
193
  col2.metric("ข่าวเชิงบวก", f"{pos_pct:.1f}%")
194
  col3.metric("ข่าวเชิงลบ", f"{neg_pct:.1f}%")
195
 
 
196
  # ธีมข่าวแทน Word Cloud
 
197
  st.subheader("📰 ธีมข่าว (Top Theme per Article)")
198
  news_df["theme"] = summarize_themes(news_df["text"].tolist())
199
  theme_counts = news_df["theme"].value_counts()
200
  st.bar_chart(theme_counts)
201
 
202
- # ส่วนกราฟ Sentiment & Price
 
 
203
  st.subheader("📈 แนวโน้มอารมณ์ของข่าว & ราคาหุ้น")
204
  news_df["date_day"] = pd.to_datetime(news_df["date"].dt.date)
205
 
@@ -211,6 +220,7 @@ def main():
211
  return "neutral"
212
 
213
  news_df["sentiment_type"] = news_df["sentiment"].apply(sentiment_type)
 
214
  daily_avg = news_df.groupby("date_day")["sentiment"].mean().reset_index(name="avg_sentiment")
215
  daily_counts = news_df.groupby(["date_day", "sentiment_type"]).size().unstack(fill_value=0).reset_index()
216
  df_sorted = pd.merge(daily_avg, daily_counts, on="date_day").sort_values("date_day")
@@ -225,6 +235,7 @@ def main():
225
  min_date, max_date = df_sorted["date_day"].min(), df_sorted["date_day"].max()
226
  st.info(f"กำลังดึงราคาหุ้น {symbol} ...")
227
  stock_df = fetch_stock_price(symbol, min_date, max_date)
 
228
  plot_data = pd.merge(df_sorted, stock_df, left_on="date_day", right_on="date", how="left")
229
 
230
  # Correlation
@@ -239,9 +250,11 @@ def main():
239
  # Forecast Sentiment
240
  plot_data["timestamp"] = (plot_data["date_day"] - plot_data["date_day"].min()).dt.days
241
  train_data = plot_data.dropna(subset=['avg_sentiment'])
 
242
  if len(train_data) >= 2:
243
  model_lr = LinearRegression()
244
  model_lr.fit(train_data[["timestamp"]], train_data["avg_sentiment"])
 
245
  future_days = 7
246
  future_timestamps = np.arange(
247
  plot_data["timestamp"].max() + 1,
@@ -250,71 +263,44 @@ def main():
250
  future_dates = [plot_data["date_day"].max() + timedelta(days=i) for i in range(1, future_days + 1)]
251
  future_preds = model_lr.predict(future_timestamps.reshape(-1, 1))
252
 
253
- # Plot
254
- fig = make_subplots(
255
- rows=2, cols=1,
256
- specs=[[{"secondary_y": True}], [{}]],
257
- row_heights=[0.7, 0.3],
258
- vertical_spacing=0.1,
259
- shared_xaxes=True
260
- )
261
 
262
- # ราคาหุ้น
263
- fig.add_trace(
264
- go.Scatter(x=plot_data["date_day"], y=plot_data["price"], name=f"{symbol} Price",
265
- mode="lines+markers", line=dict(color="orange")),
266
- row=1, col=1, secondary_y=False
267
- )
268
 
269
- # Sentiment จริง
270
- fig.add_trace(
271
- go.Scatter(x=plot_data["date_day"], y=plot_data["avg_sentiment"], name="Actual Sentiment",
272
- mode="lines+markers", line=dict(color="blue")),
273
- row=1, col=1, secondary_y=True
274
- )
275
 
276
- # Sentiment พยากรณ์
277
- if "future_preds" in locals():
278
- fig.add_trace(
279
- go.Scatter(x=future_dates, y=future_preds, name="Predicted Sentiment",
280
- mode="lines+markers", line=dict(color="#05a0fa", dash="dash")),
281
- row=1, col=1, secondary_y=True
282
- )
283
 
284
  # เส้นเชื่อม Actual -> Predicted
285
  last_actual_date = plot_data["date_day"].max()
286
  last_actual_value = plot_data["avg_sentiment"].iloc[-1]
287
  first_pred_date = future_dates[0]
288
  first_pred_value = future_preds[0]
289
- fig.add_trace(
290
- go.Scatter(x=[last_actual_date, first_pred_date], y=[last_actual_value, first_pred_value],
291
- mode="lines", line=dict(color="#05a0fa", dash="dot"),
292
- name="Connector Actual→Predicted"),
293
- row=1, col=1, secondary_y=True
294
- )
295
 
296
- # จำนวนข่าว
297
- for col in ["neutral", "negative", "positive"]:
298
- if col not in plot_data.columns:
299
- plot_data[col] = 0
300
- fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["neutral"], name="Neutral",
301
- marker_color='rgba(128, 128, 128, 0.7)'), row=2, col=1)
302
- fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["negative"], name="Negative",
303
- marker_color='rgba(255, 0, 0, 0.7)'), row=2, col=1)
304
- fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["positive"], name="Positive",
305
- marker_color='rgba(0, 128, 0, 0.7)'), row=2, col=1)
306
-
307
- fig.update_layout(title=f"แนวโน้มอารมณ์ของข่าว + ราคาหุ้น ({symbol})",
308
- barmode="stack", height=650, hovermode="x unified", template="plotly_white")
309
- st.plotly_chart(fig, use_container_width=True)
310
 
311
  # แสดงรายการข่าว
312
  st.subheader("📰 รายการข่าวทั้งหมด")
313
  st.dataframe(news_df[["date", "source", "text", "sentiment", "theme", "url"]], use_container_width=True)
314
 
315
- # --------------------------
316
  # RUN APP
317
- # --------------------------
318
  if __name__ == "__main__":
319
  nltk.download("stopwords", quiet=True)
320
- main()
 
55
  with torch.no_grad():
56
  outputs = model(**inputs)
57
  logits = outputs.logits
58
+ probs = torch.softmax(logits, dim=1).numpy()[0]
59
+ # FinBERT = [negative, neutral, positive]
60
  score = (-1 * probs[0]) + (0 * probs[1]) + (1 * probs[2])
61
+ return float(score)
62
 
63
  def summarize_themes(news_texts):
64
  """สรุปธีมข่าวด้วย Zero-shot classification"""
 
167
  st.markdown("วิเคราะห์แนวโน้มอารมณ์ของข่าวย้อนหลัง 7 วัน พร้อมราคาหุ้น")
168
 
169
  # Sidebar
170
+ with st.sidebar:
171
+ keyword = st.text_input("ค้นหา Stock Symbol (เช่น AAPL, TSLA):", "")
172
+ analyze_btn = st.button("วิเคราะห์เลย")
173
+
174
  if not analyze_btn:
175
  st.info("กรอกคำค้นแล้วกด 'วิเคราะห์เลย'")
176
  return
 
178
  # ดึงข่าว
179
  st.info(f"กำลังดึงข่าวย้อนหลัง 7 วันสำหรับ '{keyword}'...")
180
  news_df = fetch_financial_news(keyword)
181
+
182
  if news_df.empty:
183
  st.warning("ไม่พบบทความข่าว")
184
  return
 
192
  avg_sentiment = news_df["sentiment"].mean()
193
  pos_pct = (news_df["sentiment"] > 0.1).mean() * 100
194
  neg_pct = (news_df["sentiment"] < -0.1).mean() * 100
195
+
196
  col1, col2, col3 = st.columns(3)
197
  col1.metric("ค่าเฉลี่ยอารมณ์ข่าว", f"{avg_sentiment:.2f}")
198
  col2.metric("ข่าวเชิงบวก", f"{pos_pct:.1f}%")
199
  col3.metric("ข่าวเชิงลบ", f"{neg_pct:.1f}%")
200
 
201
+ # ---------------------------------------------------------
202
  # ธีมข่าวแทน Word Cloud
203
+ # ---------------------------------------------------------
204
  st.subheader("📰 ธีมข่าว (Top Theme per Article)")
205
  news_df["theme"] = summarize_themes(news_df["text"].tolist())
206
  theme_counts = news_df["theme"].value_counts()
207
  st.bar_chart(theme_counts)
208
 
209
+ # ---------------------------------------------------------
210
+ # ส่วนกราฟ Sentiment & Price (เหมือนเดิม)
211
+ # ---------------------------------------------------------
212
  st.subheader("📈 แนวโน้มอารมณ์ของข่าว & ราคาหุ้น")
213
  news_df["date_day"] = pd.to_datetime(news_df["date"].dt.date)
214
 
 
220
  return "neutral"
221
 
222
  news_df["sentiment_type"] = news_df["sentiment"].apply(sentiment_type)
223
+
224
  daily_avg = news_df.groupby("date_day")["sentiment"].mean().reset_index(name="avg_sentiment")
225
  daily_counts = news_df.groupby(["date_day", "sentiment_type"]).size().unstack(fill_value=0).reset_index()
226
  df_sorted = pd.merge(daily_avg, daily_counts, on="date_day").sort_values("date_day")
 
235
  min_date, max_date = df_sorted["date_day"].min(), df_sorted["date_day"].max()
236
  st.info(f"กำลังดึงราคาหุ้น {symbol} ...")
237
  stock_df = fetch_stock_price(symbol, min_date, max_date)
238
+
239
  plot_data = pd.merge(df_sorted, stock_df, left_on="date_day", right_on="date", how="left")
240
 
241
  # Correlation
 
250
  # Forecast Sentiment
251
  plot_data["timestamp"] = (plot_data["date_day"] - plot_data["date_day"].min()).dt.days
252
  train_data = plot_data.dropna(subset=['avg_sentiment'])
253
+
254
  if len(train_data) >= 2:
255
  model_lr = LinearRegression()
256
  model_lr.fit(train_data[["timestamp"]], train_data["avg_sentiment"])
257
+
258
  future_days = 7
259
  future_timestamps = np.arange(
260
  plot_data["timestamp"].max() + 1,
 
263
  future_dates = [plot_data["date_day"].max() + timedelta(days=i) for i in range(1, future_days + 1)]
264
  future_preds = model_lr.predict(future_timestamps.reshape(-1, 1))
265
 
266
+ # Plot
267
+ fig = make_subplots(rows=2, cols=1, specs=[[{"secondary_y": True}], [{}]], row_heights=[0.7, 0.3], vertical_spacing=0.1, shared_xaxes=True)
 
 
 
 
 
 
268
 
269
+ # ราคาหุ้น
270
+ fig.add_trace(go.Scatter(x=plot_data["date_day"], y=plot_data["price"], name=f"{symbol} Price", mode="lines+markers", line=dict(color="orange")), row=1, col=1, secondary_y=False)
 
 
 
 
271
 
272
+ # Sentiment จริง
273
+ fig.add_trace(go.Scatter(x=plot_data["date_day"], y=plot_data["avg_sentiment"], name="Actual Sentiment", mode="lines+markers", line=dict(color="blue")), row=1, col=1, secondary_y=True)
 
 
 
 
274
 
275
+ # Sentiment พยากรณ์
276
+ if "future_preds" in locals():
277
+ fig.add_trace(go.Scatter(x=future_dates, y=future_preds, name="Predicted Sentiment", mode="lines+markers", line=dict(color="#05a0fa", dash="dash")), row=1, col=1, secondary_y=True)
 
 
 
 
278
 
279
  # เส้นเชื่อม Actual -> Predicted
280
  last_actual_date = plot_data["date_day"].max()
281
  last_actual_value = plot_data["avg_sentiment"].iloc[-1]
282
  first_pred_date = future_dates[0]
283
  first_pred_value = future_preds[0]
284
+ fig.add_trace(go.Scatter(x=[last_actual_date, first_pred_date], y=[last_actual_value, first_pred_value], mode="lines", line=dict(color="#05a0fa", dash="dot"), name="Connector Actual→Predicted"), row=1, col=1, secondary_y=True)
 
 
 
 
 
285
 
286
+ # จำนวนข่าว
287
+ for col in ["neutral", "negative", "positive"]:
288
+ if col not in plot_data.columns:
289
+ plot_data[col] = 0
290
+ fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["neutral"], name="Neutral", marker_color='rgba(128, 128, 128, 0.7)'), row=2, col=1)
291
+ fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["negative"], name="Negative", marker_color='rgba(255, 0, 0, 0.7)'), row=2, col=1)
292
+ fig.add_trace(go.Bar(x=plot_data["date_day"], y=plot_data["positive"], name="Positive", marker_color='rgba(0, 128, 0, 0.7)'), row=2, col=1)
293
+
294
+ fig.update_layout(title=f"แนวโน้มอารมณ์ของข่าว + ราคาหุ้น ({symbol})", barmode="stack", height=650, hovermode="x unified", template="plotly_white")
295
+ st.plotly_chart(fig, use_container_width=True)
 
 
 
 
296
 
297
  # แสดงรายการข่าว
298
  st.subheader("📰 รายการข่าวทั้งหมด")
299
  st.dataframe(news_df[["date", "source", "text", "sentiment", "theme", "url"]], use_container_width=True)
300
 
301
+ # ---------------------------------------------------------
302
  # RUN APP
303
+ # ---------------------------------------------------------
304
  if __name__ == "__main__":
305
  nltk.download("stopwords", quiet=True)
306
+ main()