diff --git a/Frends.Community.ExcelFinancialFunctions.Tests/XIrr.Tests.cs b/Frends.Community.ExcelFinancialFunctions.Tests/XIrr.Tests.cs
index c058c59..c0e3d7f 100644
--- a/Frends.Community.ExcelFinancialFunctions.Tests/XIrr.Tests.cs
+++ b/Frends.Community.ExcelFinancialFunctions.Tests/XIrr.Tests.cs
@@ -36,13 +36,12 @@ public void ThreeXIrrToolss()
var options = new Options
{
- Tolerance = 0.00000001,
- MaxIterations = 100
+ Guess = 0.1
};
var ret = XIrrTools.CalculateXIrr(input, options, new System.Threading.CancellationToken());
- Assert.That(ret.Value, Is.EqualTo("77.4425237947709"));
+ Assert.That(ret.Value, Is.EqualTo("77.4425237947701"));
}
}
}
diff --git a/Frends.Community.ExcelFinancialFunctions/Definition.cs b/Frends.Community.ExcelFinancialFunctions/Definition.cs
index 32d378d..021c178 100644
--- a/Frends.Community.ExcelFinancialFunctions/Definition.cs
+++ b/Frends.Community.ExcelFinancialFunctions/Definition.cs
@@ -11,7 +11,7 @@ namespace Frends.Community.ExcelFinancialFunctions
public class Parameters
{
///
- /// JArray string with value and date
+ /// JArray string with value and date Dates should be sorted in ascending order.
///
///
/// [{value: 1.234, date: "2021-05-25"}, {value: 2.345, date: "2022-05-25"}]
@@ -26,16 +26,25 @@ public class Parameters
public class Options
{
///
- /// Tolerance that will be used in calculations.
+ /// Guess is a number that you guess is close to the result of XIRR.
///
- [DefaultValue(0.00000001)]
- public double Tolerance { get; set; }
+ [DefaultValue(0.1)]
+ public double Guess { get; set; }
///
- /// Max number of iterations(to prevent infinite looping).
+ /// If set, allows you to ignore errors and return specified value.
+ /// If not set, error will be thrown normally.
///
- [DefaultValue(100)]
- public int MaxIterations { get; set; }
+ [DefaultValue(false)]
+ public bool ReturnValueOnError { get; set; }
+
+ ///
+ /// What task should return on failure (string)
+ ///
+ [UIHint(nameof(ReturnValueOnError), "", true)]
+ [DisplayFormat(DataFormatString = "Text")]
+ [DefaultValue("NM")]
+ public string ReturnValue { get; set; }
}
public class Result
diff --git a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj
index adbd40e..a1928d8 100644
--- a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj
+++ b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj
@@ -2,6 +2,7 @@
netstandard2.0;net471
+ Tasks for financial calculations using Excel Functions
HiQ Finland
HiQ Finland
MIT
@@ -9,7 +10,7 @@
true
Frends
true
- 0.1.6
+ 0.1.13
@@ -19,6 +20,8 @@
+
+
diff --git a/Frends.Community.ExcelFinancialFunctions/Methods.cs b/Frends.Community.ExcelFinancialFunctions/Methods.cs
index ce10e8a..53c49d0 100644
--- a/Frends.Community.ExcelFinancialFunctions/Methods.cs
+++ b/Frends.Community.ExcelFinancialFunctions/Methods.cs
@@ -1,90 +1,44 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Threading;
namespace Frends.Community.ExcelFinancialFunctions
{
internal class Methods
{
- public delegate double fx(double x);
-
- public static fx composeFunctions(fx f1, fx f2)
- {
- return (double x) => f1(x) + f2(x);
- }
-
- public static fx f_xirr(double p, double dt, double dt0)
- {
- return (double x) => p * Math.Pow((1.0 + x), ((dt0 - dt) / 365.0));
- }
-
- public static fx df_xirr(double p, double dt, double dt0)
- {
- return (double x) => (1.0 / 365.0) * (dt0 - dt) * p * Math.Pow((x + 1.0), (((dt0 - dt) / 365.0) - 1.0));
- }
-
- public static fx total_f_xirr(double[] payments, double[] days)
+ ///
+ /// Calculates XIrr using ExcelFinancialFunctions .NET Standard library
+ ///
+ ///
+ public static List getPaymentsFromJArray(JArray jarray, CancellationToken cancellationToken)
{
- fx resf = (double x) => 0.0;
+ var values = new List();
- for (int i = 0; i < payments.Length; i++)
+ foreach (var item in jarray)
{
- resf = composeFunctions(resf, f_xirr(payments[i], days[i], days[0]));
- }
-
- return resf;
- }
-
- public static fx total_df_xirr(double[] payments, double[] days)
- {
- fx resf = (double x) => 0.0;
+ cancellationToken.ThrowIfCancellationRequested();
- for (int i = 0; i < payments.Length; i++)
- {
- resf = composeFunctions(resf, df_xirr(payments[i], days[i], days[0]));
+ double value = double.Parse(item["value"].ToString());
+ values.Add(value);
}
- return resf;
+ return values;
}
-
- ///
- /// Calculates XIrr using Newton's method
- ///
- ///
- public static double Newtons_method(double guess, fx f, fx df, double tol, int maxIterations, CancellationToken cancellationToken)
+ public static List getDatesFromJArray(JArray jarray, CancellationToken cancellationToken)
{
- int i = 0;
- double x0 = guess;
- double x1 = 0.0;
- double err = 1e+100;
+ var dates = new List();
- while (err > tol && ++i < maxIterations)
+ foreach (var item in jarray)
{
cancellationToken.ThrowIfCancellationRequested();
- x1 = x0 - f(x0) / df(x0);
- err = Math.Abs(x1 - x0);
- x0 = x1;
- }
- if (i == maxIterations)
- {
- throw new InvalidOperationException("Could not calculate: No solution found. Max iterations reached.");
- }
-
- return x0;
- }
- public static double[] getPaymentsFromJArray(JArray jarray)
- {
- return jarray.Select(x => double.Parse(x["value"].ToString())).ToList().ToArray();
- }
+ DateTime date = DateTime.Parse(item["date"].ToString());
+ dates.Add(date);
+ }
- public static double[] getDaysFromJArray(JArray jarray)
- {
- return jarray.Select(x => (double)DateTime.Parse(x["date"].ToString()).DayOfYear).ToList().ToArray();
+ return dates;
}
}
}
diff --git a/Frends.Community.ExcelFinancialFunctions/XIrrTools.cs b/Frends.Community.ExcelFinancialFunctions/XIrrTools.cs
index 76c8e62..61a58c5 100644
--- a/Frends.Community.ExcelFinancialFunctions/XIrrTools.cs
+++ b/Frends.Community.ExcelFinancialFunctions/XIrrTools.cs
@@ -1,7 +1,9 @@
using System.ComponentModel;
using System.Threading;
-using Microsoft.CSharp; // You can remove this if you don't need dynamic type in .NET Standard frends Tasks
using Newtonsoft.Json.Linq;
+using Excel.FinancialFunctions;
+using System.Collections.Generic;
+using System;
#pragma warning disable 1591
@@ -14,26 +16,36 @@ public static class XIrrTools
/// Documentation: https://github.com/CommunityHiQ/Frends.Community.ExcelFinancialFunctions
///
/// Values and dates for calculations
- /// Define tollerance and max iterations.
+ /// Define guess and error value.
///
/// Object {string Value}
public static Result CalculateXIrr([PropertyTab] Parameters input, [PropertyTab] Options options, CancellationToken cancellationToken)
{
JArray jarray = JArray.Parse(input.Input);
- int maxIter = options.MaxIterations;
- double tol = options.Tolerance;
+ double guess = options.Guess;
- double[] payments = Methods.getPaymentsFromJArray(jarray); // payments
- double[] days = Methods.getDaysFromJArray(jarray); // days of payment (as day of year)
- double xirr = Methods.Newtons_method(0.1,
- Methods.total_f_xirr(payments, days),
- Methods.total_df_xirr(payments, days),
- tol,
- maxIter,
- cancellationToken);
+ List payments = Methods.getPaymentsFromJArray(jarray, cancellationToken); // payments
+ List dates = Methods.getDatesFromJArray(jarray, cancellationToken); // dates of payment
+ string xirr;
+ if (options.ReturnValueOnError)
+ {
+ try
+ {
+ xirr = Financial.XIrr(payments, dates, guess).ToString();
+ }
+ catch (Exception)
+ {
+ xirr = options.ReturnValue.ToString();
+ }
+ }
+ else
+ {
+ xirr = Financial.XIrr(payments, dates, guess).ToString();
+ }
+
var output = new Result
{
Value = xirr.ToString()
diff --git a/README.md b/README.md
index 538233d..bd06d06 100644
--- a/README.md
+++ b/README.md
@@ -20,20 +20,19 @@ https://www.myget.org/F/frends-community/api/v3/index.json and in Gallery view i
## XIrrTools
-Task calculates XIrr value using Newtons method
+Task calculates XIrr value using Excel Financial Functions from .NET library
### Properties
| Property | Type | Description | Example |
| -------- | -------- | -------- | -------- |
-| Input | `string` | JArray string with values and dates. | `[{value: 1.234, date: "2021-05-25"}, {value: 2.345, date: "2022-05-25"}]` |
+| Input | `string` | JArray string with values and dates. Dates should be sorted in ascending order.| `[{value: 1.234, date: "2021-05-25"}, {value: 2.345, date: "2022-05-25"}]` |
### Options
| Property | Type | Description | Example |
| -------- | -------- | -------- | -------- |
-| Tolerance | `double` | Tolerance used in calculations. | `0.00000001` |
-| MaxIterations | `int` | Max. number of iterations while calculating Xirr value. | `100` |
+| Guess | `double` | Guess is a number that you guess is close to the result of XIRR. | `0.1` |
### Returns
@@ -41,7 +40,7 @@ A result object with parameters.
| Property | Type | Description | Example |
| -------- | -------- | -------- | -------- |
-| Value | `string` | Calculated XIrr value. | `77.4425237947709` |
+| Value | `string` | Calculated XIrr value. | `77.4425237947701` |
Usage:
To fetch result use syntax:
@@ -87,3 +86,10 @@ NOTE: Be sure to merge the latest from "upstream" before making a pull request!
| 0.1.4 | Test case created, README updated |
| 0.1.5 | Fixed input tab |
| 0.1.6 | Minor changes to descriptions |
+| 0.1.7 | Add description to .csproj file |
+| 0.1.8 | Calculate Xirr using .NET Excel library |
+| 0.1.9 | Add FSharp.Core to the task |
+| 0.1.10 | Remove unnecessary comments and namespaces |
+| 0.1.11 | Update README |
+| 0.1.12 | Add option to return value on error |
+| 0.1.13 | Update Properties description |