how to detect last occurring fractal

Created at 27 May 2021, 09:28
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!
SK

Skypips

Joined 12.02.2019

how to detect last occurring fractal
27 May 2021, 09:28


Hi,

I am facing an issue with making the bot detect if there was a fractal in the last bar.

The strategy is very simple:

For a buy condition

1. if MAs are crossing upward, and price is above MA2

2. Detected a fractal in the last bar?

3. Place buy order

 

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, TimeZone = TimeZones.ArabicStandardTime)]

    public class SKYPIPS6MAscrossCHAOS : Robot
    {
        private bool _position;
        private MovingAverage ma1;
        private MovingAverage ma2;
        private MovingAverage ma3;
        private MovingAverage ma4;
        private MovingAverage ma5;
        private MovingAverage ma6;
        private RelativeStrengthIndex rsi;
        private Fractals fractals;

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

        [Parameter("Take Profit", DefaultValue = 15, Step = 5)]
        public double Takeprofit { get; set; }

        [Parameter("Stop Loss", DefaultValue = 5, Step = 5)]
        public double Stoploss { get; set; }

        [Parameter("Fractals", DefaultValue = 5)]
        public int fractalsperiod { get; set; }

        [Parameter("RSI Periods", DefaultValue = 4)]
        public int Periods { get; set; }

        [Parameter("MA 1 Period", DefaultValue = 5, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA1Period { get; set; }

        [Parameter("MA 2 Period", DefaultValue = 8, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA2Period { get; set; }

        [Parameter("MA 3 Period", DefaultValue = 13, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA3Period { get; set; }
        [Parameter("MA 4 Period", DefaultValue = 21, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA4Period { get; set; }
        [Parameter("MA 5 Period", DefaultValue = 48, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA5Period { get; set; }

        [Parameter("MA 6 Period", DefaultValue = 150, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA6Period { get; set; }

        [Parameter("Volume", DefaultValue = 10000, MinValue = 0)]
        public int Volume { get; set; }

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


        [Parameter("Hour To Hour", DefaultValue = false)]
        public bool HourToHour { get; set; }
        [Parameter("Start Hour", DefaultValue = 8, MaxValue = 23)]
        public int StartHour { get; set; }
        [Parameter("Stop Hour", DefaultValue = 18, MaxValue = 23)]
        public int StopHour { get; set; }
        private bool c_hour = true;
        private bool st_45 = true;



        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(Source, Periods);
            ma1 = Indicators.MovingAverage(Source, MA1Period, MAType);
            ma2 = Indicators.MovingAverage(Source, MA2Period, MAType);
            ma3 = Indicators.MovingAverage(Source, MA3Period, MAType);
            ma4 = Indicators.MovingAverage(Source, MA4Period, MAType);
            ma5 = Indicators.MovingAverage(Source, MA5Period, MAType);
            ma6 = Indicators.MovingAverage(Source, MA6Period, MAType);

            fractals = Indicators.Fractals(fractalsperiod);
        }


        protected override void OnBar()
        {

            c_hour = GetTradingHour();

            if (Trade.IsExecuting)
                return;

            var buy_position = Positions.Find("BUY", SymbolName);
            var sell_position = Positions.Find("SELL", SymbolName);

            if (buy_position == null && sell_position == null)
                _position = true;
            else
                _position = false;

            if (_position && (ma1.Result.Last(0) > ma2.Result.Last(0) && ma2.Result.Last(0) > ma3.Result.Last(0)) && c_hour && st_45 && !double.IsNaN(fractals.DownFractal.Last(1)) && Bars.ClosePrices.Last(1) > ma2.Result.Last(1))
            {

                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, "BUY", Stoploss, Takeprofit);
                _position = false;
            }

            if (_position && (ma1.Result.Last(0) < ma2.Result.Last(0) && ma2.Result.Last(0) < ma3.Result.Last(0)) && c_hour && st_45 && !double.IsNaN(fractals.UpFractal.Last(1)) && Bars.ClosePrices.Last(1) < ma2.Result.Last(1))
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, "SELL", Stoploss, Takeprofit);
                _position = false;
            }



        }


        //+------------------------------------------------------------------+
        //| Get Trading hour                                                 |
        //+------------------------------------------------------------------+
        private bool GetTradingHour()
        {
            bool h_res = true;
            if (HourToHour)
            {
                if (StartHour != StopHour)
                {
                    if ((StopHour > StartHour && Time.Hour >= StartHour && Time.Hour < StopHour) || (StartHour > StopHour && (Time.Hour >= StartHour || Time.Hour < StopHour)))
                        h_res = true;
                    else
                        h_res = false;
                }
                else
                {

                    st_45 = false;
                    h_res = false;
                }
            }
            return (h_res);
        }
    }
}

 


@Skypips
Replies

prosteel1
04 Jun 2021, 12:52

RE:

By using fractals.DownFractal.Count you can store the bar number in a variable and then check if it is greater than the variable.

I think this makes !double.IsNaN(fractals.DownFractal.Last(0)) not needed, so I removed it too.

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, TimeZone = TimeZones.UTC)]

    public class SKYPIPS6MAscrossCHAOS : Robot
    {
        private bool _position;
        private MovingAverage ma1;
        private MovingAverage ma2;
        private MovingAverage ma3;
        private MovingAverage ma4;
        private MovingAverage ma5;
        private MovingAverage ma6;
        private RelativeStrengthIndex rsi;
        private Fractals fractals;

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

        [Parameter("Take Profit", DefaultValue = 15, Step = 5)]
        public double Takeprofit { get; set; }

        [Parameter("Stop Loss", DefaultValue = 5, Step = 5)]
        public double Stoploss { get; set; }

        [Parameter("Fractals", DefaultValue = 5)]
        public int fractalsperiod { get; set; }

        [Parameter("RSI Periods", DefaultValue = 4)]
        public int Periods { get; set; }

        [Parameter("MA 1 Period", DefaultValue = 5, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA1Period { get; set; }

        [Parameter("MA 2 Period", DefaultValue = 8, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA2Period { get; set; }

        [Parameter("MA 3 Period", DefaultValue = 13, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA3Period { get; set; }
        [Parameter("MA 4 Period", DefaultValue = 21, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA4Period { get; set; }
        [Parameter("MA 5 Period", DefaultValue = 48, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA5Period { get; set; }

        [Parameter("MA 6 Period", DefaultValue = 150, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA6Period { get; set; }

        [Parameter("Volume", DefaultValue = 10000, MinValue = 0)]
        public int Volume { get; set; }

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


        [Parameter("Hour To Hour", DefaultValue = false)]
        public bool HourToHour { get; set; }
        [Parameter("Start Hour", DefaultValue = 8, MaxValue = 23)]
        public int StartHour { get; set; }
        [Parameter("Stop Hour", DefaultValue = 18, MaxValue = 23)]
        public int StopHour { get; set; }
        private bool c_hour = true;
        private bool st_45 = true;

        // Added a counter
        int downfractalcount;
        int upfractalcount;



        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(Source, Periods);
            ma1 = Indicators.MovingAverage(Source, MA1Period, MAType);
            ma2 = Indicators.MovingAverage(Source, MA2Period, MAType);
            ma3 = Indicators.MovingAverage(Source, MA3Period, MAType);
            ma4 = Indicators.MovingAverage(Source, MA4Period, MAType);
            ma5 = Indicators.MovingAverage(Source, MA5Period, MAType);
            ma6 = Indicators.MovingAverage(Source, MA6Period, MAType);

            fractals = Indicators.Fractals(fractalsperiod);

            // Write the last fractal counts
            downfractalcount = fractals.DownFractal.Count;
            upfractalcount = fractals.UpFractal.Count;
        }


        protected override void OnBar()
        {
            //Print("Down " + fractals.DownFractal.Count);
            //Print("Up " + fractals.UpFractal.Count);
            c_hour = GetTradingHour();

            if (Trade.IsExecuting)
                return;

            var buy_position = Positions.Find("BUY", SymbolName);
            var sell_position = Positions.Find("SELL", SymbolName);

            if (buy_position == null && sell_position == null)
                _position = true;
            else
                _position = false;
            // Added a check for a later fractal count
            if (_position && fractals.DownFractal.Count > downfractalcount && (ma1.Result.Last(0) > ma2.Result.Last(0) && ma2.Result.Last(0) > ma3.Result.Last(0)) && c_hour && st_45 && Bars.ClosePrices.Last(1) > ma2.Result.Last(1))
            {
                Print(fractals.DownFractal.Count + " Buy, " + fractals.DownFractal.Last(0) + " " + !double.IsNaN(fractals.DownFractal.Last(0)));
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, "BUY", Stoploss, Takeprofit);
                _position = false;
            }
            // Added a check for a later fractal count
            if (_position && fractals.UpFractal.Count > upfractalcount && (ma1.Result.Last(0) < ma2.Result.Last(0) && ma2.Result.Last(0) < ma3.Result.Last(0)) && c_hour && st_45 && Bars.ClosePrices.Last(1) < ma2.Result.Last(1))
            {
                Print(fractals.UpFractal.Count + " Sell, " + fractals.UpFractal.Last(0) + " " + !double.IsNaN(fractals.UpFractal.Last(0)));
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, "SELL", Stoploss, Takeprofit);
                _position = false;
            }

            // Update the count of the last fractals
            downfractalcount = fractals.DownFractal.Count;
            upfractalcount = fractals.UpFractal.Count;


        }


        //+------------------------------------------------------------------+
        //| Get Trading hour                                                 |
        //+------------------------------------------------------------------+
        private bool GetTradingHour()
        {
            bool h_res = true;
            if (HourToHour)
            {
                if (StartHour != StopHour)
                {
                    if ((StopHour > StartHour && Time.Hour >= StartHour && Time.Hour < StopHour) || (StartHour > StopHour && (Time.Hour >= StartHour || Time.Hour < StopHour)))
                        h_res = true;
                    else
                        h_res = false;
                }
                else
                {

                    st_45 = false;
                    h_res = false;
                }
            }
            return (h_res);
        }
    }
}

 


@prosteel1