diff --git a/src/Numerics/Financial/AbsoluteReturnMeasures.cs b/src/Numerics/Financial/AbsoluteReturnMeasures.cs
new file mode 100644
index 00000000..446c9e33
--- /dev/null
+++ b/src/Numerics/Financial/AbsoluteReturnMeasures.cs
@@ -0,0 +1,102 @@
+//
+// 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-2013 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 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/AbsoluteRiskMeasures.cs b/src/Numerics/Financial/AbsoluteRiskMeasures.cs
new file mode 100644
index 00000000..2db55192
--- /dev/null
+++ b/src/Numerics/Financial/AbsoluteRiskMeasures.cs
@@ -0,0 +1,140 @@
+//
+// 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-2013 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 Statistics;
+
+ public static class AbsoluteRiskMeasures
+ {
+ //Note: The following statistics would be condidered an absolute risk statistic in the finance realm as well.
+ // Standard Deviation
+ // Annualized Standard Deviation = Math.Sqrt(Monthly Standard Deviation x ( 12 ))
+ // Skewness
+ // Kurtosis
+
+
+ ///
+ /// Calculation is similar to Standard Deviation , except it calculates an average (mean) return only for periods with a gain
+ /// and measures the variation of only the gain periods around the gain mean. Measures the volatility of upside performance.
+ /// © Copyright 1996, 1999 Gary L.Gastineau. First Edition. © 1992 Swiss Bank Corporation.
+ ///
+ ///
+ ///
+ public static double GainStandardDeviation(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var gains = data.Where(x => x >= 0);
+ return gains.StandardDeviation();
+ }
+
+ ///
+ /// Similar to standard deviation, except this statistic calculates an average (mean) return for only the periods with a loss and then
+ /// measures the variation of only the losing periods around this loss mean. This statistic measures the volatility of downside performance.
+ ///
+ ///
+ ///
+ /// http://www.offshore-library.com/kb/statistics.php
+ public static double LossStandardDeviation(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var losses = data.Where(x => x < 0);
+ return losses.StandardDeviation();
+ }
+
+ ///
+ /// This measure is similar to the loss standard deviation except the downside deviation
+ /// considers only returns that fall below a defined minimum acceptable return (MAR) rather than the arithmetic mean.
+ /// For example, if the MAR is 7%, the downside deviation would measure the variation of each period that falls below
+ /// 7%. (The loss standard deviation, on the other hand, would take only losing periods, calculate an average return for
+ /// the losing periods, and then measure the variation between each losing return and the losing return average).
+ ///
+ ///
+ ///
+ ///
+ public static double DownsideDeviation(this IEnumerable data, double minimalAcceptableReturn)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var belowMARData = data.Where(x => x < minimalAcceptableReturn);
+ return belowMARData.StandardDeviation();
+ }
+
+ ///
+ /// A measure of volatility in returns below the mean. It's similar to standard deviation, but it only
+ /// looks at periods where the investment return was less than average return.
+ ///
+ ///
+ ///
+ public static double SemiDeviation(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var mean = data.Mean();
+ var belowMeanData = data.Where(x => x < mean);
+ return belowMeanData.StandardDeviation();
+ }
+
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ public static double GainLossRatio(this IEnumerable data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ var gains = data.Where(x => x >= 0);
+ var losses = data.Where(x => x < 0);
+ return Math.Abs(gains.Mean() / losses.Mean());
+ }
+ }
+}
diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index 60be540e..9249bd1a 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -105,6 +105,8 @@
+
+
diff --git a/src/Portable/Portable.csproj b/src/Portable/Portable.csproj
index d279b8b5..c471e09e 100644
--- a/src/Portable/Portable.csproj
+++ b/src/Portable/Portable.csproj
@@ -192,6 +192,12 @@
Distributions\Multivariate\Wishart.cs
+
+ Financial\AbsoluteReturnMeasures.cs
+
+
+ Financial\AbsoluteRiskMeasures.cs
+
GlobalizationHelper.cs
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
new file mode 100644
index 00000000..d57075bf
--- /dev/null
+++ b/src/UnitTests/FinancialTests/DownsideDeviationTests.cs
@@ -0,0 +1,114 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class DownsideDeviationTests
+ {
+ [Test]
+ public void returns_undefined_with_no_input_data()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ var inputData = new List();
+ //act
+ var dsDeviation = inputData.DownsideDeviation(minimumAcceptableReturn);
+ //assert
+ Assert.AreEqual(double.NaN, dsDeviation);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_positive_input()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ var inputData = new[] { 1.0 };
+ //act
+ var dsDeviation = inputData.DownsideDeviation(minimumAcceptableReturn);
+ //assert
+ Assert.AreEqual(double.NaN, dsDeviation);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_negative_input()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ var inputData = new[] { -1.0 };
+ //act
+ var dsDeviation = inputData.DownsideDeviation(minimumAcceptableReturn);
+ //assert
+ Assert.AreEqual(double.NaN, dsDeviation);
+ }
+
+ [Test]
+ public void only_uses_data_points_below_the_minimum_acceptable_return()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ var inputData = new[] { 0.0021, 0.02, 0.5, 0.12 };
+ var expectedSemiDeviation = inputData.Where(x => x < minimumAcceptableReturn).StandardDeviation();
+ //act
+ var semiDeviation = inputData.DownsideDeviation(minimumAcceptableReturn);
+ //assert
+ Assert.AreEqual(expectedSemiDeviation, semiDeviation);
+ }
+
+ [Test]
+ public void handles_negative_values()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ var inputData = new[] { -0.1, -0.02, 0.4, 0.12 };
+ var expectedSemiDeviation = inputData.Where(x => x < minimumAcceptableReturn).StandardDeviation();
+ //act
+ var semiDeviation = inputData.DownsideDeviation(minimumAcceptableReturn);
+ //assert
+ Assert.AreEqual(expectedSemiDeviation, semiDeviation);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ const double minimumAcceptableReturn = 0.05;
+ List inputData = null;
+ //act
+ inputData.DownsideDeviation(minimumAcceptableReturn);
+ }
+
+ }
+}
diff --git a/src/UnitTests/FinancialTests/GainLossRatioTests.cs b/src/UnitTests/FinancialTests/GainLossRatioTests.cs
new file mode 100644
index 00000000..571345df
--- /dev/null
+++ b/src/UnitTests/FinancialTests/GainLossRatioTests.cs
@@ -0,0 +1,123 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class GainLossRatioTests
+ {
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.GainLossRatio();
+ }
+
+ [Test]
+ //Not sure this is correct. Undefined may be more correct.
+ public void returns_NaN_for_a_single_positive_input()
+ {
+ //arrange
+ var inputData = new[] { 1.0 };
+ //act
+ var gainLossRatio = inputData.GainLossRatio();
+ //assert
+ Assert.AreEqual(double.NaN, gainLossRatio);
+ }
+
+ [Test]
+ //Not sure this is correct. Undefined may be more correct.
+ public void returns_NaN_for_a_single_negative_input()
+ {
+ //arrange
+ var inputData = new[] { -1.0 };
+ //act
+ var gainLossRatio = inputData.GainLossRatio();
+ //assert
+ Assert.AreEqual(double.NaN, gainLossRatio);
+ }
+
+ [Test]
+ //Not sure this is correct. Undefined may be more correct.
+ 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(double.NaN, gainLossRatio);
+ }
+
+ [Test]
+ //Not sure this is correct. Undefined may be more correct.
+ 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(double.NaN, gainLossRatio);
+ }
+
+ [Test]
+ public void handles_a_value_of_zero_as_a_positive()
+ {
+ //arrange
+ var inputData = new[] { 0.0, -1.0 };
+ //act
+ var gainLossRatio = inputData.GainLossRatio();
+ //assert
+ Assert.AreEqual(0.0, gainLossRatio); //0.0 / -1.0 => 0.0
+ }
+
+ [Test]
+ public void calculates_the_correct_ratio_given_a_set_of_gains_and_losses()
+ {
+ //arrange
+ var inputData = new[] { -2.0, -1.0, 0.0, 1.0, 2.0 };
+ var meanOfGains = inputData.Where(x => x >= 0).Mean();
+ var meanOfLosses = inputData.Where(x => x < 0).Mean();
+ var expectedRatio = Math.Abs(meanOfGains / meanOfLosses);
+ //act
+ var gainLossRatio = inputData.GainLossRatio();
+ //assert
+ Assert.AreEqual(expectedRatio, gainLossRatio);
+ }
+ }
+}
diff --git a/src/UnitTests/FinancialTests/GainMeanTests.cs b/src/UnitTests/FinancialTests/GainMeanTests.cs
new file mode 100644
index 00000000..c91d9460
--- /dev/null
+++ b/src/UnitTests/FinancialTests/GainMeanTests.cs
@@ -0,0 +1,106 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class GainMeanTests
+ {
+ [Test]
+ public void returns_zero_when_its_the_only_data()
+ {
+ //arrange
+ var inputData = new[] { 0.0 };
+ //act
+ var gainMean = inputData.GainMean();
+ //assert
+ Assert.AreEqual(0.0, gainMean);
+ }
+ [Test]
+ 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(double.NaN, gainMean);
+ }
+
+ [Test]
+ public void returns_same_as_mean_when_all_values_are_positive()
+ {
+ //arrange
+ var inputData = new[] { 1.0, 2.0, 3.0 };
+ var mean = inputData.Mean();
+ //act
+ var gainMean = inputData.GainMean();
+ //assert
+ Assert.AreEqual(mean, gainMean);
+ }
+
+ [Test]
+ public void does_not_use_negative_input_values()
+ {
+ //arrange
+ var inputData = new[] { 1.0, -1.0 };
+ //act
+ var gainMean = inputData.GainMean();
+ //assert
+ Assert.AreEqual(1.0, gainMean);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void throws_when_input_data_is_null() //assert
+ {
+ //arrange
+ var inputData = new[] { 1.0 };
+ inputData = null;
+ //act
+ inputData.GainMean();
+ }
+
+ [Test]
+ public void returns_NaN_with_no_input_data()
+ {
+ //arrange
+ var inputData = new List();
+ //act
+ var gainMean = inputData.GainMean();
+ //assert
+ Assert.AreEqual(double.NaN, gainMean);
+ }
+
+ }
+}
diff --git a/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs b/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs
new file mode 100644
index 00000000..d9dbc79b
--- /dev/null
+++ b/src/UnitTests/FinancialTests/GainStandardDeviationTests.cs
@@ -0,0 +1,120 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class GainStandardDeviationTests
+ {
+ [Test]
+ public void returns_undefined_with_no_input_data()
+ {
+ //arrange
+ var inputData = new List();
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, gainStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_positive_input()
+ {
+ //arrange
+ var inputData = new[] { 1.0 };
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, gainStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_negative_input()
+ {
+ //arrange
+ var inputData = new[] { -1.0 };
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, gainStdDev);
+ }
+
+ [Test]
+ public void does_not_use_negative_input_data()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 1.0, -2.0, 2.0 };
+ var expectedGainStdDeviation = inputData.Where(x => x >= 0).StandardDeviation();
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(expectedGainStdDeviation, gainStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_for_a_set_of_all_negative_numbers()
+ {
+ //arrange
+ var inputData = new[] { -1.0, -1.0, -2.0, -3.0 };
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, gainStdDev);
+ }
+
+ [Test]
+ public void handles_zero_in_the_data_input_as_a_positive_number()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 0.0, 1.0, 2.0 };
+ var expectedGainStdDeviation = inputData.Where(x => x >= 0).StandardDeviation();
+ //act
+ var gainStdDev = inputData.GainStandardDeviation();
+ //assert
+ Assert.AreEqual(expectedGainStdDeviation, gainStdDev);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.GainStandardDeviation();
+ }
+
+ public double gainStdDev { get; set; }
+ }
+}
diff --git a/src/UnitTests/FinancialTests/LossMeanTests.cs b/src/UnitTests/FinancialTests/LossMeanTests.cs
new file mode 100644
index 00000000..6646cc87
--- /dev/null
+++ b/src/UnitTests/FinancialTests/LossMeanTests.cs
@@ -0,0 +1,106 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class LossMeanTests
+ {
+ [Test]
+ public void returns_NaN_when_zero_is_the_only_input()
+ {
+ //arrange
+ var inputData = new[] { 0.0 };
+ //act
+ var lossMean = inputData.LossMean();
+ //assert
+ Assert.AreEqual(double.NaN, lossMean);
+ }
+
+ [Test]
+ public void returns_NaN_when_all_input_is_positive()
+ {
+ //arrange
+ var inputData = new[] { 0.0, 1.0 };
+ //act
+ var lossMean = inputData.LossMean();
+ //assert
+ Assert.AreEqual(double.NaN, lossMean);
+ }
+
+ [Test]
+ public void returns_the_same_as_mean_when_all_values_are_negative()
+ {
+ //arrange
+ var inputData = new[] { -1.0, -2.0 };
+ var mean = inputData.Mean();
+ //act
+ var lossMean = inputData.LossMean();
+ //assert
+ Assert.AreEqual(mean, lossMean);
+ }
+
+ [Test]
+ public void does_not_use_positive_input_values()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 2.0 };
+ //act
+ var lossMean = inputData.LossMean();
+ //assert
+ Assert.AreEqual(-1.0, lossMean);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.LossMean();
+ }
+
+ [Test]
+ public void returns_NaN_with_no_input_data()
+ {
+ //arrange
+ var inputData = new List();
+ //act
+ var lossMean = inputData.LossMean();
+ //assert
+ Assert.AreEqual(double.NaN, lossMean);
+ }
+ }
+}
diff --git a/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs b/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs
new file mode 100644
index 00000000..27728703
--- /dev/null
+++ b/src/UnitTests/FinancialTests/LossStandardDeviationTests.cs
@@ -0,0 +1,118 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class LossStandardDeviationTests
+ {
+ [Test]
+ public void returns_undefined_with_no_input_data()
+ {
+ //arrange
+ var inputData = new List();
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, lossStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_positive_input()
+ {
+ //arrange
+ var inputData = new[] { 1.0 };
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, lossStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_negative_input()
+ {
+ //arrange
+ var inputData = new[] { -1.0 };
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, lossStdDev);
+ }
+
+ [Test]
+ public void does_not_use_positive_input_data()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 1.0, -2.0, 2.0 };
+ var expectedLossStdDeviation = inputData.Where(x => x < 0).StandardDeviation();
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(expectedLossStdDeviation, lossStdDev);
+ }
+
+ [Test]
+ public void handles_zero_in_the_data_input_as_a_positive_number()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 0.0, -6.0, 2.0 };
+ var expectedLossStdDeviation = inputData.Where(x => x < 0).StandardDeviation();
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(expectedLossStdDeviation, lossStdDev);
+ }
+
+ [Test]
+ public void returns_undefined_for_a_set_of_all_positive_numbers()
+ {
+ //arrange
+ var inputData = new[] { 1.0, 1.0, 2.0, 3.0 };
+ //act
+ var lossStdDev = inputData.LossStandardDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, lossStdDev);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.LossStandardDeviation();
+ }
+ }
+}
diff --git a/src/UnitTests/FinancialTests/SemiDeviationTests.cs b/src/UnitTests/FinancialTests/SemiDeviationTests.cs
new file mode 100644
index 00000000..8f631f93
--- /dev/null
+++ b/src/UnitTests/FinancialTests/SemiDeviationTests.cs
@@ -0,0 +1,109 @@
+//
+// 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 MathNet.Numerics.Financial;
+ using MathNet.Numerics.Statistics;
+ using NUnit.Framework;
+
+ [TestFixture]
+ [Category("FinancialTests")]
+ public class SemiDeviationTests
+ {
+ [Test]
+ public void returns_undefined_with_no_input_data()
+ {
+ //arrange
+ var inputData = new List();
+ //act
+ var semiDeviation = inputData.SemiDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, semiDeviation);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_positive_input()
+ {
+ //arrange
+ var inputData = new[] { 1.0 };
+ //act
+ var semiDeviation = inputData.SemiDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, semiDeviation);
+ }
+
+ [Test]
+ public void returns_undefined_with_single_negative_input()
+ {
+ //arrange
+ var inputData = new[] { -1.0 };
+ //act
+ var semiDeviation = inputData.SemiDeviation();
+ //assert
+ Assert.AreEqual(double.NaN, semiDeviation);
+ }
+
+ [Test]
+ public void only_uses_data_points_below_the_mean_of_all_data()
+ {
+ //arrange
+ var inputData = new[] { 1.0, 2.0, 3.0, 4.0 };
+ var mean = inputData.Mean();
+ var expectedSemiDeviation = inputData.Where(x => x < mean).StandardDeviation();
+ //act
+ var semiDeviation = inputData.SemiDeviation();
+ //assert
+ Assert.AreEqual(expectedSemiDeviation, semiDeviation);
+ }
+
+ [Test]
+ public void handles_negative_values()
+ {
+ //arrange
+ var inputData = new[] { -1.0, 2.0, 3.0, 4.0 };
+ var mean = inputData.Mean();
+ var expectedSemiDeviation = inputData.Where(x => x < mean).StandardDeviation();
+ //act
+ var semiDeviation = inputData.SemiDeviation();
+ //assert
+ Assert.AreEqual(expectedSemiDeviation, semiDeviation);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))] //assert
+ public void throws_when_input_data_is_null()
+ {
+ //arrange
+ List inputData = null;
+ //act
+ inputData.SemiDeviation();
+ }
+ }
+}
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index 5afd12db..487e3c6f 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -122,6 +122,14 @@
+
+
+
+
+
+
+
+