Posted by: Zeeshan Amjad | July 4, 2013

Exponential Moving Average using Mindscape


Moving average is very common technique in finance and technical analysis. In simple moving average, we simply select the window size and calculate the average of dataset in that window and then keep moving the window. Therefore it is also known as rolling average or running average or simple moving average (SMA). Usually we are calculating SMA for historical price, volume or other stock data. Here is its formula.

SMA_1

The other common averages used in finance and technical analysis are weighted moving average (WMA) and exponential moving average (EMA) or exponentially weighted moving average (EWMA). The purpose of EMA is to give the higher weight of today’s price (volume or other stock data) and lower weight to older data.

The main difference between these two are in weighted moving average, the weight assigned to data are decrease with same interval making athematic progression. However, in case of exponential moving average the weight assigned to the data decrease exponentially. It means that older data in WMA has higher weight than the same data in EMA. However it is quite possible that the weight of older data in WMA is zero but there is little weight in EMA.

Let’s take a look at graphical representation of both of these to see the difference. Here is a formula to calculate the weight of WMA for different date.

WMA_Weight

Here “Wi” is the weight for ith day and n is the windows size. Let’s try to draw the graph of 20 days weight calculated when n is equal to 12.

WMA_Weight_Graph

Here is a formula to calculate the weight of EMA for different date.

EMA_Weight

Here “Wi” is the weight for the ith day and n is the window size. Here is a graph of 20 days weight calculatged when n is equal to 12.

EMA_Weight_Graph

These graph clearly shows the difference of weight between WMA and EMA. Now lets make a simple program using mindscape.

Now lets calculate the exponential moving average. Here is a simple formula to calculate the EMA.

EMA_Formula

Here EMAn is the EMA for nth day and EMAn-1 is the EMA for previous day and here is the formula to calculate the factor.

EMA_Factor

For the first day, we don’t have any EMA for previous day, so we use SMA then uses EMA for all next calculations. Here are the auxiliary functions to calculate the EMA.

Code Snippet
double Sum(double[] data)
{
    double sum = 0;

    foreach (var d in data)
    {
        sum += d;
    }

    return sum;
}

double Average(double[] data)
{
    if (data.Length == 0)
        return 0;

    return Sum(data) / data.Length;
}

private double CalculateFactor(int days)
{
    if (days < 0)
        return 0;

    return 2.0 / (days + 1);
}

 

Here is a function to calculate exponential moving average (EMA).

Code Snippet
double[] ExponentialMovingAverage(double[] data, int window)
{
    if (data.Length < window)
        return null;

    int diff = data.Length – window;
    double[] newdata = data.Take(window).ToArray();
    double factor = CalculateFactor(window);
    double sma = Average(newdata);

    IList<double> result = new List<double>();
    result.Add(Math.Round(sma, 2));
    emaData.ChartData.Add(Math.Round(sma, 2));

    for (int i = 0; i < diff; i++)
    {
        double prev = result[result.Count – 1];
        double price = data[window + i];
        double next = factor * (price – prev) + prev;
        result.Add(Math.Round(next, 2));
    }
    
    return result.ToArray();
}

 

Here is complete XAML code of the program.

Code Snippet
<Window x:Class="WpfEMA.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
              xmlns:ms="clr-namespace:Mindscape.WpfElements.Charting;assembly=Mindscape.WpfElements"
        Title="Exponential Moving Average" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
          <ms:Chart Margin="5" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
                  Title="Exponential Moving Average" DataContext="{Binding ChartData}">
            <ms:Chart.XAxis>
                <ms:ChartAxis Title="Time"/>
            </ms:Chart.XAxis>
            <ms:Chart.YAxis>
                <ms:ChartAxis Title="Price"/>
            </ms:Chart.YAxis>
            <ms:LineSeries ItemsSource="{Binding}"
                           SeriesBrush="Green"
                                       YBinding="{Binding}" Title="EMA"/>
        </ms:Chart>
        <TextBlock Grid.Column="0" Grid.Row="1" Margin="10" VerticalAlignment="Center">
            Window Length
        </TextBlock>
        <ComboBox Grid.Column="1" Grid.Row="1" Margin="10" HorizontalContentAlignment="Center"
                  ItemsSource="{Binding WindowLength}"
                  SelectedItem="{Binding SelectedWindowLength}" />
        <Button Grid.Column="2" Grid.Row="1" Margin="10" Click="Button_Click">
            Calculate
        </Button>
    </Grid>
</Window>

 

And here is complete C# code of the program.

Code Snippet
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;

namespace WpfEMA
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private EMA emaData = new EMA();
        IList<double> data = new List<double>();

        public MainWindow()
        {
            InitializeComponent();                        

            data.Add(22.27);
            data.Add(22.19);
            data.Add(22.08);
            data.Add(22.17);
            data.Add(22.18);
            data.Add(22.13);
            data.Add(22.23);
            data.Add(22.43);
            data.Add(22.24);
            data.Add(22.29);
            data.Add(22.15);
            data.Add(22.39);
            data.Add(22.38);
            data.Add(22.61);
            data.Add(23.36);
            data.Add(24.05);
            data.Add(23.75);
            data.Add(23.83);
            data.Add(23.95);
            data.Add(23.63);
            data.Add(23.82);
            data.Add(23.87);

            emaData.WindowLength.Add(8);
            emaData.WindowLength.Add(9);
            emaData.WindowLength.Add(10);
            emaData.WindowLength.Add(11);
            emaData.WindowLength.Add(12);
            
            DataContext = emaData;
        }

        double[] ExponentialMovingAverage(double[] data, int window)
        {
            if (data.Length < window)
                return null;

            int diff = data.Length – window;
            double[] newdata = data.Take(window).ToArray();
            double factor = CalculateFactor(window);
            double sma = Average(newdata);

            IList<double> result = new List<double>();
            result.Add(Math.Round(sma, 2));
            emaData.ChartData.Add(Math.Round(sma, 2));

            for (int i = 0; i < diff; i++)
            {
                double prev = result[result.Count – 1];
                double price = data[window + i];
                double next = factor * (price – prev) + prev;
                result.Add(Math.Round(next, 2));
            }
            
            return result.ToArray();
        }

        double Sum(double[] data)
        {
            double sum = 0;

            foreach (var d in data)
            {
                sum += d;
            }

            return sum;
        }

        double Average(double[] data)
        {
            if (data.Length == 0)
                return 0;

            return Sum(data) / data.Length;
        }

        private double CalculateFactor(int days)
        {
            if (days < 0)
                return 0;

            return 2.0 / (days + 1);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            emaData.ChartData.Clear();

            double[] ema = ExponentialMovingAverage(data.ToArray(), emaData.SelectedWindowLength);

            foreach (var d in ema)
            {
                emaData.ChartData.Add(d);
            }
        }
    }    

    public class EMA : INotifyPropertyChanged
    {
        private ObservableCollection<int> _windowLength;
        private ObservableCollection<double> _chartData;
        private int _selectedWindowLength;

        public EMA()
        {
            _windowLength = new ObservableCollection<int>();
            _chartData = new ObservableCollection<double>();

            SelectedWindowLength = 9;
        }

        public ObservableCollection<double> ChartData
        {
            get
            {
                return _chartData;
            }
            
            set
            {
                _chartData = value;
                RaisePropertyChanged("ChartData");
            }
        }

        public ObservableCollection<int> WindowLength
        {
            get
            {
                return _windowLength;
            }
            set
            {
                _windowLength = value;
                RaisePropertyChanged("WindowLength");
            }
        }

        public int SelectedWindowLength
        {
            get
            {
                return _selectedWindowLength;
            }
            set
            {
                _selectedWindowLength = value;
                RaisePropertyChanged("SelectedWindowLength");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }    

    }
}

 

Here is the output of the program.

EMA_Output

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: