Browse Source

Financial: ATR indicator minor cleanup

atr-indicator
Christoph Ruegg 11 years ago
parent
commit
ad9c25fbeb
  1. 49
      src/Numerics/Financial/Bar.cs
  2. 31
      src/Numerics/Financial/Indicators.cs
  3. 10
      src/UnitTests/FinancialTests/IndicatorsTests.cs
  4. 33
      src/UnitTests/FinancialTests/StockDataReader.cs

49
src/Numerics/Financial/Bar.cs

@ -1,19 +1,44 @@
using System; // <copyright file="Bar.cs" company="Math.NET">
using System.Collections.Generic; // Math.NET Numerics, part of the Math.NET Project
using System.Linq; // http://numerics.mathdotnet.com
using System.Text; // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2015 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.
// </copyright>
namespace MathNet.Numerics.Financial namespace MathNet.Numerics.Financial
{ {
/// <summary> /// <summary>
/// Repressentation of a stock bar /// Representation of a stock bar
/// </summary> /// </summary>
public struct Bar public struct Bar
{ {
private readonly double _high; readonly double _high;
private readonly double _low; readonly double _low;
private readonly double _open; readonly double _open;
private readonly double _close; readonly double _close;
/// <summary> /// <summary>
/// High of the bar /// High of the bar
@ -46,14 +71,12 @@ namespace MathNet.Numerics.Financial
{ {
get { return _close; } get { return _close; }
} }
/// <summary>
/// ctor
/// </summary>
/// <param name="high"> High of the bar</param> /// <param name="high"> High of the bar</param>
/// <param name="low"> Low of the bar</param> /// <param name="low"> Low of the bar</param>
/// <param name="open"> Open of the bar</param> /// <param name="open"> Open of the bar</param>
/// <param name="close"> Close of the bar</param> /// <param name="close"> Close of the bar</param>
public Bar(double high,double low,double open,double close) public Bar(double high, double low, double open, double close)
{ {
_high = high; _high = high;
_low = low; _low = low;

31
src/Numerics/Financial/Indicators.cs

@ -27,10 +27,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using MathNet.Numerics.Statistics; using MathNet.Numerics.Statistics;
namespace MathNet.Numerics.Financial namespace MathNet.Numerics.Financial
@ -41,29 +41,27 @@ namespace MathNet.Numerics.Financial
public static class Indicators public static class Indicators
{ {
/// <summary> /// <summary>
/// Evaluates the sample mean over a moving window, for each samples. /// Calculate the Simple Moving Average (SMA).
/// Returns NaN if no data is empty or if any entry is NaN.
/// </summary> /// </summary>
/// <param name="samples">The sample stream to calculate the mean of.</param> /// <param name="samples">Input samples</param>
/// <param name="period">The number of last samples to consider.</param> /// <param name="period">Period of calculation</param>
/// <returns>The SMA for samples</returns>
public static IEnumerable<double> SMA(this IEnumerable<double> samples, int period) public static IEnumerable<double> SMA(this IEnumerable<double> samples, int period)
{ {
return samples.MovingAverage(period); return samples.MovingAverage(period);
} }
/// <summary> /// <summary>
/// Calculate the Average True Range (ATR) /// Calculate the Average True Range (ATR).
/// </summary> /// </summary>
/// <param name="samples">Input samples</param> /// <param name="samples">Input samples</param>
/// <param name="period">Period of calculation</param> /// <param name="period">Period of calculation</param>
/// <returns></returns>
public static IEnumerable<double> ATR(this IEnumerable<Bar> samples, int period) public static IEnumerable<double> ATR(this IEnumerable<Bar> samples, int period)
{ {
if (period<=0) if (period <= 0)
throw new ArgumentException("period should be greater than 0","period"); throw new ArgumentException("period should be greater than 0", "period");
if(samples==null) if (samples == null)
throw new ArgumentNullException("samples", "samples should not be null"); throw new ArgumentNullException("samples", "samples should not be null");
if (period > (samples.Count() +1)) if (period > (samples.Count()))
throw new ArgumentException("samples", "samples should be greater than period"); throw new ArgumentException("samples", "samples should be greater than period");
var trList = new List<double>(); var trList = new List<double>();
@ -77,11 +75,11 @@ namespace MathNet.Numerics.Financial
{ {
var currentBar = enumerator.Current; var currentBar = enumerator.Current;
var hl = Math.Round(currentBar.High - currentBar.Low,10); var hl = Math.Round(currentBar.High - currentBar.Low, 10);
hl = Math.Abs(hl); hl = Math.Abs(hl);
var pdch = Math.Round(lastBar.Close - currentBar.High,10); var pdch = Math.Round(lastBar.Close - currentBar.High, 10);
pdch = Math.Abs(pdch); pdch = Math.Abs(pdch);
var pdcl = Math.Round(lastBar.Close - currentBar.Low,10); var pdcl = Math.Round(lastBar.Close - currentBar.Low, 10);
pdcl = Math.Abs(pdcl); pdcl = Math.Abs(pdcl);
double tr = Math.Max(hl, Math.Max(pdch, pdcl)); double tr = Math.Max(hl, Math.Max(pdch, pdcl));
@ -98,7 +96,7 @@ namespace MathNet.Numerics.Financial
//remove first tr, this is not valid //remove first tr, this is not valid
trList.RemoveAt(0); trList.RemoveAt(0);
while (trList.Count>=period) while (trList.Count >= period)
{ {
var mean = trList.Take(period).Mean(); var mean = trList.Take(period).Mean();
var meanRounded = Math.Round(mean, 2); var meanRounded = Math.Round(mean, 2);
@ -108,6 +106,5 @@ namespace MathNet.Numerics.Financial
return atrList; return atrList;
} }
} }
} }

10
src/UnitTests/FinancialTests/IndicatorsTests.cs

@ -27,12 +27,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MathNet.Numerics.Financial; using MathNet.Numerics.Financial;
using NUnit.Framework; using NUnit.Framework;
@ -57,7 +55,7 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
var expectedValueAtBar20 = 132.33; var expectedValueAtBar20 = 132.33;
var actual = atr.ElementAt(20); var actual = atr.ElementAt(20);
Assert.AreEqual(expectedValueAtBar20, actual); Assert.AreEqual(expectedValueAtBar20, actual);
} }
[Test] [Test]
@ -79,12 +77,11 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
Assert.That(() => inputBars.ATR(period), Throws.Exception.TypeOf<ArgumentException>()); Assert.That(() => inputBars.ATR(period), Throws.Exception.TypeOf<ArgumentException>());
} }
private IEnumerable<Bar> GenerateValidBars() private IEnumerable<Bar> GenerateValidBars()
{ {
StockDataReader reader = new StockDataReader(); StockDataReader reader = new StockDataReader();
var data = reader.ReadFile("./data/Finance/DaxHistoricalData.dat"); var data = reader.ReadFile("./data/Finance/DaxHistoricalData.dat");
List<Bar> inputBars = new List<Bar>(); List<Bar> inputBars = new List<Bar>();
foreach (var stockData in data) foreach (var stockData in data)
@ -95,5 +92,4 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
return inputBars; return inputBars;
} }
} }
} }

33
src/UnitTests/FinancialTests/StockDataReader.cs

@ -2,26 +2,26 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MathNet.Numerics.UnitTests.FinancialTests namespace MathNet.Numerics.UnitTests.FinancialTests
{ {
/// <summary> /// <summary>
/// Class reads a file with stockdata /// Class reads a file with stock data
/// </summary> /// </summary>
internal class StockDataReader internal class StockDataReader
{ {
/// <summary> /// <summary>
/// Reads a file with stockquotes /// Reads a file with stock quotes
/// </summary> /// </summary>
/// <param name="filePath">Path of the file</param> /// <param name="filePath">Path of the file</param>
/// <returns>Stockdata</returns> /// <returns>StockData</returns>
public IEnumerable<StockData> ReadFile(string filePath) public IEnumerable<StockData> ReadFile(string filePath)
{ {
List<StockData> resultList = new List<StockData>(); List<StockData> resultList = new List<StockData>();
var dateFormat = new CultureInfo("de-DE", false).DateTimeFormat;
var numberFormat = CultureInfo.InvariantCulture.NumberFormat;
using (var reader = new StreamReader(filePath)) using (var reader = new StreamReader(filePath))
{ {
var firstLine = reader.ReadLine(); var firstLine = reader.ReadLine();
@ -40,13 +40,12 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
var stringValues = line.Split(';'); var stringValues = line.Split(';');
//first Datetime: DateTime date = DateTime.Parse(stringValues[0], dateFormat);
DateTime date = DateTime.Parse(stringValues[0]); double open = double.Parse(stringValues[1], numberFormat);
double open = double.Parse(stringValues[1], CultureInfo.InvariantCulture); double high = double.Parse(stringValues[2], numberFormat);
double high = double.Parse(stringValues[2], CultureInfo.InvariantCulture); double low = double.Parse(stringValues[3], numberFormat);
double low = double.Parse(stringValues[3], CultureInfo.InvariantCulture); double close = double.Parse(stringValues[4], numberFormat);
double close = double.Parse(stringValues[4], CultureInfo.InvariantCulture); int volume = int.Parse(stringValues[5], numberFormat);
int volume = int.Parse(stringValues[5], CultureInfo.InvariantCulture);
StockData stockData = new StockData(date, open, close, high, low, volume); StockData stockData = new StockData(date, open, close, high, low, volume);
resultList.Add(stockData); resultList.Add(stockData);
@ -57,13 +56,10 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
} }
} }
/// <summary> /// <summary>
/// Entity class for holding stockdata /// Entity class for holding stock data
/// </summary> /// </summary>
internal class StockData internal class StockData
{ {
/// <summary>
/// Ctor
/// </summary>
/// <param name="dateTime">Date</param> /// <param name="dateTime">Date</param>
/// <param name="open">Open quote</param> /// <param name="open">Open quote</param>
/// <param name="close">Open quote</param> /// <param name="close">Open quote</param>
@ -104,7 +100,4 @@ namespace MathNet.Numerics.UnitTests.FinancialTests
/// </summary> /// </summary>
public int Volume { get; private set; } public int Volume { get; private set; }
} }
} }

Loading…
Cancel
Save