Team Ai
Apppublic

Ruby20260314/StockData0401

sourceHugging Faceotherupdated 6mo agoView on Hugging Face
0likes
app.py209 linesDownload Raw Back to root
1"""2櫃買中心 本益比/殖利率/股價淨值比 分析儀表板3執行方式:4    pip install streamlit pandas requests plotly openpyxl5    streamlit run tpex_streamlit_app.py6"""7 8import io9import requests10import pandas as pd11import plotly.express as px12import streamlit as st13 14# ── 頁面設定 ──────────────────────────────────────────────────────────────────15st.set_page_config(16    page_title="櫃買中心 股票指標分析",17    page_icon="📊",18    layout="wide",19)20 21st.title("📊 櫃買中心 股票指標分析儀表板")22st.caption("資料來源:臺灣證券交易所 TPEx 即時資料")23 24# ── 1. 抓取資料(快取 10 分鐘)────────────────────────────────────────────────25@st.cache_data(ttl=600)26def load_data():27    url = (28        "https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/"29        "pera_result.php?l=zh-tw&o=data"30    )31    resp = requests.get(url, timeout=15)32    resp.encoding = "utf-8-sig"33    df = pd.read_csv(io.StringIO(resp.text), encoding="utf-8-sig")34    df = df.dropna()35    df["本益比"]    = pd.to_numeric(df["本益比"],    errors="coerce")36    df["殖利率"]    = pd.to_numeric(df["殖利率"],    errors="coerce")37    df["股價淨值比"] = pd.to_numeric(df["股價淨值比"], errors="coerce")38    df = df.dropna(subset=["本益比", "殖利率", "股價淨值比"])39    df["股票代號"] = df["股票代號"].astype(str)40    return df41 42with st.spinner("資料載入中…"):43    df = load_data()44 45st.success(f"✅ 共載入 {len(df)} 筆有效資料")46 47# ── 2. 側邊欄篩選器 ───────────────────────────────────────────────────────────48with st.sidebar:49    st.header("⚙️ 篩選條件")50 51    top_n = st.slider("顯示前幾筆(圖表)", 10, 100, 60, step=10)52 53    yield_threshold = st.number_input(54        "殖利率標記閾值(塗黃條件 >)", min_value=0.0, max_value=20.0,55        value=6.0, step=0.556    )57 58    pe_range = st.slider(59        "本益比範圍篩選",60        float(df["本益比"].min()), float(df["本益比"].max()),61        (float(df["本益比"].min()), float(df["本益比"].max())),62    )63 64    yield_range = st.slider(65        "殖利率範圍篩選",66        float(df["殖利率"].min()), float(df["殖利率"].max()),67        (float(df["殖利率"].min()), float(df["殖利率"].max())),68    )69 70    st.markdown("---")71    st.info("圖表支援互動操作(縮放、懸停、點擊圖例篩選)")72 73# ── 套用篩選 ──────────────────────────────────────────────────────────────────74filtered_df = df[75    df["本益比"].between(*pe_range) &76    df["殖利率"].between(*yield_range)77].copy()78 79plot_df = filtered_df.head(top_n).copy()80 81st.markdown(f"**篩選後:{len(filtered_df)} 筆 | 圖表顯示前 {top_n} 筆**")82 83# ── 3. KPI 摘要卡片 ───────────────────────────────────────────────────────────84col1, col2, col3, col4 = st.columns(4)85col1.metric("平均本益比",    f"{filtered_df['本益比'].mean():.2f}")86col2.metric("平均殖利率",    f"{filtered_df['殖利率'].mean():.2f}%")87col3.metric("平均股價淨值比", f"{filtered_df['股價淨值比'].mean():.2f}")88col4.metric(f"殖利率 > {yield_threshold}% 家數",89            f"{(filtered_df['殖利率'] > yield_threshold).sum()} 家")90 91st.divider()92 93# ── 4. 動態圓餅圖 ─────────────────────────────────────────────────────────────94st.subheader("🥧 殖利率分布圓餅圖")95fig_pie = px.pie(96    plot_df,97    names="股票代號",98    values="殖利率",99    title=f"股票殖利率分布(前 {top_n} 筆)",100    hover_data=["本益比", "股價淨值比"],101)102fig_pie.update_traces(textposition="inside", textinfo="label+percent")103fig_pie.update_layout(height=520)104st.plotly_chart(fig_pie, use_container_width=True)105 106st.divider()107 108# ── 5. 動態柱狀圖 ─────────────────────────────────────────────────────────────109st.subheader("📊 本益比柱狀圖")110fig_bar = px.bar(111    plot_df,112    x="股票代號",113    y="本益比",114    color="殖利率",115    color_continuous_scale="Viridis",116    title=f"各股票本益比(前 {top_n} 筆)",117    hover_data=["殖利率", "股價淨值比"],118    text="本益比",119)120fig_bar.update_traces(texttemplate="%{text:.1f}", textposition="outside")121fig_bar.update_layout(122    xaxis_tickangle=-45,123    coloraxis_colorbar_title="殖利率",124    height=520,125)126st.plotly_chart(fig_bar, use_container_width=True)127 128st.divider()129 130# ── 6. 動態旭日圖 ─────────────────────────────────────────────────────────────131st.subheader("☀️ 旭日圖(殖利率分組)")132 133def yield_group(v):134    if v >= 6:   return "高殖利率(≥6%)"135    elif v >= 3: return "中殖利率(3~6%)"136    else:        return "低殖利率(<3%)"137 138plot_df["殖利率分組"] = plot_df["殖利率"].apply(yield_group)139 140fig_sun = px.sunburst(141    plot_df,142    path=["殖利率分組", "股票代號"],143    values="股價淨值比",144    color="殖利率",145    color_continuous_scale="RdYlGn",146    title="旭日圖:殖利率分組 → 股票代號(大小 = 股價淨值比)",147    hover_data=["本益比"],148)149fig_sun.update_layout(height=600)150st.plotly_chart(fig_sun, use_container_width=True)151 152st.divider()153 154# ── 7. 資料表格(Styler 塗黃)────────────────────────────────────────────────155st.subheader(f"📋 資料明細(殖利率 > {yield_threshold}% 標記黃色)")156 157cols = ["股票代號", "本益比", "殖利率", "股價淨值比"]158export_df = filtered_df[cols].copy()159 160def highlight_yield(row):161    color = "background-color: #FFD700; color: #333;" if row["殖利率"] > yield_threshold else ""162    return [color] * len(row)163 164styled = (165    export_df.style166    .apply(highlight_yield, axis=1)167    .format({"本益比": "{:.2f}", "殖利率": "{:.2f}", "股價淨值比": "{:.2f}"})168)169 170st.dataframe(styled, use_container_width=True, height=420)171 172# ── 8. Excel 下載按鈕 ─────────────────────────────────────────────────────────173st.subheader("⬇️ 下載 Excel 報表")174 175def build_excel(df_export, threshold):176    buf = io.BytesIO()177    with pd.ExcelWriter(buf, engine="openpyxl") as writer:178        # 塗黃樣式179        styled_export = (180            df_export.style181            .apply(182                lambda row: ["background-color: yellow" if row["殖利率"] > threshold else "" for _ in row],183                axis=1184            )185            .format({"本益比": "{:.2f}", "殖利率": "{:.2f}", "股價淨值比": "{:.2f}"})186        )187        styled_export.to_excel(writer, sheet_name="個股指標", index=False)188 189        ws = writer.sheets["個股指標"]190        for col in ws.columns:191            max_len = max(len(str(cell.value)) if cell.value else 0 for cell in col)192            ws.column_dimensions[col[0].column_letter].width = max_len + 4193 194        wb = writer.book195        info_ws = wb.create_sheet("說明")196        info_ws["A1"] = f"黃色標記條件:殖利率 > {threshold}%"197        info_ws["A2"] = "資料來源:臺灣證券交易所 TPEx"198 199    return buf.getvalue()200 201excel_bytes = build_excel(export_df, yield_threshold)202 203st.download_button(204    label="📥 下載 Excel(含黃色標記)",205    data=excel_bytes,206    file_name="tpex_analysis.xlsx",207    mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",208)209