2025年11月30日 星期日

2025 年第 48 周記事

周五下班時遇到樓上張先生, 突然告知社區網路要結束了, 當天已斷網, 我驚訝地問原因, 原來參加的用戶只剩五戶, 應該是入不敷出, 再經營下去會賠錢了. 雖然社區網速不高, 大概只有 30MB, 但看 Netflix 與上網下載都夠用, 且每個月才 250 元而已, 還算堪用啦, 只是偶而路由器故障斷網要等張先生回家處理才行有點小困擾. 替代方案就是用光世代了, 我問中華電信客服目前 100M 優惠價每月 799 元, 下周臨櫃申請安裝.  

申請居家服務到府煮菜後, 我週日上市場購買周一至周五的食材, 固定買魚與三塊豆腐, 以及青菜, 週三下班回鄉下一趟, 主要是煮新的一鍋飯, 並清點冰箱食材, 將周四周五的肉品從冷凍移到冷藏. 小舅周三來菜園遇到我剛好要上班, 說不用跑一趟, 需要青菜或白飯他可以帶過來, 他樓上也有種菜, 但我又不想太麻煩他, 其實一周的中間回一趟老家其實時間也不趕. 

過去一個多月由於事情多都沒去河堤快走, 周四終於有空去運動, 路上遇到一對老夫婦叫住我 (他們可能以前有注意到我幾乎每天會去運動兼餵貓), 問我有沒有看到河堤小咪, 我說已經超過一個月沒來河堤了, 他說河堤小咪好像失蹤了, 都沒看到了, 又說明誠橋這邊的黑貓也被一隻毒蛇咬死了, 所以最近這一帶都沒半隻貓咪. 我走了兩圈呼喚牠果真都沒蹤影, 讓我好失望. 我已經餵牠一年多了, 我去河堤有時並非為了運動 (有時很累或很懶), 而是餵貓. 

自從 10 月官升一級後工作就比較忙了, 本周起已被通知要接第一主管代理人, 之前代理的學長得知我升官訊息後, 迫不及待地向上面要求要卸除第一代理人, 於是我就從第二代理人變成第一代理人了. 批假單是還好啦, 問題是主管不在時我得代理參加各種會議很令我頭疼, 我最討厭開會了. 

今天早上終於看到鄉下的貓婆婆小灰回來了, 自從她女兒毛小妹生了四隻小貓後, 似乎就讓出地盤出外去流浪 (以前幾乎都在家), 只有餓了時才回家吃乾糧. 但最近兩周都沒遇到她, 我以為再也不回來了. 今天看到她時她正要穿過菜園離開, 我叫住她問她要不要吃飯, 她看我去倒乾糧就走回來吃了一陣, 我想到冰箱有已開的貓罐罐, 進去舀了一盤四湯匙出來, 她看了看盤子後就跳下田消失在荒草中. 





傍晚去菜園巡了一下芭樂樹, 發現被小舅修枝過後已開花, 已結出四顆果實, 趕緊將其套袋起來, 我已好久沒吃到芭樂了 :




本周的學習研究放在 pandas-ta 的測試, 覺得此套件比 Ta-Lib 還好上手. 最近與明賢表弟 LINE 聊天時得知他最近在用 Claude Code 開發量化投資軟體, 並勸我放棄用詢問 AI 協作的 coding 方式, 因為時間比較寶貴, 利用 AI 可以快速且專業地完成想做的專案, 我前陣子才把 GitHub Copilot 書籍還回圖書館哩! 但見識到他所展示的成果也認同了他的論點, 唉, 軟體工程真的要走入歷史了 (y資工的前景有點 ...), Vibe coding 讓人人都能當程式員了. 

2025 剩下一個月了, 希望年底前能把 LINE Bot 的學習結束掉. 

2025年11月27日 星期四

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

本篇旨在測試 pandas-ta 套件的趨向指標 DMI (Directional Movement Index) 的 ta.adx() 函式與 df.ta.adx() 方法. 

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



11. 計算 DMI (Directional Movement Index) 指標 :  

DMI 指標是美國著名的技術分析大師 Welles Wilder 在 1978 年出版的 "New Concepts in Technical TRading Systems" 一書中所提出 (他也是 RSI 與 ATR 指標的發明人), 是唯一具有最高價, 最低價, 與收盤價相對關係, 可分開探討多空力道, 完整分析股價波動情形的指標. DMI 的核心概念是透過比較每天最高價與最低價的變動來了解買賣力量誰佔優勢, 能在多空循環中探求價格上升與下降的均衡點, 適時引導投資人進場或出場. 

DMI 由三個主要組件組成, 通常在圖表上以三條線呈現, 摘要整理如下 : 
  • 正向趨向指標 (+DI) : 
    用途 : 衡量多頭力量或向上的壓力 
    意義 : +DI 線上升時表示價格向上移動的強度增加
  • 負向趨向指標 (-DI) :
    用途 : 衡量空頭力量或向下的壓力
    意義 : -DI 線上升表示價格向下移動的強度增加
  • 平均趨向指數 (ADX) :
    用途 : 衡量整體趨勢的強度 (或稱動能方向無關。
    意義 : 這是 DMI 系統中最關鍵的指標. ADX 線上升只表示趨勢 (無論漲跌) 正在變強, ADX 線下降則表示趨勢正在減弱或市場進入盤整. 注意, ADX 只代表趨勢強弱, 不判斷多空方向.
首先計算方向移動 (Directional Movement) +DM 與 -DM, 公式如下 : 

+DM = max(High_today − High_yesterday, 0)
−DM = max(Low_yesterday − Low_today, 0)

若 +DM < −DM 則使用 −DM 
若 −DM < +DM 則使用 +DM 
若同時不成立, 則 +DM 與 −DM 設為 0

其次計算真實波幅 TR (True Range) :

TR = max(
    High_today − Low_today,
    abs(High_today − Close_yesterday),
    abs(Low_today − Close_yesterday)
)

然後用 +DM, -DM, 與 TR 計算方向指標 DI (Directional Indicator) :

 +DI = ( 平滑(+DM) / 平滑(TR) ) × 100
−DI = ( 平滑(−DM) / 平滑(TR) ) × 100

最後計算平均趨向指數 ADX (Average Directional indeX) :

DX = abs(+DI − −DI) / (+DI + −DI) × 100
ADX = DX 的平滑移動平均(常用 14 天)

DMI 指標的 +DI 與 -DI 線的相對位置提供了趨勢方向的交易信號 : 


 +DX 與 -DX 位置  趨勢  交易信號
 +DI > -DI 多頭趨勢 買盤力量佔優,可做多或持有多頭倉位
 -DI > +DI 空頭趨勢 賣盤力量佔優,可做空或持有空頭倉位
 DI 交叉 趨勢發生轉變 +DI 上穿 -DI 為買入;-DI 上穿 +DI 為賣出


DMI 指標的 ADX 線數值用來判斷當前市場狀態並選擇適合的策略 : 


 ADX 值  市場狀態  策略
 ADX > 25 強勢趨勢 適合順勢交易、趨勢追蹤或突破策略
 ADX 介於 20–25 趨勢形成中 (中等強度) 需謹慎確認,趨勢可能正在醞釀
 ADX < 20 弱勢趨勢 (盤整) 避免順勢交易,可使用震盪指標策略


整合 +DX, -DX, 與 ADX 交易信號可得下表之交易策略 : 


 指標訊號  市場狀態  交易策略與建議
+DI 上穿 −DI
(黃金交叉)
ADX > 25 強勢多頭 多頭進場訊號成立, 可偏積極布局, 適合加碼與順勢操作
ADX 介於 20–25 趨勢醞釀 可小量佈局做多, 須等待 ADX 持續上升確認趨勢避免躁進
ADX < 20 弱勢/盤整 不建議進場, 多頭訊號容易失敗, 適合等待突破或震盪策略
−DI 上穿 +DI
(死亡交叉)
ADX > 25 強勢空頭 空頭進場訊號成立, 可做空或減碼持股, 適合追空與破底策略
ADX 介於 20–25 趨勢醞釀 可小量部位做空, 須等 ADX 持續升高確認空頭行情
ADX < 20 弱勢/盤整 不建議追空, 行情可能反覆震盪, 適合區間交易策略


pandas-ta 套件提供 ta.adx() 計算 DMI 指標, 傳回值均為 DataFrame 物件. 下面程式碼利用 yfinance 取得台股 0050 價量資料來計算 DMI 指標, 並於 K 線圖的副圖中繪製 +DI, -DI, 與 ADX 這 3 條曲線 :

# pandas-ta-dmi.py
import yfinance as yf
import pandas_ta as ta
from kbar import KBar
import pandas as pd

#=========================
# 下載資料
#=========================
df=yf.download('0050.TW', start='2024-11-06', end='2025-01-09', auto_adjust=False)
df.columns=df.columns.map(lambda x: x[0] if isinstance(x, tuple) else x) # 欄位單層化

#=========================
# 計算 DMI 系統 (+DI, -DI, ADX)
# pandas-ta 預設 length=14 天
#=========================
# ta.adx() 函數會返回包含 ADX, +DI (DMP), -DI (DMN) 的 DataFrame
dmi_df=ta.adx(
    high=df['High'],
    low=df['Low'],
    close=df['Close'],
    length=14 # 使用預設 14 週期
    )

# 將 DMI 結果合併回主 DataFrame
# 欄位名稱預設為 ADX_14, DMP_14, DMN_14
df=df.join(dmi_df) 

#=========================
# 使用 pandas 創建常數序列模擬水平線 
#=========================
# 創建數值為 20 的常數序列 (用於模擬水平線)
df['HLine_20'] = pd.Series(20, index=df.index)
# 創建數值為 25 的常數序列
df['HLine_25'] = pd.Series(25, index=df.index)

#=========================
# 建 KBar + 繪圖設定
#=========================
kb=KBar(df)

# Panel 2 ➜ DMI 系統
# 繪製 ADX (趨勢強度,通常設為黑色或較粗線)
kb.addplot(df['ADX_14'], panel=2, color='black', width=1.5, ylabel='DMI / ADX')

# 繪製 +DI (多頭力量,綠色)
kb.addplot(df['DMP_14'], panel=2, color='green', width=1.0)

# 繪製 -DI (空頭力量,紅色)
kb.addplot(df['DMN_14'], panel=2, color='red', width=1.0)

# *** 繪製參考線 (使用常數序列) ***
kb.addplot(df['HLine_20'], panel=2, color='gray', linestyle='--', width=0.8)
kb.addplot(df['HLine_25'], panel=2, color='gray', linestyle='--', width=0.8)

#=========================
# 畫圖
#=========================
kb.plot(
    volume=True,      # Panel 1=Volume
    mav=(5, 10),      # K線主圖疊 5 & 10 MA
    title='K 線圖與 DMI (趨向指標) 系統'
    )

結果如下 :




可見 ADX 強度 (左側 Y 軸) 都在 10~12 之間, 遠低於 20, 表示趨勢不明顯, 股價處於盤整狀態, 市場處於弱勢震盪狀態, 交易者應避免使用強勢的趨勢追蹤策略. 

2025年11月26日 星期三

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

本篇旨在測試 pandas-ta 套件的 CO (Chaikin Oscillator, 柴京震盪) 指標與 CMF (Chaikin Money Flow, 柴京資金流) 指標函式 ta.adosc() 與 ta.cmf(). 

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



10. 計算 CO (Chaikin Oscillator) 與 CMF (Chakin Money Flow) 指標 :  

華爾街著名的技術分析師 Marc Chaikin 於 1960~1980 年代陸續發明了 A/D, CMF, 與 CO 等技術指標, 成為技術分析從價格導向轉向成交量導向的領航人物, 其核心理念為 "量先價行" (成交量領先於價格, volume precedes price), 認為在股價大幅波動之前, 通常會先看到主力資金的進出. 

最早將成交量與價格漲跌結合的指標是 Joe Granville 於 1963 年提出的 OBV (能量潮) 指標, 但 OBV 只看當天收盤價是漲還是跌, 卻忽略了當天價格在 "日內波幅" 中的位置 (例如收盤價雖然是漲了, 但如果是收在當天最低點附近的話其實是弱勢). Marc Chaikin 看到了 OBV 的這個缺點, 便於 1966 年提出了 A/D 指標, 用來判斷市場是 "買盤吸收" 還是 "賣壓出貨". 

但是 A/D 是一個累積性指標, 其值沒有固定的上下限, 可以無限增加或減少, 這使其難以進行標準化比較, 無法單憑 A/D 的數值來判斷當前的買盤壓力是強勁還是微弱. 而且 A/D 對短期的價格變化反應緩慢, 它只呈現資金總量是增加還是減少, 無法告訴我們資金流動的動能是否正在加速或減速. 

Marc Chaikin 後來在 A/D 的基礎上提出了 CO 和 CMF 指標用來解決 A/D 指標的局限性, 他引入類似 MACD 的概念, 將 A/D 進行快速與慢速 EMA 差分 (3 日 EMA 減去 10 日 EMA), 提出了 Chaikin Oscillator (CO) 指標, 解決 A/D 缺乏短期動能信號問題, 透過背離可以提前捕捉趨勢的反轉, 從而預測價格趨勢的轉折, 成為一個領先的動能指標. 

另外 Marc Chaikin 還設計了 Chaikin Money Flow (CMF) 指標, 透過將資金流動成交量除以總成交量使 CMF 數值被限制在 +1 到 -1 之間, 解決了 A/D 缺乏標準化與壓力強度衡量的問題, 讓交易者可以設定閾值 (如 +0.25 或 -0.25) 輕鬆判斷機構資金流向的持續性和強勁度. 注意, CMF 並非累加, 而是在固定期間 (例如 20 天或 21 天) 計算資金流入/流出比例, 可用來觀察趨勢轉折和背離. 

不過他提出 CO 和 CMF 的原因並不是要否定 A/D 的價值, 而是將 A/D 的原始資料進行二次加工, 使其具備動能分析 (CO) 和強度分析 (CMF) 的功能, 從而形成一個更全面更具實戰意義的資金流分析體系. 簡言之, A/D 用來計算累積資金流動的總量; CMF 用來測量資金流動的強度 (有界區間震盪指標); 而 CO 則是用來測量 A/D 累積總量的動能 (無界震盪指標). 

CMF 是基於 A/D 加權的流動資金比率, 反映資金在一段期間內的進出強弱, 公式如下 :

先計算出 MFM :

MFM = ((Close − Low) − (High − Close)) / (High − Low)
    = ((Close − Low) / (High − Low) × 2 − 1)

再計算 CMF :

CMF(n) = (∑(MFM × Volume) 過去 n 根) / (∑ Volume 過去 n 根)

CO 為 A/D 指標的 MACD 化振盪版本, 先定義兩條 A/D 移動平均線, 再比較短期與長期 A/D 平滑趨勢差異 : 

先計算 A/D 值 : 

A/D = ∑ (MFM × Volume)

再計算 A/D 的長短期 EMA 後求其差分 :

EMA_s = A/D 的短期 EMA (通常 s = 3)
EMA_l = A/D 的長期 EMA (通常 l = 10)
CHO = EMA_s(A/D) − EMA_l(A/D)

pandas-ta 套件提供 ta.adosc() 與 ta.cmf() 函式分別計算 CO 與 CMF 指標, 傳回值均為 Series 物件. 下面程式碼利用 yfinance 取得台股 0050 價量資料來計算 CO 與 CMF 指標, 並於 K 線圖的副圖中分別繪製這兩條曲線 :

# pandas-ta-co-cmf.py
import yfinance as yf
import pandas_ta as ta
from kbar import KBar

#=========================
# 下載資料
#=========================
df=yf.download('0050.TW', start='2024-11-06', end='2025-01-09', auto_adjust=False)
df.columns=df.columns.map(lambda x: x[0])  # 欄位單層化

#=========================
# 計算 Chaikin Oscillator(CO)
# pandas-ta 預設 fast=3 day, slow=10 day
#=========================
df['CO']=ta.adosc(
    high=df['High'],
    low=df['Low'],
    close=df['Close'],
    volume=df['Volume']
    )

#=========================
# 計算 Chaikin Money Flow(CMF)
# pandas-ta 預設 length=20 天
#=========================
df['CMF']=ta.cmf(
    high=df['High'],
    low=df['Low'],
    close=df['Close'],
    volume=df['Volume']
    )

#=========================
# 建 KBar + 繪圖設定
#=========================
kb=KBar(df)

# Panel 2 ➜ CO(類似 A/D 的 MACD)
kb.addplot(df['CO'], panel=2, color='darkorange', width=1.2, ylabel='CO')

# Panel 3 ➜ CMF(判斷資金多空比)
# 設顏色:>0 用綠、<0 用紅
cmf_colors=['g' if v >= 0 else 'r' for v in df['CMF']]
kb.addplot(df['CMF'], panel=3, type='bar', color=cmf_colors,
           alpha=0.4, ylabel='CMF')

#=========================
# 畫圖
#=========================
kb.plot(
    volume=True,       # Panel 1=Volume
    mav=(5, 10),       # K線主圖疊 5 & 10 MA
    title='K 線圖與 CO, CMF 指標'
    )

結果如下 :




從觀察 CO 和 CMF 曲線變化可知 : 
  • 早期確認信號 :
    12 月上旬時 CO 率先穿越零軸, 發出動能轉強訊號; 隨後 CMF 轉正, 確認累積強度, 證明價格上漲是健康的.
  • 後期警示信號 :  
    2025 年初雖然價格創下新高, 但 CMF 迅速轉負 (表示強度不足), 且 CO 動能快速衰退並轉負 (速度減慢), 兩者同時發出強烈的資金背離警訊, 提示交易者應警惕潛在的回調風險. 
總之, CMF 的核心意義反映某期間多空資金佔比強弱, 表示趨勢偏向多或空; 而 CO 則顯示資金動能是加速或減速, 可用來抓轉折訊號. 

CO 指標的核心在於測量 A/D 線的資金流動動能而非價格動能, 因此它常被視為一個領先指標 (Leading Indicator), 用於提前預測趨勢的轉折. CO 的用法如下 : 
  • 從 0 軸穿越確認趨勢方向 : 
    當 CO 穿越 0 軸由負轉正, 表示買盤動能開始主導, 確認上漲趨勢或反彈, 適合順勢做多; 當 CO 由正轉負表示賣盤動能開始主導, 確認下跌趨勢或回調, 適合減倉或做空. 
  • 從動能背離預測反轉轉折 : 
    價格創新低但 CO 未創新低, 表示資金流出動能已減弱, 預示底部即將反轉, 這是高勝率的買入信號; 當價格創新高但CO 未創新高, 表示資金流入動能已衰竭, 預示頂部即將反轉, 這是高勝率的賣出信號. 
  • 從極值與回歸評估市場情緒 : 
    當 CO 達高點後回落, 表示資金累積動能達到極致, 須需警惕市場超買或動能放緩; 當 CO 達低點後回升, 表示資金派發動能達到極致, 須警惕市場超賣或動能轉強, 要觀察是否出現零軸穿越. 
CO 被認為是最高品質的反轉訊號之一, 當價格創下新高, 但 CO 卻創下更低的波峰, 這不僅是價格動能減弱, 更是實質的機構投資人資金流入動能減弱. 當價格上漲中卻出現 CO 背離, 通常意味著主力資金已經停止追捧或正在派發 (抽離資金). 

2025年11月24日 星期一

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

本篇旨在測試 pandas-ta 套件的 A/D 技術指標函式 ta.ad() 或 df.ta.ad(). 

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



9. 計算 A/D (累積/派發線) 指標 :  

A/D 指標是由 1970 年代至 1980 年代活躍於華爾街的著名技術分析師與資深股票期權交易員 Marc Chaikin (馬克蔡金) 所提出的, 此指標在 OBV 的基礎上加入了用來衡量股價與成交量關係價格的 "位置加權" 以捕捉資金流向, 可用來判斷資金是淨流入 (Accumulation, 累積=資產的買入) 還是淨流出 (Distribution, 派發=資金流出或賣壓), 使量能的判斷更精細, 可提前發現股價可能的反轉或背離. 

傳統的 OBV 指標只看收盤價是上漲或下跌, 然後將全部成交量視為買入或賣出 (贏者全拿), Marc Chaikin 認為應該看收盤價是在價格區間的哪個位置來判定買賣雙方力量最終博弈的結果才對. A/D 指標的核心設計思維就是根據收盤價在該交易日價格區間 (最低價~最高價) 中的位置對當日的成交量進行加權 : 
  • 收盤價越接近高點 : 表示買家在當日價格戰中勝利, 即使價格只微幅上漲, 也應視為強勁的累積 (Accumulation). 
  • 收盤價越接近低點 : 表示賣家在當日價格戰中勝利, 即使價格只微幅下跌, 也應視為強勁的派發 (Distribution). 
這種對成交量的細緻加權處理使 A/D 指標在偵測法人資金是在默默吸收還是釋出籌碼方面比傳統的 OBV 指標更具有參考價值. 

A/D 指標的計算是基於一個值介於 +1 與 -1 之間的 "資金流乘數 (Money Flow Multiplier)", 此乘數用來衡量收盤價相對於當日最高價 (High) 和最低價 (Low) 範圍的位置, 然後用它來乘以當日成交量 (Volume) 並進行累加. 換句話說, A/D 指標是透過收盤價的相對位置來量化買賣雙方力量的勝負, 並按比例將當日成交量加權累計, 這比單純看漲跌更細膩地反映了市場資金的真實動向. A/D 的計算公式如下 :

先計算收盤價位置比率 (Money Flow Multiplier, MFM) : 

MFM = ((Close − Low) − (High − Close)) / (High − Low)
    = ((Close − Low) / (High − Low) × 2 − 1)
  • 若收盤價接近高點 → MFM 接近 +1 → 多頭累積
  • 若收盤價接近低點 → MFM 接近 -1 → 空頭派發
然後計算資金流量 (Money Flow Volume, MFV) 

MFV = MFM × Volume

最後累加 MFV 得到 A/D 線 : 

A/D = ∑ (MFM × Volume)

注意, MFM 的值為 -1~1, 但最後計算出來的 A/D 值域並無邊界, A/D 值的大小無意義 (它取決於計算開始的起始點和標的物的總成交量), 重點是看 A/D 曲線的變化趨勢和方向 : 
  • 上升趨勢 : 代表累積 (買入) 壓力佔上風
  • 下降趨勢 : 代表派發 (賣出) 壓力佔上風
pandas-ta 套件提供 ta.ad() 函式與 df.ta.ad() 方法計算 A/D 指標, 傳回值為累積的 A/D 值組成的 Series 物件. 下面程式碼利用 yfinance 取得台股 0050 價量資料來計算 A/D 指標, 並於 K 線圖的副圖中繪製 A/D 曲線 :

# pandas-ta-ad.py
import yfinance as yf     
import pandas_ta as ta
from kbar import KBar  

# 下載資料
df=yf.download('0050.TW', start='2024-11-06', end='2025-01-09', auto_adjust=False)
df.columns=df.columns.map(lambda x: x[0])

# 計算 A/D 指標
df['AD']=ta.ad(high=df['High'], low=df['Low'], close=df['Close'], volume=df['Volume'])

# 建立 KBar 物件並繪圖
kb=KBar(df)
kb.addplot(df['AD'], panel=2, color='red', width=1.2, ylabel='A/D')
kb.plot(volume=True, mav=(5, 10), title='K 線圖與 A/D 指標')

執行結果 : 




從 11 月底至 12 月的 A/D 線緩慢回升, 顯示底部累積正在發生, 價格可能上漲, 可底部買入. 2025 年初的 A/D 線短暫尖峰後急跌, 顯示在關鍵價位派發壓力的存在, 可能是頂部信號. 

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

本篇旨在測試 pandas-ta 套件的 AOBV (進階能量潮) 技術指標函式 ta.aobv() 或 df.ta.aobv(). 

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



8. 計算 AOBV (進階能量潮) 指標 :  

AOBV 指標 (Accumulation / Distribution OBV, 累積能量潮) 又稱為 Absolute OBV 或 Advanced OBV (進階能量潮),  它是傳統 OBV 指標的改良版, OBV 僅靠收盤價漲跌決定是否加減成交量, 容易忽略 intraday 的多空力量; 而 AOBV 則加入 "價格位置" 資訊, 其計算邏輯比較接近 Chaikin A/D (ADL) 指標 (僅使用收盤價與成交量), 但仍保有 OBV 的累積特性, 使得 AOBV 比 OBV 更敏感反應更快, 適合偵測吸貨/出貨, 主力動向或是否背離等, 比 OBV 更能準確地反映市場內部力量, 對趨勢改變與背離反應更快, 更有 "量先價行" 指標之作用. 

AOBV 指標是 OBV 的進化版本 (OBV 的加權 + 平滑), 但它並非是某個人的個人發明, 而是技術分析界結合量價累積指標 OBV (能量潮) 與 A/D 指標 (吸貨/出貨) 對價格位置的敏感度發展而成的衍生複合指標, 它用更精準的方式分配成交量, 使量能訊號更敏感, 兩者之比較如下表 : 


項目 OBV (On Balance Volume) AOBV (Accumulation OBV)
概念來源 1963 年 Joseph Granville 2000 年後量化圈改良版本
基本精神 成交量依「收盤價漲跌」累加 成交量依「收盤價在區間的位置」分配
判斷依據 今日收盤價比昨日高或低 收盤價在最高價/最低價的相對位置
公式 OBV(n) = OBV(n-1) + Vol
(若 Close > PrevClose)
OBV(n) = OBV(n-1) - Vol
(若 Close < PrevClose)
AOBV = ∑ (MF × Vol)
MF = (Close − Low) − (High − Close)
MF = ((Close − Low) / (High − Low) × 2 − 1)
成交量分配方式 全量加或全量減 依價格位置加部分量或減部分量
訊號敏感度 較不敏感(容易延遲) 較敏感(能提前反映)
缺點 對長上影/下影缺乏反應 易受極端影線干擾,需要平滑
與 ADL 關係 無關,僅用收盤價漲跌 類似 ADL,但為 OBV 版本


AOBV 的核心概念是 : 以 OBV 累積成交量, 但依漲跌幅大小給成交量不同的加權. 

計算步驟如下 : 


(1). 計算今日價格變動比例 :  

R_t = (Close_t − Close_{t−1}) / Close_{t−1}

若收盤價上漲 → R_t > 0 
若收盤價下跌 → R_t < 0
若整理盤 → R_t ≈ 0


(2). 計算加權成交量 :  

WV_t = Volume_t × |R_t|

成交量加上漲跌幅度的權重
漲跌越大 → 權重成交量越大
漲跌越小 → 權重成交量越小


(3). 累計 AOBV 值 :  

若 Close_t > Close_{t−1} : AOBV_t = AOBV_{t−1} + WV_t
若 Close_t < Close_{t−1} : AOBV_t = AOBV_{t−1} − WV_t
若 Close_t = Close_{t−1} : AOBV_t = AOBV_{t−1}

整合上述計算為如下公式 : 

AOBV_t = AOBV_{t−1} + sign(Close_t − Close_{t−1}) × Volume_t × |(Close_t − Close_{t−1}) / Close_{t−1}|

其中 : 

sign(x) = 1  若 x > 0
              −1 若 x < 0
                0 若 x = 0

pandas-ta 套件提供 ta.aobv() 函式與 df.ta.aobv() 方法計算 OBV 指標, 計算結果為 1 或 0. 與 OBV 不同的是, 長短期 AOBV 的值並非累積的成交量, 而是透過收盤價在區間的位置計算量能方向是否支持趨勢, +1 為看多 (量能支持上升); 0 為看空 (量能支持下降).

以下利用 yfinance 取得台股 0050 價量資料來計算 OBV 與 AOBV 指標, 並於 K 線圖的副圖中分別繪製 OBV 與 AOBV 曲線 ( 使用 df.ta.aobv() 也會同時自動產生原始 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])   

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

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

aobv(close, volume, fast=None, slow=None, max_lookback=None, min_lookback=None, mamode=None, offset=None, **kwargs)
    Indicator: Archer On Balance Volume (AOBV)

可見 ta.aobv() 要傳入收盤價與成交量, 其傳回值為一個 DatFrame, 如果是呼叫 df.ta.aobv() 方法, 它會將計算結果自動加入 df 中 :

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

[45 rows x 7 columns]

其中 AOBV_LR_2 與 AOBV_SR_2 即為 AOBV 指標計算結果, 分別為長短期 AOBV 指標, 注意, 它的值只有 0 與 1, 它是將連續的 OBV 累積線轉換為更易於判讀的二元 (Binary) 買賣信號以便於趨勢判斷, 0 代表賣出/趨勢向下 (Sell/Down), 表示該時間框架內的淨累積量趨勢為負向 (即賣盤力量大於買盤); 1 代表買入/趨勢向上 (Buy/Up), 表示該時間框架內的淨累積量趨勢為正向 (即買盤力量大於賣盤). 

檢視 df 欄位 :

>>> df.columns   
Index(['Adj Close', 'Close', 'High', 'Low', 'Open', 'Volume', 'OBV',
       'OBV_min_2', 'OBV_max_2', 'OBVe_4', 'OBVe_12', 'AOBV_LR_2',
       'AOBV_SR_2'],
      dtype='object')

可見 df.ta.aobv() 將計算結果加入 df 中, 新欄位說明如下 :
  • OBV : 原始 On-Balance Volume
  • OBV_min_2 : OBV 最低值 (期間 2 日)
  • OBV_max_2 : OBV 最高值 (期間 2 日)
  • OBVe_4 : 指數平滑 OBV (期間 4 日)
  • OBVe_12 : 指數平滑 OBV (期間 12 日)
  • AOBV_LR_2 : AOBV 長期加權累積量信號 (期間 2 日)
  • AOBV_SR_2 : AOBV 短期加權累積量信號 (期間 2 日)
其中 AOBV_LR_2 為長期 AOBV, 顯示趨勢方向; 而 AOBV_SR_2 為短期 AOBV, 顯示近期資金流入/流出變化, 可用 kbar 套件來繪製 K 線圖, OBV, 與 AOBV 的長短期加權累積量變化 :

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

先在 pannel 2 繪製原始 OBV 曲線副圖 : 

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

然後在 pannel 3 繪製 AOBV 長期 (紅色) 加權累積量線 : 

>>> kb.addplot(
    df['AOBV_LR_2'],
    panel=3,
    color='red',  # AOBV 長期加權累積量線顏色
    width=1.2,
    ylabel='AOBV'    # 設定此副圖的 Y 軸標籤
    )

同樣在 pannel 3 繪製 AOBV 短期 (藍色) 加權累積量線 :

>>> kb.addplot(
    df['AOBV_SR_2'],
    panel=3,
    color='blue',  # AOBV 短期加權累積量線顏色
    width=1.2
    )

呼叫 KBar 物件的 plot() 方法繪製 K 線圖 : 

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

完整程式碼 :

# pandas_ta_aobv.py
import yfinance as yf     
import pandas_ta as ta
from kbar import KBar  

df=yf.download('0050.TW', start='2024-11-06', end='2025-01-09', auto_adjust=False)
df.columns=df.columns.map(lambda x: x[0])
df.ta.aobv(close='Close', append=True)
kb=KBar(df)
kb.addplot(df['OBV'], panel=2, color='red', width=1.2, ylabel='OBV')
kb.addplot(df['AOBV_LR_2'], panel=3, color='red', width=1.2, ylabel='AOBV')
kb.addplot(df['AOBV_SR_2'], panel=3, color='blue', width=1.2)
kb.plot(volume=True, mav=(5, 10), title='K 線圖與 OBV, AOBV 指標')

執行結果 : 




其中 AOBV 藍線 (長期 AOBV, LR) 趨勢變化較慢, 代表較長期的資金累積或趨勢方向, 當藍線變為 1 (上方) 時代表長期資金積累趨勢向上; 變為 0 (下方) 時代表趨勢向下. AOBV 紅線 (短期 AOBV, SR) 趨勢變化較快, 代表較短期的資金累積或市場情緒, 當紅線變為 1 (上方) 時通常代表短期買盤增強; 變為 0 (下方) 時代表短期賣盤增強. 

解讀如下 :
  • 2024-11-06 ~ 2024-11-22 :
    長短期 AOBV 均為 0, 空頭趨勢確認, 長短期資金累積皆為負向, 股價從高點 $50.5 附近開始下跌並盤整於 $48 上下. 
  • 2024-11-25 :
    SR 線從 0 轉 1, 短期買盤出現, 短期資金累積轉正, 股價在低檔 $47.5 附近震盪, 但尚未上漲. 
  • 2024-12-31 :
    LR 線從 0 轉 1, 長期趨勢轉正, 長期資金累積開始轉正, 死叉發生 (SR 回到 0), 但 LR 的轉正顯示長期動能恢復, 股價仍在 $47 附近, 但 OBV 曲線開始築底回升. 
  • 2024-12-11 :
     SR 線轉 1, 短期買盤再次出現, 短期資金積極, 股價從 $47.5 附近開始回升, 進入 $48 左右的盤整區.
  • 2024-12-13 :
    LR 線從 0 轉 1, 長期趨勢再轉正, 長期資金累積轉正, 死叉發生, 股價開始在 $48 上方站穩.
  • 2024-12-20 :
    SR 線轉 1, 短期買盤強勁, 股價小幅拉升, 股價突破 $48.5$.
  • 2024-12-24 :
     LR 線從 0 轉 1, 長期趨勢再轉正, 股價上漲, 股價突破 $49$ 關卡.
  • 2024-12-31 :
    SR 線轉 1, 短期買盤主導, 價格向上嘗試突破, 股價在 $50 附近震盪.
  • 2025-01-06 :
    LR 線轉 1, 強力多頭確認, 隨後幾日 SR 線再次轉 0, 但 LR 線持續為 1, 顯示長期資金累積趨勢非常強勁。股價突破 $50$ 並持續走高, 創下圖中新高. 
總之, 長期訊號 AOBV_LR_2 用來判斷長期量能方向; 而短期訊號 AOBV_SR_2 則是用來判斷短期量能方向, 解讀規則總結如下表 :


 AOBV 指標組合  說明
 LR=1, SR=0 長期多頭,短期整理 → 穩健上升
 LR=0, SR=1 長期空頭,短期反彈 → 短期買點,但整體偏空
 LR=1, SR=1 長短期都偏多 → 強勢多頭
 LR=0, SR=0 長短期都偏空 → 強勢空頭或盤整


2025年11月23日 星期日

PyPI 學習筆記索引

今天將 kbar 套件升版為 v0.1.4 版並上傳 PyPI 網站發佈後, 把關於開發 Python 套件發佈於 PyPI 的筆記做成索引以便查考 :



~進行中~

因為沒有很多時間來寫套件 (通常是為了自己方便不得不寫), 所以整理索引久久用一次時才好恢復記憶. 

2025 年第 47 周記事

上週的寒流讓我鼻子受不了, 過敏打噴嚏好幾天. 本周終於回溫總算好過些了. 今天去全聯看到湯圓已擺出來, 不知不覺就快到年底了. 前陣子聽到樓上同事明年 228 要提早退休, 本來無此打算的我居然有點心動, 但回歸理性後覺得退了不知要幹啥, 還是繼續工作為好. 前陣子爸靜脈曲張手術返家, 我有兩周從鄉下通勤, 發現每天這樣往返城市與鄉下其實也還可以, 晚上七點回到鄉下到就寢還有四個小時, 我反而能專心學習與做研究哩. 

最近兩周忙著兩台樹莓派主機 Pi 400 與 Pi 3A+ 的 Python 執行環境, Pi 400 原先安裝前一代的 Bookworm 作業系統, 因為在 Python 虛擬環境無法匯入套件, 誤以為是內建的 Python 3.11 太舊, 於是改燒錄最新的 Trixie, 結果還是一樣, 與 AI 來回推敲與測試, 才發現是因為安裝的 Streamlit 使用的部分 C extension 與 OS 不相容導致 Python 環境崩潰. Pi 3A+ 則是因 DRAM 容量小效能低, 改燒錄無桌面但效能較好的 Trixie Lite. 

我上個月在露天有兩筆交易踩雷, 一是花了 1000 元買兩個小米 c200 攝影機, 賣家寄來兩個仿小米的中國製爛貨, 我拍照反映要求退換貨, 賣家說會問倉庫寄出貨品, 結果再三催促都回已寄出, 過了快一個月收到露天通知信說此交易將結束, 我馬上跟露天反映此事並要求退貨還錢. 但露天說金流不是經過露天, 但會跟業者反映. 二是不鏽鋼材質腳踏車手機架, 結果收到的是全塑膠製品, 與商品頁照片不符, 也是說可能倉庫寄錯會再補寄, 一個月了還是沒收到. 我常在露天買東西, 經此兩次教訓, 覺得露天比蝦皮還爛, 買家很容易被騙, 向露天投訴基本上沒用, 且因為賣家有交付商品 (雖然是不符的爛貨), 無法構成詐騙, 屬於民事糾紛而已. 我決定以後盡量上 momo 買, 交貨快又有保障. 

K 線圖套件 kbar 升版 v0.1.4

最近在樹莓派 Pi 400 與 Pi 3A+ 的 Trixie 與 Trixie Lite 作業系統上安裝 Python 套件時, 發現我之前寫的 kbar 套件指定所依賴的 numpy 須不高於 1.23 版沒有必要 (pandas 與 matplotlib 也是), 那時不知哪裡得到錯誤訊息 (可能是 ChatGPT), 誤以為此要求來自 mplfinance, 才將 numpy 等版本上限寫進 dependencies 條件裡, 實測發現 mplfinance 在這些依賴套件的最新版中可順利執行, 於是將 kbar 套件升版為 v0.1.4 版 (原本是 v0.1.3, 但這版本號被我上傳 TestPyPI 時用掉了, 只好再跳一號), 主要就是移除 numpy, pandas, 與 matplotlib 的版本上限, 附帶一些與功能無關的小修正. 


更新檔案與發佈上傳程序主要參考第三篇. 


1. 修改 project.toml : 

移除 numpy, pandas, 與 matplotlib 上限, 並於 project.urls 項目下添加 Documentation 參數 URL, 指向 GitHub 上的 README.md 檔, 修改後內容如下 (黃底色為修改或增加部分) :

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "kbar"
version = "0.1.4"
description = "A lightweight K-line (candlestick) plotting tool with matplotlib and mplfinance."
readme = "README.md"
requires-python = ">=3.9"
license = { file = "LICENSE" }
authors = [
  { name = "Tony Y.H. Huang" }
]
keywords = ["finance", "candlestick", "mplfinance", "k-line", "stock"]
classifiers = [
  "Development Status :: 3 - Alpha",
  "Intended Audience :: Developers",
  "Intended Audience :: Financial and Insurance Industry",
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License",
  "Operating System :: OS Independent"
]

dependencies = [
  "numpy>=1.23",
  "pandas>=2.0",
  "matplotlib>=3.7",
  "mplfinance>=0.12.10b0",
  "pyarrow>=14.0.2"
]

[project.optional-dependencies]
dev = [
  "pytest>=8.0",
  "coverage>=7.0"
]

[tool.pytest.ini_options]
addopts = "-v --maxfail=3 --disable-warnings"
testpaths = ["tests"]

[tool.coverage.run]
branch = true
source = ["kbar"]

[tool.coverage.report]
show_missing = true
skip_covered = true

[tool.setuptools.packages.find]
where = ["src"]  

[project.urls]
"Homepage" = "https://github.com/tony1966/kbar/"
"Bug Tracker" = "https://github.com/tony1966/kbar/issues"
"Documentation" = "https://github.com/tony1966/kbar/#readme"



2. 修改 src/kbar/__init__.py : 

添加了 __version__ 參數與前面的套件說明, 這樣匯入套件後就可以用 __version__ 屬性查看版本號 : 

"""
KBar: A lightweight stock candlestick plotting utility with Chinese font auto-detection.
"""

from .kbar import KBar, detect_font

__all__ = ["KBar", "detect_font"]
__version__ = "0.1.4"


3. 新增版本異動記錄檔 CHANGELOG.md : 

用來記錄升版修正與共能異動 :

\# Changelog



All notable changes to this project will be documented in this file.



The format is based on \[Keep a Changelog](https://keepachangelog.com/en/1.0.0/),  

and this project adheres to \[Semantic Versioning](https://semver.org/spec/v2.0.0.html).



---



\## \[0.1.4] - 2025-11-22



\### Changed

\- 移除對 `numpy <2` 的不必要限制(允許使用 `numpy>=1.23`)。

\- 移除對 `pandas <3.0` 的不必要限制(允許使用 `pandas>=2.0`)。

\- 移除對 `matplotlib <4.0` 的不必要限制(允許使用 `matplotlib>=3.7`)。



---



4. 清理專案資料夾 & Build 專案 : 

先將專案資料夾下的下列子目錄刪除 (如果有的話) :
  • __pycache__ : 存放 Python 產生的 bytecode 暫存檔的目錄
  • build : 執行 python -m build 生成的中間建構資料夾
  • dist : 上次打包生成的 wheel 與 sdist
  • *.egg-info : setuptools 生成的套件資訊資料夾 (在 src 資料夾下)
清理完上一版的發佈資料後, 用 tree 指令查看是否如下乾淨 :

D:\PyPi>tree kbar /f  
Folder PATH listing for volume 新增磁碟區
Volume serial number is 1258-16B8
D:\PYPI\KBAR
│   .gitignore
│   CHANGELOG.md
│   LICENSE
│   pyproject.toml
│   README.md
├───src
│   └───kbar
│           kbar.py
│           __init__.py
└───tests
        test_kbar.py
        __init__.py

這樣就可以進入專案資料夾 kbar 用 python -m build 指令打包專案 :

D:\PyPi>cd kbar  
D:\PyPi\kbar>python -m build     
... (略) ...
Copying src\kbar.egg-info to build\bdist.win-amd64\wheel\.\kbar-0.1.4-py3.10.egg-info
running install_scripts
creating build\bdist.win-amd64\wheel\kbar-0.1.4.dist-info\WHEEL
creating 'D:\PyPi\kbar\dist\.tmp-zbsfxpp2\kbar-0.1.4-py3-none-any.whl' and adding 'build\bdist.win-amd64\wheel' to it
adding 'kbar/__init__.py'
adding 'kbar/kbar.py'
adding 'kbar-0.1.4.dist-info/licenses/LICENSE'
adding 'kbar-0.1.4.dist-info/METADATA'
adding 'kbar-0.1.4.dist-info/WHEEL'
adding 'kbar-0.1.4.dist-info/top_level.txt'
adding 'kbar-0.1.4.dist-info/RECORD'
removing build\bdist.win-amd64\wheel
Successfully built kbar-0.1.4.tar.gz and kbar-0.1.4-py3-none-any.whl

這樣就得到 .gz (原始碼) 與 .whl (安裝檔) 這兩個打包後結果了. 

跳回上一層檢視 build 後的檔案目錄結構 :

d:\PyPi\kbar>cd .. 
d:\PyPi>tree kbar /f    
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\PYPI\KBAR
│  .gitignore
│  CHANGELOG.md
│  LICENSE
│  pyproject.toml
│  README.md
├─dist
│      kbar-0.1.4-py3-none-any.whl
│      kbar-0.1.4.tar.gz
├─src
│  ├─kbar
│  │      kbar.py
│  │      __init__.py
│  │
│  └─kbar.egg-info
│          dependency_links.txt
│          PKG-INFO
│          requires.txt
│          SOURCES.txt
│          top_level.txt
└─tests
        test_kbar.py
        __init__.py


5. 安裝 whl 檔進行發佈前測試 : 

先用 pip uninstall kbar 解壓縮之前本機安裝的 kbar, 然後安裝上面打包的 whl 檔 :

d:\PyPi\kbar>pip install dist\kbar-0.1.4-py3-none-any.whl    
Processing d:\pypi\kbar\dist\kbar-0.1.4-py3-none-any.whl
Requirement already satisfied: numpy>=1.23 in c:\users\tony1\appdata\local\programs\python\python312\lib\site-packages (from kbar==0.1.4) (1.26.4)
Requirement already satisfied: pandas>=2.0 in c:\users\tony1\appdata\local\programs\python\python312\lib\site-packages (from kbar==0.1.4) (2.3.1)
Requirement already satisfied: matplotlib>=3.7 in c:\users\tony1\appdata\local\programs\python\python312\lib\site-packages (from kbar==0.1.4) (3.10.5)
Requirement already satisfied: mplfinance>=0.12.10b0 in c:\users\tony1\appdata\local\programs\python\python312\lib\site-packages (from kbar==0.1.4) (0.12.10b0)
... (略) ...
Requirement already satisfied: six>=1.5 in c:\users\tony1\appdata\local\programs\python\python312\lib\site-packages (from python-dateutil>=2.7->matplotlib>=3.7->kbar==0.1.4) (1.16.0)
Installing collected packages: kbar
Successfully installed kbar-0.1.4

進入 REPL 測試 __version__ 屬性 : 

d:\PyPi\kbar>python   
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import kbar   
>>> kbar.__version__   
'0.1.4'

用下列程式測試是否可正常繪製 K 線圖 :

# kbar_test.py
from kbar import KBar   
import yfinance as yf   
df=yf.download('0050.TW', start='2024-07-01', end='2024-08-21', auto_adjust=False)   
df.columns=df.columns.map(lambda x: x[0])    # 改成舊版單層索引
kb=KBar(df)    # 未傳 font 參數預設使用正黑體
kb.plot(title='台灣五十(0050.TW)', volume=True)




功能看來沒問題. 


6. 發佈到 PyPI 升版 : 

利用 twine 套件將專案上傳到 PyPI : 

D:\PyPi\kbar>python -m twine upload dist/*  
Uploading distributions to https://upload.pypi.org/legacy/
Enter your API token:   (按 Ctrl+V 貼上 PyPI API Token 按 Enter )
Uploading kbar-0.1.4-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 17.3/17.3 kB • 00:00 • ?
Uploading kbar-0.1.4.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.2/19.2 kB • 00:00 • ?

View at:

這樣便完成新版 kbar 上傳發佈作業了. 





先用 pip uninstall kbar 解除安裝本機舊版 kbar, 然後重新安裝 kbar :

d:\python\test>pip install kbar   
... (略) ...
Requirement already satisfied: pillow>=8 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib>=3.7->kbar) (11.3.0)
Requirement already satisfied: pyparsing>=2.3.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib>=3.7->kbar) (3.2.3)
Requirement already satisfied: python-dateutil>=2.7 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib>=3.7->kbar) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from pandas>=2.0->kbar) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from pandas>=2.0->kbar) (2025.2)
Requirement already satisfied: six>=1.5 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from python-dateutil>=2.7->matplotlib>=3.7->kbar) (1.17.0)
Downloading kbar-0.1.4-py3-none-any.whl (7.9 kB)
Installing collected packages: kbar
Successfully installed kbar-0.1.4

可見不指定版本預設會從 PyPI 下載最新版 v0.1.4 來安裝, 執行上面的 kbar_test.py :




OK 收工啦! 


2025-11-23 補充 :

我在 Pi 400 安裝 kbar 檢查版本號, 才發現 __init__.py 裡面的 __version__ 屬性忘記改, 還是顯示 0.1.3, 啊! 讓完美主義的我捶心肝 : 

(myenv313) pi@raspberrypi:~ $ pip install kbar   
Collecting kbar
  Downloading kbar-0.1.4-py3-none-any.whl.metadata (6.1 kB)
Requirement already satisfied: numpy>=1.23 in ./myenv313/lib/python3.13/site-packages (from kbar) (2.2.6)
Requirement already satisfied: pandas>=2.0 in ./myenv313/lib/python3.13/site-packages (from kbar) (2.3.3)
... (略) ...
Requirement already satisfied: six>=1.5 in ./myenv313/lib/python3.13/site-packages (from python-dateutil>=2.7->matplotlib>=3.7->kbar) (1.17.0)
Downloading kbar-0.1.4-py3-none-any.whl (7.9 kB)
Downloading pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl (45.0 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 45.0/45.0 MB 641.4 kB/s eta 0:00:00
Installing collected packages: pyarrow, kbar
Successfully installed kbar-0.1.4 pyarrow-22.0.0
(myenv313) pi@raspberrypi:~ $ python   
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import kbar  
>>> kbar.__version__   
'0.1.3'  

算了, 就當作是小 Bug 吧! 反正 v0.1.4 其實就是 v0.1.3, 只是因為 TestPyPI 佔了版本號而已. 

2025年11月22日 星期六

如何清理樹莓派垃圾

忙了兩周, 今天終於搞定 Pi 400 與 Pi 3A+ 兩台樹莓派主機 Python 虛擬環境的套件安裝, 過程雖是一波三折, 但我也從中獲益良多. 過程中可能產生的垃圾有哪些? 要如何刪除? 


1. 清空 pip cache : 

(myenv313) pi@raspberrypi:~ $ pip cache purge   
Files removed: 1018 (348.1 MB)


2. 清理 /tmp : 

(myenv313) pi@raspberrypi:~ $ deactivate   
pi@raspberrypi:~ $ sudo rm -rf /tmp/*   


3. 清理系統 build 依賴暫存檔 :

pi@raspberrypi:~ $ sudo apt clean   
pi@raspberrypi:~ $ sudo apt autoremove   

Python 學習筆記 : 如何重建 venv 虛擬環境

最近在兩台樹莓派主機 Pi 400 與 Pi 3A+ 上的 Python 執行環境安裝套件, 因為樹莓派 OS 自 Bookworm 之後不允許在系統的 Python 環境下用 pip install 安裝套件, 必須先建立虛擬環境, 再進入虛擬環境下用 pip install 安裝套件. 如果虛擬環境不需要了, 只要將其資料夾直接移除即可, 

下面以刪除虛擬環境 myenv313 後重建為例說明 :

先跳出虛擬環境 : 

(myenv313) pi@raspberrypi:~ $ deactivate   

用 rm -rf  指令刪除虛擬目錄資料夾 : 
 
pi@raspberrypi:~ $ rm -rf ~/myenv313   

用 ls 指令確認已刪除 : 

pi@raspberrypi:~ $ ls -ls myenv313   
ls: 無法存取 'myenv313': 沒有此一檔案或目錄

重建同名虛擬目錄 : 

pi@raspberrypi:~ $ python3 -m venv ~/myenv313  

啟動虛擬目錄 : 

pi@raspberrypi:~ $ source ~/myenv313/bin/activate   

用 pip list 檢視套件列表, 應該只有 pip 才對 : 

(myenv313) pi@raspberrypi:~ $ pip list  
Package Version
------- -------
pip     25.1.1

檢查 Python 執行檔路徑, 應該是在虛擬目錄的 bin 下面 : 

(myenv313) pi@raspberrypi:~ $ which python  
which pip   
/home/pi/myenv313/bin/python
/home/pi/myenv313/bin/pip

在安裝套件之前, 先清除 pip 快取, 避免 pip 從舊快取安裝可能有問題的 wheel : 

(myenv313) pi@raspberrypi:~ $ pip cache purge   
Files removed: 1875 (960.1 MB)
(myenv313) pi@raspberrypi:~ $ 

這樣就可以開始在虛擬目錄下用 pip 安裝套件了. 
 

在樹莓派新版 OS (Trixie) 上安裝 Python 套件的方法

這幾天在 Pi 400 的樹莓派 OS Trixie 上測試 Python 程式, 得知從 Bookworm 版本開始, Raspberry Pi OS 就遵循 PEP 668 限制, 禁止在系統 Python 安裝第三方套件, 必須建立虛擬環境去安裝, 然後進入虛擬環境執行 Python 程式. 如果在系統環境只能使用預載的套件 (例如 requests) : 

pi@raspberrypi:~ $ python   
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd    # pandas 不是系統預載套件
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    import pandas as pd
ModuleNotFoundError: No module named 'pandas'
>>> import requests      # requests 是系統預載套件
>>> 

我以為建立虛擬套件並在其內安裝好第三方套件即可, 但實測發現套件雖然順利安裝, 但是匯入時卻出現 "無效指令" 並跳出 Python 互動環境 : 

pi@raspberrypi:~ $ source myenv/bin/activate   
(myenv) pi@raspberrypi:~ $ python  
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yfinance as yf   
無效指令
(myenv) pi@raspberrypi:~ $

詢問 ChatGPT 答覆說可能是這些套件不支援 Python 3.13, 叫我安裝較舊的 Python, 我就比照一切跑得順順的 LG Gram 筆電, 下載編譯安裝 Python 3.10.14, 參考 :


然後建立虛擬環境安裝套件, 例如 yfinance, 但是問題仍然存在 :

pi@raspberrypi:~ $ source myenv310/bin/activate 
(myenv310) pi@raspberrypi:~ $ python   
Python 3.10.14 (main, Nov 19 2025, 21:45:00) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yfinance as yf  
無效指令
(myenv310) pi@raspberrypi:~ $ 

今天與 ChatGPT 進一步討論這問題, 它這時才提到說可能是缺少開發套件與編譯依賴, 有些套件例如 pandas, numpy, pandas-ta, 與 yfinance 等不是純 Python, 而是 C extension/Cython 編譯的套件, 需要在安裝時編譯 .so 檔, 且編譯過程依賴 libffi, zlib, readline, ncurses, 與 sqlite3 等系統套件, 如果這些依賴沒有安裝, pip 會在安裝時編譯失敗或跳過某些 C module, 套件雖然安裝完成, 但 import 時會因為 C extension 不存在或無法載入, Python REPL 就會出現 "無效指令" 而不是丟 exception. 

總之, 在虛擬環境中安裝套件之前, 還必須用 apt 安裝下表套件 (不早一點說, 害我白花時間去下載編譯安裝 Python 3.10) :


 套件  用途
 build-essential  安裝 GCC 與編譯器工具,用於編譯 Python 擴充套件
 libssl-dev  支援 HTTPS、SSL、Python 的 ssl 模組
 zlib1g-dev  支援壓縮功能,啟用 gzip、zipfile 等模組
 libncurses5-dev / libncursesw5-dev  提供互動終端介面支援(如 Python 互動輸入、編輯器)
 libreadline-dev  支援 command line 操作時的輸入、歷史紀錄
 libffi-dev  讓 Python 的 ctypes 和 cffi 模組正常工作
 libsqlite3-dev  支援 Python 內建 sqlite3 資料庫模組
 libbz2-dev  bz2 壓縮支援,啟用 Python 的 bz2 模組
 liblzma-dev  LZMA 壓縮支援,啟用 Python 的 lzma 模組(例如 tar.xz)
 libgdbm-dev  支援 Python shelve / dbm 資料儲存模組
 libdb-dev  支援 Berkeley DB,啟用 dbm 模組
 libexpat1-dev  支援 XML parsing,啟用 Python 的 xml parser 模組
 libmpdec-dev  支援 decimal 模組的高精度數學運算
 tk-dev  啟用 tkinter GUI 支援(可視介面)
 uuid-dev  支援 Python 的 uuid 模組,用於生成唯一識別碼


所以, 其實系統的 Python 3.13 必須先用 apt 安裝這些套件後, 再建立虛擬環境來安裝第三方套件, 這樣 pandas 等依賴 C extension 的套件才能正常匯入使用, 先更新套件清單 :

sudo apt update
sudo apt upgrade -y

然後執行下列指令即可 :  

sudo apt install -y python3.13-venv python3.13-dev build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libffi-dev libsqlite3-dev libbz2-dev wget curl llvm

安裝完成後建立一個虛擬環境 myenv313 : 

pi@raspberrypi:~ $ python3.13 -m venv ~/myenv313 

進入虛擬環境 : 

pi@raspberrypi:~ $ source myenv313/bin/activate   

然後在此虛擬環境下安裝套件 :


1. 資料科學基礎套件 : 

pip install numpy==2.2.6
pip install pandas
pip install scipy
pip install matplotlib
pip install seaborn
pip install bokeh
pip install plotly
pip install scikit-learn

註 : 因 pandas-ta 0.4.71b 依賴 numpy 2.2.6, 故先行指定此版本. 


2. 深度學習框架 : 

pip install torch torchvision torchaudio


3. Web UI : 

pip install django
pip install streamlit  
pip install gradio

註 : streamlit 依賴許多 C extension, 與樹莓派 Trixie 的 Python 3.13 部分不相容, 會導致 Python 執行環境崩潰, 勿安裝. 


4. 爬蟲 : 

pip install html5lib
pip install selenium
pip install scrapy


5. 量化投資 : 

pip install yfinance
pip install twstock
pip install mplfinance
pip install ta
pip install kbar
pip install backtrader
pip install pyfolio-reloaded


6. Bot 套件 : 

pip install line-bot-sdk
pip install python-telegram-bot


7. LLM 套件 : 

pip install openai
pip install google-generativeai


8. 開發工具 : 

pip install jupyterlab


安裝完後測試看看能否正常匯入套件 : 

pi@raspberrypi:~ $ source ~myenv313/bin/activate
(myenv313) pi@raspberrypi:~ $ python   
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yfinance as yf  
>>> yf.__version__ 
'0.2.66'
>>> import pandas_ta as ta  
>>> ta.version   
'0.4.71b0'

可見 pandas-ta 已經是最新版 0.4.71b 了. 

回顧之前在 Bookworm 上遇到的無法匯入已安裝好的第三方套件問題, 其原因也是如此, 沒有先安裝 C extension/Cython 開發套件與編譯依賴就直接在虛擬環境下用 pip 安裝套件, 貌似順利安裝完成, 但其實過程中找不到 C extension 依賴檔就跳過, 誤以為安裝成功所致. 既然在最新版的 Trixie 上已找到問題原因並解決了, 那也沒必要回去用 Bookworm 啦. 

如果要用 Thonny 開發 Python 應用, 須至 "工具/選項/直譯器" 選單中, 設定 Python 直譯器為 :

home/pi/myenv313/bin/python

2025年11月19日 星期三

樹莓派 Pi 400 Rapberry PI OS (Trixie) 安裝 Python 3.10

昨天將 Pi 400 的 Rapberry PI OS (Bookworm) TF 卡換成最新版的 Trixie, 原以為在內建的 Python 3.13 環境下, pandas-ta 等套件的問題就可解決, 但結果卻出乎意料地糟, 舊問題不僅沒解決, 反而因為 Python 版本太新, 某些套件 (例如 Seaborn 與 pandas-ta) 一匯入就讓 Python 3.13 崩潰而跳出 (exit code -4) , 其他套件像 matplotlib 則無問題 :




詢問 ChatGPT, 說可能是因為在 Python 3.13 + ARM64 上的 Seaborn 或其依賴套件不穩定, 導致在某些 API 呼叫中觸發 numpy 或 pandas 的 C extension 崩潰. AI 建議安裝較低版本的 Python, 考慮我的 LG Gram 筆電跑 Python 3.10 安裝各種套件都用得很順 (除了 pandas-ta 須安裝較舊的版本), 所以就叫 ChatGPT 幫我寫了一個一鍵安裝 Python 3.10 的 shell 程式 : 

pi@raspberrypi:~ $ nano install-py310.sh  

#!/bin/bash
set -e

echo "Updating system..."
sudo apt update
sudo apt install -y \
    build-essential checkinstall \
    libreadline-dev libncursesw5-dev libssl-dev \
    libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev \
    libffi-dev zlib1g-dev liblzma-dev libnss3-dev wget

echo "Download Python 3.10.14 source..."
cd /usr/src
sudo wget https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz
sudo tar xzf Python-3.10.14.tgz
cd Python-3.10.14

echo "Configuring, this may take some time..."
sudo ./configure --enable-optimizations --with-ensurepip=install

echo "Compiling (use all cores)..."
sudo make -j$(nproc)

echo "Installing Python 3.10 (without replacing system python)..."
sudo make altinstall

echo "Done! Installed python3.10 and pip3.10"
python3.10 --version
pip3.10 --version

先用 chmod 指令更改權限為可執行 : 

pi@raspberrypi:~ $ chmod +x install-py310.sh   

執行此 shell 程式安裝 Python 3.10 (編譯安裝約需 20 分鐘) :

pi@raspberrypi:~ $ ./install-py310.sh 

... (略) ...
Done! Installed python3.10 and pip3.10
Python 3.10.14
pip 23.0.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)

這樣就完成 Python 3.10 的安裝了, 其執行指令是 python3.10 : 

pi@raspberrypi:~ $ ls /usr/local/bin/python*   
/usr/local/bin/python3.10  /usr/local/bin/python3.10-config   

自己編譯安裝的 Python 放在 /usr/local/bin 下, 系統內建的則是放在 /usr/bin 下 :

pi@raspberrypi:~ $ ls /usr/bin/python*  
/usr/bin/python   /usr/bin/python3.13         /usr/bin/python3-config
/usr/bin/python3  /usr/bin/python3.13-config  /usr/bin/python-dotenv

用 python3.10 指令建立一個虛擬環境 myenv310 :

pi@raspberrypi:~ $ python3.10 -m venv myenv310  
pi@raspberrypi:~ $ source myenv310/bin/activate   
(myenv310) pi@raspberrypi:~ $ python  
Python 3.10.14 (main, Nov 19 2025, 21:45:00) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

檢視儲存空間 : 

(myenv310) pi@raspberrypi:~ $ df -h   
檔案系統        容量  已用  可用 已用% 掛載點
udev            1.6G     0  1.6G    0% /dev
tmpfs           760M  9.5M  750M    2% /run
/dev/mmcblk0p2   59G   12G   44G   21% /
tmpfs           1.9G  488K  1.9G    1% /dev/shm
tmpfs           5.0M   12K  5.0M    1% /run/lock
tmpfs           1.0M     0  1.0M    0% /run/credentials/systemd-journald.service
tmpfs           1.9G   14M  1.9G    1% /tmp
/dev/mmcblk0p1  510M  103M  408M   21% /boot/firmware
tmpfs           380M   88K  380M    1% /run/user/1000
tmpfs           1.0M     0  1.0M    0% /run/credentials/getty@tty1.service

安裝 Python 3.10 之前是 45GB, 可見 Python 3.10 用掉約 1GB. 

接下來在 Python 3.10 虛擬環境安裝工作所需的套件 :  


1. 資料科學基礎套件 : 

pip install numpy==1.26.4   (mplfinance 要求)
pip install pandas
pip install scipy
pip install matplotlib
pip install seaborn
pip install bokeh
pip install plotly
pip install altair
pip install scikit-learn

注意, 為了避免安裝 kbar 時刪除最新的 numpy, 重新下載編譯 numpy 1.26.4 版耗費時間, 此處直接指定安裝 numpy 1.26.4 版. 


2. 深度學習框架 : 

pip install torch torchvision torchaudio


3. Web UI : 

pip install django
pip install streamlit
pip install gradio


4. 爬蟲 : 

pip install html5lib
pip install selenium
pip install scrapy


5. 量化投資 : 

pip install yfinance
pip install twstock
pip install mplfinance
pip install ta
pip install kbar
pip install backtrader
pip install pyfolio-reloaded


6. Bot 套件 : 

pip install line-bot-sdk
pip install python-telegram-bot


7. LLM 套件 : 

pip install openai
pip install google-generativeai


8. 開發工具 : 

pip install jupyterlab

最後安裝 pandas-ta, 因 PyPi 上是要求 Python >= 3.12 的最新版 0.4.71b, 所以要從 Source Forge 下載支援 Python 3.10 的 pandas-ta 0.3.14b 版 Python 原始碼自行 build 為 whl 檔後安裝 : 


參考 : 


先建立 Python 3.10 的虛擬環境 : 

pi@raspberrypi:~ $ python3.10 -m venv myenv310   
pi@raspberrypi:~ $ source myenv310/bin/activate   
(myenv310) pi@raspberrypi:~ $ 

將下載的 zip 檔解壓縮, 把原始碼資料夾更名為 pandas-ta-0.3.14b 後進去此資料夾 :

(myenv310) pi@raspberrypi:~/ cd 下載  
(myenv310) pi@raspberrypi:~/下載 $ cd pandas-ta-0.3.14b   

先安裝 build 套件 : 

(myenv310) pi@raspberrypi:~/下載/pandas-ta-0.3.14b $ pip install build  
Collecting build
  Downloading build-1.3.0-py3-none-any.whl.metadata (5.6 kB)
Requirement already satisfied: packaging>=19.1 in /home/pi/myenv310/lib/python3.10/site-packages (from build) (25.0)
Collecting pyproject_hooks (from build)
  Downloading pyproject_hooks-1.2.0-py3-none-any.whl.metadata (1.3 kB)
Requirement already satisfied: tomli>=1.1.0 in /home/pi/myenv310/lib/python3.10/site-packages (from build) (2.3.0)
Downloading build-1.3.0-py3-none-any.whl (23 kB)
Downloading pyproject_hooks-1.2.0-py3-none-any.whl (10 kB)
Installing collected packages: pyproject_hooks, build
Successfully installed build-1.3.0 pyproject_hooks-1.2.0

執行 python -m build : 

(myenv310) pi@raspberrypi:~/下載/pandas-ta-0.3.14b $ python -m build    
... (略) ...

build 完成後進入 dist 子資料夾 :

(myenv310) pi@raspberrypi:~/下載/pandas-ta-0.3.14b $ cd dist  
(myenv310) pi@raspberrypi:~/下載/pandas-ta-0.3.14b/dist $ ls -ls     
總用量 360
216 -rw-rw-r-- 1 pi pi 219862 11月 20 00:34 pandas_ta-0.3.14b0-py3-none-any.whl   
144 -rw-rw-r-- 1 pi pi 144836 11月 20 00:34 pandas_ta-0.3.14b0.tar.gz

可見已建立 whl 檔, 用 pip 安裝即可 : 

(myenv310) pi@raspberrypi:~/下載/pandas-ta-0.3.14b/dist $ pip install pandas_ta-0.3.14b0-py3-none-any.whl
Processing ./pandas_ta-0.3.14b0-py3-none-any.whl
Requirement already satisfied: pandas in /home/pi/myenv310/lib/python3.10/site-packages (from pandas-ta==0.3.14b0) (2.3.3)
Requirement already satisfied: numpy>=1.22.4 in /home/pi/myenv310/lib/python3.10/site-packages (from pandas->pandas-ta==0.3.14b0) (1.26.4)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/pi/myenv310/lib/python3.10/site-packages (from pandas->pandas-ta==0.3.14b0) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /home/pi/myenv310/lib/python3.10/site-packages (from pandas->pandas-ta==0.3.14b0) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /home/pi/myenv310/lib/python3.10/site-packages (from pandas->pandas-ta==0.3.14b0) (2025.2)
Requirement already satisfied: six>=1.5 in /home/pi/myenv310/lib/python3.10/site-packages (from python-dateutil>=2.8.2->pandas->pandas-ta==0.3.14b0) (1.17.0)
Installing collected packages: pandas-ta
Successfully installed pandas-ta-0.3.14b0

進入 Python 互動環境 : 

(myenv310) pi@raspberrypi:~ $ python   
Python 3.10.14 (main, Nov 19 2025, 21:45:00) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas_ta as ta  
>>> ta.version   
'0.3.14b0'

可見 pandas-ta 已可正常運行

檢視儲存空間 : 

(myenv310) pi@raspberrypi:~ $ df -h  
檔案系統        容量  已用  可用 已用% 掛載點
udev            1.6G     0  1.6G    0% /dev
tmpfs           760M  9.5M  750M    2% /run
/dev/mmcblk0p2   59G   14G   42G   25% /
tmpfs           1.9G  488K  1.9G    1% /dev/shm
tmpfs           5.0M   12K  5.0M    1% /run/lock
tmpfs           1.0M     0  1.0M    0% /run/credentials/systemd-journald.service
tmpfs           1.9G   16M  1.9G    1% /tmp
/dev/mmcblk0p1  510M  103M  408M   21% /boot/firmware
tmpfs           380M   88K  380M    1% /run/user/1000
tmpfs           1.0M     0  1.0M    0% /run/credentials/getty@tty1.service

可見安裝 Python 套件用掉約 2GB 空間. 

如果使用 Thonny 開發測試, 因它預設的解譯器是系統的 Python 3.13, 而我們上面安裝的套件都在 Python 3.10 的虛擬環境 myenv310 下, 直接匯入這些套件都會 not found, 必須將解譯器更改為 myenv310 下的 python3.10 才行, 按 "工具" 選單點選 "選項" :





切到 "直譯器" 頁籤, 按 Python 可執行檔右邊的三個小點按鈕, 點選 /hom/pi/myenv310/bin 下面的 python3.10 按確認即可 :



這樣 Thonny 就會用 Python 3.10 虛擬環境去執行 Python 程式了. 至於之前建立的 Python 3.13 虛擬環境 myenv 與裡面所安裝的套件就留著, 等未來那些套件支援 Python 3.13 時再下載更新. 


2025-11-21 補充 :

安裝完所有套件後測試, 發現問題還是一樣, 出現 "無效指令" 後跳出 Python :

pi@raspberrypi:~ $ source myenv310/bin/activate  
(myenv310) pi@raspberrypi:~ $ python   
Python 3.10.14 (main, Nov 19 2025, 21:45:00) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas_ta as ta   
無效指令
(myenv310) pi@raspberrypi:~ $