Multiple Instances

Created at 02 Sep 2017, 07:41
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!
HT

HTtrader

Joined 19.07.2017

Multiple Instances
02 Sep 2017, 07:41


I am trying to modify my code to handle multiple instances now and am running into a bit of trouble.

            var toppre = BB.Top.Last(1);
            var bottompre = BB.Bottom.Last(1);
            var StopLoss = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);
            var volumeInUnits = Symbol.QuantityToVolume(Quantity);

            foreach (var position in Positions)
            {
                ModifyPositionAsync(position, StopLoss, position.TakeProfit);
                Print("New Position SL price is {0}", position.StopLoss);

That is the sample of code that has the problem so far. The cbot changes only 1 order correctly to have the right valued stop loss however for other instances the values seems very obsecure and I can't explain it.

It has set two of my other instances in which I ran the cbot to be 580 pips and 1080 pip stop loss respectively however according to the code the value should be only about 40 pips. Is this a bug or is it something in my code?


@HTtrader
Replies

Spotware
04 Sep 2017, 09:01

Dear hungtonydang,

Can we have a complete cBot that reproduces this issue to check and advise accordingly? We cannot see anything suspicious in the code provided but information is missing, e.g. we cannot see how the StopLoss value is set.

Also note that ModifyPositionAsync() is an asynchronous function and there is no guarantee that it will be executed before Print(). Try ModifyPosition() instead and let us know if the problem still applies.

Best Regards,

cTrader Team


@Spotware

HTtrader
05 Sep 2017, 00:18

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.None)]
    public class HunterBB : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 28, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "Pid")]
        public string PositionId { get; set; }

        BollingerBands BB;

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

        protected override void OnBar()
        {
            var toppre = BB.Top.Last(1);
            var bottompre = BB.Bottom.Last(1);
            var StopLoss = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);
            var volumeInUnits = Symbol.QuantityToVolume(Quantity);
            
            foreach (var position in Positions)
            {
                ModifyPositionAsync(position, StopLoss, position.TakeProfit);
                Print("New Position SL price is {0}", position.StopLoss);
            }
                    if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
                    {
                        ExecuteMarketOrderAsync(TradeType.Buy, Symbol, volumeInUnits, PositionId, null, TakeProfitInPips);
                        _lastExecutedOrder = DateTime.Now;
                    }
            }

        protected override void OnStop()
        {
            Stop();
        }
    }
}

Hi Ctrader team,

That is the code there, like I said when I run multiple instances of this code only 1 instance gets the Stop loss value right, do I have to manually assign a position finder and bind it to the indicator on that symbol to get the correct abdolute value? 

Thanks in advance, I may have a work around that I am testing but just wanted your opinion too.


@HTtrader

Spotware
05 Sep 2017, 09:26

Dear hungtonydang,

Thanks for sending us the cBot. Unfortunately we cannot build it since CD and _lastExecutedOrder are not defined. Can you please send us a cBot that builds successfully so that we do not need to make any assumptions?

Best Regards,

cTrader Team


@Spotware

... Deleted by UFO ...

HTtrader
05 Sep 2017, 16:13

Sorry have been cutting and pasting multiple versions of the code and trying to get it work properly. Here is the code

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.None)]
    public class HunterBB : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 28, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "Pid")]
        public string PositionId { get; set; }

        BollingerBands BB;
        private DateTime _lastExecutedOrder;

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

        protected override void OnBar()
        {
            var toppre = BB.Top.Last(1);
            var bottompre = BB.Bottom.Last(1);
            var StopLoss = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);
            var volumeInUnits = Symbol.QuantityToVolume(Quantity);

            foreach (var position in Positions)
            {
                ModifyPositionAsync(position, StopLoss, position.TakeProfit);
                Print("New Position SL price is {0}", position.StopLoss);
            }
            if (_lastExecutedOrder.AddHours(8) < DateTime.Now)
            {
                ExecuteMarketOrderAsync(TradeType.Buy, Symbol, volumeInUnits, PositionId, null, TakeProfitInPips);
                _lastExecutedOrder = DateTime.Now;
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}

 


@HTtrader

Spotware
06 Sep 2017, 11:03

Dear hungtonydang,

Thanks for the cBot. Can you please also verify that with "multiple instances" you mean that you run the cBot on different charts at the same time? If this is the case, is it running on charts of the same symbol? Is it possible to provide us with charts that you run the instances as well as exact cBot parameters? We need you to provide us as much information as possible so that we can reproduce you problem.

Best Regards,

cTrader Team


@Spotware

HTtrader
06 Sep 2017, 12:06

Hi there Ctrader team,

I had this one cbot code running on 4 different charts at the time I came across the error. It was running on eurusd gbpusd usdcad and usdyen. All trades triggered as per logic however only 1 trade had the correct value for the stoploss and all others were off by 1000 or so pips. All the input parameters I kept as default, but would like to adjust these as I like the feature of running the same cbot across multiple instances and changing these parameters to suit. 

My initial thought is you have to bind the variable I have set for the stoploss to the symbol, but then shouldn't that already be the case when I declared the source or do I need to declare the symbol as a parameter too?

Much appreciated help on this as I would like to run the cbot across multiple currency pairs. 


@HTtrader

Spotware
06 Sep 2017, 12:23

Hi hungtonydang,

If you are running multiple instances of the cBot on different symbols, then you should reconsider your logic, since in the OnBar() function you are altering not only the positions related to the symbol that the cBot is running but all open positions for all symbols. Probably this is the reason of the weird stop losses. You seem to be changing the stop loss of a position based on a Bollinger Band of another symbol.

Can you please check it and let us know?

Best Regards,

cTrader Team


@Spotware

HTtrader
06 Sep 2017, 12:42

Thanks ctrader team that was my guess. I am going to run some more tests tonight including the following but would like your thoughts. 

Rather than multiple instances on the one cbot would the code run right if it was an individual cbot run across multiple instances with the same logic. ie gpbusd eurusd usdyen but each has its own cbot of cbot1 cbot2 cbot3 but all 3 cbots have the same code logic. Would this scenario make the parameters work right?


@HTtrader

Spotware
06 Sep 2017, 16:11

Hi hungtonydang,

No this would not work since the problem is that you execute your code considering all open Positions each time. What you need to do is to consider the positions that have the same Symbol as the chart on which the Symbol is running on. Try adding the following condition before modifying your position

if (Symbol.Code == position.SymbolCode)

Best Regards,

cTrader Team


@Spotware

HTtrader
07 Sep 2017, 16:13

Hi Ctrader team,

I have input this code now and it comes up with this error

Error CS0103: The name 'position' does not exist in the current context

I am guessing that the variable needs to be declared before it can be used. I have tried public and private declarations but to no avail. Can you please provide some sample code so I can work this out, thanks.

 


@HTtrader

Spotware
07 Sep 2017, 16:29

Hi hingtonydang,

It should be placed inside the foreach loop. See below

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    ModifyPositionAsync(position, StopLoss, position.TakeProfit);
                    Print("New Position SL price is {0}", position.StopLoss);
                }
            }

Best Regards,

cTrader Team


@Spotware

HTtrader
08 Sep 2017, 02:23

Thanks for the help ctrader team, the cbot now builds properly however I don't think it works right, will do more testing tonight but just a thought do I have to bind the absolute value of the stop loss parameter to the symbol as well. Something like thisvar StopLoss = BB.Main.Symbol.Last(0);
@HTtrader

HTtrader
20 Sep 2017, 00:09

Hi ctrader team,

I have a new problem with this now. Are you able to confirm for me that you are not able to run 2 different cbots on the same symbol? Scenario is I was testing 2 different cbots on the same symbol eurusd, and somewhere during the testing process 1 of the cbots crashed and stopped. While the other continued as normal. Each cbot has it's own unique code that enters the market uniquely that is limit order for one cbot and market order for the other. 

Is this a common thing as I will either have to adjust my strategy or can I just open another account to get around this issue?

Thanks

Tony


@HTtrader

PanagiotisCharalampous
20 Sep 2017, 09:47

Hi hungtonydang,

It is possible to run more than two cBots on the same symbol. The crash you experience is probably related to the cBot itself. When you run two cBots on the same account, you should be very careful so that the one does not interfere with the activities of the other.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
20 Sep 2017, 10:24

Thanks Panagiotis, My 2 cbots share the some of the same code and are related back to the symbol they are working on. I will test again tonight and try to get the log of why it crashed. From what I can understand from what you have said I might need to put another if statement tying cbot to the label on positions perhaps. So far the cbots don't interfere with each other as the other crashes but it gives me something to debug.
@HTtrader

HTtrader
20 Sep 2017, 23:55

20/09/2017 09:00:00.472 | Crashed in OnBar with NullReferenceException: Object reference not set to an instance of an object.

That is the crash report from one of the cbots. The cbots work fine as an independent on their own but when I run another cbot on the same symbol this problem arises. Both cbots have trigger clauses onBar to enter the market. Panagiotis have you seen this before and could you possibly provide a sample of how I can get around this issue. My guess is the indicators that are called upon are not tied to the symbol but then isn't that the job of the cbot I am getting confused now.


@HTtrader

HTtrader
21 Sep 2017, 00:13

Ok I am really starting to get confused now. Just ran the 2 cbots on the same symbol and both produced the results as I would expect. My guess now is it would have to do something with order execution on the server side. Would a adding a 1 or 2 minute delay help in this case? Or is this issue totally unrelated. 

I can work with the bots individually but would be nice if they all worked together so I can maximise my efficiency.


@HTtrader

PanagiotisCharalampous
21 Sep 2017, 09:37

Hi hungtonydang,

A NullReferenceException makes me suspect that it is something in the code. Can you post some code, at least the part where the exception is thrown so that we can try to guess what the problem might be? Else, we will need the source code and starting parameters for both cBots to try to reproduce the exception.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
22 Sep 2017, 15:46

Ok now this has got me puzzled it works sometimes and doesn't the others. I did more testing tonight and the results showed positive for all tests. I ran both cbots on the same symbol eurusd. Please see the code below. There is no null reference error when I build the cbot. I have gone through and tried to make all parameters unique so this has got me puzzled. The only other thing I can think of is I ran the code on different symbols and more than 1 instance the other time when it crashed. Any help is much appreciated.

// -------------------------------------------------------------------------------------------------
//		Limit order testing with expiration and modifying absolute TP&orSL
//		v3 15min
//		

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.TasmaniaStandardTime, AccessRights = AccessRights.None)]
    public class BBLO : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 40, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 0.5, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Cooldown (hours)", DefaultValue = 2, MinValue = 1, Step = 1)]
        public double CD { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "Pid")]
        public string PositionId { get; set; }

        public Position position;
        private DateTime _lastExecutedOrder;

        BollingerBands BB;


        protected override void OnStart()
        {
            BB = Indicators.BollingerBands(Source, Periods, Deviations, MAType);
            Positions.Opened += OnPositionsOpened;
        }

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            if (Symbol.Code == obj.Position.SymbolCode)
            {
                _lastExecutedOrder = DateTime.Now;
            }
        }

        protected override void OnBar()
        {

            var midbb = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);

            var volumeInUnits = Symbol.QuantityToVolume(Quantity);
            var expiry = Time.AddMinutes(15);


            if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
            {
                //higher than indicator target price
                PlaceLimitOrder(TradeType.Sell, Symbol, volumeInUnits, topnow + 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
                //lower than indicator target price
                PlaceLimitOrder(TradeType.Buy, Symbol, volumeInUnits, bottomnow - 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
            }

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    ModifyPositionAsync(position, position.StopLoss, midbb);
                    Print("New Position TP price is {0}", position.TakeProfit);
                }
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}
// -------------------------------------------------------------------------------------------------
//		Market order testing modifying absolute TP &or SL
//		v3 15minute
//		

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.TasmaniaStandardTime, AccessRights = AccessRights.None)]
    public class BBMarketO : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 40, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 0.5, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Cooldown (hours)", DefaultValue = 2, MinValue = 1, Step = 1)]
        public double CD { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "BBMO")]
        public string PositionId { get; set; }

        public Position position;
        private DateTime _lastExecutedOrder;

        BollingerBands BBMO;


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

        protected override void OnBar()
        {
            var midbb = BBMO.Main.Last(0);
            var topnow = BBMO.Top.Last(0);
            var bottomnow = BBMO.Bottom.Last(0);
            var volumeInUnits = Symbol.QuantityToVolume(Quantity);


            if (Symbol.Ask > midbb)
            {
                if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
                {
                    ExecuteMarketOrderAsync(TradeType.Buy, Symbol, volumeInUnits, PositionId, null, null);
                    _lastExecutedOrder = DateTime.Now;
                }
            }
            else if (Symbol.Bid < midbb)
            {
                if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
                {
                    ExecuteMarketOrderAsync(TradeType.Sell, Symbol, volumeInUnits, PositionId, null, null);
                    _lastExecutedOrder = DateTime.Now;
                }
            }

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    if (Symbol.Ask > midbb)
                    {
                        ModifyPositionAsync(position, topnow, bottomnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                    else if (Symbol.Bid < midbb)
                    {
                        ModifyPositionAsync(position, bottomnow, topnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                }
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}

 


@HTtrader

HTtrader
22 Sep 2017, 15:50

Hi Panagoitis,
Please find attached sample code of what I am running when it crashes. It didn't crash tonight so I am a bit confused.
Both cbots build properly with no null reference.

// -------------------------------------------------------------------------------------------------
//		Market order testing modifying absolute TP &or SL
//		v3 15minute
//		

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.TasmaniaStandardTime, AccessRights = AccessRights.None)]
    public class BBMarketO : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 40, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 0.5, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Cooldown (hours)", DefaultValue = 2, MinValue = 1, Step = 1)]
        public double CD { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "BBMO")]
        public string PositionId { get; set; }

        public Position position;
        private DateTime _lastExecutedOrder;

        BollingerBands BBMO;


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

        protected override void OnBar()
        {
            var midbb = BBMO.Main.Last(0);
            var topnow = BBMO.Top.Last(0);
            var bottomnow = BBMO.Bottom.Last(0);
            var volumeInUnits = Symbol.QuantityToVolume(Quantity);


            if (Symbol.Ask > midbb)
            {
                if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
                {
                    ExecuteMarketOrderAsync(TradeType.Buy, Symbol, volumeInUnits, PositionId, null, null);
                    _lastExecutedOrder = DateTime.Now;
                }
            }
            else if (Symbol.Bid < midbb)
            {
                if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
                {
                    ExecuteMarketOrderAsync(TradeType.Sell, Symbol, volumeInUnits, PositionId, null, null);
                    _lastExecutedOrder = DateTime.Now;
                }
            }

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    if (Symbol.Ask > midbb)
                    {
                        ModifyPositionAsync(position, topnow, bottomnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                    else if (Symbol.Bid < midbb)
                    {
                        ModifyPositionAsync(position, bottomnow, topnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                }
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}
// -------------------------------------------------------------------------------------------------
//        Limit order testing with expiration and modifying absolute TP&orSL
//        v3 15min
//        

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.TasmaniaStandardTime, AccessRights = AccessRights.None)]
    public class BBLO : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 40, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 0.5, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Cooldown (hours)", DefaultValue = 2, MinValue = 1, Step = 1)]
        public double CD { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "Pid")]
        public string PositionId { get; set; }

        public Position position;
        private DateTime _lastExecutedOrder;

        BollingerBands BB;


        protected override void OnStart()
        {
            BB = Indicators.BollingerBands(Source, Periods, Deviations, MAType);
            Positions.Opened += OnPositionsOpened;
        }

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            if (Symbol.Code == obj.Position.SymbolCode)
            {
                _lastExecutedOrder = DateTime.Now;
            }
        }

        protected override void OnBar()
        {

            var midbb = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);

            var volumeInUnits = Symbol.QuantityToVolume(Quantity);
            var expiry = Time.AddMinutes(15);


            if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
            {
                //higher than indicator target price
                PlaceLimitOrder(TradeType.Sell, Symbol, volumeInUnits, topnow + 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
                //lower than indicator target price
                PlaceLimitOrder(TradeType.Buy, Symbol, volumeInUnits, bottomnow - 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
            }

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    ModifyPositionAsync(position, position.StopLoss, midbb);
                    Print("New Position TP price is {0}", position.TakeProfit);
                }
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}

@HTtrader

HTtrader
22 Sep 2017, 16:06

Hi Panagoitis,

Sorry for the part messages as I was in the middle of changing devices. What I was meant to say above is that both cbots ran perfectly on testing tonight. I was running the 2 cbots on eurusd only and it performed as it should. However when it crashed the other night, I was running the cbots on multiple symbols, the code above  should exclude that error though, so I am a bit confused now. I can run one cbot at a time but that would be highly inefficient as I look for multiple opportunities across a range of symbols. Any help is much appreciated.


@HTtrader

PanagiotisCharalampous
22 Sep 2017, 17:44

Hi hungtonydang,

I suspect that the issue is related the section where you are modifying the position. Both sections where 

foreach (var position in Positions)
{
.
.
.
.
}

In this case both cBots access the same collection of Positions therefore it is possible that both cBots are modifying the same position at the same time resulting to an exception. But this is just a guess.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
25 Sep 2017, 23:57

Hi Panagiotis,

I am starting to get confused now. I did some more testing overnight and everything ran fine with the code as is. I am guessing that is was a blue moon event that caused the crash a while back. Anyways I tried adjust the code to see if that would work but then ran into a build issue. I swapped the foreach line with the if symbol code hoping that would be a straightforward fix. However not as the build came up with not valid positions variable.

My only other thought is to add another if parameter to the line before of after the foreach clause saying to only apply to 

if (position.count >1);

I will test this out again tonigh but would also like your thoughts, or should I just keep running the same code as is?

Regards,

Tony


@HTtrader

PanagiotisCharalampous
26 Sep 2017, 09:32

Hi hungtonydang,

My opinion is that if it happened once, it will definitely happen again. And you don't want this to happen while trading on a live account. It is better to share the code with the build error so that we can fix it.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
04 Oct 2017, 23:14

Hi Panagiotis,

Sorry have been a little busy with other things. Ok now to the problem at hand. The test of positions.count didn't work as planned as multiple positions could be opened at any one time so it will search for that across the board.

I had another thought would using 

if ((Positions.Find(label)) != null)

work, I have to fix up the syntax abit but that would isolate reference required to a particular cbot. My only other concern is the foreach section, can we compound the foreach to say something like this

foreach (var position.find(label) in Positions)
{
.
.
.
.
}

or is there another variation of this that I should be using?


@HTtrader

PanagiotisCharalampous
05 Oct 2017, 09:45

Hi hungtonydang,

The correct syntax for the foreach loop is the following

foreach (var position in Positions.Find(label))
{
.
.
.
.
}

Let me know if this is what you are looking for.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
09 Oct 2017, 23:18

Hi Panagiotis,

This has partially solved the problem however I had to modify the code a bit which is where the problem might lie. The code above you gave returned me this error

Error CS1579: foreach statement cannot operate on variables of type 'cAlgo.API.Position' because 'cAlgo.API.Position' does not contain a public definition for 'GetEnumerator'

However when I put the following

foreach (var position in Positions.FindAll(PositionId))

it builds perfectly and works as it should across multiple cbots but not multiple instances of the cbot I am doing further testing tonight but can I get a response to why it won't find 1 label and needs to find all of them instead to work?


@HTtrader

PanagiotisCharalampous
10 Oct 2017, 10:26

Hi hungtonydang,

Indeed in case you need to find many positions with the same label you need to use FindAll(label). If you want to get all the positions opened by a specific instance of a cBot then you need to label them all with the same label and use FindAll() function to get them. Let me know if this helps.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
12 Oct 2017, 23:10

Hi Panagiotis,

I have managed to isolate the issue now and find that this piece of code is the issue

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            <strong>if</strong> (Symbol.Code == obj.Position.SymbolCode)
            {
                _lastExecutedOrder = DateTime.Now;
            }
        }

when a position opens on another instance of the same cbot it can't recognise the difference and hence crashes, meaning only that instance that has the position opened stays active.

For example if I had a Eur/USD and USDYEN instance on the 1 cbot when 1 position is open in EURUSD for instance the USDYEN bot looks at the same open position and crashes. However I don't understand as there is code there that ties that particular instance to the symbol code.

Is there a way to get around this with another if clause?

Thanks,

Tony


@HTtrader

... Deleted by UFO ...

PanagiotisCharalampous
13 Oct 2017, 15:18

Hi hungtonydang,

Did you locate which variable becomes null and you  get a NullReferenceException? If yes, just use and if statement and check if the variable is null before accessing it.

Best Regards,

Panagiotis

 


@PanagiotisCharalampous

HTtrader
19 Oct 2017, 23:10

Hi Panagiotis,

It still seems to be crashing despite my efforts to work this out, I have tried the following that builds but still crashes the bot

if ((Positions.FindAll(PositionId)) != null)
{            
foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    if (Symbol.Ask > midbb)
                    {
                        ModifyPositionAsync(position, topnow, bottomnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                    else if (Symbol.Bid < midbb)
                    {
                        ModifyPositionAsync(position, bottomnow, topnow);
                        Print("New Position TP price is {0}", position.TakeProfit);
                    }
                }
            }
}

I then thought to add a function to find out if there is any positions with the label present with following

if ((Positions.FindAll(PositionId)) = null)

but the build doesn't work and I have tried declaring it as a variable prior

var positions = Positions.FindAll(PositionID);
if ((positions = null);
{
//do something
}
else
{
//continue
}

but that doesn't seem to work either. Am I using the wrong syntax or parts of code to identify any position in the list of positions as being null on a return of the FindAll?


@HTtrader

PanagiotisCharalampous
20 Oct 2017, 12:33

Hi hungtonydang,

Positions.FindAll() does not return null. It returns an array. See documentation here. Maybe it is better to hire a professional programmer to help you with this.

Best Regards,

Panagiotis


@PanagiotisCharalampous

HTtrader
21 Oct 2017, 01:15

Hi Panagiotis,

I have now resolved this issue. I have been chopping and changing between different coding languages as at work I am using vba and ladder logic and sometimes it gets lost in translation. The reason I am asking all these questions is because I am finding that calgo doesn't exactly use all c# ability as I use visual studio to do part of my programming. I hope this thread will serve as a reference point to all those out there looking to achieve what is set out in the topic space.

Regards,

Tony


@HTtrader

PanagiotisCharalampous
23 Oct 2017, 11:49

Hi hungtonydang,

I am happy that you have resolved the issue. Indeed, when switching between languages, these confusions happen. cAlgo is just an API built using C# and .Net framework. So any C# code should work inside a cBot. If something is not working, it might be that you are missing a reference. However, if you mean that cAlgo.API should use additional features of C# that would make your life easier, feel free to post your suggestions in the Suggestions section.

Best Regards,

Panagiotis


@PanagiotisCharalampous