Rooobert commited on
Commit
10cd19c
·
verified ·
1 Parent(s): 5cf914a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -146
app.py CHANGED
@@ -1,108 +1,7 @@
1
  import streamlit as st
2
- import plotly.graph_objects as go
3
- from plotly.subplots import make_subplots
4
- import pandas as pd
5
  import twstock
6
- from datetime import datetime, timedelta
7
-
8
- def plot_stock_data(stock_symbols):
9
- """
10
- 繪製股票價格圖表
11
- :param stock_symbols: 股票代號列表
12
- :return: Plotly figure
13
- """
14
- # 創建子圖
15
- fig = make_subplots(
16
- rows=len(stock_symbols),
17
- cols=1,
18
- subplot_titles=[f"股價走勢: {symbol}" for symbol in stock_symbols],
19
- vertical_spacing=0.05,
20
- specs=[[{"secondary_y": True}] for _ in stock_symbols]
21
- )
22
-
23
- # 為每個股票繪製圖形
24
- for idx, symbol in enumerate(stock_symbols, 1):
25
- try:
26
- # 獲取股票數據
27
- stock = twstock.Stock(symbol)
28
- recent_data = stock.fetch_31() # 抓取最近 31 天的交易數據
29
-
30
- if not recent_data:
31
- st.warning(f"無法找到 {symbol} 的股票數據")
32
- continue
33
-
34
- # 準備繪圖數據
35
- df = pd.DataFrame([
36
- {
37
- "Date": data.date,
38
- "Open": data.open,
39
- "High": data.high,
40
- "Low": data.low,
41
- "Close": data.close,
42
- "Volume": data.transaction
43
- }
44
- for data in recent_data
45
- ])
46
- df['Date'] = pd.to_datetime(df['Date'])
47
- df.set_index('Date', inplace=True)
48
-
49
- # 添加蠟燭圖
50
- fig.add_trace(
51
- go.Candlestick(
52
- x=df.index,
53
- open=df['Open'],
54
- high=df['High'],
55
- low=df['Low'],
56
- close=df['Close'],
57
- name=f'{symbol} 價格'
58
- ),
59
- row=idx, col=1
60
- )
61
-
62
- # 添加成交量柱狀圖
63
- fig.add_trace(
64
- go.Bar(
65
- x=df.index,
66
- y=df['Volume'],
67
- name=f'{symbol} 成交量',
68
- opacity=0.3
69
- ),
70
- row=idx, col=1,
71
- secondary_y=True
72
- )
73
-
74
- # 添加移動平均線
75
- for ma_days in [5, 20]:
76
- ma = df['Close'].rolling(window=ma_days).mean()
77
- fig.add_trace(
78
- go.Scatter(
79
- x=df.index,
80
- y=ma,
81
- name=f'{symbol} MA{ma_days}',
82
- line=dict(width=1)
83
- ),
84
- row=idx, col=1
85
- )
86
-
87
- except Exception as e:
88
- st.error(f"處理 {symbol} 時發生錯誤: {str(e)}")
89
-
90
- # 更新布局
91
- fig.update_layout(
92
- height=400 * len(stock_symbols),
93
- title_text="台股分析圖",
94
- showlegend=True,
95
- xaxis_rangeslider_visible=False,
96
- template="plotly_white"
97
- )
98
-
99
- # 更新軸標籤
100
- for i in range(1, len(stock_symbols) + 1):
101
- fig.update_xaxes(title_text="日期", row=i, col=1)
102
- fig.update_yaxes(title_text="價格 (TWD)", row=i, col=1)
103
- fig.update_yaxes(title_text="成交量", row=i, col=1, secondary_y=True)
104
-
105
- return fig
106
 
107
  def fetch_recent_stock_data(stock_code):
108
  """
@@ -131,12 +30,28 @@ def fetch_recent_stock_data(stock_code):
131
  for data in recent_data
132
  ]
133
  df = pd.DataFrame(data_list)
 
134
  return df
135
 
136
  except Exception as e:
137
  st.error(f"發生錯誤: {e}")
138
  return None
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  def main():
141
  st.set_page_config(page_title="台股分析工具", page_icon=":chart_with_upwards_trend:", layout="wide")
142
 
@@ -144,13 +59,13 @@ def main():
144
 
145
  # 側邊欄設置
146
  with st.sidebar:
147
- st.header("股票分析設定")
148
 
149
  # 股票代碼輸入
150
- stock_input = st.text_input(
151
- "股票代號 (用逗號分隔)",
152
- value="2330,2454",
153
- placeholder="例如: 2330,2454"
154
  )
155
 
156
  # 股票分析頁籤
@@ -159,52 +74,47 @@ def main():
159
  with tab1:
160
  # 股價走勢圖
161
  if st.button("繪製股價走勢圖"):
162
- # 處理股票代號
163
- stocks = [s.strip() for s in stock_input.split(',')]
164
 
165
- # 創建圖表
166
- fig = plot_stock_data(stocks)
167
- st.plotly_chart(fig, use_container_width=True)
 
168
 
169
  with tab2:
170
  # 近期交易數據
171
  st.subheader("個股近期交易數據")
172
 
173
- single_stock_code = st.text_input(
174
- "請輸入股票代碼",
175
- placeholder="例如: 2330"
176
- )
177
-
178
  if st.button("查詢交易數據"):
179
- if single_stock_code:
180
- # 獲取近期股票數據
181
- df = fetch_recent_stock_data(single_stock_code)
 
 
 
 
 
 
 
 
 
 
182
 
183
- if df is not None:
184
- # 顯示數據
185
- st.dataframe(df)
186
-
187
- # 統計資訊
188
- st.subheader("基本統計")
189
- col1, col2, col3 = st.columns(3)
190
-
191
- with col1:
192
- st.metric("平均收盤價", f"{df['Close'].mean():.2f}")
193
-
194
- with col2:
195
- st.metric("最高價", f"{df['High'].max():.2f}")
196
-
197
- with col3:
198
- st.metric("最低價", f"{df['Low'].min():.2f}")
199
-
200
- # 匯出 CSV
201
- csv_data = df.to_csv(index=False).encode('utf-8-sig')
202
- st.download_button(
203
- label="下載CSV",
204
- data=csv_data,
205
- file_name=f"{single_stock_code}_recent_30days.csv",
206
- mime="text/csv"
207
- )
208
 
209
  if __name__ == "__main__":
210
  main()
 
1
  import streamlit as st
 
 
 
2
  import twstock
3
+ import pandas as pd
4
+ import matplotlib.pyplot as plt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  def fetch_recent_stock_data(stock_code):
7
  """
 
30
  for data in recent_data
31
  ]
32
  df = pd.DataFrame(data_list)
33
+ df['Date'] = pd.to_datetime(df['Date'])
34
  return df
35
 
36
  except Exception as e:
37
  st.error(f"發生錯誤: {e}")
38
  return None
39
 
40
+ def plot_stock_price(df):
41
+ """
42
+ 使用 matplotlib 繪製股價走勢
43
+ """
44
+ plt.figure(figsize=(12, 6))
45
+ plt.plot(df['Date'], df['Close'], label='收盤價')
46
+ plt.plot(df['Date'], df['Close'].rolling(window=5).mean(), label='5日移動平均', linestyle='--')
47
+ plt.title('股價走勢')
48
+ plt.xlabel('日期')
49
+ plt.ylabel('股價')
50
+ plt.legend()
51
+ plt.xticks(rotation=45)
52
+ plt.tight_layout()
53
+ return plt
54
+
55
  def main():
56
  st.set_page_config(page_title="台股分析工具", page_icon=":chart_with_upwards_trend:", layout="wide")
57
 
 
59
 
60
  # 側邊欄設置
61
  with st.sidebar:
62
+ st.header("股票分析")
63
 
64
  # 股票代碼輸入
65
+ stock_code = st.text_input(
66
+ "股票代號",
67
+ value="2330",
68
+ placeholder="例如: 2330"
69
  )
70
 
71
  # 股票分析頁籤
 
74
  with tab1:
75
  # 股價走勢圖
76
  if st.button("繪製股價走勢圖"):
77
+ # 獲取股票數據
78
+ df = fetch_recent_stock_data(stock_code)
79
 
80
+ if df is not None:
81
+ # 繪製股價圖
82
+ fig = plot_stock_price(df)
83
+ st.pyplot(fig)
84
 
85
  with tab2:
86
  # 近期交易數據
87
  st.subheader("個股近期交易數據")
88
 
 
 
 
 
 
89
  if st.button("查詢交易數據"):
90
+ # 獲取近期股票數據
91
+ df = fetch_recent_stock_data(stock_code)
92
+
93
+ if df is not None:
94
+ # 顯示數據
95
+ st.dataframe(df)
96
+
97
+ # 統計資訊
98
+ st.subheader("基本統計")
99
+ col1, col2, col3 = st.columns(3)
100
+
101
+ with col1:
102
+ st.metric("平均收盤價", f"{df['Close'].mean():.2f}")
103
 
104
+ with col2:
105
+ st.metric("最高價", f"{df['High'].max():.2f}")
106
+
107
+ with col3:
108
+ st.metric("最低價", f"{df['Low'].min():.2f}")
109
+
110
+ # 匯出 CSV
111
+ csv_data = df.to_csv(index=False).encode('utf-8-sig')
112
+ st.download_button(
113
+ label="下載CSV",
114
+ data=csv_data,
115
+ file_name=f"{stock_code}_recent_30days.csv",
116
+ mime="text/csv"
117
+ )
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  if __name__ == "__main__":
120
  main()