I can only open one position on multiple bots and multiple instances

Created at 05 Jan 2022, 12:44
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
TR

triplelorenz

Joined 05.01.2022

I can only open one position on multiple bots and multiple instances
05 Jan 2022, 12:44


Hi guys,

I am struggling with my bots to open more than one position. The bots, I plan to have multiple running at the same time, I am using will be multiple instances each with their own name.

Currently I can only get 1 position to open from multiple bots and multiple positions. I am pretty sure it is the position count part, but I am struggling with my code ability. The code below is a simple bot for example purpose, but has the same "open" and "close" functions as most of my other ones.

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SuperTrend : Robot
    {

        #region User defined parameters

        [Parameter("Instance Name", Group = "Parameters", DefaultValue = "001")]
        public string InstanceName { get; set; }


        [Parameter("Source MA", Group = "Long Trend Moving Average")]
        public DataSeries Sourcehma { get; set; }

        [Parameter("Moving Average Period", Group = "Long Trend Moving Average", DefaultValue = 200, MinValue = 10, MaxValue = 300)]
        public int Periodshma { get; set; }

        [Parameter("Moving Average Type", Group = "Long Trend Moving Average", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MAType { get; set; }


        [Parameter("Source MA", Group = "Fast Moving Average")]
        public DataSeries Sourcema2 { get; set; }

        [Parameter("Moving Average Period", Group = "Fast Moving Average", DefaultValue = 50, MinValue = 10, MaxValue = 80)]
        public int Periodsma2 { get; set; }

        [Parameter("Moving Average Type", Group = "Fast Moving Average", DefaultValue = MovingAverageType.Hull)]
        public MovingAverageType MAType2 { get; set; }


        [Parameter("ATR Stop Loss ", Group = "Money Management", DefaultValue = 2, MinValue = 0.5, MaxValue = 5, Step = 0.5)]
        public double SLATR { get; set; }

        [Parameter("ATR Take Profit ", Group = "Money Management", DefaultValue = 2, MinValue = 0.5, MaxValue = 5, Step = 0.5)]
        public double TPATR { get; set; }

        [Parameter("% per trade", Group = "Money Management", DefaultValue = 2, MinValue = 0.5, MaxValue = 4, Step = 0.2)]
        public double PerTrade { get; set; }


        [Parameter("Trigger (pips)", Group = "Optimiser", DefaultValue = 2.0, MinValue = 0, MaxValue = 10)]
        public double TriggerPips { get; set; }

        [Parameter("Trail SL (pips)", Group = "Optimiser", DefaultValue = 10.0, MinValue = 1, MaxValue = 100)]
        public double TrailSLPips { get; set; }

        [Parameter("Trail TP (pips)", Group = "Optimiser", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
        public double TrailTPPips { get; set; }


        #endregion

        #region Indicator declarations

        private MovingAverage hma { get; set; }

        private MovingAverage ma2 { get; set; }

        private AverageTrueRange atr { get; set; }


        /// These are for the trader optimiser function

        Symbol currentSymbol;
        Position currentPosition;
        double? newStopLoss = 0;
        double? newTakeProfit = 0;
        int lookback;

        #endregion

        #region cTrader events


        protected override void OnStart()
        {
            /// construct the indicators

            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);

            hma = Indicators.MovingAverage(Sourcehma, Periodshma, MAType);
            ma2 = Indicators.MovingAverage(Sourcema2, Periodsma2, MAType2);

            /// the MAType is from the independent moving average, not this indicator
        }

        /// <summary>
        /// This method is called every time the price changes for the symbol
        /// </summary>
        protected override void OnTick()
        {

            var hmaline = hma.Result.Last(1);
            var Prevhmaline = hma.Result.Last(2);
            var Prev2hmaline = hma.Result.Last(3);

            var hmaline2 = ma2.Result.Last(1);
            var Prevhmaline2 = ma2.Result.Last(2);
            var Prev2hmaline2 = ma2.Result.Last(3);

            var zerovalue = 0;

            var day = Server.Time.DayOfWeek;


            if (day == DayOfWeek.Monday || day == DayOfWeek.Tuesday || day == DayOfWeek.Wednesday || day == DayOfWeek.Thursday || day == DayOfWeek.Friday || day == DayOfWeek.Saturday || day == DayOfWeek.Sunday)
            {


                ///if (rsi.Result.HasCrossedAbove(RSILow, RSIlookback) && ma2.Result.HasCrossedBelow(atrband1up, atrbandlookback) && hmaline > Prev2hmaline && Bars.ClosePrices.Last(1) > hmaline && super1.UpTrend.Last(1) < Bars.LowPrices.Last(1))
                if (hmaline > Prevhmaline)
                {
                    ClosePositions(InstanceName, TradeType.Sell);
                    OpenPosition(InstanceName, TradeType.Buy);
                }


                else if (hmaline < Prev2hmaline)
                {
                    ClosePositions(InstanceName, TradeType.Buy);
                    OpenPosition(InstanceName, TradeType.Sell);
                }

            }

            foreach (var pos in Positions)
            {
                this.currentSymbol = Symbols.GetSymbol(SymbolName);
                this.currentPosition = pos;
                if (isNearTarget())
                {

                    CalcNewValues();

                    AdjustPosition();


                }
            }
        }


        protected override void OnBar()
        {


        }

        protected override void OnStop()
        {
            // unused
        }

        #endregion


        #region Private Subs


        private void OpenPosition(string Label, TradeType TradeDirection)
        {
            //Calculate Trade Amount base on the ATR

            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var PerTradeadjust = PerTrade / 100;
            var TradeAmount = (Account.Equity * PerTradeadjust) / (PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);
            ///var cBotPositions = Positions.FindAll(InstanceName); not used

            {

                if (Positions.Count(x => x.Label == InstanceName) == 0)
                {
                    ExecuteMarketOrder(TradeDirection, SymbolName, TradeAmount, InstanceName, null, null);

                }

            }


        }
        private void ClosePositions(string Label, TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol, type);

            if (p != null)
            {
                ClosePosition(p);
            }
        }

        void CalcNewValues()
        {
            if (currentPosition.TradeType == TradeType.Buy)
            {
                newStopLoss = currentSymbol.Bid - (this.currentSymbol.PipSize * this.TrailSLPips);
                newTakeProfit = currentSymbol.Bid + (this.currentSymbol.PipSize * this.TrailTPPips);
            }
            else
            {
                newStopLoss = currentSymbol.Ask + (this.currentSymbol.PipSize * this.TrailSLPips);
                newTakeProfit = currentSymbol.Ask - (this.currentSymbol.PipSize * this.TrailTPPips);
            }
        }

        void AdjustPosition()
        {
            if (newStopLoss == 0 || newTakeProfit == 0)
                return;
            ModifyPosition(currentPosition, newStopLoss, newTakeProfit);

        }


        bool isNearTarget()
        {

            if (this.currentPosition.TradeType == TradeType.Buy)
            {
                if (currentSymbol.Bid > this.currentPosition.TakeProfit - (this.currentSymbol.PipSize * this.TriggerPips))
                    return true;

            }
            else
            {
                if (currentSymbol.Ask < this.currentPosition.TakeProfit + (this.currentSymbol.PipSize * this.TriggerPips))
                    return true;
            }

            return false;
        }
        #endregion
    }

}

 


@triplelorenz
Replies

amusleh
07 Jan 2022, 07:27 ( Updated at: 07 Jan 2022, 07:28 )

Hi,

You should use different values for your cBot "Instance Name" parameter for each instance, otherwise all the instances will only open one position.

Or you should change the code at:

        private void OpenPosition(string Label, TradeType TradeDirection)
        {
            //Calculate Trade Amount base on the ATR

            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var PerTradeadjust = PerTrade / 100;
            var TradeAmount = (Account.Equity * PerTradeadjust) / (PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);
            ///var cBotPositions = Positions.FindAll(InstanceName); not used
            if (Positions.Count(x => x.Label == InstanceName) == 0)
            {
                ExecuteMarketOrder(TradeDirection, SymbolName, TradeAmount, InstanceName, null, null);
            }
        }

 


@amusleh