2025年12月30日 星期二

[python]計算不定期不定額的年化報酬率

 ## Gemini 解釋 XIRR


對於「不定期不定額」的投資,傳統的 CAGR 公式(只看期初和期末)已經不適用了,因為它無法反映資金進出的時間點對獲利的貢獻。


在金融界,這種情況標準的計算方式是 **XIRR (Internal Rate of Return for a schedule of cash flows)**。它考慮了每一筆資金投入的精確日期,並算出一個等效的年化報酬率。


要在 Python 中計算,最推薦的方式是使用 `pyxirr` 庫,或是手動透過 `scipy` 進行數值求解。


---


### 1. XIRR 的數學原理


XIRR 是在找一個折現率 ,使得所有現金流的現值(Present Value)總和等於零:


$$0 = \sum_{i=1}^{N} \frac{P_i}{(1+r)^{\frac{d_i - d_1}{365}}}$$


* $P_i$:第  筆現金流(投入為負數,領回或當前價值為正數)。

* $d_i$:第  筆現金流發生的日期。

* $d_1$:第一筆投資發生的日期。

* $r$:就是我們要找的年化報酬率 (XIRR)。

* $N$:現金流的總次數


---


### 2. Python 程式碼實作


#### 方法 A:使用 `pyxirr` 庫(最簡單、精準)


這是目前處理 XIRR 最推薦的套件,速度快且支援各種格式。


**安裝:** `pip install pyxirr`


```python

from pyxirr import xirr

from datetime import date


# 定義現金流與日期

# 注意:投入資金設為「負值」,最後一筆「當前市值」或「贖回金額」設為「正值」

dates = [

    date(2023, 1, 1),   # 第一次投入 10,000

    date(2023, 4, 15),  # 第二次投入 5,000

    date(2023, 10, 20), # 第三次投入 8,000

    date(2024, 5, 20)   # 當前日期與帳面總價值 (假設現在值 26,000)

]


amounts = [-10000, -5000, -8000, 26000]


# 計算 XIRR

annual_return = xirr(dates, amounts)


print(f"不定期不定額的年化報酬率 (XIRR) 為: {annual_return:.2%}")


```


---


#### 方法 B:使用 `scipy` 手寫邏輯(不依賴金融庫)


如果你不想安裝額外的金融庫,可以用 `scipy` 的優化器來解方程式。


```python

import numpy as np

from scipy.optimize import newton

from datetime import date


def calculate_xirr(dates, amounts):

    # 將日期轉換為天數差距

    days = [(d - dates[0]).days for d in dates]

    

    # 定義 NPV 函數,我們要求解 NPV = 0 的 r

    def npv(r):

        return sum(amt / (1 + r) ** (d / 365) for amt, d in zip(amounts, days))

    

    # 使用牛頓法求解,初始猜測值設為 0.1 (10%)

    try:

        return newton(npv, 0.1)

    except RuntimeError:

        return None # 無法收斂時回傳 None


# 測試資料

test_dates = [date(2023, 1, 1), date(2023, 6, 1), date(2024, 1, 1)]

test_amounts = [-100, -100, 250] # 投兩次 100,最後拿回 250


result = calculate_xirr(test_dates, test_amounts)

print(f"手動計算結果: {result:.2%}")


```


---


### 3. 寫程式時的注意事項


1. **正負號邏輯:**

* **流出 (投資):** 必須是**負數**。

* **流入 (提領或結餘):** 必須是**正數**。如果你還沒賣掉,最後一筆資料就是「今天的日期」和「當前的總市值」。



2. **現金流排序:** 日期建議由遠到近排序,雖然 `pyxirr` 會自動處理,但手寫邏輯時排序能避免計算錯誤。

3. **多重解問題:** 在極少數現金流劇烈震盪的情況下,XIRR 可能會有數學上的多重解,但對於一般的投資行為,數值解通常很穩定。

沒有留言:

張貼留言