Breakout Trend Bot free

by ctid1731325 in category Trend at 21/09/2022
Description

By ForexCove. The Breakout Trend Bot trades in the direction of trend. Pending orders are placed x-pips above or below previous highest high or lowest low, and if market shows strength in the predicted direction, the trade is taken.

You can configure desired trend strength with built in ADX filter, and even let TP and SL targets be defined by ATR.

 To download a sample config file, visit this link HERE

Warning! Executing the following cBot may result in loss of funds. Use it at your own risk.
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.
Formula / Source Code
Language: C#
Trading Platform: cAlgo
´╗┐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 Breakout_cBot : Robot
    {

        [Parameter(DefaultValue = "Breakout_cBot")]
        public string cBotLabel { get; set; }

        [Parameter("Lot Size", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
        public double LotSize { get; set; }

        [Parameter("Enable Martingale", DefaultValue = false)]
        public bool EnableMartingale { get; set; }

        [Parameter("Max trade size:", DefaultValue = 0.8, MinValue = 0.01, Step = 0.01)]
        public double MaxTradeSize { get; set; }

        [Parameter("Martingale Multiplier:", DefaultValue = 2.0)]
        public double MartingaleMultiplier { get; set; }

        [Parameter("StopLoss in pips", DefaultValue = 20.0)]
        public double StopLoss { get; set; }

        [Parameter("TakeProfit in pips", DefaultValue = 20.0)]
        public double TakeProfit { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MAType { get; set; }

        [Parameter("MA Period", DefaultValue = 14)]
        public int MAPeriod { get; set; }

        [Parameter("Offsetfrom Highest/lowest pricee in pips", DefaultValue = 3.0)]
        public double OffsetHL { get; set; }

        [Parameter("Adjust Initial Volume  (true/false)", DefaultValue = true)]
        public bool ParamAdjustInitialVolume { get; set; }

        [Parameter("Initial Volume Adjustment", DefaultValue = 40, Step = 1)]
        public double ParamVolumeAdjustment { get; set; }

        [Parameter("Include trading hours", DefaultValue = true)]
        public bool UseTradingHours { get; set; }

        [Parameter("Trading Start Hour:0-23", DefaultValue = 8, MinValue = 0, MaxValue = 23, Step = 1)]
        public int StartTimeHour { get; set; }

        [Parameter("Trading Start Minute:0-59", DefaultValue = 0, MinValue = 0, MaxValue = 59, Step = 1)]
        public int StartTimeMinute { get; set; }

        [Parameter("Trading End Hour:0-23", DefaultValue = 22, MinValue = 0, MaxValue = 23, Step = 1)]
        public int EndTimeHour { get; set; }

        [Parameter("Trading End Minute:0-59", DefaultValue = 0, MinValue = 0, MaxValue = 59, Step = 1)]
        public int EndTimeMinute { get; set; }

        [Parameter("Use ADX", DefaultValue = true)]
        public bool UseADX { get; set; }

        [Parameter("ADX Level", DefaultValue = 25)]
        public int ADXLevel { get; set; }

        [Parameter("ADX Period", DefaultValue = 14)]
        public int ADXPeriod { get; set; }

        [Parameter("Dynamic TP/SL - Yes/No:", Group = ("Dynamic TP/SL"), DefaultValue = true)]
        public bool DynamicTPSL { get; set; }

        [Parameter("ATR periods:", Group = ("Dynamic TP/SL"), DefaultValue = 14)]
        public int ATR_Periods { get; set; }

        [Parameter("MA Type", Group = ("Dynamic TP/SL"), DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType ATR_MAType { get; set; }

        [Parameter("ATR TP Multiplier:", Group = ("Dynamic TP/SL"), DefaultValue = 300.0)]
        public double ATR_TP_Multiplier { get; set; }

        [Parameter("ATR SL Multiplier:", Group = ("Dynamic TP/SL"), DefaultValue = 200.0)]
        public double ATR_SL_Multiplier { get; set; }


        private MovingAverage MA;
        private int SignalBar;
        private double currentLotSize;
        private DateTime StartTimeHour_;
        private DateTime EndTimeHour_;
        private DateTime StartTimeMinute_;
        private DateTime EndTimeMinute_;
        private DirectionalMovementSystem dms_;

        private AverageTrueRange ATR_;


        protected override void OnStart()
        {
            MA = Indicators.MovingAverage(Bars.ClosePrices, MAPeriod, MAType);
            SignalBar = 1;
            currentLotSize = GetInitialLots(Account.Balance, ParamVolumeAdjustment);

            if (EnableMartingale == true)
                Positions.Closed += OnPositionsClosed;

            StartTimeHour_ = Server.Time.Date.AddHours(StartTimeHour);
            EndTimeHour_ = Server.Time.Date.AddHours(EndTimeHour);
            StartTimeMinute_ = Server.Time.Date.AddMinutes(StartTimeMinute);
            EndTimeMinute_ = Server.Time.Date.AddMinutes(EndTimeMinute);

            dms_ = Indicators.DirectionalMovementSystem(ADXPeriod);

            if (DynamicTPSL == true)
            {
                ATR_ = Indicators.AverageTrueRange(ATR_Periods, ATR_MAType);
            }

        }

        protected override void OnTick()
        {

        }

        protected override void OnBar()
        {
            if ((UseTradingHours == true && IsTradingHours() == true) || (UseTradingHours == false))
            {

                if (Positions.FindAll(cBotLabel, Symbol.Name).Length == 0 && (UseADX == false || (UseADX == true && CheckADX() == true)))
                {
                    if (Bars.ClosePrices.Last(SignalBar) > MA.Result.Last(SignalBar))
                    {
                        if (Bars.ClosePrices.Last(SignalBar) < Bars.OpenPrices.Last(SignalBar))
                        {
                            if (getPendingOrdersQuantity() == 0)
                                OpenStopOrder((Bars.HighPrices.Last(SignalBar) + OffsetHL * Symbol.PipSize), TradeType.Buy, currentLotSize);
                            else
                            {
                                double dNewOpenPrice = Bars.HighPrices.Last(SignalBar) + OffsetHL * Symbol.PipSize;
                                tryModifyStopOrder(TradeType.Buy, dNewOpenPrice);
                            }
                        }
                        else if (Bars.ClosePrices.Last(SignalBar) > Bars.OpenPrices.Last(SignalBar))
                        {
                            if (Bars.OpenPrices.Last(SignalBar) < MA.Result.Last(SignalBar) && getPendingOrdersQuantity() > 0)
                                cancelStopOrder(TradeType.Sell);
                        }
                    }
                    else if (Bars.ClosePrices.Last(SignalBar) < MA.Result.Last(SignalBar))
                    {
                        if (Bars.ClosePrices.Last(SignalBar) < Bars.OpenPrices.Last(SignalBar))
                        {
                            if (Bars.OpenPrices.Last(SignalBar) > MA.Result.Last(SignalBar) && getPendingOrdersQuantity() > 0)
                                cancelStopOrder(TradeType.Buy);
                        }
                        else if (Bars.ClosePrices.Last(SignalBar) > Bars.OpenPrices.Last(SignalBar))
                        {
                            if (getPendingOrdersQuantity() == 0)
                                OpenStopOrder((Bars.LowPrices.Last(SignalBar) - OffsetHL * Symbol.PipSize), TradeType.Sell, currentLotSize);
                            else
                            {
                                double dNewOpenPrice = Bars.LowPrices.Last(SignalBar) - OffsetHL * Symbol.PipSize;
                                tryModifyStopOrder(TradeType.Sell, dNewOpenPrice);
                            }
                        }
                    }
                }
            }
        }

        private int getPendingOrdersQuantity()
        {
            int count = 0;
            foreach (var order in PendingOrders)
            {
                if (order.Label == cBotLabel)
                {
                    count++;
                }
            }
            return count;
        }

        private void OpenStopOrder(double dOpenPrice, TradeType tradeType, double dLots)
        {
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(dLots);
            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.Down);

            double? TakeProfitPips = TakeProfit;
            double? StopLossPips = StopLoss;

            if (DynamicTPSL == true)
            {
                TakeProfitPips = ATR_.Result.LastValue * ATR_TP_Multiplier;
                StopLossPips = ATR_.Result.LastValue * ATR_SL_Multiplier;
            }

            var result = PlaceStopOrder(tradeType, Symbol.Name, volumeInUnits, dOpenPrice, cBotLabel, StopLossPips, TakeProfitPips);
            if (!result.IsSuccessful)
            {
                Print("Placing Stop Order Error: {0}", result.Error.Value);
                OnStop();
            }
        }

        private void tryModifyStopOrder(TradeType tradeType, double dNewOpenPrice)
        {
            foreach (var order in PendingOrders)
            {
                if (order.SymbolName == Symbol.Name && order.Label == cBotLabel && order.TradeType == tradeType)
                {
                    if ((order.TradeType == TradeType.Buy && order.TargetPrice > dNewOpenPrice) || (order.TradeType == TradeType.Sell && order.TargetPrice < dNewOpenPrice))
                        ModifyPendingOrder(order, dNewOpenPrice, order.StopLossPips, order.TakeProfitPips, order.ExpirationTime);
                }
            }
        }

        private void cancelStopOrder(TradeType tradeType)
        {
            foreach (var order in PendingOrders)
            {
                if (order.SymbolName == Symbol.Name && order.Label == cBotLabel && order.TradeType == tradeType)
                {
                    CancelPendingOrder(order);
                }
            }
        }

        void OnPositionsClosed(PositionClosedEventArgs obj)
        {
            Position closedPosition = obj.Position;
            if (closedPosition.SymbolName == Symbol.Name && closedPosition.Label == cBotLabel)
            {
                if (closedPosition.NetProfit < 0.0)
                {
                    currentLotSize = Math.Min(Math.Round((currentLotSize * MartingaleMultiplier), 2), MaxTradeSize);
                }
                else
                    currentLotSize = GetInitialLots(Account.Balance, ParamVolumeAdjustment);
            }
        }

        protected double GetInitialLots(double balance, double adjustment)
        {
            if (ParamAdjustInitialVolume == true)
            {
                double volumeDouble = balance * adjustment / 100;
                double volumeLong = Symbol.NormalizeVolumeInUnits(volumeDouble, RoundingMode.Down);
                volumeLong = Math.Max(volumeLong, Symbol.VolumeInUnitsMin);
                volumeLong = Symbol.VolumeInUnitsToQuantity(volumeLong);
                return volumeLong;
            }
            else
            {
                return LotSize;
            }
        }

        private bool IsTradingHours()
        {
            var currentTimeHour = Server.Time.TimeOfDay.Hours;
            var currentTimeMinute = Server.Time.TimeOfDay.Minutes;
            if ((StartTimeHour_.Hour < currentTimeHour && EndTimeHour_.Hour > currentTimeHour) || (StartTimeHour_.Hour == currentTimeHour && StartTimeMinute_.Minute <= currentTimeMinute) || (EndTimeHour_.Hour == currentTimeHour && EndTimeMinute_.Minute >= currentTimeMinute))
                return true;

            return false;

        }

        private bool CheckADX()
        {
            if (dms_.ADX.Last(SignalBar) > ADXLevel)
                return true;

            return false;

        }

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

nielsen - September 21, 2022 @ 14:40

Very interesting with the pending orders. Congrats!

5