diff --git a/Algorithms.Tests/Financial/PresentValueTests.cs b/Algorithms.Tests/Financial/PresentValueTests.cs new file mode 100644 index 00000000..bf2dcaea --- /dev/null +++ b/Algorithms.Tests/Financial/PresentValueTests.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Algorithms.Financial; +using FluentAssertions; +using NUnit.Framework; + +namespace Algorithms.Tests.Financial; + +public static class PresentValueTests +{ + [TestCase(0.13,new[] { 10.0, 20.70, -293.0, 297.0 },4.69)] + [TestCase(0.07,new[] { -109129.39, 30923.23, 15098.93, 29734.0, 39.0 }, -42739.63)] + [TestCase(0.07, new[] { 109129.39, 30923.23, 15098.93, 29734.0, 39.0 }, 175519.15)] + [TestCase(0.0, new[] { 109129.39, 30923.23, 15098.93, 29734.0, 39.0 }, 184924.55)] + + public static void Present_Value_General_Tests(double discountRate,double[] cashFlow ,double expected) + => + PresentValue.Calculate(discountRate, cashFlow.ToList()) + .Should() + .Be(expected); + + + [TestCase(-1.0, new[] { 10.0, 20.70, -293.0, 297.0 })] + [TestCase(1.0,new double[] {})] + + public static void Present_Value_Exception_Tests(double discountRate, double[] cashFlow) + => Assert.Throws(() => PresentValue.Calculate(discountRate, cashFlow.ToList())); +} diff --git a/Algorithms/Financial/PresentValue.cs b/Algorithms/Financial/PresentValue.cs new file mode 100644 index 00000000..805bcd14 --- /dev/null +++ b/Algorithms/Financial/PresentValue.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Algorithms.Financial; + +/// +/// PresentValue is the value of an expected income stream determined as of the date of valuation. +/// +public static class PresentValue +{ + public static double Calculate(double discountRate, List cashFlows) + { + if (discountRate < 0) + { + throw new ArgumentException("Discount rate cannot be negative"); + } + + if (cashFlows.Count == 0) + { + throw new ArgumentException("Cash flows list cannot be empty"); + } + + double presentValue = cashFlows.Select((t, i) => t / Math.Pow(1 + discountRate, i)).Sum(); + + return Math.Round(presentValue, 2); + } +}