AlanRex commited on
Commit
d6d5c2d
·
verified ·
1 Parent(s): 7e525e0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -113
app.py CHANGED
@@ -14,14 +14,8 @@ import plotly.express as px
14
  import plotly.graph_objects as go
15
  from plotly.subplots import make_subplots
16
 
17
-
18
-
19
- app = dash.Dash(__name__, suppress_callback_exceptions=True)
20
-
21
-
22
- # 台股代號對應表
23
  TAIWAN_STOCKS = {
24
- '台指期': 'TXF=F', # 台指期貨
25
  '台積電': '2330.TW',
26
  '聯發科': '2454.TW',
27
  '鴻海': '2317.TW',
@@ -34,10 +28,10 @@ TAIWAN_STOCKS = {
34
  '日月光': '2311.TW',
35
  '長榮': '2306.TW',
36
  '慧洋-KY': '2637.TW',
37
- '上銀' : '2049.TW',
38
- '台泥' : '1101.TW',
39
- '譜瑞-KY' :'4966.TW',
40
- '貿聯-KY' :'3665.TW'
41
  }
42
 
43
  # 產業分類
@@ -54,10 +48,10 @@ INDUSTRY_MAPPING = {
54
  '2311.TW': '半導體',
55
  '2306.TW': '航運',
56
  '2637.TW': '散裝航運',
57
- '2049.TW' : '工具機',
58
- '1101.TW' : '營建',
59
- '4966.TW' :'高速傳輸',
60
- '3665.TW' :'連接器'
61
  }
62
 
63
  def get_stock_data(symbol, period='1y'):
@@ -249,14 +243,52 @@ app = dash.Dash(__name__, suppress_callback_exceptions=True)
249
  app.layout = html.Div([
250
  html.H1("台股分析儀表板", style={'text-align': 'center', 'margin-bottom': '30px'}),
251
 
252
- # 控制面板
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  html.Div([
254
  html.Div([
255
  html.Label("選擇股票:"),
256
  dcc.Dropdown(
257
  id='stock-dropdown',
258
  options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()],
259
- value='TXF=F',
260
  style={'margin-bottom': '10px'}
261
  )
262
  ], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
@@ -294,9 +326,6 @@ app.layout = html.Div([
294
  # 股價資訊卡片
295
  html.Div(id='stock-info-cards', style={'margin-bottom': '30px'}),
296
 
297
- # AI預測區塊 (只在選擇台指期時顯示)
298
- html.Div(id='prediction-section', style={'margin-bottom': '30px'}),
299
-
300
  # 主要圖表區域
301
  html.Div([
302
  # 左側:股價走勢圖和技術指標
@@ -503,59 +532,13 @@ app.layout = html.Div([
503
  })
504
  ])
505
 
506
- # 更新AI預測區塊
507
  @app.callback(
508
- dash.dependencies.Output('prediction-section', 'children'),
509
- [dash.dependencies.Input('stock-dropdown', 'value')],
510
- prevent_initial_call=False
511
  )
512
- def update_prediction_section(selected_stock):
513
- if selected_stock != 'TXF=F':
514
- return html.Div() # 只在選擇台指期時顯示預測功能
515
-
516
- return html.Div([
517
- html.H3("🤖 AI深度學習預測 - 台指期指數", style={'text-align': 'center', 'color': '#FFCC22'}),
518
- html.Div([
519
- html.Div([
520
- html.Label("預測期間:", style={'font-weight': 'bold', 'color': '#FFCC22'}),
521
- dcc.Dropdown(
522
- id='prediction-period',
523
- options=[
524
- {'label': '5日後預測', 'value': 5},
525
- {'label': '10日後預測', 'value': 10},
526
- {'label': '20日後預測', 'value': 20},
527
- {'label': '60日後預測', 'value': 60}
528
- ],
529
- value=5,
530
- style={'margin-bottom': '10px', 'color': '#272727'}
531
- )
532
- ], style={'width': '30%', 'display': 'inline-block'}),
533
-
534
- html.Div(id='prediction-results', style={'width': '65%', 'display': 'inline-block', 'margin-left': '5%'})
535
- ]),
536
-
537
- html.Div([
538
- dcc.Graph(id='prediction-chart')
539
- ], style={'margin-top': '20px'})
540
- ], style={
541
- 'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
542
- 'padding': '25px',
543
- 'border-radius': '15px',
544
- 'box-shadow': '0 8px 25px rgba(0,0,0,0.15)',
545
- 'color': 'white'
546
- })
547
-
548
- # 更新預測結果
549
- @app.callback(
550
- [dash.dependencies.Output('prediction-results', 'children'),
551
- dash.dependencies.Output('prediction-chart', 'figure')],
552
- [dash.dependencies.Input('prediction-period', 'value'),
553
- dash.dependencies.Input('stock-dropdown', 'value')]
554
- )
555
- def update_prediction(predict_days, selected_stock):
556
- if selected_stock != 'TXF=F':
557
- return html.Div(), {}
558
-
559
  # 獲取台指期歷史資料
560
  data = get_stock_data('^TWII', '2y')
561
  if data.empty:
@@ -720,7 +703,7 @@ def update_price_chart(selected_stock, period, chart_type):
720
 
721
  return fig
722
 
723
- # 更新RSI圖表(保持兼容性)
724
  @app.callback(
725
  dash.dependencies.Output('rsi-chart', 'figure'),
726
  [dash.dependencies.Input('stock-dropdown', 'value'),
@@ -753,8 +736,6 @@ def update_rsi_chart(selected_stock, period):
753
 
754
  return fig
755
 
756
-
757
-
758
  # 新增:進階技術指標圖表
759
  @app.callback(
760
  dash.dependencies.Output('advanced-technical-chart', 'figure'),
@@ -1137,39 +1118,23 @@ def update_analysis_text(selected_stock, period):
1137
 
1138
  # 基本面分析
1139
  industry = INDUSTRY_MAPPING.get(selected_stock, '綜合')
1140
- if selected_stock == 'TXF=F':
1141
- fundamental_text = html.Div([
1142
- html.P([
1143
- html.Strong("總體經濟:"),
1144
- "台指期反映台股整體表現,當前需關注聯準會政策、國際貿易情勢及台灣出口動能。"
1145
- ]),
1146
- html.P([
1147
- html.Strong("產業輪動:"),
1148
- "觀察半導體、電子等權重產業表現,以及傳統產業復甦力道。"
1149
- ]),
1150
- html.P([
1151
- html.Strong("資金面:"),
1152
- "外資動向、匯率變化及市場流動性為主要觀察重點。"
1153
- ])
1154
- ])
1155
- else:
1156
- fundamental_text = html.Div([
1157
- html.P([
1158
- html.Strong("產業地位:"),
1159
- f"{stock_name}屬於{industry}產業,在產業鏈中具有",
1160
- html.Span("重要地位" if selected_stock in ['2330.TW', '2454.TW', '2317.TW'] else "一定影響力",
1161
- style={'font-weight': 'bold'}),
1162
- "。"
1163
- ]),
1164
- html.P([
1165
- html.Strong("營運展望:"),
1166
- f"考量{industry}產業前景及公司基本面,建議持續關注季報表現及未來指引。"
1167
- ]),
1168
- html.P([
1169
- html.Strong("風險評估:"),
1170
- "注意產業週期性變化、國際競爭及法規環境變化等風險因子。"
1171
- ])
1172
  ])
 
1173
 
1174
  # 市場展望
1175
  if price_change > 10:
@@ -1429,10 +1394,5 @@ if __name__ == '__main__':
1429
  if not pmi_data.empty:
1430
  print(f"PMI資料預覽:\n{pmi_data.head()}")
1431
 
1432
- # 在 Colab 中需要使用以下方式啟動
1433
- app.run(host="0.0.0.0", port=7860, debug=True)
1434
-
1435
-
1436
-
1437
- # 如果在本地環境執行,使用以下方式
1438
- # app.run_server(debug=True)
 
14
  import plotly.graph_objects as go
15
  from plotly.subplots import make_subplots
16
 
17
+ # 台股代號對應表 (移除台指期,因為它現在是獨立區塊)
 
 
 
 
 
18
  TAIWAN_STOCKS = {
 
19
  '台積電': '2330.TW',
20
  '聯發科': '2454.TW',
21
  '鴻海': '2317.TW',
 
28
  '日月光': '2311.TW',
29
  '長榮': '2306.TW',
30
  '慧洋-KY': '2637.TW',
31
+ '上銀': '2049.TW',
32
+ '台泥': '1101.TW',
33
+ '譜瑞-KY': '4966.TW',
34
+ '貿聯-KY': '3665.TW'
35
  }
36
 
37
  # 產業分類
 
48
  '2311.TW': '半導體',
49
  '2306.TW': '航運',
50
  '2637.TW': '散裝航運',
51
+ '2049.TW': '工具機',
52
+ '1101.TW': '營建',
53
+ '4966.TW': '高速傳輸',
54
+ '3665.TW': '連接器'
55
  }
56
 
57
  def get_stock_data(symbol, period='1y'):
 
243
  app.layout = html.Div([
244
  html.H1("台股分析儀表板", style={'text-align': 'center', 'margin-bottom': '30px'}),
245
 
246
+ # 台指期獨立預測區塊 - 置於頂部
247
+ html.Div([
248
+ html.H2("🤖 AI深度學習預測 - 台指期指數", style={
249
+ 'text-align': 'center',
250
+ 'color': '#FFCC22',
251
+ 'margin-bottom': '25px'
252
+ }),
253
+ html.Div([
254
+ html.Div([
255
+ html.Label("預測期間:", style={'font-weight': 'bold', 'color': '#FFCC22'}),
256
+ dcc.Dropdown(
257
+ id='taiex-prediction-period',
258
+ options=[
259
+ {'label': '5日後預測', 'value': 5},
260
+ {'label': '10日後預測', 'value': 10},
261
+ {'label': '20日後預測', 'value': 20},
262
+ {'label': '60日後預測', 'value': 60}
263
+ ],
264
+ value=5,
265
+ style={'margin-bottom': '10px', 'color': '#272727'}
266
+ )
267
+ ], style={'width': '30%', 'display': 'inline-block'}),
268
+
269
+ html.Div(id='taiex-prediction-results', style={'width': '65%', 'display': 'inline-block', 'margin-left': '5%'})
270
+ ]),
271
+
272
+ html.Div([
273
+ dcc.Graph(id='taiex-prediction-chart')
274
+ ], style={'margin-top': '20px'})
275
+ ], style={
276
+ 'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
277
+ 'padding': '25px',
278
+ 'border-radius': '15px',
279
+ 'box-shadow': '0 8px 25px rgba(0,0,0,0.15)',
280
+ 'color': 'white',
281
+ 'margin-bottom': '40px'
282
+ }),
283
+
284
+ # 控制面板 (移除台指期選項)
285
  html.Div([
286
  html.Div([
287
  html.Label("選擇股票:"),
288
  dcc.Dropdown(
289
  id='stock-dropdown',
290
  options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()],
291
+ value='2330.TW', # 預設改為台積電
292
  style={'margin-bottom': '10px'}
293
  )
294
  ], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
 
326
  # 股價資訊卡片
327
  html.Div(id='stock-info-cards', style={'margin-bottom': '30px'}),
328
 
 
 
 
329
  # 主要圖表區域
330
  html.Div([
331
  # 左側:股價走勢圖和技術指標
 
532
  })
533
  ])
534
 
535
+ # 台指期獨立預測回調函數
536
  @app.callback(
537
+ [dash.dependencies.Output('taiex-prediction-results', 'children'),
538
+ dash.dependencies.Output('taiex-prediction-chart', 'figure')],
539
+ [dash.dependencies.Input('taiex-prediction-period', 'value')]
540
  )
541
+ def update_taiex_prediction(predict_days):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  # 獲取台指期歷史資料
543
  data = get_stock_data('^TWII', '2y')
544
  if data.empty:
 
703
 
704
  return fig
705
 
706
+ # 更新RSI圖表(保持兼容性)
707
  @app.callback(
708
  dash.dependencies.Output('rsi-chart', 'figure'),
709
  [dash.dependencies.Input('stock-dropdown', 'value'),
 
736
 
737
  return fig
738
 
 
 
739
  # 新增:進階技術指標圖表
740
  @app.callback(
741
  dash.dependencies.Output('advanced-technical-chart', 'figure'),
 
1118
 
1119
  # 基本面分析
1120
  industry = INDUSTRY_MAPPING.get(selected_stock, '綜合')
1121
+ fundamental_text = html.Div([
1122
+ html.P([
1123
+ html.Strong("產業地位:"),
1124
+ f"{stock_name}屬於{industry}產業,在產業鏈中具有",
1125
+ html.Span("重要地位" if selected_stock in ['2330.TW', '2454.TW', '2317.TW'] else "一定影響力",
1126
+ style={'font-weight': 'bold'}),
1127
+ "。"
1128
+ ]),
1129
+ html.P([
1130
+ html.Strong("營運展望:"),
1131
+ f"考量{industry}產業前景及公司基本面,建議持續關注季報表現及未來指引。"
1132
+ ]),
1133
+ html.P([
1134
+ html.Strong("風險評估:"),
1135
+ "注意產業週期性變化、國際競爭及法規環境變化等風險因子。"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1136
  ])
1137
+ ])
1138
 
1139
  # 市場展望
1140
  if price_change > 10:
 
1394
  if not pmi_data.empty:
1395
  print(f"PMI資料預覽:\n{pmi_data.head()}")
1396
 
1397
+ # 在 Hugging Face Spaces 中執行
1398
+ app.run_server(host="0.0.0.0", port=7860, debug=False)