【手把手教你】Python金融財務分析

微信公眾號:CuteHand
關注可了解更多的金融與Python干貨。問題或建議,請公眾號留言;
如果你覺得CuteHand對你有幫助,歡迎贊賞Thanks?(?ω?)?

1. 貨幣時間價值

實際上numpy和scipy很強大,包含了計算各種財務指標的函數,可以直接調用,終值(fv)、現(xiàn)值(pv)、凈現(xiàn)值(npv)、每期支付金額(pmt)、內部收益率(irr)、修正內部收益率(mirr)、定期付款期數(nper)、利率(rate)等等。
PV=\frac{C}{(1+r)^n} ,F(xiàn)V=C*(1+r)^n
其中,PV為現(xiàn)值,F(xiàn)V為終值;C為現(xiàn)金流,r貼現(xiàn)率,n期限。

2. 年金計算

在n個時期內,每個時期可以獲得等額現(xiàn)金流PMT,利率為r,以下是考試筆算時的公式:

  • 普通年金現(xiàn)值:PV(annuity)=\frac{PMT}{r}\left[1-\frac{1}{(1+r)^n}\right]

  • 普通年金終值:FV(annuity)=\frac{PMT}{r}\left[(1+r)^n-1\right]

  • 永續(xù)債券現(xiàn)值:
    PV(perpetuity)=\frac{c}{r}
    其中,c為未來每期可以獲得的現(xiàn)金收入,g是c的固定增長率。
    PV(perpetuity)=\frac{c}{r-g}

年金計算比較簡單,相當于等比數列求和。

#自定義計算一系列現(xiàn)金流現(xiàn)值(如年金)的函數
def pv_f(c,r,n,when=1):
    '''
    c代表每期現(xiàn)金流,可以每期不一樣,如c=[100,90,80,120]
    r貼現(xiàn)率,也可以每期不一樣,如相應的,r=[2%,3%,2%,4%]
    n為期數
    when=1表示期末計數,默認,即普通年金
    when=0表示期初計數,即預付年金
    '''
    import numpy as np  #導入numpy庫
    c=np.array(c)       
    r=np.array(r) 
    if when==1:
        n=np.arange(1,n+1)
    else:
        n=np.arange(0,n)
    pv=c/(1+r)**n
    return pv.sum()
  • 應用實例1: 有個五年的普通年金年金,每年可獲得20000元,假設貼現(xiàn)率為5%,現(xiàn)值是多少?
    擴展:如果是預付年金呢?
c=20000
r=0.05
n=5
#調用前文定義的函數pv_f(c,r,n,when=1)
pv1=pv_f(c,r,n,when=1)
print("普通年金現(xiàn)值(年末):%.2f"% pv1)
#如果是預付年金,則when=0
pv2=pv_f(c,r,n,when=0)
print("預付年金現(xiàn)值(年初):%.2f" % pv2)
普通年金現(xiàn)值(年末):86589.53
預付年金現(xiàn)值(年初):90919.01
#使用上2.年金計算公式驗證下我們自定義函數是否正確
pv1=20000/0.05*(1-1/(1+0.05)**5)
print("使用計算公式計算(年末):{:.2f}" .format(pv1))
pv2=20000/0.05*(1-1/(1+0.05)**5)*(1+0.05)
print("使用計算公式計算(年初):{:.2f}" .format(pv2))
#使用numpy自帶函數驗證
import numpy as np
print("numpy自帶公式計算(年末):{:.2f}".format(np.pv(r,5,-c),when=0))
print("numpy自帶公式計算(年初):{:.2f}".format(np.pv(r,5,-c,when=1))) 
#結果一致
使用計算公式計算(年末):86589.53
使用計算公式計算(年初):90919.01
numpy自帶公式計算(年末):86589.53
numpy自帶公式計算(年初):90919.01
  • 如果要計算一系列現(xiàn)金流的終值呢?
#自定義終值函數
def fv_f(c,r,n,when=1):
    import numpy as np  
    c=np.array(c)     
    r=np.array(r)      
    if when==1:
        n=sorted(np.arange(0,n),reverse=True) #注意n與pv里的n不一樣
    else:
        n=sorted(np.arange(1,n+1),reverse=True)
    fv=c*(1+r)**n
    return fv.sum()

#可以將二者合成一個函數,直接輸出現(xiàn)值和終值
def pv_fv(c,r,n,when=1,fv=0): 
    '''
    c,r,n參數同上;
    when用來判斷期初還是期末現(xiàn)金流,默認期末
    fv判斷求現(xiàn)值還是終值,默認是現(xiàn)值
    '''
    import numpy as np  
    c=np.array(c)     
    r=np.array(r) 
    if fv==0:
        if when==1:
            n=np.arange(1,n+1)
        else:
            n=np.arange(n)
        pv=c/(1+r)**n
        return pv.sum()
    else:
        if when==1:
            n=sorted(np.arange(0,n),reverse=True) 
        else:
            n=sorted(np.arange(1,n+1),reverse=True)
        fv=c*(1+r)**n
        return fv.sum()
  • 應用實例2:未來五年年末分別收到100、200、300、100、500元,每年貼現(xiàn)率分別為4%、5%、6%、8%和10%,求現(xiàn)值和終值。
c=[100,200,300,100,500]
r=[0.04,0.05,0.06,0.08,0.10]
n=5
pv1=pv_f(c,r,n)    #默認when=1可不寫
pv2=pv_fv(c,r,n)   #默認when=1,fv=0,
fv1=fv_f(c,r,n)    #統(tǒng)一函數下
fv2=pv_fv(c,r,n,fv=1) #統(tǒng)一函數下
print("現(xiàn)值:%.2f元; %.2f元" % (pv1,pv2)) 
print("終值:%.2f元; %.2f元" % (fv1,fv2)) 
現(xiàn)值:913.41元; 913.41元
終值:1293.59元; 1293.59元
  • 已知現(xiàn)值或終值,利率和時期,求每期支出或收入現(xiàn)金流呢?
#定義一個計算每期現(xiàn)金流的函數
def pmt(r,n,pv=0,fv=0,when=1):
    import numpy as np
    pv=np.array(pv)
    fv=np.array(fv)
    r=np.array(r)
    if fv==0:
        if when==1:
            n=np.arange(1,(n+1))
        else:
            n=np.arange(n)
        pv_pmt=pv/(1/(1+r)**n).sum()
        return pv_pmt
    
    else:
        if when==1:
            n=sorted(np.arange(0,n),reverse=True) 
        else:
            n=sorted(np.arange(1,n+1),reverse=True)
        fv_pmt=fv/((1+r)**n).sum()  #知道終值求每期現(xiàn)金流
        return fv_pmt
  • 應用實例3:假設向某銀行貸款200萬元買房,貸款利率5.0%,按月還款,30年還清本息,請問每月應該還多少錢?
pv=2000000
r=0.05/12  
n=30*12
pmt1=pmt(r,n,pv)  #套用上面公式
#numpy自帶公式計算
pmt2=np.pmt(r,n,pv,fv=0,when='end') 
print("自定義函數計算:%.2f元" % pmt1)
print("numpy自帶公式計算:%.2f元"% pmt2)  #負號代表現(xiàn)金流支出
自定義函數計算:10736.43元
numpy自帶公式計算:-10736.43元
  • 應用實例3擴展:假設計息利率調整一次,前15年利率保持5%,后15年利率上調到6%??梢岳斫鉃椋杭僭O前15年每月按照10736元還款,后15年如果利率上升到6%,應該每月還多少?
c0=10736
n0=n1=15*12
r0=0.05/12
r1=0.07/12
pv0=pv_f(c0,r0,n0)   #每月還10736,還15現(xiàn)值
pv1=pv-pv0           #還完15年后剩余還款現(xiàn)值
pv2=pv1*(1+0.05)**15 #轉化成15年后的終值
pmt1=pmt(r1,n1,pv2)  #以6%利率接著還剩下的15年
print("后15年每年應還款金額:%.2f元" % pmt1)
后15年每年應還款金額:12003.44
  • 應用實例4:假設計劃15年后要給小孩準備一筆300萬元的留學資金,投資收益率為8%,請問從現(xiàn)在開始每月需要投入多少錢?
fv=3000000
r=0.08/12
n=15*12
#使用自定義公式
pmt1=pmt(r,n,fv=fv,when=0)
#使用numpy自帶公式
pmt2=np.pmt(r,n,pv=0,fv=fv,when='begin')  
print("自定義函數計算:%.2f元" % pmt1)
print("numpy自帶公式計算:%.2f元"% pmt2)  
#可見如果每年投資收益率可以達到8%,
#每月只需投資8612.15元,15年后就可以收到300萬元啦
#問題是普通工人大眾很難持續(xù)獲得8%/年的投資收益率,
#一般是放銀行定期,5年以上5%以內
pmt3=pmt(0.05/12,n,fv=fv,when=0)
#每月投資支出增加
p=(pmt3-pmt1)/pmt1
print("假設利率為5%情況:{0:.2f}元,
每月支出增加比例:{1:.2f} %".format(pmt3,p*100))
#如果考慮通貨膨脹,實際也沒多少收益率了
自定義函數計算:8612.15元
numpy自帶公式計算:-8612.15元
假設利率為5%情況:11177.24元,每月支出增加比例:29.78 %

3. 實際利率

EAR=\left[1+\frac{APR}{m}\right]^m-1
其中,EAR為實際年利率(effective annual rate);AP為名義年利率(Annual Percentage Rate);m是一年內復利的頻率。
R_{m_2}^{effective}=\left(1+\frac{APR_1}{m_1}\right)^{\frac{m_1}{m_2}}-1

  • 連續(xù)復利(Continuously compounded interest rate)
    R_c=m*\ln \left(1+\frac{APR}{m} \right)

知識回顧
名義利率與實際利率跟通脹率對應的名義利率不同。實際利率是什么呢?

  • 情景一:年初存入銀行100塊錢,銀行承諾利率12%。于是年末能拿到112塊錢。這里的12塊錢就是利息,12%就是實際利率。
  • 情景二:年初存入銀行100塊錢,銀行承諾利率12%。聰明的人發(fā)現(xiàn)一個漏洞(假設半年就是12%/2),銀行承諾12%,也就是半年利率可記為6%。然后當存入100塊半年后,取出來106塊錢,接著轉身去另一個柜員處存入106塊半年,期末將得106*(1+6%)=112.36白白多得3毛6。這里的實際利率就是12.36%。
  • 情景三:年初存入銀行100塊錢,銀行承諾利率12%。更加聰明的人把100塊錢存取了三次,就是100*(1+4%)^3=112.4864比聰明的人還多得1毛2分6厘4。此時的實際利率是12.4864%。

【這里銀行承諾的就是名義利率,而實際所得的是實際利率。(當然現(xiàn)實生活中的商業(yè)銀行會把半年利率調低,而不是單純的用一年的利率除以期數。)而后面兩種情景的計息方式為 復利。俗稱利滾利。不要以為利滾利就能滾上天,有一個條件限制住了它,叫名義利率。隨著存取次數的不斷增加,每一個期數內的利率也在逐漸減小?,F(xiàn)在把計息次數擴大到∞,實際利率就變成了(1+12%/∞)∞,而這玩意計算出來就是e12%。這就是所謂的連續(xù)復利?!?/p>

4. 項目投資分析

金融財務分析里關于項目投資分析判斷的方法有很多,比較常用的有凈現(xiàn)值、回收期、內部收益率法等。

  • 凈現(xiàn)值法 (Net present value,NPV)
    NPV=PV(收入)-PV(成本)

項目投資NPV法判斷依據:
\left\{ \begin{array}{lr} If\ NPV(項目)>0 \ 接受 & \\ If\ NPV(項目)<0 \ 拒絕 & \end{array} \right.

def npv_f(rate,cashflows):
    total=0.0
    for i, cashflow in enumerate(cashflows):
        total+=cashflow/(1+rate)**i
    return total
    #if total > 0.0:
    #    print("凈現(xiàn)值為%.2f,值得投資" % total)
    #else:
    #    print("凈現(xiàn)值為%.2f,不值得投資" % total)
  • 回收期法(Payback period)

\left\{ \begin{array}{lr} If\ Payback(項目)<T_{基準} \ 接受 & \\ If\ Payback(項目)>T_{基準} \ 拒絕 & \end{array}\right.

與凈現(xiàn)值法相比,優(yōu)點是簡單易懂,缺點:

  • 不考慮時間價值

  • 基準回收期的確定比較主觀

  • 內部收益率法(IRR)
    IRR:使得凈現(xiàn)值為0的貼現(xiàn)率。

\left\{ \begin{array}{lr} If\ IRR(項目)>R_{基準} \ 接受 & \\ If\ IRR(項目)<R_{基準} \ 拒絕 & \end{array}\right.

def IRR_f(cashflows,interations=10000):
    rate=1.0
    investment=cashflows[0]
    for i in range(1,interations+1):
        rate*=(1-npv_f(rate,cashflows)/investment)
    return rate
  • 應用實例5:假設貼現(xiàn)率為5%,有A、B兩個項目,前期均需投入120萬, A項目第一年至五年分別收入10、30、50、40、10萬,而項目B第一至五年分別收入30、40、40、20、10萬,項目A和B哪個投資價值高?
#分析:如果光從金額看都是投資120萬元,回報都是140萬元,
#從回收期法來看,二者都是在第四年才收回成本
#但由于貨幣的時間價值,下面從凈現(xiàn)值的角度進行分析
r=0.05
C_A=[-120, 10, 30, 50, 40, 10]
C_B=[-120, 30, 40, 40, 20, 10]
npv_A=npv_f(r,C_A)
npv_B=npv_f(r,C_B)
print("項目A的凈現(xiàn)值:%.2f萬元" % npv_A)
print("項目B的凈現(xiàn)值:%.2f萬元" % npv_B)
項目A的凈現(xiàn)值:0.67萬元
項目B的凈現(xiàn)值:3.70萬元
#內部收益率法比較
irr_A=IRR_f(C_A,interations=10000)
irr_B=IRR_f(C_B,interations=10000)
print("項目A的內部收益率:%.2f%%" % (irr_A*100))
print("項目B的內部收益率:%.2f%%" % (irr_B*100))
項目A的內部收益率:5.19%
項目B的內部收益率:6.28%

NPV與IRR比較

  • NPV:優(yōu)點:計算相對簡便易懂,結果直觀,容易理解;局限性:沒有消除初始投資額不同的差異,也沒有消除投資項目期限的差異。

  • IRR:優(yōu)點:跟NPV比較消除了初始投資額不同和項目投資期限的差異,直觀反映項目本身的報酬率;缺點是計算量大,可能存在多解或無解。

  • 凈現(xiàn)值和內部收益率適用范圍不同,凈現(xiàn)值適用于互斥方案間的擇優(yōu),而內部收益率用于獨立方案間的擇優(yōu)。

  • 應用實例6:有項目C、D,一次性投入均為100萬元,其中,C項目前六年無現(xiàn)金流入,第7年現(xiàn)金流入200萬;D項目前六年每年現(xiàn)金流入12萬,最后一年現(xiàn)金流入112萬,選擇哪個?

C=[-100,0,0,0,0,0,200]
D=[-100,12,12,12,12,12,112]
irr_C=IRR_f(C)*100
irr_D=IRR_f(D)*100
print("內部收益率:C項目{0:.0f}%,D項目{1:.0f}%" .format(irr_C,irr_D))
print("凈現(xiàn)值:C項目{0:.2f}萬元,D項目{1:.2f}萬元".format(npv_f(0.1,C),
                                             npv_f(0.1,D)))
#請問你會選哪一個呢?
內部收益率:C項目12%,D項目12%
凈現(xiàn)值:C項目12.89萬元,D項目8.71萬元
#應用實例6擴展1
E=[-100,90,50,0,0,10]
F=[-100,0,0,0,0,350]
irr_E=IRR_f(E)*100
irr_F=IRR_f(F)*100
print("內部收益率:E項目{0:.0f}%,F項目{1:.0f}%" .format(irr_E,irr_F))
print("凈現(xiàn)值:E項目{0:.2f}萬元,F(xiàn)項目{1:.2f}萬元".format(npv_f(0.1,E),
                                             npv_f(0.1,F)))
#你又會選哪一個呢?
內部收益率:E項目31%,F項目28%
凈現(xiàn)值:E項目29.35萬元,F(xiàn)項目117.32萬元
#應用實例6擴展2
G=[-100,90,50,0,0,10]
H=[-150,0,50,50,50,150]
irr_G=IRR_f(E)*100
irr_H=IRR_f(F)*100
print("內部收益率:G項目{0:.0f}%,H項目{1:.0f}%".format(irr_G,irr_H))
print("凈現(xiàn)值:G項目{0:.2f}萬元,H項目{1:.2f}萬元".format(npv_f(0.1,G),
                                             npv_f(0.1,H)))
#你又會選哪一個呢?
內部收益率:G項目31%,H項目20%
凈現(xiàn)值:G項目29.35萬元,H項目56.18萬元

5. 單利與復利增長

#單利和復利
import numpy as np
%matplotlib inline
from matplotlib import pyplot as plt
#解決中文亂碼
from pylab import mpl  
mpl.rcParams['font.sans-serif'] = ['SimHei'] 

pv=1000
r=0.08
n=10
t=np.linspace(0,n,n)
y1=np.ones(len(t))*pv  
y2=pv*(1+r*t)
y3=pv*(1+r)**t
plt.figure(figsize=(10,8))
plt.title('單利和復利')
plt.xlabel('年')
plt.ylabel('終值')
plt.xlim(0,11)
plt.ylim(800,2200)
plt.plot(t,y1,'b-')
plt.plot(t,y2,'g--')
plt.plot(t,y3,'r-')

關于CuteHand

能告訴你每天星座運勢,查天氣、附近酒店、股票行情,講笑話、小故事,聊天互動聊天,不定期分享原創(chuàng)經濟金融干貨,手把手教你使用Python做金融數據分析。分享知識,點亮智慧 ,歡迎關注CuteHand,一起學習,一起進步!


精彩回顧



最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370