thecaffeinatedtrader
thecaffeinatedtrader's avatar

Info

Username:thecaffeinatedtrader
Name:thecaffeinatedtrader
Member since: 22 Jul 2020

About

None

Signature

None

Last Forum Posts

@Writing a GetFitness args.MaxEquityDrawdownPercentages:  23 Nov 2021, 01:34


amusleh said:

Hi,

You can only set one fitness parameter not multiple, if you want to use MaxEquityDrawdownPercentages then you can't use win rate or net profit.

You can try to combine them and come up with a new metric for GetFitness, for example you can do something like this:

protected override double GetFitness(GetFitnessArgs args)
{
	// Here it adds the amount of remained equity percentage to win rate
    return 100 - args.MaxEquityDrawdownPercentages + (args.WinningTrades / args.TotalTrades);
}

So if MaxEquityDrawdownPercentages is 65% it will add the 35 to win rate and use this metric as your fitness.

You can add more parameters to the calculation of fitness if you want to and come up with something that covers multiple aspects of your result not just one single parameter.

If you use the optimizer standard criteria then you can set there to minimize MaxEquityDrawdownPercentages and maximize wining trades and net profit.

Awesome, that is very helpful! I did not know they needed to be all in one single formula. Thank you.

@Writing a GetFitness args.MaxEquityDrawdownPercentages:  22 Nov 2021, 03:59


Hi all, 

I'm a little confused on how to properly write the GetFitness arg for MaxEquityDrawdownPercentages 

I'm trying to have it optimize and return results below a set percentage amount.

for example...

I would like it only return results within optimization of anything less than 10% equity drawdown. Then after that be able to look to maximize net profits, winning trades, etc. 

I don't know if this would be the best way to optimize for it or to actually build it within parameters and return the result that way.... 

if anyone knows how this could be done it would be greatly appreciated if you could share your knowledge! 

@Lot Size Based on Risk % Parameter:  21 Oct 2021, 13:46


amusleh said:

Hi,

try this:

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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class HighVolumeHours : Robot
    {
        [Parameter("Instance Name", DefaultValue = "")]
        public string InstanceName { get; set; }

        [Parameter("Start Trading", DefaultValue = 6)]
        public double StartTime { get; set; }

        [Parameter("Stop Trading", DefaultValue = 16)]
        public double StopTime { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Fast Type")]
        public MovingAverageType Fast { get; set; }

        [Parameter("Fast Period", DefaultValue = 21)]
        public int FastPeriod { get; set; }

        [Parameter("Medium Type")]
        public MovingAverageType Medium { get; set; }

        [Parameter("Medium Period", DefaultValue = 55)]
        public int MediumPeriod { get; set; }

        [Parameter("Bias Type")]
        public MovingAverageType Bias { get; set; }

        [Parameter("Bias Period", DefaultValue = 233)]
        public int BiasPeriod { get; set; }

        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = false)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 20)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 20)]
        public int TrailingStopStep { get; set; }

        [Parameter("Position Limit", MinValue = 1, Step = 1)]
        public int PositionLimit { get; set; }

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

        private MovingAverage slowMa;
        private MovingAverage mediumMa;
        private MovingAverage fastMa;
        private DateTime _startTime;
        private DateTime _stopTime;

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, Fast);
            mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, Medium);
            slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, Bias);
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);
        }

        protected override void OnTick()
        {
            if (IncludeTrailingStop)
            {
                SetTrailingStop();
            }
        }

        protected override void OnBar()
        {
            int index = Bars.Count - 2;
            Entry(index);
        }

        private void Entry(int index)
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
            if (!istimecorrect)
                return;

            // Buy Only
            if (Bars.ClosePrices[index] > slowMa.Result[index])
            {
                // if fast crosses medium upward
                if (Positions.Count < PositionLimit && fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null);
                }
            }
            // Sell only
            else if (Bars.ClosePrices[index] < slowMa.Result[index])
            {
                // if fast crosses medium downward
                if (Positions.Count < PositionLimit && fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null);
                }
            }
        }

        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);

            foreach (var position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, null);
                }
            }

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (var position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, null);
                }
            }
        }

        private double GetVolume(double? stopLossPips = null)
        {
            double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;

            // Change this to Account.Balance if you want to
            double baseNumber = Account.Equity;

            double sizeInLots = Math.Round((baseNumber * RiskPerTrade / 100) / (stopLossPips.Value * costPerPip), 2);

            var result = Symbol.QuantityToVolumeInUnits(sizeInLots);

            if (result > Symbol.VolumeInUnitsMax)
            {
                result = Symbol.VolumeInUnitsMax;
            }
            else if (result < Symbol.VolumeInUnitsMin)
            {
                result = Symbol.VolumeInUnitsMin;
            }
            else if (result % Symbol.VolumeInUnitsStep != 0)
            {
                result = result - (result % Symbol.VolumeInUnitsStep);
            }

            return result;
        }
    }
}

So far so good... Thank you so much for your help! 

@Lot Size Based on Risk % Parameter:  21 Oct 2021, 04:30


Hi,

I have been trying to convert this bot so it enters a lot size / unit size based on a risk % parameter using either Account Balance or Account Equity.. not sure which will work better yet until I back test it... however.. when I got it to "work" it did enter trade lot sizes based on the equity or balance, but did not continue to update as the value of the account changed. 

This is the parameter I would like to use:

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

I have posted the original algo where it traded just based off a specified lot size ... If anyone knows how convert this properly it would be GREATLY appreciated.. I've been playing with this for days and nothing seems to be working for me. 

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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class HighVolumeHours : Robot
    {

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

        [Parameter("Start Trading", DefaultValue = 6)]
        public double StartTime { get; set; }

        [Parameter("Stop Trading", DefaultValue = 16)]
        public double StopTime { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Fast Type")]
        public MovingAverageType Fast { get; set; }

        [Parameter("Fast Period", DefaultValue = 21)]
        public int FastPeriod { get; set; }

        [Parameter("Medium Type")]
        public MovingAverageType Medium { get; set; }

        [Parameter("Medium Period", DefaultValue = 55)]
        public int MediumPeriod { get; set; }

        [Parameter("Bias Type")]
        public MovingAverageType Bias { get; set; }

        [Parameter("Bias Period", DefaultValue = 233)]
        public int BiasPeriod { get; set; }

        [Parameter("Stop Loss", DefaultValue = 20)]
        public int StopLoss { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = false)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 20)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 20)]
        public int TrailingStopStep { get; set; }

        [Parameter("Position Limit", MinValue = 1, Step = 1)]
        public int PositionLimit { get; set; }

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


        private double _volumeInUnits;
        private MovingAverage slowMa;
        private MovingAverage mediumMa;
        private MovingAverage fastMa;
        private DateTime _startTime;
        private DateTime _stopTime;

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, Fast);
            mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, Medium);
            slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, Bias);
            _volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
            _startTime = Server.Time.Date.AddHours(StartTime);
            _stopTime = Server.Time.Date.AddHours(StopTime);
        }

        protected override void OnTick()
        {
            if (IncludeTrailingStop)
            {
                SetTrailingStop();
            }
        }

        protected override void OnBar()
        {
            int index = Bars.Count - 2;
            Entry(index);
        }

        private void Entry(int index)
        {
            var currentHours = Server.Time.TimeOfDay.TotalHours;
            bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
            if (!istimecorrect)
                return;

            // Buy Only
            if (Bars.ClosePrices[index] > slowMa.Result[index])
            {
                // if fast crosses medium upward
                if (Positions.Count < PositionLimit && fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, InstanceName, StopLoss, null);
                }
            }
            // Sell only
            else if (Bars.ClosePrices[index] < slowMa.Result[index])
            {
                // if fast crosses medium downward
                if (Positions.Count < PositionLimit && fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, InstanceName, StopLoss, null);
                }
            }
        }

        private void SetTrailingStop()
        {

            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);


            foreach (var position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, null);
                }
            }

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (var position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, null);
                }
            }
        }
    }
}

@Find a specific FX pair rather than ALL Positions:  28 Aug 2021, 06:09


When I am running the same bot on multiple FX pairs with different parameters, how am I supposed to have it written in order to find a position in on a specific pair instead of using
"   Positions.FindAll()   "

@Bot Only Entering 3 Trades Max:  19 Aug 2021, 19:56


Hi,

I've coded my Cbot specifically to enter only 3 trades at a time on a hedging account which works wonderfully.. however.... 

I've duplicated the bot in order to use it on separate FX pairs with different parameters. 

The bot still only enters a max of 3 trades at a time when it should have been triggered to enter a 4th, 5th, 6th etc. as I have 20 pairs running.

I really thought duplicating the bot and running it independently would solve the problem but it hasn't. Any suggestions or reasons of this issue would be greatly appreciated.

@Error Message when initiating Trailing Stop Loss:  04 Aug 2021, 21:08


Hi,

I have finally completed my bot, or so I had thought. I ran it last night and it executed a trade perfectly. Had the initial hard stop loss set to the proper amount of pips which was awesome. 

However.... when it finally reached the trigger point in pips to remove the stop loss and set a trailing stop instead, it gave me an error leaving my position with no stop loss at all !!! 

We cannot be having this lol.... 

If someone could help me figure out why this has happened that would be amazing! Below is the code for the trailing stop that I have set and also the error message that was given in my trading journal.

       

private void SetTrailingStop()
        {

            var sellPositions = Positions.FindAll(Label);


            foreach (var position in sellPositions)
            {
                double distance = position.EntryPrice + Symbol.Ask;

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + (TrailingStopStep * Symbol.PipSize);

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, null);
                }
            }
            {
                var buyPositions = Positions.FindAll(Label);

                foreach (var position in buyPositions)
                {
                    double distance = Symbol.Bid - position.EntryPrice;

                    if (distance < TrailingStopTrigger * Symbol.PipSize)
                        continue;

                    double newStopLossPrice = Symbol.Bid - (TrailingStopStep * Symbol.PipSize);

                    if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                    {
                        ModifyPosition(position, newStopLossPrice, null);
                    }
                }
            }
        }

Error Message

04/08/2021 03:46:05.799 | → Request to amend position PID8541749 (SL: 151.203) is REJECTED with error "New SL for BUY position should be <= current BID price. current BID: 77.2, SL: 151.203;  "

With that said... I do understand that it tried to place the new stop loss above price which obviously cannot be done in a buy position. However, when I run it through back testing, it works perfectly fine, but live it doesn't.. I've tried to adjust it and ran it through the back testing again and it did not work... So I am a little confused as to what I am doing wrong... 

@GetFitness Args. - Optimize Your Backtesting!:  18 Apr 2021, 18:35


Hi Everyone, 

I been trying to find anything online that would have various Get Fitness codes to add to our algorithms to help with the optimization process, but haven't had much luck.
Therefore I wanted to start a Forum where we can all share various methods in one spot for easy access. 

Things such as:

     - Drawdown less than a certain percentage 

     - Sortino and Sharpe Ratio greater than a certain amount

     - Win percentage above a certain amount

     - etc. 

To start I will share the 2 that I have been able to find during my search.

protected override double GetFitness(GetFitnessArgs args)
{
        //maximize count of winning trades and minimize count of losing trades
        return args.WinningTrades / args.LosingTrades;
}
protected override double GetFitness(GetFitnessArgs args)
{
        //count of winning trades is more important than count of losing trades
        return Math.Pow(args.WinningTrades, 2) / args.LosingTrades;
}

With that said, please share your own that you have come up with or come across so others can benefit as well! 

@RSI + Bar Close Over/Under MA - Help to add Entry and Exit criteria:  17 Apr 2021, 17:20


amusleh said:

Hi,

This sample might help you:

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    /// <summary>
    /// This sample cBot shows how to use the Relative Strength Index indicator
    /// </summary>
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class RelativeStrengthIndexSample : Robot
    {
        private double _volumeInUnits;

        private RelativeStrengthIndex _relativeStrengthIndex;

        [Parameter("Volume (Lots)", DefaultValue = 0.01)]
        public double VolumeInLots { get; set; }

        [Parameter("Stop Loss (Pips)", DefaultValue = 10)]
        public double StopLossInPips { get; set; }

        [Parameter("Take Profit (Pips)", DefaultValue = 10)]
        public double TakeProfitInPips { get; set; }

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

        public Position[] BotPositions
        {
            get
            {
                return Positions.FindAll(Label);
            }
        }

        protected override void OnStart()
        {
            _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);

            _relativeStrengthIndex = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 20);
        }

        protected override void OnBar()
        {
            if (_relativeStrengthIndex.Result.Last(1) > 70 && _relativeStrengthIndex.Result.Last(2) < 70)
            {
                ClosePositions(TradeType.Buy);

                ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
            }
            else if (_relativeStrengthIndex.Result.Last(1) < 20 && _relativeStrengthIndex.Result.Last(2) > 20)
            {
                ClosePositions(TradeType.Sell);

                ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
            }
        }

        private void ClosePositions(TradeType tradeType)
        {
            foreach (var position in BotPositions)
            {
                if (position.TradeType != tradeType) continue;

                ClosePosition(position);
            }
        }
    }
}

Please start learning C# basics and read cTrader automate API references, if you don't have time then post a job request or ask one of our consultants to develop your cBot/indicator for you.

Hi,

Thanks for replying, but this is the sample that helped me get to the point I am at on this code. I am currently still learning but some steps like what I am trying to accomplish are still a little advanced for me. The sample definitely does not render the result I am looking for as I need to figure out how to create a wait function within the code somehow. I'm sure I'll figure it out eventually with some trial and error but figured I'd see if someone knew how. 

Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.

No uploaded.

Warning! Executing cBots downloaded from this section may result in loss of funds. Use them at your own risk.

No uploaded.