## 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 可能會有數學上的多重解,但對於一般的投資行為,數值解通常很穩定。
沒有留言:
張貼留言