73 lines
1.9 KiB
C#
73 lines
1.9 KiB
C#
using System;
|
|
using EvoCalculator.Core.Models.Calculation.Interfaces;
|
|
using EvoCalculator.Core.Models.Calculation.Models;
|
|
|
|
namespace EvoCalculator.Core.FinanceFormulas
|
|
{
|
|
public class XIRR : IFinanceFormula<double>
|
|
{
|
|
private readonly Flow[] _flows;
|
|
private readonly double _guess = 0.1;
|
|
|
|
public XIRR(Flow[] flows)
|
|
{
|
|
_flows = flows;
|
|
}
|
|
|
|
public XIRR(Flow[] flows, double guess)
|
|
{
|
|
_flows = flows;
|
|
_guess = guess;
|
|
}
|
|
|
|
public double GetResult()
|
|
{
|
|
var x1 = 0.0;
|
|
var x2 = _guess;
|
|
var f1 = new XNPV(_flows, x1).GetResult();
|
|
var f2 = new XNPV(_flows, x2).GetResult();
|
|
|
|
for (var i = 0; i < 100; i++)
|
|
{
|
|
if (f1 * f2 < 0.0) break;
|
|
if (Math.Abs(f1) < Math.Abs(f2))
|
|
{
|
|
x1 += 1.6 * (x1 - x2);
|
|
f1 = new XNPV(_flows, x1).GetResult();
|
|
}
|
|
else
|
|
{
|
|
x2 += 1.6 * (x2 - x1);
|
|
f2 = new XNPV(_flows, x2).GetResult();
|
|
}
|
|
}
|
|
|
|
if (f1 * f2 > 0.0) return 0;
|
|
|
|
var f = new XNPV(_flows, x1).GetResult();
|
|
var dx = 0.0;
|
|
var rtb = 0.0;
|
|
if (f < 0.0)
|
|
{
|
|
rtb = x1;
|
|
dx = x2 - x1;
|
|
}
|
|
else
|
|
{
|
|
rtb = x2;
|
|
dx = x1 - x2;
|
|
}
|
|
|
|
for (var i = 0; i < 100; i++)
|
|
{
|
|
dx *= 0.5;
|
|
var xMid = rtb + dx;
|
|
var fMid = new XNPV(_flows, xMid).GetResult();
|
|
if (fMid <= 0.0) rtb = xMid;
|
|
if (Math.Abs(fMid) < 1.0e-6 || Math.Abs(dx) < 1.0e-6) return xMid;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
} |