Category Range  Published on 22/08/2024

cBot_Pending_Tiengthu

Description

cTrader cBot with multiple pending orders and Trailing Stop functionality. 

This cbot is not the final version but it describes the principle of my cbot. I have 2 cbots running in live account, RSI_bot and XAU_bot. If you are interested, you can see my account:

https://ct.spotware.com/investor/HFWsCkwNjBM

More information or using my other cBots, email to  superalgo247@gmail.com 

or

 https://t.me/+TW8UYDE-R242NzZl


using cAlgo.API;
using System;


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


namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PendingOrderTiengthu : Robot
    {
        [Parameter("Buy Stop", DefaultValue = true)]
        public bool BuyStopEnabled { get; set; }

        [Parameter("Sell Stop", DefaultValue = true)]
        public bool SellStopEnabled { get; set; }

        [Parameter("Buy Limit", DefaultValue = true)]
        public bool BuyLimitEnabled { get; set; }

        [Parameter("Sell Limit", DefaultValue = true)]
        public bool SellLimitEnabled { get; set; }

        [Parameter("Volume (Lots)", DefaultValue = 0.01)]
        public double FirstVolume { get; set; }

        [Parameter("Number of Orders", DefaultValue = 2, MinValue = 1)]
        public int NumberOfOrders { get; set; }

        [Parameter("Distance (Pips)", DefaultValue = 50, MinValue = 1)]
        public double Distance { get; set; }

        [Parameter("Distance Between Orders (Pips)", DefaultValue = 100, MinValue = 1)]
        public double DistanceBetween { get; set; }

        [Parameter("Label", DefaultValue = "Pending_TiengThu")]
        public string Label { get; set; }

        [Parameter("SL (Pips)", DefaultValue = 0, MinValue = 0)]
        public double StopInPips { get; set; }

        [Parameter("TP (Pips)", DefaultValue = 50, MinValue = 0)]
        public double TakeProfit { get; set; }
        
        
        [Parameter("Enable Trailing Stop", DefaultValue = true)]
        public bool EnableTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (Pips)", DefaultValue = 50)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Distance (Pips)", DefaultValue = 5)]
        public int TrailingStopDistance { get; set; }

        protected override void OnStart()
        {
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(FirstVolume);
            Distance *= Symbol.PipSize;
            DistanceBetween *= Symbol.PipSize;
            var stopLoss = StopInPips == 0 ? null : (double?)StopInPips;
            var takeProfit = TakeProfit == 0 ? null : (double?)TakeProfit;      

            for (int i = 0; i < NumberOfOrders; i++)
            {
                double orderDistance = Distance + i * DistanceBetween;
                double orderPrice;

                if (BuyStopEnabled)
                {
                    orderPrice = Symbol.Ask + orderDistance;
                    PlaceStopOrder(TradeType.Buy, orderPrice, volumeInUnits, stopLoss, takeProfit);
                }

                if (SellStopEnabled)
                {
                    orderPrice = Symbol.Bid - orderDistance;
                    PlaceStopOrder(TradeType.Sell, orderPrice, volumeInUnits, stopLoss, takeProfit);
                }

                if (BuyLimitEnabled)
                {
                    orderPrice = Symbol.Ask - orderDistance;
                    PlaceLimitOrder(TradeType.Buy, orderPrice, volumeInUnits, stopLoss, takeProfit);
                }

                if (SellLimitEnabled)
                {
                    orderPrice = Symbol.Bid + orderDistance;
                    PlaceLimitOrder(TradeType.Sell, orderPrice, volumeInUnits, stopLoss, takeProfit);
                }
            }
        }

        protected override void OnBar()
        {
        
                       
        }
        
        protected override void OnTick()
        {
           
           UpdatePositionsWithLabel(Label); 
           
           if (EnableTrailingStop)
            {
                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName)
                    {
                        if (position.Pips > TrailingStopTrigger)
                        {
                            SetTrailingStop(position);
                            
                        }
                    }
                }
            }
        }
        
        private void SetTrailingStop(Position position)
        {
            double newStopLossPrice;

            if (position.TradeType == TradeType.Buy)
            {
                newStopLossPrice = Symbol.Bid - TrailingStopDistance * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
            else if (position.TradeType == TradeType.Sell)
            {
                newStopLossPrice = Symbol.Ask + TrailingStopDistance * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }
        
        
        
        
        
        private void PlaceStopOrder(TradeType tradeType, double stopPrice, double volumeInUnits, double? stopLoss, double? takeProfit)
        {
            TradeResult result = PlaceStopOrder(tradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, null);
            if (!result.IsSuccessful) Print("Error: ", result.Error);
        }

        private void PlaceLimitOrder(TradeType tradeType, double limitPrice, double volumeInUnits, double? stopLoss, double? takeProfit)
        {
            TradeResult result = PlaceLimitOrder(tradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, null);
            if (!result.IsSuccessful) Print("Error: ", result.Error);
        }
        
        
        
        
        private void UpdatePositionsWithLabel(string label)
        {
            var positionsWithLabel = Positions
                .Where(p => p.Label == label && p.SymbolName == SymbolName)
                .ToList();

            if (positionsWithLabel.Count == 0)
                return;

            double totalVolume = positionsWithLabel.Sum(p => p.VolumeInUnits);
            double totalEntryPrice = positionsWithLabel.Sum(p => p.EntryPrice * p.VolumeInUnits);
            double averageEntryPrice = totalEntryPrice / totalVolume;

            double newTakeProfitPrice;
            foreach (var position in positionsWithLabel)
            {
                if (position.TradeType == TradeType.Buy)
                {
                    newTakeProfitPrice = averageEntryPrice + TakeProfit * Symbol.PipSize;
                }
                else
                {
                    newTakeProfitPrice = averageEntryPrice - TakeProfit * Symbol.PipSize;
                }

                if (position.TakeProfit != newTakeProfitPrice)
                {
                    ModifyPosition(position, position.StopLoss, newTakeProfitPrice);
                }
            }
        }
        
        
        
        
        
        
        
    }
}


ForexViet's avatar
ForexViet

Joined on 05.05.2023

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: 23.8_Pending_TiengThu_withSourceCode.algo
  • Rating: 0
  • Installs: 157
  • Modified: 22/08/2024 23:25
Comments
Log in to add a comment.
ForexViet's avatar
ForexViet · 1 month ago

This cbot is semi-automatic, which means if you have built your own indicator system, you can use it to place pending orders, manage open orders and close them. In the code, I programmed the cbot to manage only profitable open positions, and for losing positions, if you want, you can set SL for each pending Order.

JI
jim.tollan · 1 month ago

 @emaile2008 -  on looking at the source code, this is definitely due to all the activity taking place on the OnStart() event, rather than being OnBar(). You could refactor everything out to OnBar() and add further conditions so as to play when required.

EM
emaile2008 · 1 month ago

after number of orders parameter finish all orders, it will not place any new orders unless you stop cbot and run it again

i think if there is option to reset orders like every day or every 4 hours it will be great