File size: 4,156 Bytes
a79dcc6 f101777 a79dcc6 f101777 a79dcc6 f101777 a79dcc6 f101777 a79dcc6 f101777 a79dcc6 f101777 a79dcc6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import gradio as gr
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.font_manager as fm
import tempfile
import requests
from prophet import Prophet
from datetime import datetime, timedelta
import logging
# 設置日誌
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# 字體設置
def setup_font():
try:
url_font = "https://drive.google.com/uc?id=1eGAsTN1HBpJAkeVM57_C7ccp7hbgSz3_"
response_font = requests.get(url_font)
with tempfile.NamedTemporaryFile(delete=False, suffix='.ttf') as tmp_file:
tmp_file.write(response_font.content)
tmp_file_path = tmp_file.name
fm.fontManager.addfont(tmp_file_path)
mpl.rc('font', family='Taipei Sans TC Beta')
except Exception as e:
logging.error(f"字體設置失敗: {str(e)}")
# 使用備用字體
mpl.rc('font', family='SimHei')
def predict_stock_price(stock_code, period, prediction_days):
try:
# 下載股票數據
df = yf.download(stock_code, period=period)
if df.empty:
return "無法獲取股票數據", None
# 準備數據
data = df.reset_index()
data = data[['Date', 'Close']]
data.columns = ['ds', 'y']
# 訓練 Prophet 模型
model = Prophet(daily_seasonality=True)
model.fit(data)
# 創建未來日期
future = model.make_future_dataframe(periods=prediction_days)
forecast = model.predict(future)
# 繪製圖表
plt.figure(figsize=(12, 6))
# 繪製實際數據
plt.plot(data['ds'], data['y'],
label='實際收盤價',
color='blue')
# 繪製預測數據
plt.plot(forecast['ds'], forecast['yhat'],
label='預測收盤價',
color='orange',
linestyle='--')
# 添加預測區間
plt.fill_between(forecast['ds'],
forecast['yhat_lower'],
forecast['yhat_upper'],
color='orange',
alpha=0.2)
# 設置圖表格式
plt.title(f'{stock_code} 股價預測', pad=20)
plt.xlabel('日期')
plt.ylabel('股價')
plt.xticks(rotation=45)
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
# 返回預測結果和圖表
return forecast.tail(prediction_days).to_string(), plt.gcf()
except Exception as e:
logging.error(f"預測過程發生錯誤: {str(e)}")
return f"預測過程發生錯誤: {str(e)}", None
# 初始化字體
setup_font()
# Gradio 介面
with gr.Blocks() as demo:
gr.Markdown("# 股票價格 Stock Price 預測系統 Prophet")
with gr.Column():
# 輸入區域
with gr.Row():
stock_input = gr.Textbox(
label="股票代碼",
placeholder="例如: 2330.TW",
value="2330.TW"
)
period_dropdown = gr.Dropdown(
choices=["1mo", "3mo", "6mo", "1y", "2y", "5y", "10y", "max"],
label="歷史數據期間",
value="1y"
)
prediction_days = gr.Slider(
minimum=5,
maximum=30,
value=5,
step=1,
label="預測天數"
)
predict_button = gr.Button("開始預測", variant="primary")
# 輸出區域(垂直排列)
output_plot = gr.Plot(label="股價預測圖")
output_text = gr.Textbox(label="預測結果", lines=10)
predict_button.click(
predict_stock_price,
inputs=[stock_input, period_dropdown, prediction_days],
outputs=[output_text, output_plot]
)
# 啟動應用
if __name__ == "__main__":
demo.launch() |