Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -30,7 +30,7 @@ TAIWAN_STOCKS = {
|
|
| 30 |
'慧洋-KY': '2637.TW',
|
| 31 |
'上銀': '2049.TW',
|
| 32 |
'台泥': '1101.TW',
|
| 33 |
-
'譜瑞-KY': '4966.
|
| 34 |
'貿聯-KY': '3665.TW'
|
| 35 |
}
|
| 36 |
|
|
@@ -50,7 +50,7 @@ INDUSTRY_MAPPING = {
|
|
| 50 |
'2637.TW': '散裝航運',
|
| 51 |
'2049.TW': '工具機',
|
| 52 |
'1101.TW': '營建',
|
| 53 |
-
'4966.
|
| 54 |
'3665.TW': '連接器'
|
| 55 |
}
|
| 56 |
|
|
@@ -332,7 +332,7 @@ app.layout = html.Div([
|
|
| 332 |
options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()],
|
| 333 |
value='2330.TW', # 預設改為台積電
|
| 334 |
style={'margin-bottom': '10px'}
|
| 335 |
-
)
|
| 336 |
], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
|
| 337 |
|
| 338 |
html.Div([
|
|
@@ -376,7 +376,10 @@ app.layout = html.Div([
|
|
| 376 |
dcc.Graph(id='price-chart')
|
| 377 |
], style={'margin-bottom': '20px'}),
|
| 378 |
|
| 379 |
-
|
|
|
|
|
|
|
|
|
|
| 380 |
|
| 381 |
# 右側:分析資訊面板
|
| 382 |
html.Div([
|
|
@@ -384,7 +387,19 @@ app.layout = html.Div([
|
|
| 384 |
], style={'width': '33%', 'display': 'inline-block', 'margin-left': '2%', 'vertical-align': 'top'})
|
| 385 |
]),
|
| 386 |
|
| 387 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
html.Div([
|
| 389 |
html.H3("📊 進階技術指標分析", style={'margin-bottom': '20px'}),
|
| 390 |
html.Div([
|
|
@@ -414,22 +429,6 @@ app.layout = html.Div([
|
|
| 414 |
'box-shadow': '0 2px 10px rgba(0,0,0,0.1)'
|
| 415 |
}),
|
| 416 |
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
# 新增:成交量分佈圖 (Volume Profile)
|
| 421 |
-
html.Div([
|
| 422 |
-
html.H3("📊 成交量分佈圖 (Volume Profile)"),
|
| 423 |
-
dcc.Graph(id='volume-profile-chart')
|
| 424 |
-
], style={
|
| 425 |
-
'margin-top': '30px',
|
| 426 |
-
'padding': '20px',
|
| 427 |
-
'background': 'white',
|
| 428 |
-
'border-radius': '10px',
|
| 429 |
-
'box-shadow': '0 2px 10px rgba(0,0,0,0.1)'
|
| 430 |
-
}),
|
| 431 |
-
|
| 432 |
-
|
| 433 |
# 成交量圖
|
| 434 |
html.Div([
|
| 435 |
dcc.Graph(id='volume-chart')
|
|
@@ -783,7 +782,38 @@ def update_price_chart(selected_stock, period, chart_type):
|
|
| 783 |
|
| 784 |
return fig
|
| 785 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 786 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 787 |
|
| 788 |
# 新增:進階技術指標圖表
|
| 789 |
@app.callback(
|
|
|
|
| 30 |
'慧洋-KY': '2637.TW',
|
| 31 |
'上銀': '2049.TW',
|
| 32 |
'台泥': '1101.TW',
|
| 33 |
+
'譜瑞-KY': '4966.TW',
|
| 34 |
'貿聯-KY': '3665.TW'
|
| 35 |
}
|
| 36 |
|
|
|
|
| 50 |
'2637.TW': '散裝航運',
|
| 51 |
'2049.TW': '工具機',
|
| 52 |
'1101.TW': '營建',
|
| 53 |
+
'4966.TW': '高速傳輸',
|
| 54 |
'3665.TW': '連接器'
|
| 55 |
}
|
| 56 |
|
|
|
|
| 332 |
options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()],
|
| 333 |
value='2330.TW', # 預設改為台積電
|
| 334 |
style={'margin-bottom': '10px'}
|
| 335 |
+
)
|
| 336 |
], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
|
| 337 |
|
| 338 |
html.Div([
|
|
|
|
| 376 |
dcc.Graph(id='price-chart')
|
| 377 |
], style={'margin-bottom': '20px'}),
|
| 378 |
|
| 379 |
+
html.Div([
|
| 380 |
+
dcc.Graph(id='rsi-chart')
|
| 381 |
+
])
|
| 382 |
+
], style={'width': '65%', 'display': 'inline-block', 'vertical-align': 'top'}),
|
| 383 |
|
| 384 |
# 右側:分析資訊面板
|
| 385 |
html.Div([
|
|
|
|
| 387 |
], style={'width': '33%', 'display': 'inline-block', 'margin-left': '2%', 'vertical-align': 'top'})
|
| 388 |
]),
|
| 389 |
|
| 390 |
+
# 新增:成交量分佈圖 (Volume Profile)
|
| 391 |
+
html.Div([
|
| 392 |
+
html.H3("📊 成交量分佈圖 (Volume Profile)"),
|
| 393 |
+
dcc.Graph(id='volume-profile-chart')
|
| 394 |
+
], style={
|
| 395 |
+
'margin-top': '30px',
|
| 396 |
+
'padding': '20px',
|
| 397 |
+
'background': 'white',
|
| 398 |
+
'border-radius': '10px',
|
| 399 |
+
'box-shadow': '0 2px 10px rgba(0,0,0,0.1)'
|
| 400 |
+
}),
|
| 401 |
+
|
| 402 |
+
# 技術指標選擇區域
|
| 403 |
html.Div([
|
| 404 |
html.H3("📊 進階技術指標分析", style={'margin-bottom': '20px'}),
|
| 405 |
html.Div([
|
|
|
|
| 429 |
'box-shadow': '0 2px 10px rgba(0,0,0,0.1)'
|
| 430 |
}),
|
| 431 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
# 成交量圖
|
| 433 |
html.Div([
|
| 434 |
dcc.Graph(id='volume-chart')
|
|
|
|
| 782 |
|
| 783 |
return fig
|
| 784 |
|
| 785 |
+
# 更新RSI圖表(保持兼容性)
|
| 786 |
+
@app.callback(
|
| 787 |
+
dash.dependencies.Output('rsi-chart', 'figure'),
|
| 788 |
+
[dash.dependencies.Input('stock-dropdown', 'value'),
|
| 789 |
+
dash.dependencies.Input('period-dropdown', 'value')]
|
| 790 |
+
)
|
| 791 |
+
def update_rsi_chart(selected_stock, period):
|
| 792 |
+
data = get_stock_data(selected_stock, period)
|
| 793 |
+
if data.empty:
|
| 794 |
+
return {}
|
| 795 |
|
| 796 |
+
data = calculate_technical_indicators(data)
|
| 797 |
+
|
| 798 |
+
fig = go.Figure()
|
| 799 |
+
fig.add_trace(go.Scatter(x=data.index, y=data['RSI'], mode='lines', name='RSI', line=dict(color='purple', width=2)))
|
| 800 |
+
fig.add_hline(y=70, line_dash="dash", line_color="red", annotation_text="超買線(70)")
|
| 801 |
+
fig.add_hline(y=30, line_dash="dash", line_color="green", annotation_text="超賣線(30)")
|
| 802 |
+
fig.add_hline(y=50, line_dash="dot", line_color="gray", annotation_text="中線(50)")
|
| 803 |
+
|
| 804 |
+
# 添加超買超賣區域背景
|
| 805 |
+
fig.add_hrect(y0=70, y1=100, fillcolor="red", opacity=0.1, annotation_text="超買區")
|
| 806 |
+
fig.add_hrect(y0=0, y1=30, fillcolor="green", opacity=0.1, annotation_text="超賣區")
|
| 807 |
+
|
| 808 |
+
fig.update_layout(
|
| 809 |
+
title='RSI 相對強弱指標',
|
| 810 |
+
xaxis_title='日期',
|
| 811 |
+
yaxis_title='RSI',
|
| 812 |
+
height=400,
|
| 813 |
+
yaxis=dict(range=[0, 100])
|
| 814 |
+
)
|
| 815 |
+
|
| 816 |
+
return fig
|
| 817 |
|
| 818 |
# 新增:進階技術指標圖表
|
| 819 |
@app.callback(
|