2025年11月16日 星期日

Python 學習筆記 : 技術分析套件 pandas-ta 用法 (四)

本篇旨在測試如何用 pandas-ta 套件計算技術指標 (以 MACD 為例) 並繪製在 K 線圖上. 

本系列全部文章索引參考 :



7. 計算 MACD 指標 :  

MACD (Moving Average Convergence/Divergence, 指數平滑異同移動平均線) 是用來判斷股價趨勢強度, 方向, 與轉折點的技術指標, 由快線 (DIF), 慢線 (DEA) 和 柱狀圖 (Histogram) 三部分組成, 觀察快線與慢線的交叉與發散, 以及柱狀圖的變化趨勢來判斷標的之買賣訊號. 

下面是例用 yfinance 取得之台股 0050 價量資料來計算 MACD 指標, 並視覺化到 K 線圖的副圖中. 首先匯入 yfinance 與 pandas-ta 套件 : 

>>> import yfinance as yf     
>>> import pandas_ta as ta   

下載 yfinance 股票價量資料 : 

>>> df=yf.download('0050.TW', start='2024-11-06', end='2025-01-09', auto_adjust=False)   
[*********************100%***********************]  1 of 1 completed

將 DataFrame 改為傳統的單層欄位 : 

>>> df.columns=df.columns.map(lambda x: x[0])   

顯示前 10 筆資料 :

>>> df.head()   
            Adj Close      Close       High        Low       Open     Volume
Date                                                                        
2024-11-06  47.797909  48.799999  49.512501  48.375000  48.512501   66825504
2024-11-07  48.348858  49.362499  49.512501  48.625000  48.724998   53994208
2024-11-08  48.728401  49.750000  50.000000  49.674999  49.849998   51800604
2024-11-11  48.752892  49.775002  49.775002  49.200001  49.712502   49456052
2024-11-12  47.504074  48.500000  48.962502  48.500000  48.799999  105088348

在計算指標之前, 先用 help(ta.macd) 檢視 MACD 指標的參數結構 : 

>>> help(ta.macd)   
Help on function macd in module pandas_ta.momentum.macd:

macd(close, fast=None, slow=None, signal=None, talib=None, offset=None, **kwargs)
    Moving Average Convergence Divergence (MACD)
    
    The MACD is a popular indicator to that is used to identify a security's trend.
    While APO and MACD are the same calculation, MACD also returns two more series
    called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is
    the difference of MACD and Signal.
    
    Sources:
        https://www.tradingview.com/wiki/MACD_(Moving_Average_Convergence/Divergence)
        AS Mode: https://tr.tradingview.com/script/YFlKXHnP/
    
    Calculation:
        Default Inputs:
            fast=12, slow=26, signal=9
        EMA = Exponential Moving Average
        MACD = EMA(close, fast) - EMA(close, slow)
        Signal = EMA(MACD, signal)
        Histogram = MACD - Signal
    
        if asmode:
            MACD = MACD - Signal
            Signal = EMA(MACD, signal)
            Histogram = MACD - Signal
    
    Args:
        close (pd.Series): Series of 'close's
        fast (int): The short period. Default: 12
        slow (int): The long period. Default: 26
        signal (int): The signal period. Default: 9
        talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
            version. Default: True
        offset (int): How many periods to offset the result. Default: 0
    
    Kwargs:
        asmode (value, optional): When True, enables AS version of MACD.
            Default: False
        fillna (value, optional): pd.DataFrame.fillna(value)
        fill_method (value, optional): Type of fill method
    
    Returns:
        pd.DataFrame: macd, histogram, signal columns.

可見 MACD 僅使用收盤價進行計算, 主要的特定參數有三個 :
  • fast : 短期 EMA (預設 12)
  • slow : 長期 EMA (預設 26)
  • signal : 訊號線 EMA (預設 9)
呼叫 df.ta.macd() 或 ta.macd() 即可計算 MACD 指標 :

>>> df.ta.macd(close='Close', append=True)   
            MACD_12_26_9  MACDh_12_26_9  MACDs_12_26_9
Date                                                  
2024-11-06           NaN            NaN            NaN
2024-11-07           NaN            NaN            NaN
2024-11-08           NaN            NaN            NaN
2024-11-11           NaN            NaN            NaN
2024-11-12           NaN            NaN            NaN
2024-11-13           NaN            NaN            NaN
2024-11-14           NaN            NaN            NaN
2024-11-15           NaN            NaN            NaN
2024-11-18           NaN            NaN            NaN
2024-11-19           NaN            NaN            NaN
2024-11-20           NaN            NaN            NaN
2024-11-21           NaN            NaN            NaN
2024-11-22           NaN            NaN            NaN
2024-11-25           NaN            NaN            NaN
2024-11-26           NaN            NaN            NaN
2024-11-27           NaN            NaN            NaN
2024-11-28           NaN            NaN            NaN
2024-11-29           NaN            NaN            NaN
2024-12-02           NaN            NaN            NaN
2024-12-03           NaN            NaN            NaN
2024-12-04           NaN            NaN            NaN
2024-12-05           NaN            NaN            NaN
2024-12-06           NaN            NaN            NaN
2024-12-09           NaN            NaN            NaN
2024-12-10           NaN            NaN            NaN
2024-12-11           NaN            NaN            NaN
2024-12-12           NaN            NaN            NaN
2024-12-13           NaN            NaN            NaN
2024-12-16           NaN            NaN            NaN
2024-12-17           NaN            NaN            NaN
2024-12-18           NaN            NaN            NaN
2024-12-19           NaN            NaN            NaN
2024-12-20           NaN            NaN            NaN
2024-12-23      0.137651       0.097522       0.040129
2024-12-24      0.188678       0.118839       0.069839
2024-12-25      0.238471       0.134906       0.103565
2024-12-26      0.271774       0.134567       0.137207
2024-12-27      0.307731       0.136420       0.171312
2024-12-30      0.310459       0.111318       0.199141
2024-12-31      0.268175       0.055227       0.212948
2025-01-02      0.198088      -0.011888       0.209976
2025-01-03      0.179807      -0.024135       0.203942
2025-01-06      0.286085       0.065714       0.220371
2025-01-07      0.410963       0.152474       0.258489
2025-01-08      0.443292       0.147842       0.295450

由於傳回多欄資料, 故傳回值為一個 DataFrame. 

>>> df.columns  
Index(['Adj Close', 'Close', 'High', 'Low', 'Open', 'Volume', 'MACD_12_26_9',
       'MACDh_12_26_9', 'MACDs_12_26_9'],
      dtype='object')

由於傳入 append=True 參數, 結果會自動加入 df 中, 從 df.columns 可知 df 多了 'MACD_12_26_9', 'MACDh_12_26_9', 'MACDs_12_26_9' 這三個結果欄位, pandas-ta 是以 MACD_{fast}_{slow}_{signal} 格式對欄位命名的, 說明如下 :
  • MACD_12_26_9 : MACD Line (MACD 快速線=12EMA − 26EMA)
  • MACDh_12_26_9 : MACD Histogram (MACD 柱狀圖=MACD − Signal)
  • MACDs_12_26_9 : MACD Signal Line (MACD 訊號線=MACD 的 9 日 EMA)
當快速線向上突破訊號線時為買進訊號; 快速線向下跌破訊號線時為賣出訊號. 
柱狀圖用來觀察市場動能強弱, 柱狀圖由負轉正表示多方動能變強; 柱狀圖由正轉負表示空方動能變強. 訊號線是 MACD 快速線的平滑化版本, 用來確認趨勢是否開始反轉. 

用 kbar 模組繪製 K 線圖 : 

>>> from kbar import KBar    
>>> kb=KBar(df)   
設定字型為: Microsoft JhengHei

呼叫 KBar 物件的 addplot() 方法新增副圖繪製 MACD 曲線 (副圖是從 panel 2 起算), 因為 MACD 由快速線, 訊號線, 與柱狀圖組成, 三個要同時疊在相同 pannel (副圖) 上.

由於 MACD 三條線的欄位名稱不夠直覺, 所以先定義更容易明瞭的變數名稱 :

>>> macd_line_name='MACD_12_26_9'       # 快速線
>>> signal_line_name='MACDs_12_26_9'     # 訊號線
>>> histogram_name='MACDh_12_26_9'      # 柱狀圖

接下來用串列生成式走訪柱狀圖欄位來產生一個串列, 用來設定 MACD 柱狀圖的顏色, 若值 >= 0 設為綠色 ('g'); 否則設為紅色 ('r') : 

>>> histogram_colors=['g' if v >= 0 else 'r' for v in df[histogram_name]]   

設定副圖的 pannel 編號為 2 (成交量副圖若開啟預設佔用 pannel 1) :

>>> macd_panel=2   

這樣便可以在 pannel 2 副圖上疊這三條線, 先呼叫 addplot() 方法新增 MACD 柱狀圖 (注意, 要傳入 type='bar' 指定為柱狀圖) :

>>> kb.addplot(
    df[histogram_name],
    panel=macd_panel,
    type='bar',
    color=histogram_colors,
    alpha=0.4,
    ylabel='MACD' # 設定此副圖的 Y 軸標籤
    )

其次是在 pannel 2 副圖上新增快速線 :

>>> kb.addplot(
    df[macd_line_name],
    panel=macd_panel, # 必須使用與柱狀圖相同的 Panel
    color='fuchsia', # MACD 線顏色
    width=1.0
    )

然後在 pannel 2 副圖上新增快速線 :

>>> kb.addplot(
    df[signal_line_name],
    panel=macd_panel, # 必須使用與柱狀圖相同的 Panel
    color='blue',    # 信號線顏色
    width=1.0
    )

最後, 呼叫 KBar 物件的 plot() 方法繪製 K 線圖並顯示成交量副圖與 5 日均線疊圖 : 

>>> kb.plot(
    volume=True,  # 顯示成交量副圖 (Panel 1)
    mav=(5, 10),  # K 線圖上疊加 5 日和 10 日均線
    title='K 線圖與 MACD 指標'
    )

結果如下 : 



沒有留言 :