Template to have Drawdown < x %

Created at 08 Jun 2022, 16:55
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!
KU

kurtisnauss

Joined 08.06.2022

Template to have Drawdown < x %
08 Jun 2022, 16:55


Hi, 

Looking for help to write a basic template to keep drawdown under a set percentage. 

        [Parameter("Max Drawdown Percentage", MinValue = 0.01, MaxValue = 4.5)]
        public int MaxDD { get; set; }

Using that parameter I wish to have it optimize in back-testing for any percentage below 4.5%.

I would also like to use historical data which is where I am really struggling to figure out....

I would like the Account.Balance to update before every new trade is taken.

 

If there is an easier way than this to write it, maybe by adding an IF condition instead I would be open to that as well.

I am just unsure how to get it to use the current Account.Balance before entering new trades. 


@kurtisnauss
Replies

amusleh
09 Jun 2022, 09:30 ( Updated at: 09 Jun 2022, 09:40 )

Hi,

Here is an example:

using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewcBot2 : Robot
    {
        private double _peak;
        private readonly List<double> _drawdown = new List<double>();
        private double _maxDrawdown;

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

        protected override void OnStart()
        {
            Positions.Closed += Positions_Closed;
        }

        protected override void OnStop()
        {
            Print(_maxDrawdown);
        }

        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            CalculateMaxDrawDown();
        }

        protected override void OnBar()
        {
            var lastBar = Bars.Last(1);
            var position = Positions.Find(Label, SymbolName);

            if (lastBar.Close > lastBar.Open)
            {
                if (position is not null && position.TradeType == TradeType.Sell) _ = ClosePosition(position);

                _ = ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin, Label);
            }
            else if (lastBar.Close < lastBar.Open)
            {
                if (position is not null && position.TradeType == TradeType.Buy) _ = ClosePosition(position);

                _ = ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.VolumeInUnitsMin, Label);
            }
        }

        private void CalculateMaxDrawDown()
        {
            _peak = Math.Max(_peak, Account.Equity);

            _drawdown.Add((_peak - Account.Equity) / _peak * 100);
            _drawdown.Sort();

            _maxDrawdown = _drawdown[_drawdown.Count - 1];
        }

        protected override double GetFitness(GetFitnessArgs args)
        {
            return 100 - _maxDrawdown;
        }
    }
}

The above bot calculates drawdown based on account equity, and uses it for optimization fitness.

You can change the Account.Equity to Account.Balance if you want to use balance drawdown.

You can check on "GetFitness" method if drawdown is above a fixed value then return 0.


@amusleh