用python计算基金内部收益率-基于scipy科学计算库的数值解
??最近在計算基金內部收益率的時候首先選擇的是用純python編寫的sympy科學計算庫,sympy在計算常微分方程,偏微分方程,一般線性方程組以及取微分、積分、極限等方面依靠其強大的符號體系游刃有余,并且編程語法更簡單易懂,但是當用其求解高階非線性方程的時候就暴露出python運行速度慢的短板,而在求解基金內部收益率的時候往往樣本區間數據量很多,比如本文接下來將要采用的這支基金的數據就有80期。(其實我之前寫完代碼點擊運行之后就去睡覺了,第二天起來仍然沒有算出結果,可以說python面對這種問題從來不耽誤人睡覺休息)
??其實python的numpy庫已經內置了內部收益率計算函數,可以直接調用numpy.irr([NCF],round(n))。(就不要追問我寫這篇博客的意義在哪里了!)接下來本文將會展示調用scipy.optimize最優化函數求內部收益率的高階非線性方程的數值解。
??開始之前,需要介紹一下基金內部收益率(Internal Rate of Return, IRR)的計算方法,基金內部收益率的計算需要用到基金期末、期初的總凈值(Total Net Asset, TNA)和各期現金流(Net Cash Flow, NCF),其計算公式如下:
TNA0(1+IRR)T+∑t=1TNCFt(1+IRR)(T?t)=TNAT(1)TNA_0{(1+IRR)^T}+\sum_{t=1}^TNCF_t{(1+IRR)^{(T-t)}}=TNA_T \tag{1}TNA0?(1+IRR)T+t=1∑T?NCFt?(1+IRR)(T?t)=TNAT?(1)
??其中NCFtNCF_tNCFt?的計算為:
NCFt=TNAt?TNAt?1(1+Rt)(2)NCF_t=TNA_t-TNA_{t-1}(1+R_t)\tag{2}NCFt?=TNAt??TNAt?1?(1+Rt?)(2)
??這里的RtR_tRt?表示的是基金第ttt期的收益率,TNA0TNA_0TNA0?和TNATTNA_TTNAT?分別為基金期初的總資產凈值和期末的總資產凈值。可見利用python的求解內部收益率IRRIRRIRR速度主要就取決于TTT的大小。
??首先,展示本文所使用到的數據,數據已經上傳到百度云盤(提取碼:6whe)。
??導入數據,這里所使用的是基金月度的單月回報RRR和單月總凈值TNATNATNA。
??這里的T=80T=80T=80,當然如果有好奇用sympy求解內部收益率到底是什么情況的小伙伴,在本文末尾我將展示用sympy計算內部收益率的代碼。
?? 按照公式(2)計算出基金各期的凈現金流NCFtNCF_tNCFt?
??Python的科學計算庫scipy的優化器optimize中提供了基于hybrd和hybrj算法的內置函數fsolve,可以求高階的非線性方程的數值解。這里需要設定求解內部收益率的方程,其實就是基于本文的數據按照公式(1)編寫函數
def func(x):function=Fund.TNA[0]*(1+x)**(len(NCF)-1)-Fund.TNA[-1]#len(NCF)包括了NaN空值for i in range(1,len(NCF)): #由于NCF的第一期值為空function+=NCF[i]*(1+x)**(len(NCF)-i-1) #i只能取到(len(NCF)-1)return function??fsolve(func,x0)主要有兩個參數,func為被求解方程,方程的等號右邊為0,左邊就是上面所定義的函數;x0為方程func的初始值,以列表的新式輸入,返回值也為列表形式。將初始值設定為0,求解最終得到基金的內部收益率為-0.00419273。
from scipy.optimize import fsolve root=fsolve(func,[0]) # x的初始值設為0,需要用list的形式輸入 >>>print(root) [-0.00419273]??由于fsolve在優化過程中采用迭代的方式求解非線性方程的數值解,所以我們只得到了一個解,熟悉一元二次拋物線方程的小伙伴都知道這類方程的未知數xxx最高次有幾次就會有多少個解,如果是嚴格按照這種方法求解,我們應該得到80個解,當然其中包括了復數解。求出這80個解其實是沒有必要的,而純python編寫的科學計算庫sympy就可以做到,先附上代碼
import pandas as pd import sympy as sy Fund=pd.read_csv("C:\\Users\\psj\\Desktop\\Fund.csv",index_col="Date",header=0) Fund.index=pd.to_datetime(Fund.index) NCF=Fund.TNA-Fund.TNA.shift(1)*(1+Fund.R) x=sy.symbols("x") f=Fund.TNA[0]*(1+x)**(len(NCF)-1)-Fund.TNA[-1] for j in range(1,len(NCF)):f=f+NCF[j]*(1+x)**(len(NCF)-j-1) result=sy.solve(f,x) print(result)??要得到運行結果可能是很久之后的事情了,當然也不是本人寫的代碼有bug算不出來,當我們把TTT設定為5時,只需要一段小小的等待就能得到方程的全部5個解。
Fund=Fund.iloc[:6,:] NCF=Fund.TNA-Fund.TNA.shift(1)*(1+Fund.R) x=sy.symbols("x") f=Fund.TNA[0]*(1+x)**(len(NCF)-1)-Fund.TNA[-1] for j in range(1,len(NCF)):f=f+NCF[j]*(1+x)**(len(NCF)-j-1) result=sy.solve(f,x) >>>print(result) [-0.00685850972132560, -1.62439354544479 - 0.206726589366808*I, -1.62439354544479 + 0.206726589366808*I, -0.872177199759201 - 0.925545835792086*I, -0.872177199759201 + 0.925545835792086*I]??最后,我們可以發現采用sympy.solve()求解得到的內部收益率只有第一個是實數,其余全部為復數,這在我之前的實踐當中也得到了反復驗證,所以可見采用數值計算是完全合理科學高效的。
總結
以上是生活随笔為你收集整理的用python计算基金内部收益率-基于scipy科学计算库的数值解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pycharm在win7下键盘错乱
- 下一篇: 弹性地基梁板实用计算_YJK软件前处理之