финансовая библиотека python, которая имеет функции xirr и xnpv? - PullRequest
9 голосов
/ 19 января 2012

numpy имеет функции irr и npv, но мне нужны функции xirr и xnpv.

эта ссылка указывает на то, что xirr и xnpv скоро появятся. http://www.projectdirigible.com/documentation/spreadsheet-functions.html#coming-soon

Есть ли библиотека Python, которая имеет эти две функции? ТКС.

Ответы [ 3 ]

10 голосов
/ 21 октября 2015

Вот один из способов реализации двух функций.

import scipy.optimize

def xnpv(rate, values, dates):
    '''Equivalent of Excel's XNPV function.

    >>> from datetime import date
    >>> dates = [date(2010, 12, 29), date(2012, 1, 25), date(2012, 3, 8)]
    >>> values = [-10000, 20, 10100]
    >>> xnpv(0.1, values, dates)
    -966.4345...
    '''
    if rate <= -1.0:
        return float('inf')
    d0 = dates[0]    # or min(dates)
    return sum([ vi / (1.0 + rate)**((di - d0).days / 365.0) for vi, di in zip(values, dates)])

def xirr(values, dates):
    '''Equivalent of Excel's XIRR function.

    >>> from datetime import date
    >>> dates = [date(2010, 12, 29), date(2012, 1, 25), date(2012, 3, 8)]
    >>> values = [-10000, 20, 10100]
    >>> xirr(values, dates)
    0.0100612...
    '''
    try:
        return scipy.optimize.newton(lambda r: xnpv(r, values, dates), 0.0)
    except RuntimeError:    # Failed to converge?
        return scipy.optimize.brentq(lambda r: xnpv(r, values, dates), -1.0, 1e10)
9 голосов
/ 16 июля 2012

С помощью различных реализаций, которые я нашел в сети, я придумал реализацию на python:

def xirr(transactions):
    years = [(ta[0] - transactions[0][0]).days / 365.0 for ta in transactions]
    residual = 1
    step = 0.05
    guess = 0.05
    epsilon = 0.0001
    limit = 10000
    while abs(residual) > epsilon and limit > 0:
        limit -= 1
        residual = 0.0
        for i, ta in enumerate(transactions):
            residual += ta[1] / pow(guess, years[i])
        if abs(residual) > epsilon:
            if residual > 0:
                guess += step
            else:
                guess -= step
                step /= 2.0
    return guess-1

from datetime import date
tas = [ (date(2010, 12, 29), -10000),
    (date(2012, 1, 25), 20),
    (date(2012, 3, 8), 10100)]
print xirr(tas) #0.0100612640381
0 голосов
/ 30 июля 2015

С Пандами у меня работает следующее: (обратите внимание, я использую соглашение ACT / 365)

rate = 0.10
dates= pandas.date_range(start=pandas.Timestamp('2015-01-01'),periods=5, freq="AS")
cfs = pandas.Series([-500,200,200,200,200],index=dates)

# intermediate calculations( if interested)
# cf_xnpv_days = [(cf.index[i]-cf.index[i-1]).days for i in range(1,len(cf.index))]
# cf_xnpv_days_cumulative = [(cf.index[i]-cf.index[0]).days for i in range(1,len(cf.index))]
# cf_xnpv_days_disc_factors = [(1+rate)**(float((cf.index[i]-cf.index[0]).days)/365.0)-1   for i in range(1,len(cf.index))]

cf_xnpv_days_pvs = [cf[i]/float(1+(1+rate)**(float((cf.index[i]-cf.index[0]).days)/365.0)-1)  for i in range(1,len(cf.index))]

cf_xnpv = cf[0]+ sum(cf_xnpv_days_pvs)
...