2020-10-16 16:40:54 +03:00

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;
}
}
}