使用IRR(Python)仅计算一个类别的未来值

时间:2016-02-27 21:26:47

标签: python excel if-statement for-loop irr

import xlrd
import numpy

fileWorkspace = 'C://Users/jod/Desktop/'

wb1 = xlrd.open_workbook(fileWorkspace + 'assign2.xls')
sh1 = wb1.sheet_by_index(0)

time,amount,category = [],[],[]            
for a in range(2,sh1.nrows):
    time.append(int(sh1.cell(a,0).value))        # Pulling time from excel (column A)
    amount.append(float(sh1.cell(a,1).value))    # Pulling amount from excel (column B)
    category.append(str(sh1.cell(a,2).value))    # Pulling category from excel (column C)
#print(time)
#print(amount)
#print(category)
print('\n')

p_p2 = str(sh1.cell(0,1))
p_p1 = p_p2.replace("text:'","")
pp = p_p1.replace("'","")
print(pp)                            # Printing the type of pay period (Row 1, col B)
c_p2 = str(sh1.cell(1,1))
c_p1 = c_p2.replace("text:'","")
cp = c_p1.replace("'","")
print(cp)                            # Printing the type of compound period (Row 2, col B)

netflow = 0
outflow = 0
inflow = 0
flow = 0

cat = ["Sales", "Salvage", "Subsidy", "Redeemable", "Utility", "Labor", 
       "Testing", "Marketing", "Materials", "Logistics"]

if pp == "Years" and cp == "Years":   # if pay period and compound period are both in years

    IRR = numpy.irr(amount) * 100            # Calculates the internal rate of return (IRR)
    print ("IRR:", round(IRR, 2), '%', '\n') # prints (IRR)

    for i in time:              # for every value in time array
        if cat[5] in category:  # if "Labor" for cat array is in category array or not

            # calculates the present values using all the amount values (col B) instead of 
            # just using the ones that has "Labor" category label beside them
            # Need to make every other value 0, such as beside "Redeemable" and "Salvage"
            flow = amount[i] / numpy.power((1 + (IRR/100)), time[i])
            if flow>0:                      
                inflow = inflow + flow      
            if flow<0:                      
                outflow = outflow + flow  

            print ('Present Value (P) is:', round(flow,0), '\n')

    netflow = outflow + inflow
    print("In year 0 or current year")
    print("-------")
    print ('Outflow is: ', round(outflow,0))
    print ('Inflow is: ', round(inflow,0))
    print ('Netflow is: ', round(netflow,0), '\n')

    outflow2 = (round(outflow,0))*(1+(IRR/100))**(9)
    inflow2 = (round(inflow,0))*(1+(IRR/100))**(9)
    netflow2 = outflow2 + inflow2

    print("In year 9")
    print("-------")
    print ('Outflow is: ', round(outflow2,0))
    print ('Inflow is: ', round(inflow2,0))
    print ('Netflow is: ', round(netflow2,0), '\n')

我已经评论了重要的代码行以便澄清。 这是最初的问题:

按类别说明主要项目收入和支出在第9年的项目未来价值的百分比。该图还必须清楚地表明项目在第9年的总体未来价值以及IRR。

项目可能由总共10个收入和成本类别组成。类别包括:销售,打捞,补贴,可兑换,公用事业,劳务,测试,营销,材料和物流。所有收入和支出将属于这十个类别中的一个。项目支付期和复合期将在Excel工作表的顶部标识。支付期和复合期可以指定为以下任何一种:年,季,月。

我感到困惑,因为我无法从&#34; Labor&#34;,&#34; Redeemable&#34;或&#34; Salvage&#34;旁边拉出唯一的值。我只是不知道我在哪里弄错了,或者有些东西是不完整的。以下是excel文件图片:

Excel File Image 2 Excel File Image 3

1 个答案:

答案 0 :(得分:0)

修改后,所有现金流量均在irr处打折。做了以下事情: i)确定调整采用支付期(A列)并调整是否结束年度(如果它是在适当的年份结束的月度金额)以及其每月是否在月末投入(无需调整)。如果需要每年的现金流量(每年复利),这将把支付期除以12

ii)计算内部收益率,并使用复利期来调整每月工资期的每月内部收益率

iii)所有费用在内部收益率打折并输入cat_contributions列表[&#39; category_name&#39;] = [打折期限1,打折期限2 ...]

iv)然后净流入和流出是这些的总和。

我无法在图片中输入电子表格中的数据,因为这需要一段时间,但可能会对此进行修补,看看是否可以让它发挥作用。

from __future__ import division
import xlrd
import numpy
import os
import math

def main(xls = 'xls_name.xlsx', sh = 0):
    #save script in same folder as the xls file
    os.chdir(  os.getcwd() )
    wb = xlrd.open_workbook(xls)
    sh = wb.sheet_by_index(0)

    pay_period = sh.cell_value(0,1)
    compounding_period = sh.cell_value(1,1)

    compounding_factor, pay_factor = determineAdjustments(
        pay_period, compounding_period)

    number_of_periods = max( sh.col_values(0, start_rowx = 2) )

    flow_per_period = [ 0*i for i in range( int( math.ceil( number_of_periods/pay_factor ) ) + 1 ) ]#list of length number of pay_periods
    for r in range(2,sh.nrows):
        pay_period = int( math.ceil( sh.cell_value(r,0) / pay_factor ) )
        flow_per_period[pay_period] += sh.cell_value(r,1) #unadjusted cash flows


    irr = calculateIRR(flow_per_period, compounding_factor)

    cat_contributions = sortExpenditures(sh, irr, pay_factor)
    total_cat_contributions, netflow, total_outflow, total_inflow = calculateFlows(cat_contributions)
    printStats(cat_contributions, irr, compounding_factor, pay_factor,
               total_cat_contributions, netflow, total_outflow, total_inflow)
    return

def determineAdjustments(pay_period, compounding_period):

    if compounding_period == 'years':
        compounding_factor = 1
        if pay_period == 'months':
            pay_factor = 12
        if pay_period == 'years':
            pay_factor = 1
        #assume no days pay periods

    if compounding_period == 'months':
        compounding_factor = 12
        #assume no yearly payouts and that the
        #all payments are in months
        pay_factor = 1


    return compounding_factor, pay_factor

def calculateIRR(cashflow, compounding_factor):

    irr = numpy.irr(cashflow)

    irr_comp = (1 + irr)**compounding_factor - 1

    #seems like in first example it uses rounded irr, can do something like:
    #irr_comp = round(irr_comp,4)
    return irr_comp

def sortExpenditures(sh, irr, pay_factor):
    #percentages and discounting occurs at the IRR caculated in the main
    #function

    cat = ["Sales", "Salvage", "Subsidy", "Redeemable", "Utility", "Labor", 
       "Testing", "Marketing", "Materials", "Logistics"]

    #python dictionary to sort contributions into categories
    cat_contributions = {}
    for c in cat:
        cat_contributions[c] = []

    # create list of contributions of each list item to FV in a dictionary
    for r in range(2,sh.nrows):
        try:
            #discounted cash flow of each expenditure
            #using formula FV = expenditure/(1+i)^n
            cat_contributions[sh.cell_value(r,2)].append(
                sh.cell_value(r,1) / ( (1 + irr) ** (sh.cell_value(r,0)/pay_factor) )
                )

        except KeyError:
            print "No category for type: " + sh.cell_value(r,2) +'\n'

    return cat_contributions

def calculateFlows(cat_contributions):

    total_outflow = 0
    total_inflow = 0

    total_cat_contributions = {}

    for cat in cat_contributions:
        total_cat_contributions[cat] = sum( cat_contributions[cat] )
        if total_cat_contributions[cat] < 0:
            total_outflow += total_cat_contributions[cat]
        else:
            total_inflow += total_cat_contributions[cat]

    netflow = total_inflow + total_outflow

    return total_cat_contributions, netflow, total_outflow, total_inflow

def printStats(cat_contributions, irr, compounding_factor, pay_period,
               total_cat_contributions, netflow, total_outflow, total_inflow):

    print "IRR: "+str(irr*100) +'  %'
    if compounding_factor == 1: print "Compounding: Yearly"
    if compounding_factor == 12: print "Compounding: Monthly"

    if pay_period == 1: "Cashflows: Year Ended"
    if pay_period == 12: "Cashflows: Month Ended"

    print "Future Value (Net Adjusted Cashflow): " +str(netflow) 
    print "Adjusted Inflows: " + str(total_inflow)
    print "Adjusted Outflows: " + str(total_outflow) +'\n'


    for cat in total_cat_contributions:
        if total_cat_contributions[cat] != 0:
            print '-----------------------------------------------------'
            print cat + '\n'
            print "Total Contribution to FV " + str( total_cat_contributions[cat] )
            if total_cat_contributions[cat] < 0:
                print "Contribution to Expenses: " + str ( abs(100 * total_cat_contributions[cat]/total_outflow) )
            else:
                print "Contribution to Revenues: " + str ( abs(100 * total_cat_contributions[cat]/total_inflow) ) +'\n'


main(xls='Book1.xlsx')