Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
# 系統套件
|
| 4 |
import os
|
|
@@ -477,61 +477,53 @@ def update_volume_chart(selected_stock, period):
|
|
| 477 |
fig.update_layout(title=f'{stock_name} 成交量', xaxis_title='日期', yaxis_title='成交量', height=300)
|
| 478 |
return fig
|
| 479 |
|
| 480 |
-
#
|
| 481 |
@app.callback(
|
| 482 |
dash.dependencies.Output('industry-analysis', 'figure'),
|
| 483 |
-
[dash.dependencies.Input('stock-dropdown', 'value')] #
|
| 484 |
)
|
| 485 |
def update_industry_analysis(selected_stock):
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
for symbol in TAIWAN_STOCKS.values():
|
| 490 |
-
# 這裡獲取3個月的數據來計算波動性,確保數據量足夠
|
| 491 |
-
data = get_stock_data(symbol, '3mo')
|
| 492 |
-
if not data.empty and len(data) >= 60: # 確保至少有3個月左右的交易日數據 (約60天)
|
| 493 |
-
# 計算收盤價的標準差,標準差越大,代表波動性越高
|
| 494 |
-
volatility = data['Close'].std()
|
| 495 |
-
stock_name = [name for name, symbol_code in TAIWAN_STOCKS.items() if symbol_code == symbol][0]
|
| 496 |
-
all_stocks_volatility.append({'股票': stock_name, '代碼': symbol, '波動性': volatility})
|
| 497 |
-
|
| 498 |
-
# 如果沒有任何股票數據,則直接返回空圖表
|
| 499 |
-
if not all_stocks_volatility:
|
| 500 |
-
fig = go.Figure().add_annotation(text="無法獲取任何股票數據", showarrow=False)
|
| 501 |
-
fig.update_layout(title="產業表現分析")
|
| 502 |
-
return fig
|
| 503 |
-
|
| 504 |
-
# 2. 根據波動性從高到低排序,並選出前10名
|
| 505 |
-
df_volatility = pd.DataFrame(all_stocks_volatility).sort_values(by='波動性', ascending=False)
|
| 506 |
-
top_10_volatile_stocks = df_volatility.head(10)['代碼'].tolist()
|
| 507 |
-
|
| 508 |
-
# 3. 針對這前10名股票,重新獲取1個月的數據來計算月報酬率
|
| 509 |
-
industry_data = []
|
| 510 |
-
for symbol in top_10_volatile_stocks:
|
| 511 |
data = get_stock_data(symbol, '1mo')
|
| 512 |
-
if not data.empty and len(data) > 1:
|
| 513 |
-
|
| 514 |
-
# 計算月報酬率
|
| 515 |
return_pct = ((data['Close'].iloc[-1] - data['Close'].iloc[0]) / data['Close'].iloc[0]) * 100
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
return fig
|
| 523 |
-
|
| 524 |
-
#
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
return fig
|
|
|
|
| 535 |
|
| 536 |
# 更新景氣燈號圖表
|
| 537 |
@app.callback(
|
|
|
|
| 1 |
+
# HUGING_FACE_V3.1.2.py (整合 Bert_predict 版本)
|
| 2 |
|
| 3 |
# 系統套件
|
| 4 |
import os
|
|
|
|
| 477 |
fig.update_layout(title=f'{stock_name} 成交量', xaxis_title='日期', yaxis_title='成交量', height=300)
|
| 478 |
return fig
|
| 479 |
|
| 480 |
+
# ========================= MODIFIED SECTION START =========================
|
| 481 |
@app.callback(
|
| 482 |
dash.dependencies.Output('industry-analysis', 'figure'),
|
| 483 |
+
[dash.dependencies.Input('stock-dropdown', 'value')] # Callback can be triggered by any change, e.g., the main stock selection
|
| 484 |
)
|
| 485 |
def update_industry_analysis(selected_stock):
|
| 486 |
+
performance_data = []
|
| 487 |
+
# 1. Iterate through ALL stocks to calculate their performance
|
| 488 |
+
for name, symbol in TAIWAN_STOCKS.items():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
data = get_stock_data(symbol, '1mo')
|
| 490 |
+
if not data.empty and len(data) > 1:
|
| 491 |
+
# Calculate 1-month return percentage
|
|
|
|
| 492 |
return_pct = ((data['Close'].iloc[-1] - data['Close'].iloc[0]) / data['Close'].iloc[0]) * 100
|
| 493 |
+
performance_data.append({
|
| 494 |
+
'股票': name,
|
| 495 |
+
'代碼': symbol,
|
| 496 |
+
'月報酬率(%)': return_pct,
|
| 497 |
+
'絕對波動': abs(return_pct) # Use absolute value for sorting
|
| 498 |
+
})
|
| 499 |
+
|
| 500 |
+
if not performance_data:
|
| 501 |
+
fig = go.Figure().add_annotation(text="無法計算產業資料", showarrow=False)
|
| 502 |
+
fig.update_layout(title="近一月市場波動最大標的", height=400)
|
| 503 |
return fig
|
| 504 |
+
|
| 505 |
+
# 2. Sort by the absolute fluctuation and take the top 10
|
| 506 |
+
df_performance = pd.DataFrame(performance_data)
|
| 507 |
+
df_top_movers = df_performance.sort_values(by='絕對波動', ascending=False).head(10)
|
| 508 |
+
|
| 509 |
+
# 3. Create the pie chart with the top 10 movers
|
| 510 |
+
# We use the absolute value for the pie chart size to represent volatility,
|
| 511 |
+
# but the hover data will show the actual (positive/negative) return.
|
| 512 |
+
fig = px.pie(
|
| 513 |
+
df_top_movers,
|
| 514 |
+
values='絕對波動',
|
| 515 |
+
names='股票',
|
| 516 |
+
title='近一月市場波動最大 Top 10 標的',
|
| 517 |
+
hover_data={'月報酬率(%)': ':.2f'} # Show the actual return on hover
|
| 518 |
+
)
|
| 519 |
+
fig.update_traces(
|
| 520 |
+
textposition='inside',
|
| 521 |
+
textinfo='percent+label',
|
| 522 |
+
hovertemplate="<b>%{label}</b><br>月報酬率: %{customdata[0]:.2f}%<extra></extra>"
|
| 523 |
+
)
|
| 524 |
+
fig.update_layout(height=400, showlegend=False)
|
| 525 |
return fig
|
| 526 |
+
# ========================== MODIFIED SECTION END ==========================
|
| 527 |
|
| 528 |
# 更新景氣燈號圖表
|
| 529 |
@app.callback(
|