From 43cb80b4d8ae08b3990ba788eac93babac97bf8b Mon Sep 17 00:00:00 2001 From: dleman Date: Mon, 4 Jul 2022 10:18:42 +0200 Subject: [PATCH 1/3] Add description to .csproj file --- .../Frends.Community.ExcelFinancialFunctions.csproj | 3 ++- README.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj index adbd40e..a433701 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.7 diff --git a/README.md b/README.md index 538233d..800214c 100644 --- a/README.md +++ b/README.md @@ -87,3 +87,4 @@ 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 | From 1cbcd3ef77e808fb70c0d8a331ff1a4a373d7ac8 Mon Sep 17 00:00:00 2001 From: dleman Date: Mon, 4 Jul 2022 13:16:26 +0200 Subject: [PATCH 2/3] Implement task with new approach using .NET Excel library --- .../XIrr.Tests.cs | 5 +- .../Definition.cs | 21 +++-- ...s.Community.ExcelFinancialFunctions.csproj | 4 +- .../Methods.cs | 82 ++++--------------- .../XIrrTools.cs | 36 +++++--- README.md | 12 ++- 6 files changed, 70 insertions(+), 90 deletions(-) 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..9eb6d6d 100644 --- a/Frends.Community.ExcelFinancialFunctions/Definition.cs +++ b/Frends.Community.ExcelFinancialFunctions/Definition.cs @@ -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 a433701..6364253 100644 --- a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj +++ b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj @@ -10,7 +10,7 @@ true Frends true - 0.1.7 + 0.1.12 @@ -20,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 800214c..8708c47 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ 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 @@ -32,8 +32,7 @@ Task calculates XIrr value using Newtons method | 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: @@ -88,3 +87,8 @@ NOTE: Be sure to merge the latest from "upstream" before making a pull request! | 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 | From d83e1a18a246ee6c0ebf20cd0819d96670cda299 Mon Sep 17 00:00:00 2001 From: dleman Date: Tue, 11 Oct 2022 12:39:03 +0200 Subject: [PATCH 3/3] FCOM-339: Update documentation Add information about sorting dates in asc order --- Frends.Community.ExcelFinancialFunctions/Definition.cs | 2 +- .../Frends.Community.ExcelFinancialFunctions.csproj | 2 +- README.md | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Frends.Community.ExcelFinancialFunctions/Definition.cs b/Frends.Community.ExcelFinancialFunctions/Definition.cs index 9eb6d6d..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"}] diff --git a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj index 6364253..a1928d8 100644 --- a/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj +++ b/Frends.Community.ExcelFinancialFunctions/Frends.Community.ExcelFinancialFunctions.csproj @@ -10,7 +10,7 @@ true Frends true - 0.1.12 + 0.1.13 diff --git a/README.md b/README.md index 8708c47..bd06d06 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Task calculates XIrr value using Excel Financial Functions from .NET library | 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 @@ -92,3 +92,4 @@ NOTE: Be sure to merge the latest from "upstream" before making a pull request! | 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 |