Time and Profit/Balance control

Created at 28 Mar 2017, 10:59
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!
BR

brokerof.net@gmail.com

Joined 28.03.2017

Time and Profit/Balance control
28 Mar 2017, 10:59


The idea is to pause a cbot from opening new trades after/if it has already made a certain percentage of the starting balance. No need to go on trading forever (increasing the risk of loss) if it already made a desired (pre-set) amount, say 1% a day is enough - counted from the week's starting balance, every day. Like, Monday +1%, Tue +2% (as of starting balance) and so on.

So I need to put some method/function in the beginning of an existing cbot code so that later in the code it would call that function to check if conditions are met to open a new trade (i.e. the preset percentage is still not met).

I know it has to do with Time/Date and Balance properties, but I cannot figure out how to make them to:

- store the initial balance as of beginning of the current week (on Monday 00:00 hrs) when a new session starts;

- comparing balance during the day is easy, but how to define that today is Day 2-3-.. of the week (Tue, Wed, etc);

- control that the new date has arrived (Mon changed for Tue) and a new profit target is eligible.

 

As I see it, the logic is simple: 

- it has a set of profit factors, e.g {1.01;1.02;1.03;1.04;1.05}

- it stores initial Account.Balance as of Mon 00:00 hrs

- the bot goes on working normally as per its native algorithm opening trades unless current Account.Balance is lower than initial Account.Balance * Profit Factor of this working day (Mon = 1.01, Tue = 1.02, etc)

- once the day's profit target is met, the bot is still active but just cannot open new trades (the function returns false and a new trade is not allowed), but as day changes - new profit target is defined (+1%) and the function returns true, so new trades are opened again

 

Anyone has ideas on how I can code it in? Thanks for any hints


@brokerof.net@gmail.com
Replies

Jiri
28 Mar 2017, 17:03

Hi, you can start with that. Sorry if there is any error - I don't have time to test it.

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NotTestedSample : Robot
    {
        [Parameter("Daily Target %", DefaultValue = 1)]
        public double DailyTargetPercentage { get; set; }

        private DateTime nextMonday, nextDay;
        private double weeklyStartingBalance, dailyNetTarget;
        private bool isPausedTillNextDay;

        protected override void OnStart()
        {
            DateTime lastMonday = Time.AddDays(-(int)Time.DayOfWeek + 1).Date;
            HistoricalTrade trade = History.FirstOrDefault(x => x.ClosingTime >= lastMonday); // finds first historical trade of this week

            weeklyStartingBalance = trade != null ? trade.Balance : Account.Balance; // if there is historical trade it uses its balance for better accuracy
            dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

            nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;
            nextDay = Time.AddDays(1).Date;

            Positions.Closed += OnPositionClosed;
        }

        private void OnPositionClosed(PositionClosedEventArgs obj)
        {
            double dailyNet = History.Where(x => x.ClosingTime.Date == Time.Date).Sum(x => x.NetProfit); // sums net profit of current day

            // pauses core logic if daily net target was exceeded
            if (dailyNet >= dailyNetTarget)
            {
                isPausedTillNextDay = true;
            }
        }

        protected override void OnTick()
        {
            // unpauses core logic if it's new day
            if (isPausedTillNextDay && Time >= nextDay)
            {
                isPausedTillNextDay = false;
                nextDay = nextDay.AddDays(1);
            }

            // sets new daily net target on each Monday
            if (Time >= nextMonday)
            {
                weeklyStartingBalance = Account.Balance;
                dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;
            }

            // passes if core logic isn't paused
            if (!isPausedTillNextDay)
            {
                // Put your core logic here
            }
        }
    }
}

 


@Jiri

Jiri
28 Mar 2017, 17:11

I just realized you should update nextDay each new day with following code. Because of the weekends and days when daily net target isn't exceeded.

nextDay = Time.AddDays(1).Date;

And I forgot to set new nextMonday on each monday. Line 56:

nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;

 


@Jiri

Jiri
28 Mar 2017, 17:20

Updated code.

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NotTestedSample : Robot
    {
        [Parameter("Daily Target %", DefaultValue = 1)]
        public double DailyTargetPercentage { get; set; }

        private DateTime nextMonday, nextDay;
        private double weeklyStartingBalance, dailyNetTarget;
        private bool isPausedTillNextDay;

        protected override void OnStart()
        {
            DateTime lastMonday = Time.AddDays(-(int)Time.DayOfWeek + 1).Date;
            HistoricalTrade trade = History.LastOrDefault(x => x.ClosingTime <= lastMonday); // finds last historical trade before this week

            weeklyStartingBalance = trade != null ? trade.Balance : Account.Balance; // if there is historical trade it uses its balance for better accuracy
            dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

            nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;
            nextDay = Time.AddDays(1).Date;

            Positions.Closed += OnPositionClosed;
        }

        private void OnPositionClosed(PositionClosedEventArgs obj)
        {
            double dailyNet = History.Where(x => x.ClosingTime.Date == Time.Date).Sum(x => x.NetProfit); // sums net profit of current day

            // pauses core logic if daily net target was exceeded
            if (dailyNet >= dailyNetTarget)
            {
                isPausedTillNextDay = true;
            }
        }

        protected override void OnTick()
        {
            // unpauses core logic if it's new day
            if (Time >= nextDay)
            {
                isPausedTillNextDay = false;

                nextDay = Time.AddDays(1).Date;
            }

            // sets new daily net target on each Monday
            if (Time >= nextMonday)
            {
                weeklyStartingBalance = Account.Balance;
                dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

                nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;
            }

            // passes if core logic isn't paused
            if (!isPausedTillNextDay)
            {
                // Put your core logic here
            }
        }
    }
}

 


@Jiri

brokerof.net@gmail.com
29 Mar 2017, 06:42

RE:

Wow, tmc! You're a real cAlgo shaman!) Thanks for being so elaborate!

Didn't realize my "simple" idea involves that much code)) o_O

Great you made the Daily Target as a variable parameter, now I can run it thru optimization and see which number works best (if any:)

Now let me make sure I add it correctly into the core logic. So I'm copying the code you provided into corresponding segments of the existing bot (like OnStart, OnTick sections) and then I have the opening positions part which looks like this:

                     if (shortSignal)
                    {
                        EnterInPosition(TradeType.Sell);
                    }
                    else if (longSignal)
                    {
                        EnterInPosition(TradeType.Buy);
                    }

If I get it correctly, I should be adding in both of the if/else-if brackets something like && !isPausedTillNextDay expression, right?

 

 

tmc. said:

Updated code.

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NotTestedSample : Robot
    {
        [Parameter("Daily Target %", DefaultValue = 1)]
        public double DailyTargetPercentage { get; set; }

        private DateTime nextMonday, nextDay;
        private double weeklyStartingBalance, dailyNetTarget;
        private bool isPausedTillNextDay;

        protected override void OnStart()
        {
            DateTime lastMonday = Time.AddDays(-(int)Time.DayOfWeek + 1).Date;
            HistoricalTrade trade = History.LastOrDefault(x => x.ClosingTime <= lastMonday); // finds last historical trade before this week

            weeklyStartingBalance = trade != null ? trade.Balance : Account.Balance; // if there is historical trade it uses its balance for better accuracy
            dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

            nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;
            nextDay = Time.AddDays(1).Date;

            Positions.Closed += OnPositionClosed;
        }

        private void OnPositionClosed(PositionClosedEventArgs obj)
        {
            double dailyNet = History.Where(x => x.ClosingTime.Date == Time.Date).Sum(x => x.NetProfit); // sums net profit of current day

            // pauses core logic if daily net target was exceeded
            if (dailyNet >= dailyNetTarget)
            {
                isPausedTillNextDay = true;
            }
        }

        protected override void OnTick()
        {
            // unpauses core logic if it's new day
            if (Time >= nextDay)
            {
                isPausedTillNextDay = false;

                nextDay = Time.AddDays(1).Date;
            }

            // sets new daily net target on each Monday
            if (Time >= nextMonday)
            {
                weeklyStartingBalance = Account.Balance;
                dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

                nextMonday = Time.AddDays(8 - (int)Time.DayOfWeek).Date;
            }

            // passes if core logic isn't paused
            if (!isPausedTillNextDay)
            {
                // Put your core logic here
            }
        }
    }
}

 

 


@brokerof.net@gmail.com

Jiri
29 Mar 2017, 13:40

Yes or you can put both between brackets.

if (!isPausedTillNextDay)
{
    if (shortSignal)
    {
        EnterInPosition(TradeType.Sell);
    }
    else if (longSignal)
    {
        EnterInPosition(TradeType.Buy);
    }
}

One more thing that should be updated in case the cBot would be started on Sunday.

Line 19: DateTime lastMonday = Time.AddDays(1 - (Time.DayOfWeek == 0 ? 7 : (int)Time.DayOfWeek)).Date

Line 58: nextMonday = Time.AddDays(8 - (Time.DayOfWeek == 0 ? 7 : (int)Time.DayOfWeek)).Date;

Please keep in mind I haven't tested it so there might be more to fix.


@Jiri

brokerof.net@gmail.com
30 Mar 2017, 14:44

RE:

Ok, I incorporated it as you said and changed the lines 19 and 58 with the latest update. Builds just fine.

Now I started to run optimizations on it and noticed that several best passes may sometimes differ in Daily Target parameters ranging from 0.25 to 3.5

So I was wondering whether the logic above stops the bot after current balance exceeds the Daily Target just once? I mean, if the DT is say 1% and on Monday the profit reaches that, then on Tuesday it seems to still check whether the profit is 1% higher than the initial weekly balance (which is true because the day before we reached the value and the bot stopped).

// sets new daily net target on each Monday
            if (Time >= nextMonday)
            {
                weeklyStartingBalance = Account.Balance;
                dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;
            }

The idea was if Monday hit the Daily Target, bot stops to go on Tuesday in order to try to make another 1% and then stop until Wednesday, etc.

So in the line

dailyNetTarget = weeklyStartingBalance * DailyTargetPercentage / 100;

I guess I should multiply DailyTargetPercentage by the day number (e.g 1 for Mon, 2 for Tue, etc)? Or it is easier to redefine the weeklyStartingBalance once the Daily Target is met and the bot is awaiting new day?

 

P.S.: appreciate ur help very much, tmc! Already with your previous code update the line graphs now become more edgy, which is a good thing I guess, because it stops from excessive trading and risk. So if I find the "holy grail", you will be the first to know)) http://dl4.joxi.net/drive/2017/03/30/0015/2663/1018471/71/5e0c17967e.jpg 

 

tmc. said:

Yes or you can put both between brackets.

if (!isPausedTillNextDay)
{
    if (shortSignal)
    {
        EnterInPosition(TradeType.Sell);
    }
    else if (longSignal)
    {
        EnterInPosition(TradeType.Buy);
    }
}

One more thing that should be updated in case the cBot would be started on Sunday.

Line 19: DateTime lastMonday = Time.AddDays(1 - (Time.DayOfWeek == 0 ? 7 : (int)Time.DayOfWeek)).Date

Line 58: nextMonday = Time.AddDays(8 - (Time.DayOfWeek == 0 ? 7 : (int)Time.DayOfWeek)).Date;

Please keep in mind I haven't tested it so there might be more to fix.

 


@brokerof.net@gmail.com

Jiri
31 Mar 2017, 02:16

Sorry for late reply, I didn't notice you have replied already. :)

The code I have provided is based on daily net profit, not account balance growth. It sets daily net profit on monday and doesnt change during certain week. Onn each position closed it calculates current daily net profit and if it reached the target then it stops core logic till the next day.

Update OnPositionClosed() method to following and check the log if it's working as supposed.

private void OnPositionClosed(PositionClosedEventArgs obj)
{
    double dailyNetProfit = History.Where(x => x.ClosingTime.Date == Time.Date).Sum(x => x.NetProfit); // sums net profit of current day

    // pauses core logic if daily net target was exceeded
    if (dailyNetProfit >= dailyNetTarget)
    {
        isPausedTillNextDay = true;
        Print("Pausing core logic till {0}. Daily Net target of {1} ({2} %) reached. Current net profit is {3} ({4} %).", nextDay, dailyNetTarget, DailyTargetPercentage, dailyNetProfit, Math.Round(dailyNetProfit / dailyNetTarget, 2));
    }
}

 

P.S.: That graph is looking like a holy grail already! Feel free to contact me via email below if you need to discus anything privately.


@Jiri

IRCtrader
21 Jun 2021, 16:21 ( Updated at: 21 Jun 2021, 16:23 )

@jiri

how could we use that for indicator.   i want to show dialy percent and amount profit on chart. i think you used closed postion. if i want to all postion what can i do? actually i want to close all position when i grow balnce to specfic percent so i need that.

and i have parameter to selet today , yesterday , all history , week or ...


@IRCtrader

IRCtrader
21 Jun 2021, 17:32

starting Balance

i use this code to get starting balance of day but i get error

double StartingBalance = History.Any() ? History.Last(x => x.ClosingTime.Date < Time.Date).Balance : Account.Balance;


@IRCtrader