Spaces:
Running
Running
Commit
·
2154d91
1
Parent(s):
0dbb99d
get_stock_prices
Browse files
app.py
CHANGED
@@ -83,10 +83,6 @@ def period_to_start_end(period_str: str):
|
|
83 |
|
84 |
# --- 取得股票價格與技術指標 ---
|
85 |
def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
|
86 |
-
"""
|
87 |
-
使用 start 與 end 取得歷史股價資料(避免連線到 fc.yahoo.com),
|
88 |
-
並計算 RSI、Stochastic、MACD 與 VWAP 指標。
|
89 |
-
"""
|
90 |
try:
|
91 |
start_date, end_date = period_to_start_end(period)
|
92 |
data = yf.download(
|
@@ -95,40 +91,59 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
|
|
95 |
end=end_date,
|
96 |
interval='1d'
|
97 |
)
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
102 |
data.reset_index(inplace=True)
|
103 |
-
data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
indicators = {}
|
106 |
|
107 |
-
|
108 |
-
rsi_series = RSIIndicator(df['Close'], window=14).rsi().iloc[-
|
109 |
-
indicators["RSI"] = {
|
|
|
|
|
110 |
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
114 |
|
115 |
-
# MACD 與訊號線
|
116 |
macd = MACD(df['Close'])
|
117 |
-
macd_series = macd.macd().iloc[-
|
118 |
-
indicators["MACD"] = {
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
121 |
|
122 |
-
# VWAP
|
123 |
vwap_series = volume_weighted_average_price(
|
124 |
high=df['High'],
|
125 |
low=df['Low'],
|
126 |
close=df['Close'],
|
127 |
volume=df['Volume']
|
128 |
-
).iloc[-
|
129 |
-
indicators["vwap"] = {
|
|
|
|
|
130 |
|
131 |
-
return {
|
|
|
|
|
|
|
132 |
except Exception as e:
|
133 |
return f"Error fetching price data: {str(e)}"
|
134 |
|
|
|
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(
|
|
|
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"] = {
|
126 |
+
str(date.date()): int(value) for date, value in macd_series.items()
|
127 |
+
}
|
128 |
+
macd_signal_series = macd.macd_signal().iloc[-n:]
|
129 |
+
indicators["MACD_Signal"] = {
|
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'],
|
136 |
close=df['Close'],
|
137 |
volume=df['Volume']
|
138 |
+
).iloc[-n:]
|
139 |
+
indicators["vwap"] = {
|
140 |
+
str(date.date()): int(value) for date, value in vwap_series.items()
|
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 |
|