Making a bot wait

Created at 17 Oct 2020, 17:43
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!
CA

caglar_G

Joined 20.09.2020

Making a bot wait
17 Oct 2020, 17:43


What is the best method for initating a wait for a bot, example: The bot made a trade and closed, after closing you want it to wait for an x amount of time. Is threading.sleep sufficient?

I'd rather not use threading.sleep as it basically suspends the bot for a set amount of time, I might want the bot to do some calulations in the meantime. Is there an alternative to threading.sleep to achieve something like that? Thanks!  


@caglar_G
Replies

prosteel1
18 Oct 2020, 16:54

RE:

caglar_G said:

What is the best method for initating a wait for a bot, example: The bot made a trade and closed, after closing you want it to wait for an x amount of time. Is threading.sleep sufficient?

I'd rather not use threading.sleep as it basically suspends the bot for a set amount of time, I might want the bot to do some calulations in the meantime. Is there an alternative to threading.sleep to achieve something like that? Thanks!  

I have been thinking about this too.

I'm not sure what the best way is, but in the below code you could re-write AnalysisStartDate when a trade closed and use Add.Minutes or similar to the order expiry concept. 

Positions.Closed += PositionsOnClosed; could be used in this way as it calls the method when a position is closed.

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = 0)]
        public int Minute { get; set; }
        [Parameter(DefaultValue = 0)]
        public int Hour { get; set; }
        [Parameter(DefaultValue = 18)]
        public int Day { get; set; }
        [Parameter(DefaultValue = 10)]
        public int Month { get; set; }
        [Parameter(DefaultValue = 2020)]
        public int Year { get; set; }

        DateTime AnalysisStartDate;

        protected override void OnStart()
        {
            AnalysisStartDate = new DateTime(Year, Month, Day, Hour, Minute, 0);
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnTick()
        {
            // Insert code to only run after Server.Time.Date >= AnalysisStartDate
            if (Server.Time.Date >= AnalysisStartDate)
            {
                // Insert normal Trading code
            }
            else
            {
                // Insert other Calculations
            }
        }
         private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            // Re-write AnalysisStartDate with extra delay
        }
    }
}

 


@prosteel1

firemyst
18 Oct 2020, 17:43

RE:

caglar_G said:

What is the best method for initating a wait for a bot, example: The bot made a trade and closed, after closing you want it to wait for an x amount of time. Is threading.sleep sufficient?

I'd rather not use threading.sleep as it basically suspends the bot for a set amount of time, I might want the bot to do some calulations in the meantime. Is there an alternative to threading.sleep to achieve something like that? Thanks!  

You have multiple options depending on how you want to wait.

Example #1: you want to wait until a new bar is opened. That's easy. Just create a bool flag such as "closedThisBar". In your Positions_Closed event method, set "closedThisBar" to true. In the OnBar method, set "closedThisBar" to false. Then whenever you're wanting to open a position, check the flag before opening the position.

eg, if (!closedThisBar) { OpenPosition.... }

 

Example #2: you want to wait x-minutes/second. That's a bit more involved, but not difficult. Use the timer. In the timer event method, when the number of seconds/minutes has passed, again set a flag to indicate it's ok to open positions again.

 

Example #3: you want to wait x-ticks. Similar to #1 except you also need a variable to count the number of ticks. When a position is closed, reset your tick count to zero. When your tick count reaches your set threshold, set the boolean flag to true so you can open positions again.

 

That's just 3 ways off the top of my head.

Hope it helps :-)


@firemyst

prosteel1
18 Oct 2020, 19:03

RE: RE:

firemyst said:

caglar_G said:

What is the best method for initating a wait for a bot, example: The bot made a trade and closed, after closing you want it to wait for an x amount of time. Is threading.sleep sufficient?

I'd rather not use threading.sleep as it basically suspends the bot for a set amount of time, I might want the bot to do some calulations in the meantime. Is there an alternative to threading.sleep to achieve something like that? Thanks!  

You have multiple options depending on how you want to wait.

Example #1: you want to wait until a new bar is opened. That's easy. Just create a bool flag such as "closedThisBar". In your Positions_Closed event method, set "closedThisBar" to true. In the OnBar method, set "closedThisBar" to false. Then whenever you're wanting to open a position, check the flag before opening the position.

eg, if (!closedThisBar) { OpenPosition.... }

 

Example #2: you want to wait x-minutes/second. That's a bit more involved, but not difficult. Use the timer. In the timer event method, when the number of seconds/minutes has passed, again set a flag to indicate it's ok to open positions again.

 

Example #3: you want to wait x-ticks. Similar to #1 except you also need a variable to count the number of ticks. When a position is closed, reset your tick count to zero. When your tick count reaches your set threshold, set the boolean flag to true so you can open positions again.

 

That's just 3 ways off the top of my head.

Hope it helps :-)

I like your Example #1 solution, as waiting for the current bar to close before opening a new trade if the last trade closed in loss is something I've been wanting to impliment, this is how I would do it that can run OnTick and use a different timeframe to the chart timeframe.

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 NewcBot : Robot
    {
        [Parameter("Timeframe0", DefaultValue = "Hour4")]
        public TimeFrame tf0 { get; set; }
        int i = 0;
        protected override void OnStart()
        {
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnTick()
        {
            // Insert code to only run after count is larger than the count when the last position was closed
            Bars series = MarketData.GetBars(tf0);
            if (i == 0 || i < series.Count - 1)
            {
                // Insert normal Trading code
                Print("series.Count - 1 = " + (series.Count - 1));
            }
            else
            {
                // Insert other Calculations
            }
        }
        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            // Get Bars on the specified timeframe then write the current bar to i
            Bars series = MarketData.GetBars(tf0);
            int i = series.Count - 1;
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@prosteel1

firemyst
19 Oct 2020, 04:03

RE: RE: RE:

prosteel1 said:

firemyst said:

caglar_G said:

What is the best method for initating a wait for a bot, example: The bot made a trade and closed, after closing you want it to wait for an x amount of time. Is threading.sleep sufficient?

I'd rather not use threading.sleep as it basically suspends the bot for a set amount of time, I might want the bot to do some calulations in the meantime. Is there an alternative to threading.sleep to achieve something like that? Thanks!  

You have multiple options depending on how you want to wait.

Example #1: you want to wait until a new bar is opened. That's easy. Just create a bool flag such as "closedThisBar". In your Positions_Closed event method, set "closedThisBar" to true. In the OnBar method, set "closedThisBar" to false. Then whenever you're wanting to open a position, check the flag before opening the position.

eg, if (!closedThisBar) { OpenPosition.... }

 

Example #2: you want to wait x-minutes/second. That's a bit more involved, but not difficult. Use the timer. In the timer event method, when the number of seconds/minutes has passed, again set a flag to indicate it's ok to open positions again.

 

Example #3: you want to wait x-ticks. Similar to #1 except you also need a variable to count the number of ticks. When a position is closed, reset your tick count to zero. When your tick count reaches your set threshold, set the boolean flag to true so you can open positions again.

 

That's just 3 ways off the top of my head.

Hope it helps :-)

I like your Example #1 solution, as waiting for the current bar to close before opening a new trade if the last trade closed in loss is something I've been wanting to impliment, this is how I would do it that can run OnTick and use a different timeframe to the chart timeframe.

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 NewcBot : Robot
    {
        [Parameter("Timeframe0", DefaultValue = "Hour4")]
        public TimeFrame tf0 { get; set; }
        int i = 0;
        protected override void OnStart()
        {
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnTick()
        {
            // Insert code to only run after count is larger than the count when the last position was closed
            Bars series = MarketData.GetBars(tf0);
            if (i == 0 || i < series.Count - 1)
            {
                // Insert normal Trading code
                Print("series.Count - 1 = " + (series.Count - 1));
            }
            else
            {
                // Insert other Calculations
            }
        }
        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            // Get Bars on the specified timeframe then write the current bar to i
            Bars series = MarketData.GetBars(tf0);
            int i = series.Count - 1;
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

Doing a quick read of your code, I see a few potential issues:

1) you declare the variable "i" twice in two different scopes. You have it at the class level, and then also within the PositionsOnClosed method. This could be your intention. However, the value for the variable "i" in PositionsOnClosed will never be the same as the value for "i" declared under the TimeFrame class variable.

2) Why do you do this multiple times?

Bars series = MarketData.GetBars(tf0);

Every time a tick comes in or a position is closed, your bot has to wait (and could be a while!) for ALL bar data to load!

You should declare "series" at the class level, and initialize it ONCE in the "OnStart" method. Then you can reference it anywhere else in the bot, and you won't slow down your bot on every tick waiting for all the data to constantly load over and over again.

Your code rewritten quickly (may contain errors as I'm not in front of a compiler or cTrader):

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 NewcBot : Robot
    {
        [Parameter("Timeframe0", DefaultValue = "Hour4")]
        public TimeFrame tf0 { get; set; }

	//why are you doing this twice? you declare it here and in "PositionsOnClosed". 
        int i = 0;

	//Declare once!
	Bars series;

        protected override void OnStart()
        {
		//
		//Just call it once.
		//"series" will henceforth always be updated with the latest every time a new bar is created.
		//
            series = MarketData.GetBars(tf0);

	//You can also include multiple time frames and initalize each one once
	//    series2 = MarketData.GetBars(tf1);
	//etc etc
	//just declare the variables at the higher class level scope as shown above and then 
	//you can reference anywhere in your code below.

            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnTick()
        {
            // Insert code to only run after count is larger than the count when the last position was closed

		//
		//This "i" will always be zero because that's what you set it to up above. 
		//
            if (i == 0 || i < series.Count - 1)
            {
                // Insert normal Trading code
                Print("series.Count - 1 = " + (series.Count - 1));
            }
            else
            {
                // Insert other Calculations
            }
        }
        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            // Get Bars on the specified timeframe then write the current bar to i

		//
		//why are you declaring i twice in two different scopes? 
		//The value for "i" here won't be the same as "i" used in "OnTick" because that "i" is the class scope.
		//
            int i = series.Count - 1;
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@firemyst