tbdavid2019 commited on
Commit
ee48331
·
1 Parent(s): 2154d91
Files changed (1) hide show
  1. app.py +29 -25
app.py CHANGED
@@ -81,45 +81,45 @@ def period_to_start_end(period_str: str):
81
  start = now - dt.timedelta(weeks=13)
82
  return start, now
83
 
84
- # --- 取得股票價格與技術指標 ---
85
- def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
 
86
  try:
87
- start_date, end_date = period_to_start_end(period)
88
  data = yf.download(
89
  ticker,
90
- start=start_date,
91
- end=end_date,
92
  interval='1d'
93
  )
94
 
95
  if data.empty:
96
- return f"無法取得 {ticker} 的歷史資料"
 
 
 
 
97
 
98
- # reset_index() 之後,立刻把欄位名稱都轉成字串
99
  data.reset_index(inplace=True)
100
- data.columns = [str(col) for col in data.columns]
101
 
102
- # 如果你另外有 df = data.copy() 想做技術指標,也要確保欄位一致
103
  df = data.copy()
104
 
105
- # 計算技術指標
106
- from ta.momentum import RSIIndicator, StochasticOscillator
107
- from ta.trend import MACD
108
- from ta.volume import volume_weighted_average_price
109
-
110
  indicators = {}
111
-
112
  n = min(12, len(df))
 
 
113
  rsi_series = RSIIndicator(df['Close'], window=14).rsi().iloc[-n:]
114
  indicators["RSI"] = {
115
  str(date.date()): int(value) for date, value in rsi_series.dropna().items()
116
  }
117
 
 
118
  sto_series = StochasticOscillator(df['High'], df['Low'], df['Close'], window=14).stoch().iloc[-n:]
119
  indicators["Stochastic_Oscillator"] = {
120
  str(date.date()): int(value) for date, value in sto_series.dropna().items()
121
  }
122
 
 
123
  macd = MACD(df['Close'])
124
  macd_series = macd.macd().iloc[-n:]
125
  indicators["MACD"] = {
@@ -130,6 +130,7 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
130
  str(date.date()): int(value) for date, value in macd_signal_series.items()
131
  }
132
 
 
133
  vwap_series = volume_weighted_average_price(
134
  high=df['High'],
135
  low=df['Low'],
@@ -141,34 +142,37 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
141
  }
142
 
143
  return {
144
- 'stock_price': data.to_dict(orient='records'),
145
- 'indicators': indicators
146
  }
147
  except Exception as e:
148
  return f"Error fetching price data: {str(e)}"
149
 
150
- # --- 取得財務新聞 ---
151
  def get_financial_news(ticker: str) -> Union[Dict, str]:
 
152
  try:
153
  stock = yf.Ticker(ticker)
154
- news = stock.news
155
  if not news:
156
  return {"news": "No recent news found."}
157
- latest_news = [
158
- {
 
 
 
159
  "title": item.get('title'),
160
  "publisher": item.get('publisher'),
161
  "link": item.get('link'),
162
  "published_date": item.get('providerPublishTime')
163
- }
164
- for item in news[:5]
165
- ]
166
  return {"news": latest_news}
167
  except Exception as e:
168
  return f"Error fetching news: {str(e)}"
169
 
170
- # --- 取得財務指標 ---
171
  def get_financial_metrics(ticker: str) -> Union[Dict, str]:
 
172
  try:
173
  stock = yf.Ticker(ticker)
174
  info = stock.info
 
81
  start = now - dt.timedelta(weeks=13)
82
  return start, now
83
 
84
+ @tool
85
+ def get_stock_prices(ticker: str) -> Union[Dict, str]:
86
+ """Fetches historical stock price data and technical indicator for a given ticker."""
87
  try:
 
88
  data = yf.download(
89
  ticker,
90
+ start=dt.datetime.now() - dt.timedelta(weeks=13),
91
+ end=dt.datetime.now(),
92
  interval='1d'
93
  )
94
 
95
  if data.empty:
96
+ return {"error": f"No stock data found for {ticker}"}
97
+
98
+ # 如果 columns 有多層,才做重命名
99
+ if data.columns.nlevels > 1:
100
+ data.columns = [col[0] for col in data.columns]
101
 
 
102
  data.reset_index(inplace=True)
103
+ data["Date"] = data["Date"].astype(str)
104
 
 
105
  df = data.copy()
106
 
 
 
 
 
 
107
  indicators = {}
 
108
  n = min(12, len(df))
109
+
110
+ # RSI
111
  rsi_series = RSIIndicator(df['Close'], window=14).rsi().iloc[-n:]
112
  indicators["RSI"] = {
113
  str(date.date()): int(value) for date, value in rsi_series.dropna().items()
114
  }
115
 
116
+ # Stochastic
117
  sto_series = StochasticOscillator(df['High'], df['Low'], df['Close'], window=14).stoch().iloc[-n:]
118
  indicators["Stochastic_Oscillator"] = {
119
  str(date.date()): int(value) for date, value in sto_series.dropna().items()
120
  }
121
 
122
+ # MACD
123
  macd = MACD(df['Close'])
124
  macd_series = macd.macd().iloc[-n:]
125
  indicators["MACD"] = {
 
130
  str(date.date()): int(value) for date, value in macd_signal_series.items()
131
  }
132
 
133
+ # VWAP
134
  vwap_series = volume_weighted_average_price(
135
  high=df['High'],
136
  low=df['Low'],
 
142
  }
143
 
144
  return {
145
+ "stock_price": data.to_dict(orient="records"),
146
+ "indicators": indicators
147
  }
148
  except Exception as e:
149
  return f"Error fetching price data: {str(e)}"
150
 
151
+ @tool
152
  def get_financial_news(ticker: str) -> Union[Dict, str]:
153
+ """Fetches the latest financial news related to a given ticker."""
154
  try:
155
  stock = yf.Ticker(ticker)
156
+ news = stock.news # 從 Yahoo Finance 獲取新聞
157
  if not news:
158
  return {"news": "No recent news found."}
159
+
160
+ # 只取最新5則新聞
161
+ latest_news = []
162
+ for item in news[:5]:
163
+ latest_news.append({
164
  "title": item.get('title'),
165
  "publisher": item.get('publisher'),
166
  "link": item.get('link'),
167
  "published_date": item.get('providerPublishTime')
168
+ })
 
 
169
  return {"news": latest_news}
170
  except Exception as e:
171
  return f"Error fetching news: {str(e)}"
172
 
173
+ @tool
174
  def get_financial_metrics(ticker: str) -> Union[Dict, str]:
175
+ """Fetches key financial ratios for a given ticker."""
176
  try:
177
  stock = yf.Ticker(ticker)
178
  info = stock.info