diff --git a/src/Numerics/Financial/AbsoluteReturnMeasures.cs b/src/Numerics/Financial/AbsoluteReturnMeasures.cs
new file mode 100644
index 00000000..369340a8
--- /dev/null
+++ b/src/Numerics/Financial/AbsoluteReturnMeasures.cs
@@ -0,0 +1,103 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.Financial
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using MathNet.Numerics.Statistics;
+
+ public static class AbsoluteReturnMeasures
+ {
+ ///
+ /// Compound Monthly Return or Geometric Return or Annualized Return
+ ///
+ ///
+ ///
+ public static double CompoundMonthlyReturn(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var samples = data.Count();
+ if (samples == 0)
+ return double.NaN;
+
+ double compoundReturn = 1.0;
+ foreach (var item in data)
+ {
+ compoundReturn *= (1 + item);
+ }
+ return Math.Pow(compoundReturn, 1.0 / (double)samples) - 1.0;
+ }
+
+ ///
+ /// Average Gain or Gain Mean
+ /// This is a simple average (arithmetic mean) of the periods with a gain. It is calculated by summing the returns for gain periods (return 0)
+ /// and then dividing the total by the number of gain periods.
+ ///
+ ///
+ ///
+ /// http://www.offshore-library.com/kb/statistics.php
+ public static double GainMean(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var gains = data.Where(x => x >= 0);
+ return gains.Mean();
+ }
+
+ ///
+ /// Average Loss or LossMean
+ /// This is a simple average (arithmetic mean) of the periods with a loss. It is calculated by summing the returns for loss periods (return < 0)
+ /// and then dividing the total by the number of loss periods.
+ ///
+ ///
+ ///
+ /// http://www.offshore-library.com/kb/statistics.php
+ public static double LossMean(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var losses = data.Where(x => x < 0);
+ return losses.Mean();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Numerics/Financial/AbsoluteRiskStatistics.cs b/src/Numerics/Financial/AbsoluteRiskStatistics.cs
index 0d7e8aa6..f092493e 100644
--- a/src/Numerics/Financial/AbsoluteRiskStatistics.cs
+++ b/src/Numerics/Financial/AbsoluteRiskStatistics.cs
@@ -36,7 +36,7 @@ namespace MathNet.Numerics.Financial
using System.Text;
using MathNet.Numerics.Statistics;
- public static class AbsoluteRiskStatistics
+ public static class AbsoluteRiskMeasures
{
//Note: The following statistics would be condidered an absolute risk statistic in the finance realm as well.
// Standard Deviation
@@ -135,44 +135,6 @@ namespace MathNet.Numerics.Financial
return belowMeanData.StandardDeviation();
}
- ///
- /// Average Gain or Gain Mean
- /// This is a simple average (arithmetic mean) of the periods with a gain. It is calculated by summing the returns for gain periods (return 0)
- /// and then dividing the total by the number of gain periods.
- ///
- ///
- ///
- /// http://www.offshore-library.com/kb/statistics.php
- public static double GainMean(this IEnumerable data)
- {
- if (data == null)
- {
- throw new ArgumentNullException("data");
- }
-
- var gains = data.Where(x => x >= 0);
- return gains.Mean();
- }
-
- ///
- /// Average Loss or LossMean
- /// This is a simple average (arithmetic mean) of the periods with a loss. It is calculated by summing the returns for loss periods (return < 0)
- /// and then dividing the total by the number of loss periods.
- ///
- ///
- ///
- /// http://www.offshore-library.com/kb/statistics.php
- public static double LossMean(this IEnumerable data)
- {
- if (data == null)
- {
- throw new ArgumentNullException("data");
- }
-
- var losses = data.Where(x => x < 0);
- return losses.Mean();
- }
-
///
/// Measures a fund’s average gain in a gain period divided by the fund’s average loss in a losing
/// period. Periods can be monthly or quarterly depending on the data frequency.
@@ -190,9 +152,9 @@ namespace MathNet.Numerics.Financial
var losses = data.Where(x => x < 0);
var lossMean = losses.Mean();
- if(lossMean != 0.0)
- return Math.Abs(gains.Mean() / losses.Mean());
- return 0.0;
+
+ return Math.Abs(gains.Mean() / losses.Mean());
+
}
}
}
diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index 226e8d46..8da1e940 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -105,6 +105,7 @@
+
diff --git a/src/UnitTests/FinancialTests/CompoundMonthlyReturnTests.cs b/src/UnitTests/FinancialTests/CompoundMonthlyReturnTests.cs
new file mode 100644
index 00000000..1cbc23dc
--- /dev/null
+++ b/src/UnitTests/FinancialTests/CompoundMonthlyReturnTests.cs
@@ -0,0 +1,75 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.FinancialTests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using MathNet.Numerics.Financial;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class CompoundMonthlyReturnTests
+ {
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.CompoundMonthlyReturn();
+ }
+
+ [Test]
+ public void returns_undefined_with_empty_input_data()
+ {
+ //arrange
+ List inputData = new List();
+ //act
+ var cmpdReturn = inputData.CompoundMonthlyReturn();
+ //assert
+ Assert.AreEqual(double.NaN, cmpdReturn);
+ }
+
+ [Test]
+ public void calculates_the_compound_monthly_return()
+ {
+ //arrange
+ var inputData = new[] { 0.2, 0.06, 0.01 };
+ //act
+ var cmpdReturn = inputData.CompoundMonthlyReturn();
+ //assert
+ AssertHelpers.AlmostEqual(0.0870999982199265, cmpdReturn, 15);
+ }
+
+ //Definitly need more tests here. Would love to find test data for these stats similar to the .dat files used for other tests.
+ }
+
+}
\ No newline at end of file
diff --git a/src/UnitTests/FinancialTests/DownsideDeviationTests.cs b/src/UnitTests/FinancialTests/DownsideDeviationTests.cs
index fa2e2165..d57075bf 100644
--- a/src/UnitTests/FinancialTests/DownsideDeviationTests.cs
+++ b/src/UnitTests/FinancialTests/DownsideDeviationTests.cs
@@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class DownsideDeviationTests
{
[Test]
diff --git a/src/UnitTests/FinancialTests/GainLossRatioTests.cs b/src/UnitTests/FinancialTests/GainLossRatioTests.cs
index d3c3536b..571345df 100644
--- a/src/UnitTests/FinancialTests/GainLossRatioTests.cs
+++ b/src/UnitTests/FinancialTests/GainLossRatioTests.cs
@@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class GainLossRatioTests
{
[Test]
@@ -48,61 +49,61 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
[Test]
//Not sure this is correct. Undefined may be more correct.
- public void returns_zero_for_a_single_positive_input()
+ public void returns_NaN_for_a_single_positive_input()
{
//arrange
var inputData = new[] { 1.0 };
//act
var gainLossRatio = inputData.GainLossRatio();
//assert
- Assert.AreEqual(0.0, gainLossRatio);
+ Assert.AreEqual(double.NaN, gainLossRatio);
}
[Test]
//Not sure this is correct. Undefined may be more correct.
- public void returns_zero_for_a_single_negative_input()
+ public void returns_NaN_for_a_single_negative_input()
{
//arrange
var inputData = new[] { -1.0 };
//act
var gainLossRatio = inputData.GainLossRatio();
//assert
- Assert.AreEqual(0.0, gainLossRatio);
+ Assert.AreEqual(double.NaN, gainLossRatio);
}
[Test]
//Not sure this is correct. Undefined may be more correct.
- public void returns_zero_for_a_set_of_all_positive_numbers()
+ public void returns_NaN_for_a_set_of_all_positive_numbers()
{
//arrange
var inputData = new[] { 1.0, 2.0, 3.0 };
//act
var gainLossRatio = inputData.GainLossRatio();
//assert
- Assert.AreEqual(0.0, gainLossRatio);
+ Assert.AreEqual(double.NaN, gainLossRatio);
}
[Test]
//Not sure this is correct. Undefined may be more correct.
- public void returns_zero_for_a_set_of_all_negative_numbers()
+ public void returns_NaN_for_a_set_of_all_negative_numbers()
{
//arrange
var inputData = new[] { -1.0, -2.0, -3.0 };
//act
var gainLossRatio = inputData.GainLossRatio();
//assert
- Assert.AreEqual(0.0, gainLossRatio);
+ Assert.AreEqual(double.NaN, gainLossRatio);
}
[Test]
public void handles_a_value_of_zero_as_a_positive()
{
//arrange
- var inputData = new[] { 0.0, 1.0, 2.0 };
+ var inputData = new[] { 0.0, -1.0 };
//act
- var gainLossRatio = inputData.GainLossRatio();
+ var gainLossRatio = inputData.GainLossRatio();
//assert
- Assert.AreEqual(0.0, gainLossRatio);
+ Assert.AreEqual(0.0, gainLossRatio); //0.0 / -1.0 => 0.0
}
[Test]
diff --git a/src/UnitTests/FinancialTests/GainMeanTests.cs b/src/UnitTests/FinancialTests/GainMeanTests.cs
index 154d92a1..c91d9460 100644
--- a/src/UnitTests/FinancialTests/GainMeanTests.cs
+++ b/src/UnitTests/FinancialTests/GainMeanTests.cs
@@ -33,6 +33,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class GainMeanTests
{
[Test]
@@ -46,14 +47,14 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
Assert.AreEqual(0.0, gainMean);
}
[Test]
- public void returns_zero_when_all_input_is_negative()
+ public void returns_NaN_when_all_input_is_negative()
{
//arrange
var inputData = new[] { -1.0, -2.0, -3.0 };
//act
var gainMean = inputData.GainMean();
//assert
- Assert.AreEqual(0.0, gainMean);
+ Assert.AreEqual(double.NaN, gainMean);
}
[Test]
@@ -91,14 +92,14 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
}
[Test]
- public void returns_zero_with_no_input_data()
+ public void returns_NaN_with_no_input_data()
{
//arrange
var inputData = new List();
//act
var gainMean = inputData.GainMean();
//assert
- Assert.AreEqual(0.0, gainMean);
+ Assert.AreEqual(double.NaN, gainMean);
}
}
diff --git a/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs b/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs
index f7a163fe..d9dbc79b 100644
--- a/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs
+++ b/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs
@@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class GainStandardDeviationTests
{
[Test]
diff --git a/src/UnitTests/FinancialTests/LossMeanTests.cs b/src/UnitTests/FinancialTests/LossMeanTests.cs
index 8b57a4e4..6646cc87 100644
--- a/src/UnitTests/FinancialTests/LossMeanTests.cs
+++ b/src/UnitTests/FinancialTests/LossMeanTests.cs
@@ -33,28 +33,29 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class LossMeanTests
{
[Test]
- public void returns_zero_when_zero_is_the_only_input()
+ public void returns_NaN_when_zero_is_the_only_input()
{
//arrange
var inputData = new[] { 0.0 };
//act
var lossMean = inputData.LossMean();
//assert
- Assert.AreEqual(0.0, lossMean);
+ Assert.AreEqual(double.NaN, lossMean);
}
[Test]
- public void returns_zero_when_all_input_is_positive()
+ public void returns_NaN_when_all_input_is_positive()
{
//arrange
- var inputData = new[] { 1.0 };
+ var inputData = new[] { 0.0, 1.0 };
//act
var lossMean = inputData.LossMean();
//assert
- Assert.AreEqual(0.0, lossMean);
+ Assert.AreEqual(double.NaN, lossMean);
}
[Test]
@@ -92,14 +93,14 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
}
[Test]
- public void returns_zero_with_no_input_data()
+ public void returns_NaN_with_no_input_data()
{
//arrange
var inputData = new List();
//act
var lossMean = inputData.LossMean();
//assert
- Assert.AreEqual(0.0, lossMean);
+ Assert.AreEqual(double.NaN, lossMean);
}
}
}
diff --git a/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs b/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs
index b3367ec5..27728703 100644
--- a/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs
+++ b/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs
@@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class LossStandardDeviationTests
{
[Test]
diff --git a/src/UnitTests/FinancialTests/SemiDeviationTests.cs b/src/UnitTests/FinancialTests/SemiDeviationTests.cs
index 0394b10e..8f631f93 100644
--- a/src/UnitTests/FinancialTests/SemiDeviationTests.cs
+++ b/src/UnitTests/FinancialTests/SemiDeviationTests.cs
@@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
using NUnit.Framework;
[TestFixture]
+ [Category("FinancialTests")]
public class SemiDeviationTests
{
[Test]
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index 51cb7a03..487e3c6f 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -122,6 +122,7 @@
+