Forex Blog

First-hand Forex trading experience and information about foreign exchange market that will be useful to traders

Archives

cAlgo Robots — Coding Basics

April 9, 2013 by

One of the main reasons you might want to choose cTrader as your Forex platform is to access its cAlgo part in order to develop and use custom trading robots. In MetaTrader platform, such robots are called expert advisors. In сTrader, they are called cBots. At present, the possibilities offered by cTrader/cAlgo in terms of trading automation are much less exciting than those provided by MetaTrader/MQL. Nevertheless, they are important part of the platform, so today I will describe the basics of robot building in cAlgo.

Difference with MetaTrader

The main difference between cTrader and MetaTrader robot coding is the base language. With C# as its base language, cTrader has a lot stronger toolset for coding, while MetaTrader offers a lot more trading-specific classes, events and other programming entities.

Unlike MetaTrader, cTrader robots do not have much of the chart and object interaction functions. If you plan to code a cBot, it will either work with bare price action or with some indicators.

cTrader trading orders are also quite limited compared to the ones in MetaTrader — you will not be able to use multiple order fill types or expiration types. You may set expiry date/time for a pending order but that is it. Finally, there are no stop-limit orders among pending order types.

Robot Structure

The code of a generic cBot consists of the following sections:

  • Declaration of necessary namespaces
  • Creation of robot’s class:
    • Definition of input parameters
    • Declaration of supplementary objects and variables
    • Implementation of standard Robot class event handlers:
      • OnStart()
      • OnTick()
      • OnBar()
      • OnPendingOrderCreated()
      • OnPositionOpened()
      • OnPositionClosed()
      • OnStop()
      • OnError()
      • MarketDepth.Updated
    • Implementation of custom Robot class methods

Read further for detailed description of each of those sections.

Necessary Namespaces

The same as with custom indicators, you will need to use cAlgo.API namespace if you want to create a working cBot. If you plan your robot to be based on some of the standard indicators, cAlgo.API.Indicators namespace is another one to add to your list.

There is optional cAlgo.API.Requests namespace if you want to be able to create trade requests, but the same functionality is reached with default Trade object that does not require this namespace.

Any standard C# namespace (e.g. System or System.Linq) can also be used in your custom robot if you wish to access their language constructions.

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Requests;
using cAlgo.Indicators;

Robot’s Class

A [Robot] attribute tells cAlgo that the next class declaration is a robot. The class should also belong to cAlgo.Robots namespace. [Robot] attribute can use only one property – a text name for your robot.

Your class declaration could start with something like this:

namespace cAlgo.Robots
{
    [Robot("Sample Robot")]
    public class SampleRobot : Robot
    {

Input parameters

Similarly to the custom indicators coding, your robot class can have some input parameters. Every parameter has to be declared as a class member and feature a [Parameter] attribute. It has the four properties (all are optional):

  • text name
  • input parameter default value
  • input parameter minimum value
  • input parameter maximum value

{ get; set; } accessors are a must if you want your input parameters to work.

        [Parameter("Stop Loss (pips)", DefaultValue = 50, MinValue = 1)]
        public int StopLoss { get; set; }
 
        [Parameter("Take Profit (pips)", DefaultValue = 50, MinValue = 1)]
        public int TakeProfit { get; set; }

Supplementary objects

The same as in cTrader indicator coding, you might want to add some auxiliary objects to use them inside main event handlers in your trading robot. For example, you can declare a position object to track the status of positions:

        private Position position;

Or a standard indicator object to use in trading algorithm:

        private ParabolicSAR parabolicSAR;

Or some C# system object:

        private Random random = new Random();

Or a simple variable that will be used in more than one class method:

        private double sl;

Standard event handlers

Similarly to MetaTrader and other algorithmic trading models, cTrader robots are executed based on predefined standard event handlers, which are implemented by users but are called by the trading environment. Neither of the following standard handlers are obligatory, but a working robot will need at least one of them.

OnStart()

This handler is called upon adding an instance of a robot to a chart. It is an analogue of OnInit() MT5 handler. Or cTrader indicator’s Initialize() handler. You may use it to calculate values dependent on input parameters or prepare indicators for further use inside your robot:

        protected override void OnStart()
        {
            bollingerBands = Indicators.BollingerBands(Source, Periods, Deviations, MAType);
        }
OnTick()

As its name suggests, OnTick() is called every tick. Its MT5 cousin has the same name. Usually, you would put the cBot’s main trading logic either inside OnTick() or a related OnBar() handler.

        protected override void OnTick()
        {
            if (position == null) return;
 
            double distance = Symbol.Bid - position.EntryPrice;
 
            if (distance >= Trigger * Symbol.PipSize)
            {
                double newStopLossPrice = Symbol.Bid - TrailingStop * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    Trade.ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }
OnBar()

This is something both MT4 and MT5 are missing – a special event handler that is called each time a new bar is drawn on chart. If you want your robot to act only when the previous bar is closed, this standard handler is where you put your main trading code:

        protected override void OnBar()
        {
            if (Trade.IsExecuting) return;
            bool isLongPositionOpen = _position != null && _position.TradeType == TradeType.Buy;
            bool isShortPositionOpen = _position != null && _position.TradeType == TradeType.Sell;
            double lastValue = _zigZag.Result.LastValue;
            if (!double.IsNaN(lastValue))
            {
                if (lastValue < _prevValue && !isLongPositionOpen)
                {
                     ClosePosition();
                     Buy();
                }
                else if (lastValue > _prevValue && _prevValue > 0.0 && !isShortPositionOpen)
                {
                    ClosePosition();
                    Sell();
                }
                _prevValue = lastValue;                
            }
        }
OnPendingOrderCreated()

Triggered when a pending order is placed in the market. OnPendingOrderCreated() is somewhat similar to OnTradeTransaction() and OnTrade() in MQL5 but is more specific. It can only be used if you need the robot to perform some actions upon pending order placement.

        protected override void OnPendingOrderCreated(PendingOrder newOrder)
        {
            Print("Pending order with ID {0} was created.", newOrder.Id);
        }
OnPositionOpened()

This handler triggers when position is opened in trader’s account. Like with OnPendingOrderCreated(), it is covered by OnTradeTransaction() and OnTrade() in MT5. You are expected to perform operations on your positions in this handler. For example, you could apply stop-loss:

        protected override void OnPositionOpened(Position openedPosition)
        {
            _position = openedPosition;
            Trade.ModifyPosition(openedPosition, GetAbsoluteStopLoss(openedPosition, StopLoss), null);
        }
OnPositionClosed()

As you have probably guessed by its name, this one triggers immediately upon closing a position. In MetaTrader 5, you would use either OnTradeTransaction() or OnTrade() to get the same functionality. It is a useful event if you want to open a new position when the old one closes, or if you want to stop executing your robot altogether:

        protected override void OnPositionClosed(Position closedPosition)
        {
            Stop();
        }
OnStop()

A handler that is called on stopping the cBot. It is virtually the same as OnDeinit() in MetaTrader 5.

        protected override void OnStop()
        {
            Print("cBot deinitialized.");
        }
OnError()

A special Robot class member that handles situations with errors. Errors are processed quite differently in MT5. Generally, you would want to stop executing your robot on some errors:

        protected override void OnError(Error error)
        {
            Print("{0}", error.Code);
            if (error.Code == ErrorCode.BadVolume) Stop();
        }
MarketDepth.Updated

Updated event is not a part of the Robot class but is rather a member of MarketDepth interface. It is used to handle changes in Depth of Market for the given currency pair. You would be using OnBookEvent() in its place in MetaTrader.

_marketDepth = MarketData.GetMarketDepth(Symbol);
_marketDepth.Updated += MarketDepthUpdated;
 
void MarketDepthUpdated()
{
    foreach (var entry in _marketDepth.AskEntries)
    {
        Print("{0}", entry.Price);
    }
}

Custom Robot class methods

While this stage may be avoided for the majority of simple robots, you might want to add your own functions to make things more organized. For example, this custom method can be used for position closing combined with tracking of a currently open position via a separately declared object:

private void ClosePosition()
{
    if (position != null)
    {
        Trade.Close(position);
        position = null;
    }
}

Sample Robot Code Explained

Taking all what we have learned above together yields us a picture of cBot’s code as a whole. Below, is the source code of the Sample Martingale Robot, which is bundled with cAlgo installation and is simple enough to be easily understood by a cTrader newbie, yet uses enough API instances to teach something useful. As its name suggests, this robot implements a Martingale trading system. The first trade direction is random. If it is a winner, a new random trade is opened. If it is a loser, a new trade is opened in the same direction but with doubled trading volume, and so on.

My explanations are given as code comments just above the line they explain:

// System namespace will be used for getting a random number via Random class.
using System;
// Main cAlgo API namespace
using cAlgo.API;
// Used for MarketOrderRequest class to send market execution trading orders.
using cAlgo.API.Requests;
// This namespace is not used as this robot does not use any indicators.
using cAlgo.Indicators;
 
// Next class declaration is a part of cAlgo.Robots namespace.
namespace cAlgo.Robots
{
    // Robot attribute to tell cAlgo that the next declaration is actually a robot.
    [Robot]
    // Robot class declaration.
    public class SampleMartingaleRobot : Robot
    {
        // Input parameter for initial volume. Default = 0.1 standard lot, cannot be less than 0.
        [Parameter("Initial Volume", DefaultValue = 10000, MinValue = 0)]
        // It is of type int and can be viewed and modified by user.
        public int InitialVolume { get; set; }
 
        // Stop-loss parameter in pips. Default is 40.
        [Parameter("Stop Loss", DefaultValue = 40)]
        // Also an integer number.
        public int StopLoss { get; set; }
 
        // Take-profit parameter in pips.
        [Parameter("Take Profit", DefaultValue = 40)]
        // It is of the same type int.
        public int TakeProfit { get; set; }
 
        // A new random number generator is declared.
        private Random random = new Random();
        // Position object to store information about trading positions.
        private Position position;
 
        // This function will be executed on initialization of the cBot.
        // override keyword is used to 'overwrite' the Robot class OnStart() implementation.
        protected override void OnStart()
        {
            // Custom method is called to send a trading order
            // of initial volume and random direction.
            ExecuteOrder(InitialVolume, GetRandomTradeCommand());
        }
 
        // Custom trading function declaration. Receives volume and trade direction as arguments.
        private void ExecuteOrder(int volume, TradeType tradeType)
        {
            // New request object is declared, passing the same 
            // parameters to MarketOrderRequest class constructor.
            var request = new MarketOrderRequest(tradeType, volume)
                {
                    // Label for the sent order.
                    Label = "SampleMartingaleRobot",
                    // Stop-loss for the order.
                    StopLossPips = StopLoss,
                    // Take-profit for the order.
                    TakeProfitPips = TakeProfit
                };
            // Using standard cAlgo Trade object to send the formed request.
            Trade.Send(request);
 
        }
 
        // Standard event handler that triggers upon position opening.
        // Receives the position object as an argument.
        protected override void OnPositionOpened(Position openedPosition)
        {
            // Remember the position in the custom object.
            position = openedPosition;
        }
 
        // Standard event handler that triggers upon position closing.
        // Receives the position object as an argument.
        protected override void OnPositionClosed(Position closedPosition)
        {
            // If closed position was in profit
            if (closedPosition.GrossProfit > 0)
            {
                // Call custom class method to send a market order 
                // with initial volume and random direction.
                ExecuteOrder(InitialVolume, GetRandomTradeCommand());
            }
            // If closed position was in loss or at breakeven
            else
            {
                // Call custom class method to send a market order 
                // with doubled volume and the same direction.
                ExecuteOrder((int) position.Volume * 2, position.TradeType);
            }
        }
 
        // Standard error-handling method. Receives error object as an argument.
        protected override void OnError(Error error)
        {
            // If error is generated due to badly formed volume
            if (error.Code == ErrorCode.BadVolume)
                // Stop executing the cBot.
                Stop();
        }
 
        // Custom function to get random trade direction based on random number.
        private TradeType GetRandomTradeCommand()
        {
            // If random integer number between 0 and 1 is 0, then return Buy direction.
            // If random integer number between 0 and 1 is 1, then return Sell direction.
            return random.Next(2) == 0 ? TradeType.Buy : TradeType.Sell;
        }
    }
}

What’s Next?

Now that you are acquainted with the basics of Forex robot-building in cTrader/cAlgo trading environment, you may start developing your own automated system. I would recommend following these steps when you decide to build a cTrader robot:

  1. Look through sample robots’ source code, which is bundled with cAlgo installation.
  2. Download some community-contributed robots from cTDN and browse their code.
  3. Use cAlgo API Reference Explorer to get more information on something you cannot understand.
  4. Visit cTDN forums when you need help.


If you have some questions about cAlgo robots (cBots) or the IDE used to code these robots, please use the commentary form below.

5 Responses to “cAlgo Robots — Coding Basics”

  1. alberto

    como podia conseguir informacion suficiente acerca del sistema de programacion
    c.Algo
    a ser posible en español
    para iniciarme en su programacion

    Reply

  2. Riad Ahmed

    I am a forex trader , I do trade daily, it’s true no such a robot will be accurate 100% but it’s possible to make robot for profit maximum. It could be next plat form written with meta quote mql5 and c hybrid platform because c has limitations of coding. But future traders will rely on robots as an advantage.

    Reply

  3. lgwsyq

    Hi, please help.

    1. if i have closed three positions, then how i get the close time?

    2. in cTrade, which function is similar the Global Variables of MT4?

    Thank you advance.

    Reply

    Andriy Moraru Reply:

    1. As far as I understand, you can reach closed trades via HistoricalTrade interface:

    foreach (var historical_trade in History)
    {
    	if ((Symbol.Code == historical_trade.SymbolCode) &amp;&amp; (MyLabel == historical_trade.Label))
    	{
    		if (historical_trade.TradeType == TradeType.Sell)
    			// Do some stuff with a past Sell trade.
    		if (historical_trade.TradeType == TradeType.Buy)
    			// Do some stuff with a past Buy trade.
    	}
    }

    2. No, there is nothing like MetaTrader’s Global Variables in cTrader. But if you badly need some communication between your cBots, you can use files, DBs, and so on to set it up using the C# functions.

    Reply

  4. Juliano

    Hi! Can someone share code for small ctrader robot witch closes all my pending orders and active trades when one of active trades hit take profit?
    i imagine to use it like that: 1.place pending orders
    2.turn on robot
    3.if one trade of all hit take profit then close all pending ordes and all active trades.
    4.turn off robot
    5. repeat process

    Reply

Leave a Reply

required
required (will not be published)
optional