Skip to content

cBot code samples

This page provides several Python and C# code examples for creating trading bots and developing algorithms. Note that none of the cBots listed below guarantee any financial returns. Make sure to backtest and customise your cBots before deploying any instances on a live account.

cBot sample repositories

Comprehensive cBot code samples, including ready-to-run templates for various automated strategies and trading styles, are available in separate Python and C# repositories in GitHub.

Synchronous operations

All cBots in this section execute their operations synchronously.

Execute market orders

  • A simple cBot performing successful operations

    The following trading bot creates a market order upon startup and saves the result in the result variable.

    If order execution is successful, the entry price is printed in the log.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);
    
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print("Position entry price is {0}", position.EntryPrice);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    class Sample_cBot():
        def on_start(self):
            result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000)
    
            if result.IsSuccessful:
                position = result.Position
                api.Print(f"Position entry price is {position.EntryPrice}")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD
    • Executing Market Order to Buy 10000 EURUSD SUCCEEDED, Position PID14576001
    • Position entry price is 1.19067
  • A simple cBot with customisable parameters

    When declaring various cBot properties, you can turn them into customisable parameters using the [Parameter()] declaration. When a new instance of your cBot is launched, you (or other users) will be able to assign custom values to these.

    Consider the following example.

    1
    2
    [Parameter("SMA Period", DefaultValue = 14)]
    public int SmaPeriod { get; set; }
    

    Note

    Python cBots use customisable parameters declared in their .cs files.

    1
    2
    [Parameter("SMA Period", DefaultValue = 14)]
    public int SmaPeriod { get; set; }
    

    In the above example, we define the following characteristics:

    • The name of the parameter. It will, subsequently, appear in the cTrader UI ("SMA Period").
    • The default value of the parameter that will apply to all new instances unless it is changed by users (DefaultValue = 14).

    In the code below, we show how the SmaPeriod property can be used in an actual trading bot.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SamplecBotReferenceSMA : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }
    
        [Parameter("SMA Period", DefaultValue = 14)]
        public int SmaPeriod { get; set; }
    
        private SampleSMA sma;
    
        protected override void OnStart()
        {
            sma = Indicators.GetIndicator<SampleSMA>(Source, SmaPeriod);
        }
    
        protected override void OnTick()
        {
            Print("{0}", sma.Result.LastValue);
        }
    }
    

    Note

    Python cBots use customisable parameters declared in their .cs files.

    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            self.sma = api.Indicators.GetIndicator<SampleSMA>(api.Source, api.SmaPeriod)
    
        def on_tick(self):
            api.Print(f"{self.sma.Result.LastValue}")
    

    Our bot takes the customisable SmaPeriod property and, on start, passes its value to the Indicators.GetIndicator<SampleSMA>() method. This method returns a simple moving average value for the specified period.

    When creating a cBot instance, all adjustable parameters can be set up in the Add instance window.

    When launched, the cBot informs us of what the last simple moving average value was on every tick.

    Log output

    • CBot instance [Sample cBot Reference SMA, EURUSD, h1] started.
    • 0.975685714285714
    • 0.975681428571429
    • 0.97568
    • CBot instance [Sample cBot Reference SMA, EURUSD, h1] stopped by user.
  • Execute a market order with more arguments

    In the previous example, we passed the minimum possible number of arguments to the ExecuteMarketOrder() method. They were the trade type (TradeType.Buy), the symbol (Symbol) and volume (-1).

    The ExecuteMarketOrder() method can be called with additional arguments such as Label, StopLoss, TakeProfit and Comment. The example below specifies the label ("order 1"), the stop-loss protection mechanism (10) and the take-profit level (10).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    [Robot(TimeZone = TimeZones.UTC)]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "order 1", 10, 10);
    
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print("Position entry price is {0}", position.EntryPrice);
                Print("Position SL price is {0}", position.StopLoss);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    class Sample_cBot():
        def on_start(self):
            result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "order 1", 10, 10)
    
            if result.IsSuccessful:
                position = result.Position
                api.Print(f"Position entry price is {position.EntryPrice}")
                api.Print(f"Position SL price is {position.StopLoss}")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10)
    • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10) SUCCEEDED, Position PID14576098
    • Position entry price is 1.1896
    • Position SL price is 1.1886

Modify a position

In the below example, we only add a take profit value (10) when an order is executed. Afterwards, we modify the position to add a stop loss.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[Robot()]
public class SamplecBbot : Robot
{
    protected override void OnStart()
    {
        var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000,
                                "order 1", null, 10);
        if (result.IsSuccessful)
        {
            var position = result.Position;
            Print("Position SL price is {0}", position.StopLoss);

            var stopLoss = position.EntryPrice - 10*Symbol.PipSize;
            ModifyPosition(position, stopLoss, position.TakeProfit);

            Print("New Position SL price is {0}", position.StopLoss);

        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Sample_cBot():
    def on_start(self):
        result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "order 1", None, 10)

        if result.IsSuccessful:
            position = result.Position
            api.Print(f"Position SL price is {position.StopLoss}")
            stopLoss = position.EntryPrice - 10 * api.Symbol.PipSize
            api.ModifyPosition(position, stopLoss, position.TakeProfit)
            api.Print(f"New Position SL price is {position.StopLoss}")

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Executing Market Order to Buy 10000 EURUSD (TP: 10)
  • Executing Market Order to Buy 10000 EURUSD (TP: 10) SUCCEEDED, Position PID14576161
  • Position SL price is null
  • Modifying position PID14576161 (SL: 1.18744, TP: 1.18944)
  • Modifying position PID14576161 (SL: 1.18744, TP: 1.18944) SUCCEEDED, Position PID14576161
  • New Position SL price is 1.18744

Close a position

  • Perform a full close

    The code sample below places a market order. If the gross profit of the resulting position exceeds a certain value (null && position.GrossProfit > 10), it is closed.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "myLabel");
        }
    
        protected override void OnTick()
        {
            var position = Positions.Find("myLabel");
            if (position != null && position.GrossProfit > 10)
            {
                ClosePosition(position);
                Stop();
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "myLabel")
    
        def on_tick(self):
            position = api.Positions.Find("myLabel")
            if position is not None and position.GrossProfit > 10:
                api.ClosePosition(position)
                api.Stop()
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD
    • Executing Market Order to Buy 10000 EURUSD SUCCEEDED, Position PID14576180
  • Perform a partial close

    We will modify the previous example to create two market orders with the same labels ("myLabel"). On each new bar, our trading bot will close exactly one-half of one of these orders but only if its volume is equal to or greater than 20,000.

    We also use the Positions.FindAll() method. It returns a list of positions that we can iterate through.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 20000, "myLabel");
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 30000, "myLabel");
        }
    
        protected override void OnBar()
        {
            var positions = Positions.FindAll("myLabel", SymbolName, TradeType.Buy);
    
            foreach (var position in positions)
            {
                if (position.VolumeInUnits >= 20000)
                {
                    ClosePosition(position, 15000);
                }
            }
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 20000, "myLabel")
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 30000, "myLabel")
    
        def on_tick(self):
            positions = api.Positions.FindAll("myLabel", api.SymbolName, TradeType.Buy)
            for position in positions:
                if position.VolumeInUnits >= 20000:
                    api.ClosePosition(position, 15000)
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 20000 EURUSD
    • Executing Market Order to Buy 20000 EURUSD SUCCEEDED, Position PID14579299
    • Executing Market Order to Buy 30000 EURUSD
    • Executing Market Order to Buy 30000 EURUSD SUCCEEDED, Position PID14579300

Create pending orders

  • Create limit and stop orders

    Limit and stop orders are pending orders; despite this, they are created similarly to market orders. However, when creating limit and stop orders, you also have to specify their target price and there is no market range.

    This cBot creates two limit orders and a stop order. It then iterates through the orders and prints their labels and IDs to the log.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            PlaceLimitOrder(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLimitOrder");
            PlaceLimitOrder(TradeType.Buy, SymbolName, 20000, Symbol.Bid-2*Symbol.PipSize,
                    "myLimitOrder");
            PlaceStopOrder(TradeType.Buy, SymbolName, 10000, Symbol.Ask, "myStopOrder");
    
            foreach (var pendingOrder in PendingOrders)
            {
                Print("Order placed with label {0}, id {1}", pendingOrder.Label, pendingOrder.Id);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    class Sample_cBot():
        def on_start(self):
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLimitOrder")
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 20000, api.Symbol.Bid - 2 * api.Symbol.PipSize, "myLimitOrder")
            api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask, "myStopOrder")
    
            for pendingOrder in api.PendingOrders:
                Print(f"Order placed with label {pendingOrder.Label}, id {pendingOrder.Id}")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19036)
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19036) SUCCEEDED, PendingOrder OID25220794
    • Placing Limit Order to Buy 20000 EURUSD (Price: 1.19017)
    • Placing Limit Order to Buy 20000 EURUSD (Price: 1.19017) SUCCEEDED, PendingOrder OID25220795
    • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19040)
    • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19040) SUCCEEDED, PendingOrder OID25220796
    • Order placed with label myLimitOrder, id 25220794
    • Order placed with label myLimitOrder, id 25220795
    • Order placed with label myStopOrder, id 25220796
  • Create pending orders with more parameters

    As is the case with market orders, you can also specify the order label, various protection mechanisms, the order expiry date and provide a comment.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var midnight = Server.Time.AddDays(1).Date;
    
            PlaceLimitOrder(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "mySample_cBot", 10, null, midnight, "First");
    
            PlaceStopOrder(TradeType.Buy, SymbolName, 10000, Symbol.Ask, "mySample_cBot", 10, 10, null, "Second");
    
            foreach (var order in PendingOrders)
            {
                var sl = order.StopLoss == null ? "" : "SL: " + order.StopLoss;
                var tp = order.TakeProfit == null ? "" : " TP: " + order.TakeProfit;
    
                var text = string.Format("{0} {1}", sl, tp);
    
                if (order.OrderType == PendingOrderType.Limit)
                    Print(order.Comment + " Limit Order " + text);
                else
                    Print(order.Comment + " Stop Order " + text);
            }
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    class Sample_cBot():
        def on_start(self):
            midnight = api.Server.Time.AddDays(1).Date
    
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "mySample_cBot", 10, None, midnight, "First")
            api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask, "mySample_cBot", 10, 10, None, "Second")
    
            for order in api.PendingOrders:
                sl = "" if order.StopLoss is None else f"SL: {order.StopLoss}"
                tp = "" if order.TakeProfit is None else f"TP: {order.TakeProfit}"
    
                api.Print(f"{order.Comment} {order.OrderType} Order {sl} {tp}")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19049, SL: 10, ExpireTime: 12/05/2018 00:00:00)
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19049, SL: 10, ExpireTime: 12/05/2018 00:00:00) SUCCEEDED, PendingOrder OID25220807
    • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19053, SL: 10, TP: 10)
    • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19053, SL: 10, TP: 10) SUCCEEDED, PendingOrder OID25220808
    • Limit Order
    • First Limit Order SL: 1.18949
    • Second Stop Order SL: 1.18953 TP: 1.19153

Modify pending orders

It is possible to modify several characteristics of pending orders.

The example below showcases how to modify the target price, the protection levels or the expiration date and time of a pending order.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var price = Symbol.Ask + 10 * Symbol.PipSize;
        var expiry = Server.Time.AddHours(12);
        PlaceStopOrder(TradeType.Buy, SymbolName, 10000, price, "myLabel", 10, 10, expiry);
    }

    protected override void OnBar()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel")
            {
                double newPrice = Symbol.Ask + 5 * Symbol.PipSize;
                ModifyPendingOrder(order, newPrice, order.StopLossPips,
                                                            order.TakeProfitPips, order.ExpirationTime);
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Sample_cBot():
    def on_start(self):
        price = api.Symbol.Ask + 10 * api.Symbol.PipSize
        expiry = Server.Time.AddHours(12)

        api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, price, "myLabel", 10, 10, expiry)

    def on_bar(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel":
                newPrice = api.Symbol.Ask + 5 * api.Symbol.PipSize
                api.ModifyPendingOrder(order, newPrice, order.StopLossPips, order.TakeProfitPips, order.ExpirationTime)

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19254, SL: 10, TP: 10, ExpireTime: 11/05/2018 20:07:25)
  • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19254, SL: 10, TP: 10, ExpireTime: 11/05/2018 20:07:25) SUCCEEDED, PendingOrder OID25220877

Cancel pending orders

The syntax for cancelling an order is CancelPendingOrder(order), where order is of type PendingOrder.

The below example shows cancelling all orders with the label "myLabel".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnTick()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel")
            {
                CancelPendingOrder(order);
            }
        }
    }
}
1
2
3
4
5
class Sample_cBot():
    def on_tick(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel":
                api.CancelPendingOrder(order)

Position events

It is possible to subscribe to events related to various trading operations. For example, to test whether a position is opened, we subscribe to an event that is raised for all Position objects on open.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        Positions.Opened += PositionsOnOpened;
        ExecuteMarketOrder(TradeType.Buy, Symbol, 10000, "myLabel", 10, 10);
    }

    private void PositionsOnOpened(PositionOpenedEventArgs args)
    {
        var pos = args.Position;
        Print("Position opened at {0}", pos.EntryPrice);
    }
}
1
2
3
4
5
6
7
8
class Sample_cBot():
    def on_start(self):
        api.Positions.Opened += self.on_position_opened
        api.ExecuteMarketOrder(TradeType.Buy, api.Symbol, 10000, "myLabel", 10, 10)

    def on_position_opened(self, args):
        pos = args.Position
        api.Print(f"Position opened at {pos.EntryPrice}")

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10)
  • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10) SUCCEEDED, Position PID14579468
  • Position opened at 1.19224

Similarly, it is possible to subscribe to events that are raised every time a position is closed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        Positions.Closed += PositionsOnClosed;
        ExecuteMarketOrder(TradeType.Buy, Symbol, 10000, "myLabel", 10, 10);
    }

    protected override void OnBar()
    {
        var position = Positions.Find("myLabel");
        if (position != null)
            ClosePosition(position);
    }

    private void PositionsOnClosed(PositionClosedEventArgs args)
    {
        var pos = args.Position;
        Print("Position closed with {0} profit", pos.GrossProfit);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Sample_cBot():
    def on_start(self):
        api.Positions.Closed += self.on_position_closed
        api.ExecuteMarketOrder(TradeType.Buy, api.Symbol, 10000, "myLabel", 10, 10)

    def on_bar(self):
        position = api.Positions.Find("myLabel")

        if position is not None:
            api.ClosePosition(position);            

    def on_position_closed(self, args):
        pos = args.Position
        api.Print(f"Position closed with {pos.GrossProfit} profit")

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10)
  • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10) SUCCEEDED, Position PID14579479
  • Closing position PID14579299
  • Closing position PID14579299 SUCCEEDED, Position PID14579299
  • Position closed with 20.64 profit

Coordinates conversion

The below cBot allows users to place limit orders in a suitable direction simply by right-clicking on a chart. It achieves this by converting mouse Y-coordinates to chart Y-coordinates (which, for symbols, correspond to symbol prices).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[Robot(AccessRights = AccessRights.None)]
public class CoordinatesConverter : Robot
{
    protected override void OnStart()
    {
        Chart.MouseUp += Chart_MouseUp;
    }

    private void Chart_MouseUp(ChartMouseEventArgs obj)
    {
        var desiredPrice = Chart.YToYValue(obj.MouseY);
        var desiredTradeType = desiredPrice > Symbol.Bid ? TradeType.Sell : TradeType.Buy;
        PlaceLimitOrder(desiredTradeType, SymbolName, 10000, desiredPrice);
    }
}
1
2
3
4
5
6
7
8
class Sample_cBot():
    def on_start(self):
        api.Chart.MouseUp += self.on_chart_mouse_up        

    def on_chart_mouse_up(self, args):
        desiredPrice = api.Chart.YToYValue(args.MouseY)
        desiredTradeType = TradeType.Sell if desiredPrice > api.Symbol.Bid else TradeType.Buy
        api.PlaceLimitOrder(desiredTradeType, api.SymbolName, 10000, desiredPrice)

Asynchronous execution

The code samples above are designed to implement trading robots using synchronous execution. C# and Python both support asynchronous operations, allowing your cBot to perform several actions within the same timeframe.

Execute market orders asynchronously

The syntax of the asynchronous methods is similar to that of the synchronous ones. While they accept the same types of arguments, their return type is TradeOperation instead of TradeResult.

  • Basic asynchronous operations

    The following cBot demonstrates how asynchronous operations work. A market order is created; in the next conditional, the cBot checks if the operation is executing.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000);
    
            if (operation.IsExecuting)
            {
                Print("Operation Is Executing");
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000)
    
            if operation.IsExecuting:
                api.Print("Operation Is Executing")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD
    • Operation Is Executing
    • Executing Market Order to Buy 10000 EURUSD SUCCEEDED, Position PID14579532
  • Execute an order

    The next example highlights the difference between synchronous and asynchronous methods.

    The cBot checks if an operation is executing right after calling an asynchronous method. It does it again after calling a synchronous method. The log output for these two actions is different.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000);
            Print(operation.IsExecuting ? "Operation Is Executing" : "Operation executed");
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 20000);
            Print(operation.IsExecuting ? "Operation Is Executing" : "Operation executed");
        }
    }
    
    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000)
            api.Print("Operation Is Executing" if operation.IsExecuting else "Operation executed")
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 20000)
            api.Print("Operation Is Executing" if operation.IsExecuting else "Operation executed")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD
    • Operation Is Executing
    • Executing Market Order to Buy 20000 EURUSD
    • Executing Market Order to Buy 10000 EURUSD SUCCEEDED, Position PID14579541
    • Executing Market Order to Buy 20000 EURUSD SUCCEEDED, Position PID14579542
    • Operation executed
  • Execute an order with more parameters

    The following cBot places an order specifying its label ("myLabel"), protection levels (10, 10), symbol (SymbolName) and volume (10000).

    The example also contains the Positions collection and the FindAll() method. Find() and FindAll() can be used to find positions with the same label, symbol and trade type.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, "myLabel", 10, 10);
        }
        protected override void OnTick()
        {
            var positions = Positions.FindAll("myLabel", SymbolName, TradeType.Buy);
    
            if (positions.Length == 0)
                return;
    
            foreach (var position in positions)
                Print("Buy at {0} SL {1}", position.EntryPrice, position.StopLoss);
    
            Stop();
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", 10, 10)
    
        def on_tick(self):
            positions = api.Positions.FindAll("myLabel", api.SymbolName, TradeType.Buy)
    
            if positions.Length == 0:
                return
    
            for position in positions:
                api.Print(f"Buy at {position.EntryPrice} SL {position.StopLoss}")
    
            api.Stop()            
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10)
    • Executing Market Order to Buy 10000 EURUSD (SL: 10, TP: 10) SUCCEEDED, Position PID14579719
    • Buy at 1.19087 SL null
    • Buy at 1.19357 SL 1.19257
    • cBot "New cBot" was stopped for EURUSD, h1.

Modify position asynchronously

The cBot below places a market order and then modifies the newly opened position.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, "myLabel", null, 10);
    }

    protected override void OnTick()
    {
        Position myPosition = Positions.Find("myLabel");
        if (myPosition != null && myPosition.StopLoss == null)
        {
            double stopLoss = Symbol.Bid - 10 * Symbol.PipSize;
            ModifyPositionAsync(myPosition, stopLoss, myPosition.TakeProfit);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Sample_cBot():
    def on_start(self):
        api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", None, 10)

    def on_tick(self):
        myPosition = Positions.Find("myLabel")

        if myPosition is None or myPosition.StopLoss is not None:
            return

        stopLoss = api.Symbol.Bid - 10 * api.Symbol.PipSize

        api.ModifyPositionAsync(myPosition, stopLoss, myPosition.TakeProfit)        

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Executing Market Order to Buy 10000 EURUSD (TP: 10)
  • Executing Market Order to Buy 10000 EURUSD (TP: 10) SUCCEEDED, Position PID14579736
  • Modifying position PID14579300 (SL: 1.19213, TP: null)
  • Modifying position PID14579300 (SL: 1.19213, TP: null) SUCCEEDED, Position PID14579300

Close a position asynchronously

The next example demonstrates closing a position asynchronously if it exists.

The Find() method is used to search the Positions collection for the position with a specific label.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        ExecuteMarketOrderAsync(TradeType.Buy, Symbol, 10000, "myLabel", null, 10);
    }

    protected override void OnTick()
    {
        Position myPosition = Positions.Find("myLabel");
        if (myPosition != null && myPosition.GrossProfit > 10)
        {
            ClosePositionAsync(myPosition);
            Stop();
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Sample_cBot():
    def on_start(self):
        api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", None, 10)

    def on_tick(self):
        myPosition = Positions.Find("myLabel")

        if myPosition is None or myPosition.GrossProfit <= 10:
            return

        api.ClosePositionAsync(myPosition)
        api.Stop()        

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Executing Market Order to Buy 10000 EURUSD (TP: 10)
  • Executing Market Order to Buy 10000 EURUSD (TP: 10) SUCCEEDED, Position PID14579740
  • Closing position PID14579300
  • Closing position PID14579300 SUCCEEDED, Position PID14579300
  • cBot "New cBot" was stopped for EURUSD, h1.

Place limit and stop orders asynchronously

As stated above, placing pending orders is similar to creating market orders.

However, there are some slight differences in the arguments between these two methods. The market range is absent from the arguments list. Moreover, you have to specify the target price, and you can pass an optional argument specifying the order expiration date.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var expiry = Server.Time.AddHours(12);
        PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLabel", null, null, expiry);
        PlaceStopOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Ask + 10 * Symbol.PipSize, "myLabel", null, null, expiry);
    }
}
1
2
3
4
5
class Sample_cBot():
    def on_start(self):
        expiry = api.Server.Time.AddHours(12)
        api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLabel", None, None, expiry)
        api.PlaceStopOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask + 10 * api.Symbol.PipSize, "myLabel", None, None, expiry)    

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19382, ExpireTime: 12/05/2018 00:18:19)
  • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19487, ExpireTime: 12/05/2018 00:18:19)
  • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19382, ExpireTime: 12/05/2018 00:18:19) SUCCEEDED, PendingOrder OID25221859
  • Placing Stop Order to Buy 10000 EURUSD (Price: 1.19487, ExpireTime: 12/05/2018 00:18:19) SUCCEEDED, PendingOrder OID25221860

Modify pending orders asynchronously

The following cBot modifies limit orders asynchronously.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var expiry = Server.Time.AddHours(12);
        PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLabel", null, 10, expiry);

    }
    protected override void OnTick()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel" && order.StopLoss == null)
                ModifyPendingOrderAsync(order, order.TargetPrice, 10, 10, null);
        }
    }
}
1
2
3
4
5
6
7
8
9
class Sample_cBot():
    def on_start(self):
        expiry = api.Server.Time.AddHours(12)
        api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLabel", None, 10, expiry)

    def on_tick(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel" and order.StopLoss is None:
                api.ModifyPendingOrderAsync(order, order.TargetPrice, 10, 10, None)

Log output

  • cBot "New cBot" was started successfully for EURUSD, h1.
  • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19347, TP: 10, ExpireTime: 12/05/2018 00:22:08)
  • Modifying pending order OID25221860 (Volume: 10000, Price: 1.19487, SL: 10, TP: 10, ExpireTime: 12/05/2018 00:18:19)
  • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19347, TP: 10, ExpireTime: 12/05/2018 00:22:08) SUCCEEDED, PendingOrder OID25221906
  • Modifying pending order OID25221860 (Volume: 10000, Price: 1.19487, SL: 10, TP: 10, ExpireTime: 12/05/2018 00:18:19) SUCCEEDED, PendingOrder OID25221860
  • Modifying pending order OID25221906 (Volume: 10000, Price: 1.19347, SL: 10, TP: 10, ExpireTime: 12/05/2018 00:22:08)
  • Modifying pending order OID25221906 (Volume: 10000, Price: 1.19347, SL: 10, TP: 10, ExpireTime: 12/05/2018 00:22:08) SUCCEEDED, PendingOrder OID25221906

Cancel pending orders asynchronously

  • Cancel all pending orders

    The cBot below asynchronously cancels all currently pending orders.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnBar()
        {
            foreach (var pendingOrder in PendingOrders)
            {
                CancelPendingOrderAsync(pendingOrder);
            }
        }
    }
    
    1
    2
    3
    4
    class Sample_cBot():
        def on_bar(self):
            for order in api.PendingOrders:
                api.CancelPendingOrderAsync(order)
    

    Log output

    • cBot "cancel pending order" was started successfully for EURUSD, h1.
    • Cancelling pending order OID274705
    • Cancelling pending order OID274706
    • Cancelling pending order OID274707
    • Cancelling pending order OID274708
    • Cancelling pending order OID274709
    • Cancelling pending order OID274705 SUCCEEDED, PendingOrder OID274705
    • Cancelling pending order OID274706 SUCCEEDED, PendingOrder OID274706
    • Cancelling pending order OID274707 SUCCEEDED, PendingOrder OID274707
    • Cancelling pending order OID274708 SUCCEEDED, PendingOrder OID274708
    • Cancelling pending order OID274709 SUCCEEDED, PendingOrder OID274709
  • Cancel pending orders with a certain label

    This cBot only cancels pending orders with a certain label.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnBar()
        {
            foreach (var pendingOrder in PendingOrders)
            {
                if (pendingOrder.Label == "myLabel")
                    CancelPendingOrderAsync(pendingOrder);
            }
        }
    }
    
    1
    2
    3
    4
    5
    class Sample_cBot():
        def on_bar(self):
            for order in api.PendingOrders:
                if order.Label == "myLabel":
                    api.CancelPendingOrderAsync(order)
    

Callback functions for asynchronous methods

Once a result is returned, using asynchronous operations often requires controlling execution. To handle this, you can add a callback function at the end of the list of parameters of all asynchronous methods.

This function will be called as soon as a response is received from the server. For instance, it could be called when a position is opened, modified or closed.

  • Asynchronous market order with a callback

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, PositionOpened);
            if (operation.IsExecuting)
                Print(operation.ToString());
            else
                Print(operation.TradeResult.ToString());
    
        }
    
        private void PositionOpened(TradeResult tradeResult)
        {
            var position = tradeResult.Position;
            Print(tradeResult.ToString());
            if (tradeResult.IsSuccessful)
                Print("Position {0} opened at {1}", position.Id, position.EntryPrice);
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from System import Action
    
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, Action[TradeResult](self.on_position_opened))
    
            if (operation.IsExecuting)
                api.Print(operation.ToString())
            else
                api.Print(operation.TradeResult.ToString())
    
        def on_position_opened(self, tradeResult):
            position = tradeResult.Position
    
            api.Print(tradeResult.ToString())
    
            if tradeResult.IsSuccessful:
                api.Print(f"Position {position.Id} opened at {position.EntryPrice}")
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Executing Market Order to Buy 10000 EURUSD
    • TradeOperation (Executing Market Order to Buy 10000 EURUSD EXECUTING)
    • Executing Market Order to Buy 10000 EURUSD SUCCEEDED, Position PID14579835
    • TradeResult (Success, Position: PID14579835)
    • Position 14579835 opened at 1.19414
  • Using lambda expressions

    Instead of defining a named callback method you can use lambda expressions.

    In the following example, when an order is placed the description of the result will be printed to the log.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000,
                    Symbol.Ask - 20 * Symbol.PipSize, "myLabel", result => Print(result.ToString()));
        }
    }
    
    1
    2
    3
    4
    5
    from System import Action
    
    class Samples():
        def on_start(self):
            operation = api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask - 20 * api.Symbol.PipSize, "myLabel", Action[TradeResult](lambda result: api.Print(result.ToString())))
    

    Log output

    • cBot "New cBot" was started successfully for EURUSD, h1.
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19320)
    • Placing Limit Order to Buy 10000 EURUSD (Price: 1.19320) SUCCEEDED, PendingOrder OID25222083
    • TradeResult (Success, PendingOrder: OID25222083)

Image title