diff options
author | Travis Oliphant <oliphant@enthought.com> | 2009-08-28 15:36:42 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2009-08-28 15:36:42 +0000 |
commit | 2b01ee6b966b9ca298247e6717e3a5be16a92970 (patch) | |
tree | 6bbb8ee8eebdfe2ef3eb26f13994193b313c6fe7 /numpy/lib/financial.py | |
parent | c2191bc97da8a0879cec8d3e9a7a93fe9e66fcd8 (diff) | |
parent | fddd4b9c3b8f18ba7cf386f766b70ec3328b1c69 (diff) | |
download | numpy-2b01ee6b966b9ca298247e6717e3a5be16a92970.tar.gz |
Re-base the date-time branch back to the trunk.
Diffstat (limited to 'numpy/lib/financial.py')
-rw-r--r-- | numpy/lib/financial.py | 198 |
1 files changed, 177 insertions, 21 deletions
diff --git a/numpy/lib/financial.py b/numpy/lib/financial.py index 0cef1c4d2..503d43647 100644 --- a/numpy/lib/financial.py +++ b/numpy/lib/financial.py @@ -28,6 +28,18 @@ def fv(rate, nper, pmt, pv, when='end'): """ Compute the future value. + Given: + * a present value, `pv` + * an interest `rate` compounded once per period, of which + there are + * `nper` total + * a (fixed) payment, `pmt`, paid either + * at the beginning (`when` = {'begin', 1}) or the end + (`when` = {'end', 0}) of each period + + Return: + the value at the end of the `nper` periods + Parameters ---------- rate : scalar or array_like of shape(M, ) @@ -61,6 +73,17 @@ def fv(rate, nper, pmt, pv, when='end'): fv + pv + pmt * nper == 0 + References + ---------- + .. [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May). + Open Document Format for Office Applications (OpenDocument)v1.2, + Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version, + Pre-Draft 12. Organization for the Advancement of Structured Information + Standards (OASIS). Billerica, MA, USA. [ODT Document]. + Available: + http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula + OpenDocument-formula-20090508.odt + Examples -------- What is the future value after 10 years of saving $100 now, with @@ -94,6 +117,19 @@ def pmt(rate, nper, pv, fv=0, when='end'): """ Compute the payment against loan principal plus interest. + Given: + * a present value, `pv` (e.g., an amount borrowed) + * a future value, `fv` (e.g., 0) + * an interest `rate` compounded once per period, of which + there are + * `nper` total + * and (optional) specification of whether payment is made + at the beginning (`when` = {'begin', 1}) or the end + (`when` = {'end', 0}) of each period + + Return: + the (fixed) periodic payment. + Parameters ---------- rate : array_like @@ -102,8 +138,8 @@ def pmt(rate, nper, pv, fv=0, when='end'): Number of compounding periods pv : array_like Present value - fv : array_like - Future value + fv : array_like (optional) + Future value (default = 0) when : {{'begin', 1}, {'end', 0}}, {string, int} When payments are due ('begin' (1) or 'end' (0)) @@ -117,7 +153,7 @@ def pmt(rate, nper, pv, fv=0, when='end'): Notes ----- - The payment ``pmt`` is computed by solving the equation:: + The payment is computed by solving the equation:: fv + pv*(1 + rate)**nper + @@ -127,16 +163,37 @@ def pmt(rate, nper, pv, fv=0, when='end'): fv + pv + pmt * nper == 0 + for ``pmt``. + + Note that computing a monthly mortgage payment is only + one use for this function. For example, pmt returns the + periodic deposit one must make to achieve a specified + future balance given an initial deposit, a fixed, + periodically compounded interest rate, and the total + number of periods. + + References + ---------- + .. [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May). + Open Document Format for Office Applications (OpenDocument)v1.2, + Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version, + Pre-Draft 12. Organization for the Advancement of Structured Information + Standards (OASIS). Billerica, MA, USA. [ODT Document]. + Available: + http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula + OpenDocument-formula-20090508.odt + Examples -------- - What would the monthly payment need to be to pay off a $200,000 loan in 15 + What is the monthly payment needed to pay off a $200,000 loan in 15 years at an annual interest rate of 7.5%? >>> np.pmt(0.075/12, 12*15, 200000) -1854.0247200054619 - In order to pay-off (i.e. have a future-value of 0) the $200,000 obtained - today, a monthly payment of $1,854.02 would be required. + In order to pay-off (i.e., have a future-value of 0) the $200,000 obtained + today, a monthly payment of $1,854.02 would be required. Note that this + example illustrates usage of `fv` having a default value of 0. """ when = _convert_when(when) @@ -282,6 +339,18 @@ def pv(rate, nper, pmt, fv=0.0, when='end'): """ Compute the present value. + Given: + * a future value, `fv` + * an interest `rate` compounded once per period, of which + there are + * `nper` total + * a (fixed) payment, `pmt`, paid either + * at the beginning (`when` = {'begin', 1}) or the end + (`when` = {'end', 0}) of each period + + Return: + the value now + Parameters ---------- rate : array_like @@ -302,7 +371,7 @@ def pv(rate, nper, pmt, fv=0.0, when='end'): Notes ----- - The present value ``pv`` is computed by solving the equation:: + The present value is computed by solving the equation:: fv + pv*(1 + rate)**nper + @@ -312,6 +381,45 @@ def pv(rate, nper, pmt, fv=0.0, when='end'): fv + pv + pmt * nper = 0 + for `pv`, which is then returned. + + References + ---------- + .. [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May). + Open Document Format for Office Applications (OpenDocument)v1.2, + Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version, + Pre-Draft 12. Organization for the Advancement of Structured Information + Standards (OASIS). Billerica, MA, USA. [ODT Document]. + Available: + http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula + OpenDocument-formula-20090508.odt + + Examples + -------- + What is the present value (e.g., the initial investment) + of an investment that needs to total $15692.93 + after 10 years of saving $100 every month? Assume the + interest rate is 5% (annually) compounded monthly. + + >>> np.pv(0.05/12, 10*12, -100, 15692.93) + -100.00067131625819 + + By convention, the negative sign represents cash flow out + (i.e., money not available today). Thus, to end up with + $15,692.93 in 10 years saving $100 a month at 5% annual + interest, one's initial deposit should also be $100. + + If any input is array_like, ``pv`` returns an array of equal shape. + Let's compare different interest rates in the example above: + + >>> a = np.array((0.05, 0.04, 0.03))/12 + >>> np.pv(a, 10*12, -100, 15692.93) + array([ -100.00067132, -649.26771385, -1273.78633713]) + + So, to end up with the same $15692.93 under the same $100 per month + "savings plan," for annual interest rates of 4% and 3%, one would + need initial investments of $649.27 and $1273.79, respectively. + """ when = _convert_when(when) rate, nper, pmt, fv, when = map(np.asarray, [rate, nper, pmt, fv, when]) @@ -391,24 +499,54 @@ def irr(values): """ Return the Internal Rate of Return (IRR). - This is the rate of return that gives a net present value of 0.0. + This is the "average" periodically compounded rate of return + that gives a net present value of 0.0; for a more complete explanation, + see Notes below. Parameters ---------- values : array_like, shape(N,) - Input cash flows per time period. At least the first value would be - negative to represent the investment in the project. + Input cash flows per time period. By convention, net "deposits" + are negative and net "withdrawals" are positive. Thus, for example, + at least the first element of `values`, which represents the initial + investment, will typically be negative. Returns ------- out : float Internal Rate of Return for periodic input values. + Notes + ----- + The IRR is perhaps best understood through an example (illustrated + using np.irr in the Examples section below). Suppose one invests + 100 units and then makes the following withdrawals at regular + (fixed) intervals: 39, 59, 55, 20. Assuming the ending value is 0, + one's 100 unit investment yields 173 units; however, due to the + combination of compounding and the periodic withdrawals, the + "average" rate of return is neither simply 0.73/4 nor (1.73)^0.25-1. + Rather, it is the solution (for :math:`r`) of the equation: + + .. math:: -100 + \\frac{39}{1+r} + \\frac{59}{(1+r)^2} + + \\frac{55}{(1+r)^3} + \\frac{20}{(1+r)^4} = 0 + + In general, for `values` :math:`= [v_0, v_1, ... v_M]`, + irr is the solution of the equation: [G]_ + + .. math:: \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0 + + References + ---------- + .. [G] L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., + Addison-Wesley, 2003, pg. 348. + Examples -------- >>> np.irr([-100, 39, 59, 55, 20]) 0.2809484211599611 + (Compare with the Example given for numpy.lib.financial.npv) + """ res = np.roots(values[::-1]) # Find the root(s) between 0 and 1 @@ -430,8 +568,14 @@ def npv(rate, values): rate : scalar The discount rate. values : array_like, shape(M, ) - The values of the time series of cash flows. Must be the same - increment as the `rate`. + The values of the time series of cash flows. The (fixed) time + interval between cash flow "events" must be the same as that + for which `rate` is given (i.e., if `rate` is per year, then + precisely a year is understood to elapse between each cash flow + event). By convention, investments or "deposits" are negative, + income or "withdrawals" are positive; `values` must begin with + the initial investment, thus `values[0]` will typically be + negative. Returns ------- @@ -440,9 +584,21 @@ def npv(rate, values): Notes ----- - Returns the result of: + Returns the result of: [G]_ + + .. math :: \\sum_{t=0}^M{\\frac{values_t}{(1+rate)^{t}}} + + References + ---------- + .. [G] L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., + Addison-Wesley, 2003, pg. 346. - .. math :: \\sum_{t=1}^M{\\frac{values_t}{(1+rate)^{t}}} + Examples + -------- + >>> np.npv(0.281,[-100, 39, 59, 55, 20]) + -0.0066187288356340801 + + (Compare with the Example given for numpy.lib.financial.irr) """ values = np.asarray(values) @@ -456,7 +612,7 @@ def mirr(values, finance_rate, reinvest_rate): ---------- values : array_like Cash flows (must contain at least one positive and one negative value) - or nan is returned. + or nan is returned. The first value is considered a sunk cost at time zero. finance_rate : scalar Interest rate paid on the cash flows reinvest_rate : scalar @@ -469,13 +625,13 @@ def mirr(values, finance_rate, reinvest_rate): """ - values = np.asarray(values) + values = np.asarray(values, dtype=np.double) + n = values.size pos = values > 0 neg = values < 0 - if not (pos.size > 0 and neg.size > 0): + if not (pos.any() and neg.any()): return np.nan + numer = np.abs(npv(reinvest_rate, values*pos))*(1 + reinvest_rate) + denom = np.abs(npv(finance_rate, values*neg))*(1 + finance_rate) + return (numer/denom)**(1.0/(n - 1))*(1 + reinvest_rate) - 1 - n = pos.size + neg.size - numer = -npv(reinvest_rate, values[pos])*((1+reinvest_rate)**n) - denom = npv(finance_rate, values[neg])*(1+finance_rate) - return (numer / denom)**(1.0/(n-1)) - 1 |