Click here to Skip to main content
Licence CPOL
First Posted 3 Aug 2006
Views 48,018
Downloads 862
Bookmarked 64 times

Creating a Mechanical Trading System Part 1: Technical Indicators

By | 3 Aug 2006 | Article
How to program the building blocks of a mechanical trading system: creating technical indicators
Sample Image - Technical_Indicators.jpg

Introduction

This article explains how to code technical analysis indicators on the .NET platform using the C# language. This is the first step towards creating a fully automated trading robot that does not depend on any underlying platform to perform its tasks. The final product will receive quotes directly from a broker via an API, perform price analysis, and decide whether or not to place orders to buy or sell.

The code provided here is part of a larger project to create a backtesting platform and an automated FOREX trading robot. The source code for this project is available here.

This will cover the implementation details of the Exponential Moving Average, and the Moving Average Convergence Divergence (MACD) indicators. These two indicators have been chosen to exemplify how modular design and object oriented programming can help create complex indicators out of simple ones.

The MACD indicator has been chosen for this article since it produces a rather distinct entry signal based on its two lines crossing. This article does not advocate taking the crossovers both as entry and exit signals since this indicator is lagging and produces signals once the trend has changed. The entries provided by this indicator should be complemented with exit techniques based on other indicators. Of particular interest are exits described by Charles Le Beau using the Average True Range indicator such as the Chandelier and Yoyo Exits.

Background

The nature of the final product, a trading robot, demands that the indicators are coded with real time signals in mind. Each indicator has four important methods:

  • Constructor: Initializes the object and instantiates any other indicators needed.
  • ReceiveTick: Informs the indicator that a new value has been received. The indicator can now store it in an internal buffer, or perform computations with the new value
  • Value: Returns the value of the indicator. This method uses the internal buffer filled by ReceiveTick to compute its data.
  • IsPrimed: Returns true when the indicator has received enough values to start producing a meaningful output. For example, a 14 period simple moving average will not return output values until 14 input values are received.

The MACD indicator is constructed with three EMAs. A slow (longer period) EMA and a fast (shorter period) EMA both receive the current price. The difference from the fast and slow EMAs is called the MACD, and is sent to a third EMA called the Signal. The values plotted in the chart are the MACD and the Signal. By instantiating three EMA objects and defining the relationships between them, a more complex indicator such as the MACD can be easily created.

Indicators have to be instantiated first with the proper parameters. Then the ReceiveTick method needs to be called with a value. To obtain the result from the indicator, the Value method needs to be called. This method returns a value of 0 if not enough values have been received. The IsPrimed method can be called to determine if the indicator has received enough values to compute a value.

Note that the ReceiveTick method can either receive price data, or data from another indicator. This flexibility is what enables the MACD indicator to be built from three Exponential Moving Average objects.

Source Code

//
// 4X Lab.NET © Copyright 2005-2006 ASCSE LLC
// http://www.4xlab.net
// email: 4xlab@4xlab.net
//

using System;

namespace _4XLab.NET
{
    public class iEMA
    {
        private int tickcount;
        private int periods;
        private double dampen;
        private double emav;

        public iEMA(int pPeriods)
        {
            periods = pPeriods;
            dampen  = 2/((double)1.0+periods);
        }

        public void ReceiveTick(double Val)
        {
            if (tickcount < periods)
                emav += Val;
            if (tickcount ==periods)
                emav /= periods;
            if (tickcount > periods)
                emav = (dampen*(Val-emav))+emav;

            if (tickcount <= (periods+1) )
            {            
                // avoid overflow by stopping use of tickcount
                // when indicator is fully primed
                tickcount++;
            }
        }

        public double Value()
        {
            double v;

            if (isPrimed())
                v = emav;
            else
                v = 0;

            return v;
        }

        public bool isPrimed()
        {    
            bool v = false;
            if (tickcount > periods)
            {
                v = true;
            }
            return v;
        }
    }

    public class iMACD
    {
        int pSlowEMA, pFastEMA, pSignalEMA;
        iEMA slowEMA, fastEMA, signalEMA;

        // restriction: pPFastEMA < pPSlowEMA
        public iMACD(int pPFastEMA, int pPSlowEMA, int pPSignalEMA)
        {
            pFastEMA = pPFastEMA;
            pSlowEMA = pPSlowEMA;
            pSignalEMA = pPSignalEMA;

            slowEMA = new iEMA(pSlowEMA);
            fastEMA = new iEMA(pFastEMA);
            signalEMA = new iEMA(pSignalEMA);
        }

        public void ReceiveTick(double Val)
        {
            slowEMA.ReceiveTick(Val);
            fastEMA.ReceiveTick(Val);

            if (slowEMA.isPrimed() && fastEMA.isPrimed())
            {
                signalEMA.ReceiveTick(fastEMA.Value()-slowEMA.Value());
            }
        }

        public void Value(out double MACD, out double signal, out double hist)
        {
            if (signalEMA.isPrimed())
            {
                MACD = fastEMA.Value() - slowEMA.Value();
                signal = signalEMA.Value();
                hist = MACD - signal;
            }
            else
            {
                MACD = 0;
                signal = 0;
                hist = 0;
            }
        }

        public bool isPrimed()
        {    
            bool v = false;
            if (signalEMA.isPrimed())
            {
                v = true;
            }
            return v;
        }
    }
}

Credits

The image in this article was obtained with a product that includes software developed as part of the NPlot library project available from here.

Read More About It

History

  • 3rd August, 2006: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Alejandro Simon



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralPlease Pinmembertapfuma5:47 5 Mar '11  
QuestionError Pinmemberahmedalhoseny0:38 13 Jan '10  
QuestionCalculate Macd Value Pinmemberibrahim198012:28 1 Jan '10  
GeneralImpressed Pinmembermbaocha20:28 25 Aug '09  
GeneralGreat Work! PinmemberPatrick_SURFThru6:43 4 Feb '09  
GeneralCoding Pinmemberjingyeu20:20 6 Dec '07  
Generalabout NPlot Pinmember775852121:32 15 Aug '06  
GeneralRe: about NPlot PinmemberAlejandro Simon12:42 25 Aug '06  
The candle graph with the overlaid MACD indicator was generated with an unpublished program that uses the NPlot library. I just sat with the example they provide and figured out how to modify it for my use, not really an expert in using this library.
 
I am thinking of publishing the source code to 4XPlot.exe for people to download and modify in the website www.4xlab.net
General*Very* interesting, keep it up! Pinmemberaxelriet7:12 4 Aug '06  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 4 Aug 2006
Article Copyright 2006 by Alejandro Simon
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid