2025年11月17日 星期一

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

本篇旨在測試 pandas-ta 套件的 OBV 技術指標函式 ta.obv() 或 df.ta.obv(). 

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



8. 計算 OBV (能量潮) 指標 :  

OBV 是 Joe Granville 在 1963 年提出的一個量價關係指標, 結合收盤價與成交量來衡量市場買賣力道和趨勢動能, 依據收盤價漲跌或持平累積計算成交量而得到 OBV 值, 計算原理如下 :
  • 收盤價上漲 (今日收盤 > 昨日收盤) : 今日成交量加到 OBV
  • 收盤價下跌 (今日收盤 < 昨日收盤) : 今日成交量從 OBV 扣除
  • 收盤價持平 : OBV 不變
OBV 指標的核心概念為 "量先價行", 認為成交量的變化通常會領先於價格的變化, OBV 透過累積計算成交量來研判市場資金的流向和聚集趨勢, 從而推測股價未來可能的走向, 關鍵在於觀察其走勢方向與價格走勢是配合或背離, 可判斷市場趨勢的潛在反轉訊號. 

pandas-ta 套件提供 ta.obv() 函式計算 OBV 指標, 以下利用 yfinance 取得台股 0050 價量資料來計算 OBV 指標, 並於 K 線圖的副圖中繪製 OBV 曲線. 

首先匯入 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

為了取值與繪製 K 線圖, 須將 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.obv) 檢視 OBV 指標的參數結構 : 

>>> help(ta.obv)   
Help on function obv in module pandas_ta.volume.obv:

obv(close, volume, talib=None, offset=None, **kwargs)
    On Balance Volume (OBV)
    
    On Balance Volume is a cumulative indicator to measure buying and selling
    pressure.
    
    Sources:
        https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
        https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
        https://www.motivewave.com/studies/on_balance_volume.htm
    
    Calculation:
        signed_volume = signed_series(close, initial=1) * volume
        obv = signed_volume.cumsum()
    
    Args:
        close (pd.Series): Series of 'close's
        volume (pd.Series): Series of 'volume's
        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:
        fillna (value, optional): pd.DataFrame.fillna(value)
        fill_method (value, optional): Type of fill method
    
    Returns:
        pd.Series: New feature generated.

可見 ta.obv() 有兩個必要參數 : close (收盤價) 與 volume (成交量), 呼叫 df.ta.obv() 並指定 close='Close' 指定未還原權值收盤價進行計算, 這是因為 df 有 Adj Close 與 Close 兩個欄位, 為避免 pandas-ta 自動抓欄位時抓到 Adj Close, 故明確指定, volume 則不用特別指定 : 

>>> df.ta.obv(close='Close', append=True)   
Date
2024-11-06     66825504.0
2024-11-07    120819712.0
2024-11-08    172620316.0
2024-11-11    222076368.0
2024-11-12    116988020.0
2024-11-13     80209660.0
2024-11-14     31623200.0
2024-11-15     61165524.0
2024-11-18      7587460.0
2024-11-19     38060744.0
2024-11-20     37748744.0
2024-11-21    -25757724.0
2024-11-22      6104624.0
2024-11-25    -25202028.0
2024-11-26    -70765316.0
2024-11-27   -127056060.0
2024-11-28   -179492516.0
2024-11-29   -146979636.0
2024-12-02   -104803324.0
2024-12-03    -64990900.0
2024-12-04    -39169904.0
2024-12-05     -9385092.0
2024-12-06    -36623116.0
2024-12-09    -18063660.0
2024-12-10    -35972888.0
2024-12-11    -62831644.0
2024-12-12    -42722680.0
2024-12-13    -24640972.0
2024-12-16      4733396.0
2024-12-17     41910312.0
2024-12-18     41910312.0
2024-12-19    -10269876.0
2024-12-20    -54763452.0
2024-12-23    -10059188.0
2024-12-24     22724420.0
2024-12-25     46348912.0
2024-12-26     27134668.0
2024-12-27     55084336.0
2024-12-30     20375272.0
2024-12-31    -10970864.0
2025-01-02    -62161672.0
2025-01-03    -33708188.0
2025-01-06     64802984.0
2025-01-07    128578360.0
2025-01-08     81155492.0
Name: OBV, dtype: float64

因為計算結果為單欄資料, 故 df.ta.obv() 傳回值為 Series 物件, 此傳回值因 append=True 會被自動加入 df 中, 欄位名稱為 OBV :

>>> df.columns   
Index(['Adj Close', 'Close', 'High', 'Low', 'Open', 'Volume', 'OBV'], dtype='object')
>>> df  
            Adj Close      Close       High  ...       Open     Volume          OBV
Date                                         ...                                   
2024-11-06  47.797909  48.799999  49.512501  ...  48.512501   66825504   66825504.0
2024-11-07  48.348858  49.362499  49.512501  ...  48.724998   53994208  120819712.0
2024-11-08  48.728401  49.750000  50.000000  ...  49.849998   51800604  172620316.0
2024-11-11  48.752892  49.775002  49.775002  ...  49.712502   49456052  222076368.0
2024-11-12  47.504074  48.500000  48.962502  ...  48.799999  105088348  116988020.0
2024-11-13  47.197987  48.187500  48.500000  ...  48.462502   36778360   80209660.0
2024-11-14  46.769474  47.750000  48.125000  ...  48.075001   48586460   31623200.0
2024-11-15  47.100044  48.087502  48.212502  ...  48.012501   29542324   61165524.0
2024-11-18  46.438900  47.412498  47.924999  ...  47.862499   53578064    7587460.0
2024-11-19  47.075554  48.062500  48.237499  ...  47.674999   30473284   38060744.0
2024-11-20  46.879662  47.862499  47.862499  ...  47.862499     312000   37748744.0
2024-11-21  46.365444  47.337502  47.537498  ...  47.500000   63506468  -25757724.0
2024-11-22  47.271446  48.262501  48.299999  ...  47.775002   31862348    6104624.0
2024-11-25  47.100044  48.087502  48.687500  ...  48.674999   31306652  -25202028.0
2024-11-26  46.487877  47.462502  47.575001  ...  47.525002   45563288  -70765316.0
2024-11-27  45.814495  46.775002  47.362499  ...  47.287498   56290744 -127056060.0
2024-11-28  45.741032  46.700001  46.775002  ...  46.750000   52436456 -179492516.0
2024-11-29  45.851223  46.812500  47.000000  ...  46.237499   32512880 -146979636.0
2024-12-02  46.940880  47.924999  47.924999  ...  47.125000   42176312 -104803324.0
2024-12-03  47.577534  48.575001  48.712502  ...  48.575001   39812424  -64990900.0
2024-12-04  47.859127  48.862499  48.862499  ...  48.674999   25820996  -39169904.0
2024-12-05  48.116238  49.125000  49.150002  ...  48.937500   29784812   -9385092.0
2024-12-06  47.932587  48.937500  49.174999  ...  49.125000   27238024  -36623116.0
2024-12-09  47.993805  49.000000  49.062500  ...  49.037498   18559456  -18063660.0
2024-12-10  47.650993  48.650002  49.112499  ...  48.937500   17909228  -35972888.0
2024-12-11  47.234715  48.224998  48.562500  ...  48.250000   26858756  -62831644.0
2024-12-12  47.785667  48.787498  48.937500  ...  48.724998   20108964  -42722680.0
2024-12-13  47.822399  48.825001  48.900002  ...  48.662498   18081708  -24640972.0
2024-12-16  48.018291  49.025002  49.412498  ...  49.250000   29374368    4733396.0
2024-12-17  48.263161  49.275002  49.512501  ...  49.275002   37176916   41910312.0
2024-12-18  48.263161  49.275002  49.462502  ...  49.200001   26215508   41910312.0
2024-12-19  47.602016  48.599998  48.700001  ...  48.587502   52180188  -10269876.0
2024-12-20  47.161259  48.150002  48.437500  ...  48.437500   44493576  -54763452.0
2024-12-23  48.299889  49.312500  49.325001  ...  48.674999   44704264  -10059188.0
2024-12-24  48.434566  49.450001  49.775002  ...  49.625000   32783608   22724420.0
2024-12-25  48.581482  49.599998  49.625000  ...  49.625000   23624492   46348912.0
2024-12-26  48.544750  49.562500  49.625000  ...  49.599998   19214244   27134668.0
2024-12-27  48.703915  49.724998  49.762501  ...  49.400002   27949668   55084336.0
2024-12-30  48.434566  49.450001  49.662498  ...  49.537498   34709064   20375272.0
2024-12-31  47.932587  48.937500  49.224998  ...  49.174999   31346136  -10970864.0
2025-01-02  47.516315  48.512501  48.912498  ...  48.912498   51190808  -62161672.0
2025-01-03  47.993805  49.000000  49.237499  ...  49.000000   28453484  -33708188.0
2025-01-06  49.499729  50.537498  50.575001  ...  49.662498   98511172   64802984.0
2025-01-07  50.050682  51.099998  51.500000  ...  51.237499   63775376  128578360.0
2025-01-08  49.303841  50.337502  50.837502  ...  50.662498   47422868   81155492.0

[45 rows x 7 columns]

用 kbar 模組繪製 K 線圖, 並且在 pannel=2 副圖繪製 OBV 曲線 : 

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

呼叫 KBar 物件的 addplot() 方法新增副圖繪製 OBV 曲線 (副圖是從 panel 2 起算) :

>>> kb.addplot(
    df['OBV'],
    panel=2,
    color='red',  # OBV 線顏色
    width=1.2,
    ylabel='OBV'    # 設定此副圖的 Y 軸標籤
    )

呼叫 plot() 繪製 K 線圖 : 

>>> kb.plot(
    volume=True,  # 顯示成交量 (預設占用 Panel=1)
    mav=(5, 10),  # 主圖加均線
    title='K 線圖與 OBV 指標'
    )
使用指定字型: Microsoft JhengHei
字型候選清單: ['Microsoft JhengHei', 'DejaVu Sans', 'Arial']

結果如下 :




OBV 是累積值, 觀察 OBV 主要看趨勢而不是每一天的變化大小 : 
  • OBV 是否與股價同向 (趨勢確認)
  • OBV 是否早於股價突破 (量先價行)
OBV 曲線的判讀核心在於觀察它與股價趨勢的同步性或背離性 :


OBV 走勢 股價走勢 市場意義 訊號解讀
持續上升 同步上漲 資金持續流入,買盤積極且強勁 上漲趨勢確認 (趨勢穩固)
持續下降 同步下跌 資金持續流出,賣壓沉重且強勁 下跌趨勢確認 (趨勢穩固)
盤整整理 橫盤整理 買賣力量相對均衡。 觀望或等待突破


沒有留言 :