Comparing version 0.0.16 to 0.0.17
@@ -461,2 +461,123 @@ 'use strict'; | ||
/** | ||
* Return the Internal Rate of Return (IRR). | ||
* | ||
* 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. | ||
* | ||
* @param values - 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. | ||
* @param guess - Starting guess for solving the Internal Rate of Return | ||
* @param tol - Required tolerance for the solution | ||
* @param maxIter - Maximum iterations in finding the solution | ||
* | ||
* @returns Internal Rate of Return for periodic input values | ||
* | ||
* ## Notes | ||
* | ||
* The IRR is perhaps best understood through an example (illustrated | ||
* using `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 `r`) of the equation: | ||
* | ||
* ``` | ||
* -100 + 39/(1+r) + 59/((1+r)^2) + 55/((1+r)^3) + 20/((1+r)^4) = 0 | ||
* ``` | ||
* | ||
* In general, for `values` = `[0, 1, ... M]`, | ||
* `irr` is the solution of the equation: | ||
* | ||
* ``` | ||
* \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0 | ||
* ``` | ||
* | ||
* ## Example | ||
* | ||
* ```javascript | ||
* import { irr } from 'financial' | ||
* | ||
* irr([-100, 39, 59, 55, 20]) // 0.28095 | ||
* irr([-100, 0, 0, 74]) // -0.0955 | ||
* irr([-100, 100, 0, -7]) // -0.0833 | ||
* irr([-100, 100, 0, 7]) // 0.06206 | ||
* irr([-5, 10.5, 1, -8, 1]) // 0.0886 | ||
* ``` | ||
* | ||
* ## References | ||
* | ||
* - L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., | ||
* Addison-Wesley, 2003, pg. 348. | ||
*/ | ||
function irr(values, guess, tol, maxIter) { | ||
if (guess === void 0) { | ||
guess = 0.1; | ||
} | ||
if (tol === void 0) { | ||
tol = 1e-6; | ||
} | ||
if (maxIter === void 0) { | ||
maxIter = 100; | ||
} | ||
// Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
// ASF licensed (check the link for the full license) | ||
// Credits: algorithm inspired by Apache OpenOffice | ||
// Initialize dates and check that values contains at | ||
// least one positive value and one negative value | ||
var dates = []; | ||
var positive = false; | ||
var negative = false; | ||
for (var i = 0; i < values.length; i++) { | ||
dates[i] = i === 0 ? 0 : dates[i - 1] + 365; | ||
if (values[i] > 0) { | ||
positive = true; | ||
} | ||
if (values[i] < 0) { | ||
negative = true; | ||
} | ||
} // Return error if values does not contain at least one positive value and one negative value | ||
if (!positive || !negative) { | ||
return Number.NaN; | ||
} // Initialize guess and resultRate | ||
var resultRate = guess; // Implement Newton's method | ||
var newRate, epsRate, resultValue; | ||
var iteration = 0; | ||
var contLoop = true; | ||
do { | ||
resultValue = _irrResult(values, dates, resultRate); | ||
newRate = resultRate - resultValue / _irrResultDeriv(values, dates, resultRate); | ||
epsRate = Math.abs(newRate - resultRate); | ||
resultRate = newRate; | ||
contLoop = epsRate > tol && Math.abs(resultValue) > tol; | ||
} while (contLoop && ++iteration < maxIter); | ||
if (contLoop) { | ||
return Number.NaN; | ||
} // Return internal rate of return | ||
return resultRate; | ||
} | ||
/** | ||
* This function is here to simply have a different name for the 'fv' | ||
@@ -492,5 +613,47 @@ * function to not interfere with the 'fv' keyword argument within the 'ipmt' | ||
} | ||
/** | ||
* Calculates the resulting amount. | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
function _irrResult(values, dates, rate) { | ||
var r = rate + 1; | ||
var result = values[0]; | ||
for (var i = 1; i < values.length; i++) { | ||
result += values[i] / Math.pow(r, (dates[i] - dates[0]) / 365); | ||
} | ||
return result; | ||
} | ||
/** | ||
* Calculates the first derivation | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
function _irrResultDeriv(values, dates, rate) { | ||
var r = rate + 1; | ||
var result = 0; | ||
for (var i = 1; i < values.length; i++) { | ||
var frac = (dates[i] - dates[0]) / 365; | ||
result -= frac * values[i] / Math.pow(r, frac + 1); | ||
} | ||
return result; | ||
} | ||
exports.fv = fv; | ||
exports.ipmt = ipmt; | ||
exports.irr = irr; | ||
exports.nper = nper; | ||
@@ -497,0 +660,0 @@ exports.pmt = pmt; |
@@ -1,2 +0,2 @@ | ||
"use strict";var e;function t(e,t,n,r,o){if(void 0===o&&(o=exports.PaymentDueTime.End),0===e)return-(r+n*t);var i=Math.pow(1+e,t);return-r*i-n*(1+e*(o===exports.PaymentDueTime.Begin?1:0))/e*(i-1)}function n(e,t,n,r,o){void 0===r&&(r=0),void 0===o&&(o=exports.PaymentDueTime.End);var i=0===e,u=Math.pow(1+e,t),a=o===exports.PaymentDueTime.Begin?1:0,m=i?1:e;return-(r+n*u)/(i?t:(1+m*a)*(u-1)/m)}function r(e,t,r,i,u,a){if(void 0===u&&(u=0),void 0===a&&(a=exports.PaymentDueTime.End),t<1)return Number.NaN;if(a===exports.PaymentDueTime.Begin&&1===t)return 0;var m=o(e,t,n(e,r,i,u,a),i,a)*e;return a===exports.PaymentDueTime.Begin&&t>1&&(m/=1+e),m}function o(e,n,r,o,i){return t(e,n-1,r,o,i)}function i(e,t,n,r,o,i){var u=i===exports.PaymentDueTime.Begin?1:0,a=Math.pow(e+1,t),m=Math.pow(e+1,t-1);return(o+a*r+n*(a-1)*(e*u+1)/e)/(t*m*r-n*(a-1)*(e*u+1)/Math.pow(e,2)+t*n*m*(e*u+1)/e+n*(a-1)*u/e)}Object.defineProperty(exports,"__esModule",{value:!0}),(e=exports.PaymentDueTime||(exports.PaymentDueTime={})).Begin="begin",e.End="end",exports.fv=t,exports.ipmt=r,exports.nper=function(e,t,n,r,o){if(void 0===r&&(r=0),void 0===o&&(o=exports.PaymentDueTime.End),0===e)return-(r+n)/t;var i=t*(1+e*(o===exports.PaymentDueTime.Begin?1:0))/e;return Math.log((-r+i)/(n+i))/Math.log(1+e)},exports.pmt=n,exports.ppmt=function(e,t,o,i,u,a){return void 0===u&&(u=0),void 0===a&&(a=exports.PaymentDueTime.End),n(e,o,i,u,a)-r(e,t,o,i,u,a)},exports.pv=function(e,t,n,r,o){void 0===r&&(r=0),void 0===o&&(o=exports.PaymentDueTime.End);var i=o===exports.PaymentDueTime.Begin?1:0,u=0===e,a=Math.pow(1+e,t);return-(r+n*(u?t:(1+e*i)*(a-1)/e))/a},exports.rate=function(e,t,n,r,o,u,a,m){void 0===o&&(o=exports.PaymentDueTime.End),void 0===u&&(u=.1),void 0===a&&(a=1e-6),void 0===m&&(m=100);for(var p=u,s=0,v=!1;s<m&&!v;){var d=p-i(p,e,t,n,r,o);v=Math.abs(d-p)<a,s++,p=d}return v?p:Number.NaN}; | ||
"use strict";var e;function t(e,t,r,n,o){if(void 0===o&&(o=exports.PaymentDueTime.End),0===e)return-(n+r*t);var i=Math.pow(1+e,t);return-n*i-r*(1+e*(o===exports.PaymentDueTime.Begin?1:0))/e*(i-1)}function r(e,t,r,n,o){void 0===n&&(n=0),void 0===o&&(o=exports.PaymentDueTime.End);var i=0===e,a=Math.pow(1+e,t),u=o===exports.PaymentDueTime.Begin?1:0,p=i?1:e;return-(n+r*a)/(i?t:(1+p*u)*(a-1)/p)}function n(e,t,n,i,a,u){if(void 0===a&&(a=0),void 0===u&&(u=exports.PaymentDueTime.End),t<1)return Number.NaN;if(u===exports.PaymentDueTime.Begin&&1===t)return 0;var p=o(e,t,r(e,n,i,a,u),i,u)*e;return u===exports.PaymentDueTime.Begin&&t>1&&(p/=1+e),p}function o(e,r,n,o,i){return t(e,r-1,n,o,i)}function i(e,t,r,n,o,i){var a=i===exports.PaymentDueTime.Begin?1:0,u=Math.pow(e+1,t),p=Math.pow(e+1,t-1);return(o+u*n+r*(u-1)*(e*a+1)/e)/(t*p*n-r*(u-1)*(e*a+1)/Math.pow(e,2)+t*r*p*(e*a+1)/e+r*(u-1)*a/e)}function a(e,t,r){for(var n=r+1,o=e[0],i=1;i<e.length;i++)o+=e[i]/Math.pow(n,(t[i]-t[0])/365);return o}function u(e,t,r){for(var n=r+1,o=0,i=1;i<e.length;i++){var a=(t[i]-t[0])/365;o-=a*e[i]/Math.pow(n,a+1)}return o}Object.defineProperty(exports,"__esModule",{value:!0}),(e=exports.PaymentDueTime||(exports.PaymentDueTime={})).Begin="begin",e.End="end",exports.fv=t,exports.ipmt=n,exports.irr=function(e,t,r,n){void 0===t&&(t=.1),void 0===r&&(r=1e-6),void 0===n&&(n=100);for(var o=[],i=!1,p=!1,m=0;m<e.length;m++)o[m]=0===m?0:o[m-1]+365,e[m]>0&&(i=!0),e[m]<0&&(p=!0);if(!i||!p)return Number.NaN;var v,s,d,x=t,f=0,h=!0;do{v=x-(d=a(e,o,x))/u(e,o,x),s=Math.abs(v-x),x=v,h=s>r&&Math.abs(d)>r}while(h&&++f<n);return h?Number.NaN:x},exports.nper=function(e,t,r,n,o){if(void 0===n&&(n=0),void 0===o&&(o=exports.PaymentDueTime.End),0===e)return-(n+r)/t;var i=t*(1+e*(o===exports.PaymentDueTime.Begin?1:0))/e;return Math.log((-n+i)/(r+i))/Math.log(1+e)},exports.pmt=r,exports.ppmt=function(e,t,o,i,a,u){return void 0===a&&(a=0),void 0===u&&(u=exports.PaymentDueTime.End),r(e,o,i,a,u)-n(e,t,o,i,a,u)},exports.pv=function(e,t,r,n,o){void 0===n&&(n=0),void 0===o&&(o=exports.PaymentDueTime.End);var i=o===exports.PaymentDueTime.Begin?1:0,a=0===e,u=Math.pow(1+e,t);return-(n+r*(a?t:(1+e*i)*(u-1)/e))/u},exports.rate=function(e,t,r,n,o,a,u,p){void 0===o&&(o=exports.PaymentDueTime.End),void 0===a&&(a=.1),void 0===u&&(u=1e-6),void 0===p&&(p=100);for(var m=a,v=0,s=!1;v<p&&!s;){var d=m-i(m,e,t,r,n,o);s=Math.abs(d-m)<u,v++,m=d}return s?m:Number.NaN}; | ||
//# sourceMappingURL=financial.cjs.production.min.js.map |
@@ -308,1 +308,61 @@ /** | ||
export declare function rate(nper: number, pmt: number, pv: number, fv: number, when?: PaymentDueTime, guess?: number, tol?: number, maxIter?: number): number; | ||
/** | ||
* Return the Internal Rate of Return (IRR). | ||
* | ||
* 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. | ||
* | ||
* @param values - 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. | ||
* @param guess - Starting guess for solving the Internal Rate of Return | ||
* @param tol - Required tolerance for the solution | ||
* @param maxIter - Maximum iterations in finding the solution | ||
* | ||
* @returns Internal Rate of Return for periodic input values | ||
* | ||
* ## Notes | ||
* | ||
* The IRR is perhaps best understood through an example (illustrated | ||
* using `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 `r`) of the equation: | ||
* | ||
* ``` | ||
* -100 + 39/(1+r) + 59/((1+r)^2) + 55/((1+r)^3) + 20/((1+r)^4) = 0 | ||
* ``` | ||
* | ||
* In general, for `values` = `[0, 1, ... M]`, | ||
* `irr` is the solution of the equation: | ||
* | ||
* ``` | ||
* \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0 | ||
* ``` | ||
* | ||
* ## Example | ||
* | ||
* ```javascript | ||
* import { irr } from 'financial' | ||
* | ||
* irr([-100, 39, 59, 55, 20]) // 0.28095 | ||
* irr([-100, 0, 0, 74]) // -0.0955 | ||
* irr([-100, 100, 0, -7]) // -0.0833 | ||
* irr([-100, 100, 0, 7]) // 0.06206 | ||
* irr([-5, 10.5, 1, -8, 1]) // 0.0886 | ||
* ``` | ||
* | ||
* ## References | ||
* | ||
* - L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., | ||
* Addison-Wesley, 2003, pg. 348. | ||
*/ | ||
export declare function irr(values: number[], guess?: number, tol?: number, maxIter?: number): number; |
@@ -458,2 +458,123 @@ /** | ||
/** | ||
* Return the Internal Rate of Return (IRR). | ||
* | ||
* 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. | ||
* | ||
* @param values - 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. | ||
* @param guess - Starting guess for solving the Internal Rate of Return | ||
* @param tol - Required tolerance for the solution | ||
* @param maxIter - Maximum iterations in finding the solution | ||
* | ||
* @returns Internal Rate of Return for periodic input values | ||
* | ||
* ## Notes | ||
* | ||
* The IRR is perhaps best understood through an example (illustrated | ||
* using `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 `r`) of the equation: | ||
* | ||
* ``` | ||
* -100 + 39/(1+r) + 59/((1+r)^2) + 55/((1+r)^3) + 20/((1+r)^4) = 0 | ||
* ``` | ||
* | ||
* In general, for `values` = `[0, 1, ... M]`, | ||
* `irr` is the solution of the equation: | ||
* | ||
* ``` | ||
* \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0 | ||
* ``` | ||
* | ||
* ## Example | ||
* | ||
* ```javascript | ||
* import { irr } from 'financial' | ||
* | ||
* irr([-100, 39, 59, 55, 20]) // 0.28095 | ||
* irr([-100, 0, 0, 74]) // -0.0955 | ||
* irr([-100, 100, 0, -7]) // -0.0833 | ||
* irr([-100, 100, 0, 7]) // 0.06206 | ||
* irr([-5, 10.5, 1, -8, 1]) // 0.0886 | ||
* ``` | ||
* | ||
* ## References | ||
* | ||
* - L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., | ||
* Addison-Wesley, 2003, pg. 348. | ||
*/ | ||
function irr(values, guess, tol, maxIter) { | ||
if (guess === void 0) { | ||
guess = 0.1; | ||
} | ||
if (tol === void 0) { | ||
tol = 1e-6; | ||
} | ||
if (maxIter === void 0) { | ||
maxIter = 100; | ||
} | ||
// Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
// ASF licensed (check the link for the full license) | ||
// Credits: algorithm inspired by Apache OpenOffice | ||
// Initialize dates and check that values contains at | ||
// least one positive value and one negative value | ||
var dates = []; | ||
var positive = false; | ||
var negative = false; | ||
for (var i = 0; i < values.length; i++) { | ||
dates[i] = i === 0 ? 0 : dates[i - 1] + 365; | ||
if (values[i] > 0) { | ||
positive = true; | ||
} | ||
if (values[i] < 0) { | ||
negative = true; | ||
} | ||
} // Return error if values does not contain at least one positive value and one negative value | ||
if (!positive || !negative) { | ||
return Number.NaN; | ||
} // Initialize guess and resultRate | ||
var resultRate = guess; // Implement Newton's method | ||
var newRate, epsRate, resultValue; | ||
var iteration = 0; | ||
var contLoop = true; | ||
do { | ||
resultValue = _irrResult(values, dates, resultRate); | ||
newRate = resultRate - resultValue / _irrResultDeriv(values, dates, resultRate); | ||
epsRate = Math.abs(newRate - resultRate); | ||
resultRate = newRate; | ||
contLoop = epsRate > tol && Math.abs(resultValue) > tol; | ||
} while (contLoop && ++iteration < maxIter); | ||
if (contLoop) { | ||
return Number.NaN; | ||
} // Return internal rate of return | ||
return resultRate; | ||
} | ||
/** | ||
* This function is here to simply have a different name for the 'fv' | ||
@@ -489,4 +610,45 @@ * function to not interfere with the 'fv' keyword argument within the 'ipmt' | ||
} | ||
/** | ||
* Calculates the resulting amount. | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
export { PaymentDueTime, fv, ipmt, nper, pmt, ppmt, pv, rate }; | ||
function _irrResult(values, dates, rate) { | ||
var r = rate + 1; | ||
var result = values[0]; | ||
for (var i = 1; i < values.length; i++) { | ||
result += values[i] / Math.pow(r, (dates[i] - dates[0]) / 365); | ||
} | ||
return result; | ||
} | ||
/** | ||
* Calculates the first derivation | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
function _irrResultDeriv(values, dates, rate) { | ||
var r = rate + 1; | ||
var result = 0; | ||
for (var i = 1; i < values.length; i++) { | ||
var frac = (dates[i] - dates[0]) / 365; | ||
result -= frac * values[i] / Math.pow(r, frac + 1); | ||
} | ||
return result; | ||
} | ||
export { PaymentDueTime, fv, ipmt, irr, nper, pmt, ppmt, pv, rate }; | ||
//# sourceMappingURL=financial.esm.js.map |
@@ -5,3 +5,3 @@ { | ||
"author": "Luciano Mammino <no@spam.com> (https://loige.co)", | ||
"version": "0.0.16", | ||
"version": "0.0.17", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
@@ -91,3 +91,3 @@ # Financial | ||
- [X] `rate` | ||
- [ ] `irr` | ||
- [X] `irr` | ||
- [ ] `npv` | ||
@@ -94,0 +94,0 @@ - [ ] `mirr` |
@@ -399,2 +399,109 @@ /** | ||
/** | ||
* Return the Internal Rate of Return (IRR). | ||
* | ||
* 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. | ||
* | ||
* @param values - 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. | ||
* @param guess - Starting guess for solving the Internal Rate of Return | ||
* @param tol - Required tolerance for the solution | ||
* @param maxIter - Maximum iterations in finding the solution | ||
* | ||
* @returns Internal Rate of Return for periodic input values | ||
* | ||
* ## Notes | ||
* | ||
* The IRR is perhaps best understood through an example (illustrated | ||
* using `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 `r`) of the equation: | ||
* | ||
* ``` | ||
* -100 + 39/(1+r) + 59/((1+r)^2) + 55/((1+r)^3) + 20/((1+r)^4) = 0 | ||
* ``` | ||
* | ||
* In general, for `values` = `[0, 1, ... M]`, | ||
* `irr` is the solution of the equation: | ||
* | ||
* ``` | ||
* \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0 | ||
* ``` | ||
* | ||
* ## Example | ||
* | ||
* ```javascript | ||
* import { irr } from 'financial' | ||
* | ||
* irr([-100, 39, 59, 55, 20]) // 0.28095 | ||
* irr([-100, 0, 0, 74]) // -0.0955 | ||
* irr([-100, 100, 0, -7]) // -0.0833 | ||
* irr([-100, 100, 0, 7]) // 0.06206 | ||
* irr([-5, 10.5, 1, -8, 1]) // 0.0886 | ||
* ``` | ||
* | ||
* ## References | ||
* | ||
* - L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed., | ||
* Addison-Wesley, 2003, pg. 348. | ||
*/ | ||
export function irr (values: number[], guess = 0.1, tol = 1e-6, maxIter = 100): number { | ||
// Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
// ASF licensed (check the link for the full license) | ||
// Credits: algorithm inspired by Apache OpenOffice | ||
// Initialize dates and check that values contains at | ||
// least one positive value and one negative value | ||
const dates : number[] = [] | ||
let positive = false | ||
let negative = false | ||
for (var i = 0; i < values.length; i++) { | ||
dates[i] = (i === 0) ? 0 : dates[i - 1] + 365 | ||
if (values[i] > 0) { | ||
positive = true | ||
} | ||
if (values[i] < 0) { | ||
negative = true | ||
} | ||
} | ||
// Return error if values does not contain at least one positive value and one negative value | ||
if (!positive || !negative) { | ||
return Number.NaN | ||
} | ||
// Initialize guess and resultRate | ||
let resultRate = guess | ||
// Implement Newton's method | ||
let newRate, epsRate, resultValue | ||
let iteration = 0 | ||
let contLoop = true | ||
do { | ||
resultValue = _irrResult(values, dates, resultRate) | ||
newRate = resultRate - resultValue / _irrResultDeriv(values, dates, resultRate) | ||
epsRate = Math.abs(newRate - resultRate) | ||
resultRate = newRate | ||
contLoop = (epsRate > tol) && (Math.abs(resultValue) > tol) | ||
} while (contLoop && (++iteration < maxIter)) | ||
if (contLoop) { | ||
return Number.NaN | ||
} | ||
// Return internal rate of return | ||
return resultRate | ||
} | ||
/** | ||
* This function is here to simply have a different name for the 'fv' | ||
@@ -432,1 +539,36 @@ * function to not interfere with the 'fv' keyword argument within the 'ipmt' | ||
} | ||
/** | ||
* Calculates the resulting amount. | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
function _irrResult (values: number[], dates: number[], rate: number): number { | ||
const r = rate + 1 | ||
let result = values[0] | ||
for (let i = 1; i < values.length; i++) { | ||
result += values[i] / Math.pow(r, (dates[i] - dates[0]) / 365) | ||
} | ||
return result | ||
} | ||
/** | ||
* Calculates the first derivation | ||
* | ||
* Based on https://gist.github.com/ghalimi/4591338 by @ghalimi | ||
* ASF licensed (check the link for the full license) | ||
* | ||
* @private | ||
*/ | ||
function _irrResultDeriv (values: number[], dates: number[], rate: number) : number { | ||
const r = rate + 1 | ||
let result = 0 | ||
for (let i = 1; i < values.length; i++) { | ||
const frac = (dates[i] - dates[0]) / 365 | ||
result -= frac * values[i] / Math.pow(r, frac + 1) | ||
} | ||
return result | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
146048
2106