終值:Excel、Matlab 和 Numpy Financial 中的函式在周期數較大時不起作用
未來價值函式及其預期行為
Excel 的函式
FV(rate, nper, pmt, pv)
根據定期、固定付款和固定利率計算投資的未來價值。FV 應該是 = -pv 如果 pmt =-pv * rate ; 把它想像成只支付貸款的利息:現值為 100,利率為 10%,您每期支付 10,無論期數如何,終值為 -100。即您只支付了利息但不攤銷一分錢。
例如
FV(0.1,10,-10,100) = -100 FV(0.1,20,-10,100) = -100 FV(0.1,300,-10,100) = -100
Excel中的錯誤
但是,如果 nper(週期數)高於 300ish,則結果沒有意義。
nper = 320 --> FV =-100.25 nper = 350 --> FV = -104 nper = 390 --> FV = 256 nper = 400 --> FV = 0
Python 的 numpy_financial 中的相同錯誤
我在 Python 的numpy 財務包中註意到了類似的行為(請參閱此錯誤報告):
conda install -c conda-forge numpy-financial npf.fv(0.1,200,-10,100) --> -100.0 npf.fv(0.1,300,-10,100) --> -100.03125 npf.fv(0.1,380,-10,100) --> -128.0 npf.fv(0.1,400,-10,100) --> 0
Matlab中的相同錯誤
我沒有安裝 Matlab,但是,從 Matlab Financial Toolbox 的文件網站,可以測試執行函式 fvfix 來計算未來值;當週期數 > 300 時,該函式的行為也很奇怪:
fvfix(0.1,400,-10,100) = 3584
不知道 R 的包
我試圖安裝 R 的 FinCal 包,但我無法讓它工作 - 顯然我必須編譯它並且不知道如何。
我的問題
- 為什麼會這樣?
- 這是一個已知的錯誤嗎?
- 大多數金融圖書館都會發生這種情況嗎?例如,在 R、Matlab 等中怎麼樣?
- 推薦的解決方案是什麼?Excel 和 Python 中是否有更可靠的函式/庫?
- 有這方面的任何文件嗎?除了連結的 Python 錯誤報告之外,我找不到任何東西,但我肯定不會是第一個遇到這個問題的人嗎?此外,在大多數這些軟體包中,財務功能往往相互依賴,因此未來價值計算中的錯誤也會影響其他財務功能
到目前為止我所了解的
這些公式計算
(1 + rate ) ^ nper
;我想問題的出現是因為當 nper 很大時,結果可能超過軟體允許的最大精度?例如 1.1^400 = 3.6e16 Excel 只能儲存 15 位有效數字。
這不是錯誤,只是電腦的工作方式。不過在非金融論壇上提問會更好。它被稱為(整數)溢出。如果你喜歡閱讀幽默聊天,你可以看看這裡。
您可以在大多數文件中找到解釋。Numpy很有趣,因為 Python 沒有這個問題。
我認為可以公平地說作者沒想到有人會在金融領域使用如此長的時間。畢竟,從長遠來看,我們都死了。
編輯:
我今天工作時遇到了一個有點相關的問題,因此更詳細地研究了這個問題。您在這裡遇到的問題比我最初假設的要微妙(已解釋)。在這裡,您遇到的不僅是溢出,還有浮點數學。在二進制(或以 2 為底)中,只有分母以 2 作為質因數的分數才能乾淨地表示為小數。
- 例如:1/2, 1/4, 1/8 都會被清晰地表達出來
- 而 1/5 或 1/10 在電腦使用的 base-2 系統中重複小數(它們在我們的 base-10 系統中是小數)
我建議閱讀David Goldberg 的 What Every Computer Scientist Should Know About Floating-Point Arithmetic,了解更多詳細資訊。
長話短說,程式語言將右除運算符
/
表示為浮點結果。julia> 0.1 + 0.2 0.30000000000000004
或等效地,
julia> 0.1 + 0.2 == 0.3 false
所以,
julia> i = 0.1 for N = 20:20:500 println(10*(BigFloat(1+i)^N-1)/i-(100*(BigFloat(1+i))^N)) end
可能更重要的是,有理數作為浮點數的不精確表示會變得越來越有問題,因為上述函式中的指數越大(如在第一個螢幕截圖中可以清楚地看到)。
幸運的是,像 Julia 這樣的一些程式語言也提供有理數類型來表示整數的精確比率。設置 i = 1//10 我們得到以下結果(預期結果):
julia> i = 1//10 for N = 20:20:500 println(10*(BigFloat(1+i)^N-1)/i-(100*(BigFloat(1+i))^N)) end
例如,使用 Python 會有點混亂(據我所知)。 例如, Sympy和分數模組提供有理數。但是,這些可能會溢出,並且bigfloat包要求您在 pip 安裝 bigfloat 之前在系統上安裝 C 庫GMP和MPFR 。根據文件,評論中提到的
mpmath
包使用二進制算術;請參閱稱為小數問題的部分。我簡單地嘗試在 mpmath 中混合 sympy 有理數和分數,但它似乎並不能防止溢出(我懷疑是因為實際的分數和 sympy 實現溢出。最後但並非最不重要的一點是,該問題有一個指向numpy “錯誤報告”的連結,使用者在其中寫道 Julia 的環繞行為讓他感到驚訝。使用本機機器整數運算是經過深思熟慮的選擇,它允許LLVM 編譯器優化“基本”整數算法的機器程式碼,這也意味著 Int 值的範圍是有界的,並且在兩端環繞,以便加法、減法和乘法整數可以溢出或下溢(這是機器程式碼的工作方式)。對於任何感興趣的人,Julia 的文件在常見問題解答部分中對此選擇提供了詳盡的解釋。
電腦程序正在評估以下表達式:
$ FV(i,N,PMT,PV)=-PMT[\frac{(1+i)^N-1}{i}]-PV(1+i)^N $
您正在執行的測試案例是您選擇的特殊情況 $ PMT=-i\cdot PV $
如果我們以符號方式(而不是數字方式)評估公式,我們會幸運地取消:
$ FV(i,N,-i \cdot PV,PV)= PV(1+i)^N-PV(1+i)^N-PV=-PV $
麻煩的術語 $ (1+i)^N $ 與大 $ N $ 完全消失。
但是,有時會發生,數值評估不遵循普通數學規則,並且出現問題。取消並沒有完全發生。
(誠然,這並沒有增加已經說過的內容)。