C # Calculating the moving median of time series SortedList <DateTime, double> - improves performance?

I have a method that calculates the moving average value of a time series. Like a moving average, it uses a fixed window or period (sometimes called the lookback period). If the period is 10, it will create an array of the first 10 values ​​(0-9), and then find their average value. He will repeat this, increasing the window by 1 step (now the values ​​are 1-10), etc ... therefore, the moving part of it. This process is exactly the same as the moving average.

The average value is determined by:

  • Sort array values
  • If the array has an odd number of values, take the average value. The median of a sorted array of 5 values ​​will be the third value.
  • If the array has an even number of values, take two values ​​on each side of the middle and average them. The median of a sorted array of 6 values ​​will be (2 + 3) / 2.

I created a function that calculates this by filling in List<double>, calling List<>.Sort(), and then finding the appropriate values.

Computing is correct, but I was wondering if there is a way to improve the performance of this calculation. Perhaps by manually turning the sort on double[], rather than using a list.

My implementation is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Moving_Median_TimeSeries
{
    class Program
    {
        static void Main(string[] args)
        {
            // created a a sample test time series of 10 days
            DateTime Today = DateTime.Now;
            var TimeSeries = new SortedList<DateTime, double>();
            for (int i = 0; i < 10; i++)
                TimeSeries.Add(Today.AddDays(i), i * 10);

            // write out the time series
            Console.WriteLine("Our time series contains...");
            foreach (var item in TimeSeries) 
                Console.WriteLine("   {0}, {1}", item.Key.ToShortDateString(), item.Value);

            // calculate an even period moving median 
            int period = 6;
            var TimeSeries_MovingMedian = MovingMedian(TimeSeries, period);

            // write out the result of the calculation
            Console.WriteLine("\nThe moving median time series of {0} periods contains...", period);
            foreach (var item in TimeSeries_MovingMedian)
                Console.WriteLine("   {0}, {1}", item.Key.ToShortDateString(), item.Value);

            // calculate an odd period moving median 
            int period2 = 5;
            var TimeSeries_MovingMedian2 = MovingMedian(TimeSeries, period);

            // write out the result of the calculation
            Console.WriteLine("\nThe moving median time series of {0} periods contains...", period2);
            foreach (var item in TimeSeries_MovingMedian2)
                Console.WriteLine("   {0}, {1}", item.Key.ToShortDateString(), item.Value);
        }

        public static SortedList<DateTime, double> MovingMedian(SortedList<DateTime, double> TimeSeries, int period)
        {
            var result = new SortedList<DateTime, double>();

            for (int i = 0; i < TimeSeries.Count(); i++)
            {
                if (i >= period - 1)
                {
                    // add all of the values used in the calc to a list... 
                    var values = new List<double>();
                    for (int x = i; x > i - period; x--)
                        values.Add(TimeSeries.Values[x]);

                    // ... and then sort the list <- there might be a better way than this
                    values.Sort();

                    // If there is an even number of values in the array (example 10 values), take the two mid values
                    // and average them.  i.e. 10 values = (5th value + 6th value) / 2. 
                    double median;
                    if (period % 2 == 0) // is any even number
                        median = (values[(int)(period / 2)] + values[(int)(period / 2 - 1)]) / 2;
                    else // is an odd period
                    // Median equals the middle value of the sorted array, if there is an odd number of values in the array
                        median = values[(int)(period / 2 + 0.5)];

                    result.Add(TimeSeries.Keys[i], median);
                }
            }
            return result;
        }

    }
}
+3
source share
2 answers

there may be a better way than this

- , , , . wikipedia .

0

N P , , - O (N * P lgP). O (N * lg P), 2 heaps.

-, P/2 , P-P/2, . , , , , . , . P . P .

c. . P.

0

All Articles