Finance
  • Introduction
  • 財務報表
    • 可轉債
    • 質押比
    • 毛利率、營業利益率、純益率
  • IRR
  • NOI, EBIT, Capitalization Rate
  • 複利
  • 股市技術面
    • RSV 與 KD
    • 移動平均線 ( MA )
    • RSI 指標
    • 布林通道
    • EMA
    • 型態分析
      • W 型態
  • TradingView 使用
    • 撰寫 Pine script
  • 期貨與選擇權
    • 期貨
    • 選擇權
  • Startup
Powered by GitBook
On this page
  • IRR (Internal Rate of Return)
  • 用程式計算:
  • 較複雜的公式
  • 但上面的公式還是會有不準確的時候

Was this helpful?

IRR

Previous毛利率、營業利益率、純益率NextNOI, EBIT, Capitalization Rate

Last updated 5 years ago

Was this helpful?

IRR (Internal Rate of Return)

假設:

(1) 現在資產價值(PV)=100
(2) 十年後的未來資產價值(FV)=121.8994
(3) 利率(rate) R= 2%
(4) 期數(nper) n=10 (年)
(5) 十年後的末來值:FV= PV x [(1+R) ^n] = 100 x [(1+2%) ^10] =121.8994元
(6) 現值 :PV = FV / [(1+R)^n] = 121.8994 / [(1+2%) ^10]= 100

所以:

已知本金為100元及十年後的定存本利和為121.8994元,但不知道定存利率為多少,就以用 IRR 來做計算出定存利率的值。

用程式計算:

IRR = Math.round((Math.pow(121.899/100, 1/10) - 1) * 100)

及為Math.round((Math.pow(投資結束後資金總和/原始投入資金, 1/投資總年數) - 1) * 100)

Math.pow(x, y)為 x的y次方,所以轉換為10分之1次方,然後因為原本100 * (1.02 ** 10) ,所以會有121.899/100

最後面 - 1) * 100) 的原因是要把 1.02 轉換為 2%,方便看。

Math.round 為化整,四捨五入

參考:

較複雜的公式

function IRR(values, guess) {
  // Calculates the resulting amount
  const irrResult = function(values, dates, rate) {
    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
  const irrResultDeriv = function(values, dates, rate) {
    const r = rate + 1;
    let 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;
  };

  // Initialize dates and check that values contains at least one positive value and one negative value
  let dates = [];
  let positive = false;
  let negative = false;
  for (let 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 '#NUM!';

  // Initialize guess and resultRate
  guess = typeof guess === 'undefined' ? 0.1 : guess;
  let resultRate = guess;

  // Set maximum epsilon for end of iteration
  let epsMax = 1e-10;

  // Set maximum number of iterations
  let iterMax = 50;

  // 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 > epsMax && Math.abs(resultValue) > epsMax;
  } while (contLoop && ++iteration < iterMax);

  if (contLoop) return '#NUM!';

  // Return internal rate of return
  return resultRate;
}

e.g. 第一年投入25,之後每年的利息分別為,2,3,3,3最後一年退出時賣出30

IRR([-25,2,3,3,3,30]) = 0.12258040492894852 = 12.26%

e.g. 投入三年,第一年投入10元,之後三年的利息均得到2元,利率及為20%。

IRR([-10,2,2,12]) = 0.2

但上面的公式還是會有不準確的時候

let guess = Math.pow(arrSum(values) / values[0], 1 / ((values.length - 1) / 2 + 1)) - 1;

加強版

function IRR(values) {
  // Calculates the resulting amount
  const irrResult = function(values, dates, rate) {
    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
  const irrResultDeriv = function(values, dates, rate) {
    const r = rate + 1;
    let 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;
  };

  // Initialize dates and check that values contains at least one positive value and one negative value
  let dates = [];
  let positive = false;
  let negative = false;
  for (let 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 '#NUM!';

  // Initialize guess and resultRate

  // This value of guess is from Enhanced Newton-Raphson Algorithm

  const arrSum = values => values.reduce((a, b) => a + b, 0);
  // 參考至 https://www.ijeat.org/wp-content/uploads/papers/v8i3S/C10810283S19.pdf
  let guess = Math.pow(arrSum(values) / values[0], 1 / ((values.length - 1) / 2 + 1)) - 1;

  let resultRate = guess ? guess : 1e-8;
  // Set maximum epsilon for end of iteration
  let epsMax = 1e-10;

  // Set maximum number of iterations
  let iterMax = 50;

  // 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 > epsMax && Math.abs(resultValue) > epsMax;
  } while (contLoop && ++iteration < iterMax);

  if (contLoop) return '#NUM!';

  // Return internal rate of return
  return resultRate;
}

參考 新增了加強版的算法

https://www.moneysmart.tw/articles/%E8%B2%B7%E5%84%B2%E8%93%84%E9%9A%AA%E5%85%88%E6%87%82-irr/
https://www.ijeat.org/wp-content/uploads/papers/v8i3S/C10810283S19.pdf