Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -131,42 +131,31 @@ def advanced_xgboost_predict(data, predict_days):
|
|
| 131 |
print("XGBoost 模型未載入或數據為空")
|
| 132 |
return None
|
| 133 |
|
| 134 |
-
#
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
print("歷史數據不足,無法使用 XGBoost 模型")
|
| 138 |
-
return None
|
| 139 |
-
|
| 140 |
-
# 使用最新的資料點來進行未來預測
|
| 141 |
-
input_df = data.tail(1).copy()
|
| 142 |
-
|
| 143 |
-
# 檢查必要欄位是否存在
|
| 144 |
-
required_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
|
| 145 |
-
missing_columns = [col for col in required_columns if col not in input_df.columns]
|
| 146 |
-
if missing_columns:
|
| 147 |
-
print(f"缺少必要欄位: {missing_columns}")
|
| 148 |
return None
|
| 149 |
|
| 150 |
try:
|
| 151 |
-
# 2. 呼叫模型預測
|
| 152 |
print(f"呼叫 XGBoost 模型進行 {predict_days} 天預測...")
|
| 153 |
-
predictions = xgb_model.predict('xgboost_model', input_df)
|
| 154 |
|
| 155 |
-
#
|
| 156 |
-
|
|
|
|
|
|
|
| 157 |
day_to_key_map = {
|
| 158 |
-
1: 'Close_t0_pred',
|
| 159 |
5: 'Close_t5_pred',
|
| 160 |
10: 'Close_t10_pred',
|
| 161 |
20: 'Close_t20_pred'
|
| 162 |
}
|
| 163 |
|
| 164 |
-
# 找到對應的預測鍵
|
| 165 |
prediction_key = day_to_key_map.get(predict_days)
|
| 166 |
|
| 167 |
if prediction_key is None or prediction_key not in predictions:
|
| 168 |
-
print(f"警告: XGBoost 模型沒有提供 {predict_days}
|
| 169 |
-
|
|
|
|
| 170 |
available_days = [1, 5, 10, 20]
|
| 171 |
closest_day = min(available_days, key=lambda x: abs(x - predict_days))
|
| 172 |
prediction_key = day_to_key_map[closest_day]
|
|
@@ -176,11 +165,10 @@ def advanced_xgboost_predict(data, predict_days):
|
|
| 176 |
current_price = data['Close'].iloc[-1]
|
| 177 |
change_pct = ((predicted_price - current_price) / current_price) * 100
|
| 178 |
|
| 179 |
-
# 4. 包裝成主程式所需的格式
|
| 180 |
result = {
|
| 181 |
'predicted_price': float(predicted_price),
|
| 182 |
'change_pct': float(change_pct),
|
| 183 |
-
'confidence': 0.85
|
| 184 |
}
|
| 185 |
|
| 186 |
print(f"XGBoost 預測成功: 當前價格={current_price:.2f}, 預測價格={predicted_price:.2f}, 變化={change_pct:.2f}%")
|
|
@@ -249,7 +237,6 @@ def calculate_technical_indicators(df):
|
|
| 249 |
df['ADX'] = df['DX'].ewm(com=13, adjust=False).mean()
|
| 250 |
return df
|
| 251 |
|
| 252 |
-
# 修正後的 calculate_volume_profile 函數
|
| 253 |
def calculate_volume_profile(df, num_bins=50):
|
| 254 |
if df.empty or 'High' not in df.columns or 'Low' not in df.columns or 'Volume' not in df.columns:
|
| 255 |
return None, None, None
|
|
@@ -262,23 +249,18 @@ def calculate_volume_profile(df, num_bins=50):
|
|
| 262 |
all_prices = np.concatenate([df_clean['High'].values, df_clean['Low'].values])
|
| 263 |
min_price, max_price = all_prices.min(), all_prices.max()
|
| 264 |
|
| 265 |
-
|
| 266 |
-
price_for_volume = (df_clean['High'] + df_clean['Low'] + df_clean['Close']) / 3
|
| 267 |
-
|
| 268 |
-
# 移除 NaN 值並確保對應的權重也被移除
|
| 269 |
-
price_indicator = price_for_volume.dropna()
|
| 270 |
-
corresponding_volume = df_clean['Volume'].loc[price_indicator.index]
|
| 271 |
-
|
| 272 |
-
# 再次檢查是否有空數據
|
| 273 |
-
if len(price_indicator) == 0 or len(corresponding_volume) == 0:
|
| 274 |
return None, None, None
|
| 275 |
|
|
|
|
|
|
|
|
|
|
| 276 |
try:
|
| 277 |
hist, bin_edges = np.histogram(
|
| 278 |
-
|
| 279 |
bins=num_bins,
|
| 280 |
range=(min_price, max_price),
|
| 281 |
-
weights=
|
| 282 |
)
|
| 283 |
price_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
|
| 284 |
return bin_edges, hist, price_centers
|
|
|
|
| 131 |
print("XGBoost 模型未載入或數據為空")
|
| 132 |
return None
|
| 133 |
|
| 134 |
+
# 確保數據有足夠的歷史記錄來計算技術指標
|
| 135 |
+
if len(data) < 30:
|
| 136 |
+
print("歷史數據不足,無法計算技術指標")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
return None
|
| 138 |
|
| 139 |
try:
|
|
|
|
| 140 |
print(f"呼叫 XGBoost 模型進行 {predict_days} 天預測...")
|
|
|
|
| 141 |
|
| 142 |
+
# 呼叫修正後的預測方法
|
| 143 |
+
predictions = xgb_model.predict('xgboost_model', data)
|
| 144 |
+
|
| 145 |
+
# 根據 predict_days 解析輸出
|
| 146 |
day_to_key_map = {
|
| 147 |
+
1: 'Close_t0_pred',
|
| 148 |
5: 'Close_t5_pred',
|
| 149 |
10: 'Close_t10_pred',
|
| 150 |
20: 'Close_t20_pred'
|
| 151 |
}
|
| 152 |
|
|
|
|
| 153 |
prediction_key = day_to_key_map.get(predict_days)
|
| 154 |
|
| 155 |
if prediction_key is None or prediction_key not in predictions:
|
| 156 |
+
print(f"警告: XGBoost 模型沒有提供 {predict_days} 天的預測結果。")
|
| 157 |
+
print(f"可用的預測鍵: {list(predictions.keys())}")
|
| 158 |
+
# 使用最接近的預測天期
|
| 159 |
available_days = [1, 5, 10, 20]
|
| 160 |
closest_day = min(available_days, key=lambda x: abs(x - predict_days))
|
| 161 |
prediction_key = day_to_key_map[closest_day]
|
|
|
|
| 165 |
current_price = data['Close'].iloc[-1]
|
| 166 |
change_pct = ((predicted_price - current_price) / current_price) * 100
|
| 167 |
|
|
|
|
| 168 |
result = {
|
| 169 |
'predicted_price': float(predicted_price),
|
| 170 |
'change_pct': float(change_pct),
|
| 171 |
+
'confidence': 0.85
|
| 172 |
}
|
| 173 |
|
| 174 |
print(f"XGBoost 預測成功: 當前價格={current_price:.2f}, 預測價格={predicted_price:.2f}, 變化={change_pct:.2f}%")
|
|
|
|
| 237 |
df['ADX'] = df['DX'].ewm(com=13, adjust=False).mean()
|
| 238 |
return df
|
| 239 |
|
|
|
|
| 240 |
def calculate_volume_profile(df, num_bins=50):
|
| 241 |
if df.empty or 'High' not in df.columns or 'Low' not in df.columns or 'Volume' not in df.columns:
|
| 242 |
return None, None, None
|
|
|
|
| 249 |
all_prices = np.concatenate([df_clean['High'].values, df_clean['Low'].values])
|
| 250 |
min_price, max_price = all_prices.min(), all_prices.max()
|
| 251 |
|
| 252 |
+
if min_price == max_price:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
return None, None, None
|
| 254 |
|
| 255 |
+
# 使用典型價格作為價格指標
|
| 256 |
+
price_for_volume = (df_clean['High'] + df_clean['Low'] + df_clean['Close']) / 3
|
| 257 |
+
|
| 258 |
try:
|
| 259 |
hist, bin_edges = np.histogram(
|
| 260 |
+
price_for_volume.values,
|
| 261 |
bins=num_bins,
|
| 262 |
range=(min_price, max_price),
|
| 263 |
+
weights=df_clean['Volume'].values
|
| 264 |
)
|
| 265 |
price_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
|
| 266 |
return bin_edges, hist, price_centers
|