iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Software Development

30 天打造專屬盯盤機器人:資料爬取、策略指標到 Telegram/LINE 推播系列 第 18 篇

Day 18:基本面大進擊 — 導入上市櫃月營收 (YoY/MoM) 與營收爆發警報!

  • 分享至 

  • xImage
  •  

今天是第十八天!昨天我們幫機器人注入了「三大法人籌碼面」數據,讓我們的看盤報告具備了技術面與籌碼面的雙重判斷!

但是,不論技術線圖畫得再好看、法人買得多熱烈,「企業有沒有賺錢」 永遠是股價最長遠的基石!在台股市場,每個月 1~10 號都是極其關鍵的「營收公佈期」。當一家公司的月營收創下歷史新高,或是年增率(YoY)大幅暴增時,往往就是股價噴發的起漲點!

今天我們的目標,就是在我們的專案架構中,導入「上市櫃個股月營收數據(MoM 月增率 / YoY 年增率)」抓取與診斷邏輯,打造出具備「基本面營收爆發警示」的全方位 Telegram 看盤小幫手!

步驟一:先釐清邏輯
營收診斷與警報的運作邏輯非常清晰直覺:

  • 抓取營收數據(fetcher.py):向數據源(如 FinMind API 或 公開資訊觀測站/Yahoo Finance)抓取個股最新一期的單月營收數字、上月營收與去年同期營收。
  • 計算成長率指標:
    MoM(Month-on-Month,月增率):(本月營收 - 上月營收) / 上月營收 * 100%
    YoY(Year-on-Year,年增率):(本月營收 - 去年同期營收) / 去年同期營收 * 100%
  • 設定基本面門檻與診斷:當 YoY 成長超過 20% 或 MoM 成長超過 10% 時,定義為「營收強勁成長」;超過 50% 則觸發「營收爆發警報」!
  • 整合進報告(bot.py):將營收資訊排版至 Telegram 分析報告中,讓你在盤後第一時間掌握公司的基本面績效!

接下來,知道邏輯後,我們就可以來寫程式碼了!

步驟二:完整實作程式碼
我們同樣繼續維護我們優雅的模組化架構,要改的是 fetcher.py 和 bot.py!

  1. fetcher.py
    在 fetcher.py 中新增抓取最新營收資料的邏輯,並計算 MoM 與 YoY:
import pandas as pd
import pandas_ta as ta
import yfinance as yf

def get_stock_data(symbol):
    formatted_symbol = symbol.strip().upper()
    if not formatted_symbol.endswith('.TW') and not formatted_symbol.endswith('.TWO'):
        formatted_symbol += '.TW'

    print(f"[INFO] 正在抓取數據、籌碼與基本面營收: {formatted_symbol}...")

    # 1. 抓取股價歷史資料
    ticker = yf.Ticker(formatted_symbol)
    df = ticker.history(period="6mo")

    if df.empty and formatted_symbol.endswith('.TW'):
        alt_symbol = formatted_symbol.replace('.TW', '.TWO')
        ticker = yf.Ticker(alt_symbol)
        df = ticker.history(period="6mo")
        if not df.empty:
            formatted_symbol = alt_symbol

    if df.empty:
        return None, None, None, None

    if isinstance(df.columns, pd.MultiIndex):
        df.columns = df.columns.get_level_values(0)

    # 技術指標計算
    df['MA5'] = df['Close'].rolling(window=5).mean()
    df['MA20'] = df['Close'].rolling(window=20).mean()
    df['RSI'] = df.ta.rsi(length=14)

    macd_df = df.ta.macd(fast=12, slow=26, signal=9)
    df['MACD'] = macd_df['MACD_12_26_9']
    df['MACD_signal'] = macd_df['MACDs_12_26_9']
    df['MACD_hist'] = macd_df['MACDh_12_26_9']
    df['Vol_MA5'] = df['Volume'].rolling(window=5).mean()

    # 2. 三大法人籌碼模擬數據
    chip_data = {
        "foreign": 1250,
        "investment": 800,
        "dealer": -150
    }
    chip_data["total"] = chip_data["foreign"] + chip_data["investment"] + chip_data["dealer"]

    # 3. 最新月營收基本面數據 (單位:千元)
    # 實際運作時可連接 FinMind API 或 MOPS 數據
    revenue_data = {
        "month": "2026-09",
        "revenue": 75000000,    # 本月營收 750 億
        "mom": 8.5,             # 月增率 MoM +8.5%
        "yoy": 32.4             # 年增率 YoY +32.4%
    }

    return formatted_symbol, df, chip_data, revenue_data
  1. bot.py
    要更改 generate_report_text 函式,將「營收數據區塊」與「基本面評語」加入其中:
def generate_report_text(symbol, df, chip_data=None, revenue_data=None):
    latest = df.iloc[-1]
    prev = df.iloc[-2]

    rsi_val = latest['RSI']
    latest_vol = latest['Volume']
    vol_ma5_val = latest['Vol_MA5']

    caption = f"【{symbol} 盤後三維度全方位分析報告】\n"
    caption += f"日期:{df.index[-1].strftime('%Y-%m-%d')}\n"
    caption += f"收盤價:{latest['Close']:.2f}\n"
    caption += f"5MA: {latest['MA5']:.2f} | 20MA: {latest['MA20']:.2f}\n"
    caption += f"RSI(14):{rsi_val:.1f}\n"

    # 籌碼面區塊
    if chip_data:
        caption += f"-----------------------------------\n"
        caption += f"【三大法人籌碼動向】(單位: 張)\n"
        caption += f"外資:{chip_data['foreign']:+d} | 投信:{chip_data['investment']:+d}\n"
        caption += f"法人合計:{chip_data['total']:+d}\n"

    # 基本面營收區塊
    if revenue_data:
        caption += f"-----------------------------------\n"
        caption += f"【最新月營收報告】({revenue_data['month']})\n"
        caption += f"單月營收:{revenue_data['revenue'] / 100000:.2f} 億元\n"
        caption += f"MoM (月增率):{revenue_data['mom']:+.1f}%\n"
        caption += f"YoY (年增率):{revenue_data['yoy']:+.1f}%\n"

    caption += f"-----------------------------------\n"

    signals = []

    # 基本面訊號判斷
    if revenue_data:
        if revenue_data['yoy'] >= 30:
            signals.append("[基本面] 月營收年增率 (YoY) 突破 30%,營收強勁成長!")
        elif revenue_data['yoy'] <= -15:
            signals.append("[基本面] 月營收年增率 (YoY) 衰退超過 15%,留意基本面利空!")

    # 籌碼面訊號判斷
    if chip_data:
        if chip_data['foreign'] > 0 and chip_data['investment'] > 0:
            signals.append("[籌碼] 外資與投信同買,法人作多力道強勁!")

    # 技術面與量能訊號
    if prev['MA5'] <= prev['MA20'] and latest['MA5'] > latest['MA20']:
        signals.append("[MA] 5MA 向上突破 20MA(黃金交叉)")

    if latest_vol > vol_ma5_val * 1.5:
        signals.append("[量能] 今日成交量爆發(高於 5 日均量 1.5 倍)!")

    if not signals:
        caption += "評語:技術面、籌碼面與基本面處於平穩狀態,建議持續觀察。"
    else:
        caption += "關鍵訊號彙整:\n" + "\n".join(signals)

    return caption

解釋一下程式碼吧!
三維度整合(技術面 + 籌碼面 + 基本面):
報告從單一的 K 線圖,升級成「技術面 (MA/RSI/MACD/量能)」、「籌碼面 (三大法人)」與「基本面 (月營收 YoY/MoM)」的三合一報告。

營收單位換算與格式化:
原始營收金額通常很大,我們在輸出時除以 100,000 轉換成習慣閱讀的「億元」單位,搭配 {revenue_data['yoy']:+.1f}% 自動標示正負號,讓資訊更加清晰!
步驟三:執行與測試
在終端機輸入:

python main.py

最後會像這樣!
小結一下:
月營收 YoY 成長率是觀察長線趨勢最重要的指標之一,當看到「YoY > 30% 且 法人同買」時,通常代表公司有實質業績支撐!
今天我們成功將「月營收 YoY / MoM」納入機器人的診斷系統,達成「技術面 + 籌碼面 + 基本面」的全方位三維度分析!


上一篇
Day 17:籌碼面大解析 — 導入三大法人買賣超數據與籌碼診斷!
下一篇
Day 19:效能與穩定度升級 — 導入 SQLite 資料庫快取與查詢優化!
系列文
30 天打造專屬盯盤機器人:資料爬取、策略指標到 Telegram/LINE 推播 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言