Rooobert commited on
Commit
fdbabd0
1 Parent(s): a435715

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ import plotly.graph_objs as go
5
+ from plotly.subplots import make_subplots
6
+
7
+ def fetch_etf_data(ticker_codes):
8
+ """
9
+ 抓取台灣ETF歷史數據
10
+
11
+ 參數:
12
+ ticker_codes (str): ETF代碼,逗號分隔
13
+
14
+ 返回:
15
+ tuple: 數據框和圖表
16
+ """
17
+ # 拆分代碼
18
+ ticker_list = [code.strip() for code in ticker_codes.split(',')]
19
+
20
+ # 儲存所有ETF的數據
21
+ results = {}
22
+
23
+ # 創建子圖
24
+ fig = make_subplots(
25
+ rows=len(ticker_list),
26
+ cols=1,
27
+ shared_xaxes=True,
28
+ vertical_spacing=0.02,
29
+ subplot_titles=[f"{code}.TW" for code in ticker_list]
30
+ )
31
+
32
+ # 顏色列表
33
+ colors = ['blue', 'green', 'red', 'purple', 'orange']
34
+
35
+ # 遍歷每個ETF代碼
36
+ output_text = ""
37
+ for i, ticker_code in enumerate(ticker_list, 1):
38
+ try:
39
+ # 添加 ".TW" 後綴(台灣交易所)
40
+ full_ticker = f"{ticker_code}.TW"
41
+
42
+ # 獲取ETF數據
43
+ etf = yf.Ticker(full_ticker)
44
+
45
+ # 獲取1年歷史數據
46
+ df = etf.history(period="1y")
47
+
48
+ # 如果數據為空,跳過此ETF
49
+ if df.empty:
50
+ output_text += f"警告:未找到 {full_ticker} 的數據\n"
51
+ continue
52
+
53
+ # 儲存數據
54
+ results[ticker_code] = df
55
+
56
+ # 添加K線圖
57
+ fig.add_trace(
58
+ go.Candlestick(
59
+ x=df.index,
60
+ open=df['Open'],
61
+ high=df['High'],
62
+ low=df['Low'],
63
+ close=df['Close'],
64
+ name=full_ticker,
65
+ increasing_line_color=colors[i % len(colors)],
66
+ decreasing_line_color='gray'
67
+ ),
68
+ row=i, col=1
69
+ )
70
+
71
+ # 添加成交量柱狀圖
72
+ fig.add_trace(
73
+ go.Bar(
74
+ x=df.index,
75
+ y=df['Volume'],
76
+ name=f'{full_ticker} 成交量',
77
+ opacity=0.5
78
+ ),
79
+ row=i, col=1
80
+ )
81
+
82
+ # 生成文本輸出
83
+ output_text += f"\n{full_ticker} 最近數據:\n"
84
+ output_text += df.tail().to_string() + "\n"
85
+
86
+ except Exception as e:
87
+ output_text += f"{ticker_code} 發生錯誤: {e}\n"
88
+
89
+ # 更新佈局
90
+ fig.update_layout(
91
+ height=300 * len(ticker_list), # 根據ETF數量調整高度
92
+ title='台灣ETF走勢圖',
93
+ xaxis_rangeslider_visible=False # 關閉範圍滑塊
94
+ )
95
+
96
+ # 合併CSV
97
+ if results:
98
+ combined_df = pd.concat([df for df in results.values()], keys=results.keys(), names=['ETF', 'index'])
99
+ combined_df.to_csv("combined_etf_data.csv", encoding='utf-8-sig')
100
+ output_text += "\n所有ETF數據已合併保存到 combined_etf_data.csv"
101
+
102
+ return fig, output_text
103
+
104
+ def create_gradio_interface():
105
+ """
106
+ 創建Gradio界面
107
+ """
108
+ with gr.Blocks(title="台灣ETF數據分析") as demo:
109
+ gr.Markdown("## 台灣ETF數據抓取與分析")
110
+
111
+ with gr.Row():
112
+ with gr.Column():
113
+ # 輸入框
114
+ ticker_input = gr.Textbox(
115
+ label="輸入ETF代碼",
116
+ placeholder="例如:00878, 00940, 0050",
117
+ value="00878, 00940, 0050"
118
+ )
119
+
120
+ # 提交按鈕
121
+ submit_btn = gr.Button("分析ETF")
122
+
123
+ with gr.Column():
124
+ # 文本輸出
125
+ output_text = gr.Textbox(label="分析結果")
126
+
127
+ # 圖表輸出
128
+ output_plot = gr.Plot(label="ETF走勢圖")
129
+
130
+ # 提交事件
131
+ submit_btn.click(
132
+ fn=fetch_etf_data,
133
+ inputs=ticker_input,
134
+ outputs=[output_plot, output_text]
135
+ )
136
+
137
+ return demo
138
+
139
+ # 啟動Gradio應用
140
+ def main():
141
+ demo = create_gradio_interface()
142
+ demo.launch(
143
+ share=True, # 創建公開連結
144
+ server_name='0.0.0.0', # 允許外部訪問
145
+ server_port=7860 # 指定端口
146
+ )
147
+
148
+ # 運行主程序
149
+ if __name__ == "__main__":
150
+ main()