KYTHY commited on
Commit
221c693
·
verified ·
1 Parent(s): d66e5b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -26
app.py CHANGED
@@ -17,7 +17,7 @@ import yfinance as yf
17
  # CONFIG
18
  # --------------------------
19
  st.set_page_config(page_title="📰 SentimentSync NewsAI", layout="wide")
20
- API_KEY = "88bc396d4eab4be494a4b86ec842db47"
21
 
22
  # --------------------------
23
  # UTILITIES
@@ -118,27 +118,29 @@ def fetch_financial_news(keyword):
118
 
119
 
120
  # --------------------------
121
- # ดึงราคาหุ้ย้อนหลัง (แก้ไขให้ตรงกับช่วงข่าว)
 
122
  # --------------------------
123
  @st.cache_data(ttl=3600)
124
  def fetch_stock_price(symbol):
125
  try:
126
- # ดึงข้อมูลย้อนหลัง 8 ัน (เพื่อให้คลุมช่วงข่าว 7 วัน)
127
  end_date = datetime.now()
128
- start_date = end_date - timedelta(days=8)
129
 
130
  df = yf.download(symbol,
131
  start=start_date.strftime('%Y-%m-%d'),
132
  end=end_date.strftime('%Y-%m-%d'),
133
  interval="1d")
134
-
135
  if df.empty:
136
  st.warning("ไม่พบข้อมูลราคาหุ้นในช่วง 8 วันที่ผ่านมา")
137
  return pd.DataFrame()
138
 
139
  df = df.reset_index()[["Date", "Close"]]
140
  df.rename(columns={"Date": "date", "Close": "price"}, inplace=True)
141
- df["date"] = pd.to_datetime(df["date"])
 
142
  return df
143
  except Exception as e:
144
  st.warning(f"ไม่สามารถดึงราคาหุ้นได้: {e}")
@@ -146,7 +148,7 @@ def fetch_stock_price(symbol):
146
 
147
 
148
  # --------------------------
149
- # MAIN APP
150
  # --------------------------
151
  def main():
152
  st.title("📰 SentimentSync NewsAI")
@@ -170,11 +172,12 @@ def main():
170
  st.warning("ไม่พบบทความข่าวในช่วง 7 วันที่ผ่านมา")
171
  return
172
 
173
- # วิเคราะห์ sentiment
174
  st.info("กำลังวิเคราะห์อารมณ์ของข่าว...")
175
  news_df["sentiment"] = news_df["text"].apply(lambda x: analyze_text(x, vader))
176
  news_df["date"] = pd.to_datetime(news_df["date"])
177
 
 
178
  avg_sentiment = news_df["sentiment"].mean()
179
  pos_pct = (news_df["sentiment"] > 0.1).mean() * 100
180
  neg_pct = (news_df["sentiment"] < -0.1).mean() * 100
@@ -185,55 +188,67 @@ def main():
185
  col2.metric("ข่าวเชิงบวก", f"{pos_pct:.1f}%")
186
  col3.metric("ข่าวเชิงลบ", f"{neg_pct:.1f}%")
187
 
188
- # Wordcloud
189
  st.subheader("☁️ Word Cloud ของข่าว")
190
  all_text = " ".join(news_df["text"].tolist())
191
  img = generate_wordcloud(all_text)
192
  st.image(f"data:image/png;base64,{img}", use_column_width=True)
193
 
194
- # แนวโน้ม + พยากรณ์ + ราคาหุ้น
 
 
195
  st.subheader("📈 แนวโน้มอารมณ์ของข่าว & ราคาหุ้น")
196
- df_sorted = news_df.sort_values("date").copy()
197
- df_sorted["timestamp"] = (df_sorted["date"] - df_sorted["date"].min()).dt.days
 
 
 
 
 
 
 
 
 
 
198
 
199
  # Train sentiment model
200
  model = LinearRegression()
201
- model.fit(df_sorted[["timestamp"]], df_sorted["sentiment"])
202
 
203
  # Forecast next 7 days
204
  future_days = 7
205
  future_timestamps = np.arange(df_sorted["timestamp"].max() + 1, df_sorted["timestamp"].max() + future_days + 1)
206
- future_dates = [df_sorted["date"].max() + timedelta(days=i) for i in range(1, future_days + 1)]
207
  future_preds = model.predict(future_timestamps.reshape(-1, 1))
208
 
209
- # ดึงราคาหุ้น
210
  _, symbol = resolve_company_symbol(keyword)
211
- stock_df = fetch_stock_price(symbol)
212
 
213
- # Plot
214
  fig = go.Figure()
215
- # Actual sentiment
 
216
  fig.add_trace(go.Scatter(
217
- x=df_sorted["date"], y=df_sorted["sentiment"],
218
- mode="lines+markers", name="Actual Sentiment",
219
  line=dict(color="blue")
220
  ))
221
- # Predicted sentiment
 
222
  fig.add_trace(go.Scatter(
223
  x=future_dates, y=future_preds,
224
  mode="lines+markers", name="Predicted Sentiment (7-day Forecast)",
225
  line=dict(color="orange", dash="dash")
226
  ))
227
 
228
- # Stock price
229
  if not stock_df.empty:
230
- # ----- (นี่คือบรรทัดที่แก้ไข) -----
231
- fig.add_trace(go.Scatter(
232
  x=stock_df["date"], y=stock_df["price"],
233
  mode="lines+markers", name=f"{symbol} Stock Price",
234
  line=dict(color="green"), yaxis="y2"
235
  ))
236
- # --------------------------------
237
 
238
  fig.update_layout(
239
  title=f"แนวโน้มและพยากรณ์อารมณ์ข่าว & ราคาหุ้น '{keyword}'",
@@ -246,7 +261,7 @@ def main():
246
 
247
  st.plotly_chart(fig, use_container_width=True)
248
 
249
- # แสดงข่าว
250
  st.subheader("📰 รายการข่าว")
251
  st.dataframe(news_df[["date", "source", "text", "sentiment", "url"]], use_container_width=True)
252
 
 
17
  # CONFIG
18
  # --------------------------
19
  st.set_page_config(page_title="📰 SentimentSync NewsAI", layout="wide")
20
+ API_KEY = "88bc396d4eab4be494a4b86ec842db47" # (อย่าลืมเปลี่ยนคีย์ของคุณถ้าแชร์โค้ด)
21
 
22
  # --------------------------
23
  # UTILITIES
 
118
 
119
 
120
  # --------------------------
121
+ # (*** ส่วที่ 1: แก้ไข)
122
+ # ดึงราคาหุ้นย้อนหลัง 8 วัน
123
  # --------------------------
124
  @st.cache_data(ttl=3600)
125
  def fetch_stock_price(symbol):
126
  try:
127
+ # แก้ไ: ใชstart/end date ที่ชดเจน ให้งกับช่วงข่าว
128
  end_date = datetime.now()
129
+ start_date = end_date - timedelta(days=8) # ดึง 8 วัน เผื่อวันหยุด
130
 
131
  df = yf.download(symbol,
132
  start=start_date.strftime('%Y-%m-%d'),
133
  end=end_date.strftime('%Y-%m-%d'),
134
  interval="1d")
135
+
136
  if df.empty:
137
  st.warning("ไม่พบข้อมูลราคาหุ้นในช่วง 8 วันที่ผ่านมา")
138
  return pd.DataFrame()
139
 
140
  df = df.reset_index()[["Date", "Close"]]
141
  df.rename(columns={"Date": "date", "Close": "price"}, inplace=True)
142
+ # **สำคัญมาก** เราต้อง normalize date ให้เป็น date (00:00)
143
+ df["date"] = pd.to_datetime(df["date"].dt.date)
144
  return df
145
  except Exception as e:
146
  st.warning(f"ไม่สามารถดึงราคาหุ้นได้: {e}")
 
148
 
149
 
150
  # --------------------------
151
+ # MAIN APP (*** ส่วนที่ 2: แก้ไข)
152
  # --------------------------
153
  def main():
154
  st.title("📰 SentimentSync NewsAI")
 
172
  st.warning("ไม่พบบทความข่าวในช่วง 7 วันที่ผ่านมา")
173
  return
174
 
175
+ # วิเคราะห์ sentiment (รายบทความ)
176
  st.info("กำลังวิเคราะห์อารมณ์ของข่าว...")
177
  news_df["sentiment"] = news_df["text"].apply(lambda x: analyze_text(x, vader))
178
  news_df["date"] = pd.to_datetime(news_df["date"])
179
 
180
+ # แสดง Metric (ยังใช้ข้อมูลทั้งหมด)
181
  avg_sentiment = news_df["sentiment"].mean()
182
  pos_pct = (news_df["sentiment"] > 0.1).mean() * 100
183
  neg_pct = (news_df["sentiment"] < -0.1).mean() * 100
 
188
  col2.metric("ข่าวเชิงบวก", f"{pos_pct:.1f}%")
189
  col3.metric("ข่าวเชิงลบ", f"{neg_pct:.1f}%")
190
 
191
+ # Wordcloud (ยังใช้ข้อมูลทั้งหมด)
192
  st.subheader("☁️ Word Cloud ของข่าว")
193
  all_text = " ".join(news_df["text"].tolist())
194
  img = generate_wordcloud(all_text)
195
  st.image(f"data:image/png;base64,{img}", use_column_width=True)
196
 
197
+ # -----------------------------------------------------------------
198
+ # (ส่วนที่แก้ไข) แนวโน้ม + พยากรณ์ + ราคาหุ้น
199
+ # -----------------------------------------------------------------
200
  st.subheader("📈 แนวโน้มอารมณ์ของข่าว & ราคาหุ้น")
201
+
202
+ # 1. (ใหม่) รวบรวมข้อมูลข่าวเป็น "ค่าเฉลี่ยรายวัน"
203
+ # **สำคัญมาก** เราต้อง normalize date ให้เป็น date (00:00)
204
+ news_df["date_day"] = pd.to_datetime(news_df["date"].dt.date)
205
+
206
+ daily_sentiment_df = news_df.groupby("date_day").agg(
207
+ avg_sentiment=('sentiment', 'mean')
208
+ ).reset_index()
209
+
210
+ # 2. (ใหม่) ใช้ข้อมูล "รายวัน" นี้ในการเทรนโมเดล
211
+ df_sorted = daily_sentiment_df.sort_values("date_day").copy()
212
+ df_sorted["timestamp"] = (df_sorted["date_day"] - df_sorted["date_day"].min()).dt.days
213
 
214
  # Train sentiment model
215
  model = LinearRegression()
216
+ model.fit(df_sorted[["timestamp"]], df_sorted["avg_sentiment"])
217
 
218
  # Forecast next 7 days
219
  future_days = 7
220
  future_timestamps = np.arange(df_sorted["timestamp"].max() + 1, df_sorted["timestamp"].max() + future_days + 1)
221
+ future_dates = [df_sorted["date_day"].max() + timedelta(days=i) for i in range(1, future_days + 1)]
222
  future_preds = model.predict(future_timestamps.reshape(-1, 1))
223
 
224
+ # 3. ดึงราคาหุ้น (ซึ่งตอนนี้เราแก้ฟังก์ชัน `fetch_stock_price` แล้ว)
225
  _, symbol = resolve_company_symbol(keyword)
226
+ stock_df = fetch_stock_price(symbol)
227
 
228
+ # 4. Plot (ตอนนี้ X-axis ทั้ง 3 เส้นจะตรงกันแล้ว)
229
  fig = go.Figure()
230
+
231
+ # Actual sentiment (จากค่าเฉลี่ยรายวัน)
232
  fig.add_trace(go.Scatter(
233
+ x=df_sorted["date_day"], y=df_sorted["avg_sentiment"],
234
+ mode="lines+markers", name="Actual Sentiment (Daily Avg)",
235
  line=dict(color="blue")
236
  ))
237
+
238
+ # Predicted sentiment (จากโมเดลรายวัน)
239
  fig.add_trace(go.Scatter(
240
  x=future_dates, y=future_preds,
241
  mode="lines+markers", name="Predicted Sentiment (7-day Forecast)",
242
  line=dict(color="orange", dash="dash")
243
  ))
244
 
245
+ # Stock price (จาก yfinance ที่เป็นรายวัน)
246
  if not stock_df.empty:
247
+ fig.add_trace(go.Scatter(
 
248
  x=stock_df["date"], y=stock_df["price"],
249
  mode="lines+markers", name=f"{symbol} Stock Price",
250
  line=dict(color="green"), yaxis="y2"
251
  ))
 
252
 
253
  fig.update_layout(
254
  title=f"แนวโน้มและพยากรณ์อารมณ์ข่าว & ราคาหุ้น '{keyword}'",
 
261
 
262
  st.plotly_chart(fig, use_container_width=True)
263
 
264
+ # แสดงข่าว (ยังใช้ข้อมูลดิบรายบทความ)
265
  st.subheader("📰 รายการข่าว")
266
  st.dataframe(news_df[["date", "source", "text", "sentiment", "url"]], use_container_width=True)
267