Index: branches/Benchmarking/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs
===================================================================
--- branches/Benchmarking/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs	(revision 6917)
+++ branches/Benchmarking/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs	(revision 7000)
@@ -22,10 +22,9 @@
 using System;
 using System.Collections.Generic;
+using HeuristicLab.Common;
 
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  public class OnlineWeightedDirectionalSymmetryCalculator : IOnlineCalculator {
-    private double prevEstimated;
-    private double prevOriginal;
+  public class OnlineWeightedDirectionalSymmetryCalculator : IOnlineTimeSeriesCalculator {
     private int n;
     private double correctSum;
@@ -52,22 +51,33 @@
     }
 
-    public void Add(double original, double estimated) {
-      if (double.IsNaN(estimated) || double.IsInfinity(estimated) || double.IsNaN(original) || double.IsInfinity(original) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
+    public void Add(double startValue, IEnumerable<double> actualContinuation, IEnumerable<double> predictedContinuation) {
+      if (double.IsNaN(startValue) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
         errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
-      } else if (n == 0) {
-        prevOriginal = original;
-        prevEstimated = estimated;
-        n++;
       } else {
-        double err = Math.Abs(original - estimated);
-        if ((original - prevOriginal) * (estimated - prevEstimated) >= 0.0) {
-          correctSum += err;
+        var actualEnumerator = actualContinuation.GetEnumerator();
+        var predictedEnumerator = predictedContinuation.GetEnumerator();
+        while (actualEnumerator.MoveNext() & predictedEnumerator.MoveNext() & errorState != OnlineCalculatorError.InvalidValueAdded) {
+          double actual = actualEnumerator.Current;
+          double predicted = predictedEnumerator.Current;
+          if (double.IsNaN(actual) || double.IsNaN(predicted)) {
+            errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+          } else {
+            double err = Math.Abs(actual - predicted);
+            // count as correct only if the trend (positive/negative/no change) is predicted correctly
+            if ((actual - startValue) * (predicted - startValue) > 0.0 ||
+              (actual - startValue).IsAlmost(predicted - startValue)) {
+              correctSum += err;
+            } else {
+              incorrectSum += err;
+            }
+            n++;
+          }
+        }
+        // check if both enumerators are at the end to make sure both enumerations have the same length
+        if (actualEnumerator.MoveNext() || predictedEnumerator.MoveNext()) {
+          errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
         } else {
-          incorrectSum += err;
+          errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded); // n >= 1
         }
-        n++;
-        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
-        prevOriginal = original;
-        prevEstimated = estimated;
       }
     }
@@ -77,35 +87,27 @@
       correctSum = 0;
       incorrectSum = 0;
-      prevOriginal = double.NaN;
-      prevEstimated = double.NaN;
       errorState = OnlineCalculatorError.InsufficientElementsAdded;
     }
 
 
-    public static double Calculate(IEnumerable<double> first, IEnumerable<double> second, out OnlineCalculatorError errorState) {
-      IEnumerator<double> firstEnumerator = first.GetEnumerator();
-      IEnumerator<double> secondEnumerator = second.GetEnumerator();
-      OnlineWeightedDirectionalSymmetryCalculator dsCalculator = new OnlineWeightedDirectionalSymmetryCalculator();
-      
-      // add first element of time series as a reference point
-      firstEnumerator.MoveNext();
-      secondEnumerator.MoveNext();
-      dsCalculator.Add(firstEnumerator.Current, secondEnumerator.Current);
+    public static double Calculate(IEnumerable<double> startValues, IEnumerable<IEnumerable<double>> actualContinuations, IEnumerable<IEnumerable<double>> predictedContinuations, out OnlineCalculatorError errorState) {
+      IEnumerator<double> startValueEnumerator = startValues.GetEnumerator();
+      IEnumerator<IEnumerable<double>> actualContinuationsEnumerator = actualContinuations.GetEnumerator();
+      IEnumerator<IEnumerable<double>> predictedContinuationsEnumerator = predictedContinuations.GetEnumerator();
+      OnlineWeightedDirectionalSymmetryCalculator calculator = new OnlineWeightedDirectionalSymmetryCalculator();
 
-      // always move forward both enumerators (do not use short-circuit evaluation!)
-      while (firstEnumerator.MoveNext() & secondEnumerator.MoveNext()) {
-        double estimated = secondEnumerator.Current;
-        double original = firstEnumerator.Current;
-        dsCalculator.Add(original, estimated);
-        if (dsCalculator.ErrorState != OnlineCalculatorError.None) break;
+      // always move forward all enumerators (do not use short-circuit evaluation!)
+      while (startValueEnumerator.MoveNext() & actualContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
+        calculator.Add(startValueEnumerator.Current, actualContinuationsEnumerator.Current, predictedContinuationsEnumerator.Current);
+        if (calculator.ErrorState != OnlineCalculatorError.None) break;
       }
 
-      // check if both enumerators are at the end to make sure both enumerations have the same length
-      if (dsCalculator.ErrorState == OnlineCalculatorError.None &&
-          (secondEnumerator.MoveNext() || firstEnumerator.MoveNext())) {
-        throw new ArgumentException("Number of elements in first and second enumeration doesn't match.");
+      // check if all enumerators are at the end to make sure both enumerations have the same length
+      if (calculator.ErrorState == OnlineCalculatorError.None &&
+          (startValueEnumerator.MoveNext() || actualContinuationsEnumerator.MoveNext() || predictedContinuationsEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in startValues, actualContinuations and estimatedValues predictedContinuations doesn't match.");
       } else {
-        errorState = dsCalculator.ErrorState;
-        return dsCalculator.WeightedDirectionalSymmetry;
+        errorState = calculator.ErrorState;
+        return calculator.WeightedDirectionalSymmetry;
       }
     }
