1. 程式人生 > >【手把手教你】Python金融財務分析

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

內容來自:微信公眾號:python金融量化
關注可瞭解更多的金融與Python乾貨。

內容目錄

  1. 貨幣時間價值
  2. 年金計算
  3. 實際利率
  4. 專案投資分析
  5. 單利與複利增長
    關於CuteHand

1. 貨幣時間價值

實際上numpy和scipy很強大,包含了計算各種財務指標的函式,可以直接呼叫,終值(fv)、現值(pv)、淨現值(npv)、每期支付金額(pmt)、內部收益率(irr)、修正內部收益率(mirr)、定期付款期數(nper)、利率(rate)等等。
在這裡插入圖片描述

其中,PV為現值,FV為終值;C為現金流,r貼現率,n期限。

2. 年金計算

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

普通年金現值:
在這裡插入圖片描述

普通年金終值:
在這裡插入圖片描述

永續債券現值:
在這裡插入圖片描述

其中,c為未來每期可以獲得的現金收入,g是c的固定增長率。
在這裡插入圖片描述

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

#自定義計算一系列現金流現值(如年金)的函式
def pv_f(c,r,n,when=1):
    '''
    c代表每期現金流,可以每期不一樣,
    如c=[100,90,80,120],
    r貼現率,也可以每期不一樣,如相應的,
    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元,假設貼現率為5%,現值是多少?
擴充套件:如果是預付年金呢?

c=20000
r=0.05
n=5
#呼叫前文定義的函式pv_f(c,r,n,when=1)
pv1=pv_f(c,r,n,when=1)
print("普通年金現值(年末):%.2f"% pv1)
#如果是預付年金,則when=0
pv2=pv_f(c,r,n,when=0)
print("預付年金現值(年初):%.2f" % pv2)
普通年金現值(年末):86589.53
預付年金現值(年初):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

如果要計算一系列現金流的終值呢?

#自定義終值函式
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()

#可以將二者合成一個函式,直接輸出現值和終值
def pv_fv(c,r,n,when=1,fv=0): 
    '''
    c,r,n引數同上;
    when用來判斷期初還是期末現金流,預設期末
    fv判斷求現值還是終值,預設是現值
    '''
    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元,每年貼現率分別為4%、5%、6%、8%和10%,求現值和終值。

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)    #統一函式下
fv2=pv_fv(c,r,n,fv=1) #統一函式下
print("現值:%.2f元; %.2f元" % (pv1,pv2)) 
print("終值:%.2f元; %.2f元" % (fv1,fv2)) 
現值:913.41元; 913.41元
終值:1293.59元; 1293.59元

已知現值或終值,利率和時期,求每期支出或收入現金流呢?

#定義一個計算每期現金流的函式
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()  
            #知道終值求每期現金流
        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)  
#負號代表現金流支出
自定義函式計算:10736.43元
numpy自帶公式計算:-10736.43元

應用例項3擴充套件:假設計息利率調整一次,前15年利率保持5%,後15年利率上調到6%。可以理解為:假設前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現值
pv1=pv-pv0           #還完15年後剩餘還款現值
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%,請問從現在開始每月需要投入多少錢?

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萬元啦
#問題是普通工人大眾很難持續獲得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為實際年利率(effective annual rate);AP為名義年利率(Annual Percentage Rate);m是一年內複利的頻率。
在這裡插入圖片描述

連續複利(Continuously compounded interest rate)
在這裡插入圖片描述
知識回顧
名義利率與實際利率跟通脹率對應的名義利率不同。實際利率是什麼呢?

情景一:年初存入銀行100塊錢,銀行承諾利率12%。於是年末能拿到112塊錢。這裡的12塊錢就是利息,12%就是實際利率。
情景二:年初存入銀行100塊錢,銀行承諾利率12%。聰明的人發現一個漏洞(假設半年就是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%。
【這裡銀行承諾的就是名義利率,而實際所得的是實際利率。(當然現實生活中的商業銀行會把半年利率調低,而不是單純的用一年的利率除以期數。)而後面兩種情景的計息方式為 複利。俗稱利滾利。不要以為利滾利就能滾上天,有一個條件限制住了它,叫名義利率。隨著存取次數的不斷增加,每一個期數內的利率也在逐漸減小。現在把計息次數擴大到∞,實際利率就變成了(1+12%/∞)∞,而這玩意計算出來就是e12%。這就是所謂的連續複利。】

4. 專案投資分析

金融財務分析裡關於專案投資分析判斷的方法有很多,比較常用的有淨現值、回收期、內部收益率法等。

淨現值法 (Net present value,NPV)
在這裡插入圖片描述
專案投資NPV法判斷依據:
在這裡插入圖片描述

def npv_f(rate,cashflows):
    total=0.0
    for i, cashflow in enumerate(cashflows):
        total+=cashflow/(1+rate)**i
    return total

回收期法(Payback period)
在這裡插入圖片描述

與淨現值法相比,優點是簡單易懂,缺點:

不考慮時間價值

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

內部收益率法(IRR)
IRR:使得淨現值為0的貼現率。
在這裡插入圖片描述

def IRR_f(cashflows,interations=10000):
    rate=1.0
    inv=cashflows[0]
    for i in range(1,interations+1):
        rate*=(1-npv_f(rate,cashflows)/inv)
    return rate

應用例項5:假設貼現率為5%,有A、B兩個專案,前期均需投入120萬, A專案第一年至五年分別收入10、30、50、40、10萬,而專案B第一至五年分別收入30、40、40、20、10萬,專案A和B哪個投資價值高?

#分析:如果光從金額看都是投資120萬元,
#回報都是140萬元,
#從回收期法來看,二者都是在第四年才收回成本
#但由於貨幣的時間價值,下面從淨現值的角度進行分析
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的淨現值:%.2f萬元" % npv_A)
print("專案B的淨現值:%.2f萬元" % npv_B)
專案A的淨現值:0.67萬元
專案B的淨現值: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:優點:計算相對簡便易懂,結果直觀,容易理解;侷限性:沒有消除初始投資額不同的差異,也沒有消除投資專案期限的差異。

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

淨現值和內部收益率適用範圍不同,淨現值適用於互斥方案間的擇優,而內部收益率用於獨立方案間的擇優。

應用例項6:有專案C、D,一次性投入均為100萬元,其中,C專案前六年無現金流入,第7年現金流入200萬;D專案前六年每年現金流入12萬,最後一年現金流入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("淨現值:C專案{0:.2f}萬元,D專案
    {1:.2f}萬元".format(npv_f(0.1,C),
    npv_f(0.1,D)))
#請問你會選哪一個呢?
內部收益率:C專案12%,D專案12%
淨現值: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("淨現值:E專案{0:.2f}萬元,F專案
  {1:.2f}萬元".format(npv_f(0.1,E),
   npv_f(0.1,F)))
#你又會選哪一個呢?
內部收益率:E專案31%,F專案28%
淨現值:E專案29.35萬元,F專案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("淨現值:G專案{0:.2f}萬元,H專案
  {1:.2f}萬元".format(npv_f(0.1,G),
  npv_f(0.1,H)))
#你又會選哪一個呢?
內部收益率:G專案31%,H專案20%
淨現值: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-')

在這裡插入圖片描述