Fractals and engulfing

Created at 14 Sep 2021, 11:31
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!
WA

waym77

Joined 22.07.2021

Fractals and engulfing
14 Sep 2021, 11:31


Hi, I'm working with fractals and I'm having trouble with the logic of how the logic is supposed to work.

Here is an image example of what I need:



 

 

 

 

 

 

 

 

 

 

 

 

I understand that fractals will take some extra bars to form (in this instance, the period is set to 3), which means the entry will come when Bar 0 turns into Bar 1.

In a bearish situation such as the image, if Bar 1 has printed an up fractal and Bar 0 became a bearish engulfing, a sell should happen. The reverse is true for bullish.

I would like this to be defined by a boolean, where true would be bullish and false would be bearish. I have added some code to explain where I'm struggling.

_FractalQ = GetFractal();
_EngulfingQ = GetEngulfing();



private bool GetFractal()
        {
            //??
        }

private bool GetEngulfing()
        {
            //??
        }

 


@waym77
Replies

amusleh
15 Sep 2021, 11:53

I recommend you to calculate the fractals by your self, instead of using cTrader fractals indicator, that way you will be sure about how it works and what kind of result it should give you.

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Fractal Period", DefaultValue = 5, MinValue = 5)]
        public int Period { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double FirstVolume { get; set; }

        private Fractals _fractal;

        protected override void OnStart()
        {
            _fractal = Indicators.Fractals(Period);
        }

        protected override void OnBar()
        {
            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.UpFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }

            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.DownFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }
        }
    }
}

My sample uses cTrader fractals and if the next candle after fractal was an engulfing candle it executes the trade.

But I don't know how the cTrader fractals indicator works, so its better to calculate it by yourself or search and you might find some fractal indicators already developed by other community members.


@amusleh

waym77
15 Sep 2021, 12:33

RE:

amusleh said:

I recommend you to calculate the fractals by your self, instead of using cTrader fractals indicator, that way you will be sure about how it works and what kind of result it should give you.

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Fractal Period", DefaultValue = 5, MinValue = 5)]
        public int Period { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double FirstVolume { get; set; }

        private Fractals _fractal;

        protected override void OnStart()
        {
            _fractal = Indicators.Fractals(Period);
        }

        protected override void OnBar()
        {
            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.UpFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }

            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.DownFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }
        }
    }
}

My sample uses cTrader fractals and if the next candle after fractal was an engulfing candle it executes the trade.

But I don't know how the cTrader fractals indicator works, so its better to calculate it by yourself or search and you might find some fractal indicators already developed by other community members.

Hi amusleh,

 

Thanks for the code suggestions, I'll have a look at it now.

The cTrader fractals has a natural limitation of min 5 periods, which didn't work for me. As a result, I am already using a custom fractal system I found on the community forum.

 

Basic fractals, but with a min limit of < 5.

 

Thanks again.


@waym77

waym77
15 Sep 2021, 15:34 ( Updated at: 21 Dec 2023, 09:22 )

RE:

amusleh said:

I recommend you to calculate the fractals by your self, instead of using cTrader fractals indicator, that way you will be sure about how it works and what kind of result it should give you.

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Fractal Period", DefaultValue = 5, MinValue = 5)]
        public int Period { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double FirstVolume { get; set; }

        private Fractals _fractal;

        protected override void OnStart()
        {
            _fractal = Indicators.Fractals(Period);
        }

        protected override void OnBar()
        {
            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.UpFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }

            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.DownFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }
        }
    }
}

My sample uses cTrader fractals and if the next candle after fractal was an engulfing candle it executes the trade.

But I don't know how the cTrader fractals indicator works, so its better to calculate it by yourself or search and you might find some fractal indicators already developed by other community members.

Hi,

I have adapted the code from a bot to an indicator, however, I am struggling to get the logic working in the correct order. As I mentioned before: As soon as the latest bar closes and turns into Bar 1, there needs to have been a fractal on 1 and an engulfing on 0. This is only possible with fractal at 3.

 

Additionally, I need these signals to print further over the index so I can backtest it. 

For clarification, please see the image, code in question, and custom fractals indicator:

 

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class FractalMomentum : Indicator
    {
        [Parameter("Fractal Period", DefaultValue = 3, MinValue = 1)]
        public int Period { get; set; }

        [Parameter("Print Offset (Pips)", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 100.0, Step = 0.1)]
        public double _PO_Parameter { get; set; }

        private double _offset, _offset_calc;

        private CustomFractals _fractal;

        protected override void Initialize()
        {
            _fractal = Indicators.GetIndicator<CustomFractals>(Period);
        }

        public override void Calculate(int index)
        {
            _offset = _PO_Parameter * Symbol.PipValue;

            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                _offset_calc = Bars.LowPrices.LastValue - _offset;
                Chart.DrawIcon("Sell", ChartIconType.DownTriangle, Bars.OpenTimes.LastValue, _offset_calc, Color.OrangeRed);
            }
            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                _offset_calc = Bars.HighPrices.LastValue + _offset;
                Chart.DrawIcon("Buy", ChartIconType.UpTriangle, Bars.OpenTimes.LastValue, _offset_calc, Color.Green);
            }
        }
    }
}

--------------------

 

using cAlgo.API;


namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class CustomFractals : Indicator
    {
        [Parameter(DefaultValue = 3, MinValue = 1)]
        public int Period { get; set; }

        [Output("Up Fractal", LineColor = "Red", PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries UpFractal { get; set; }

        [Output("Down Fractal", LineColor = "Green", PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries DownFractal { get; set; }

        public override void Calculate(int index)
        {
            if (index < Period)
                return;

            DrawUpFractal(index);
            DrawDownFractal(index);

        }

        private void DrawUpFractal(int index)
        {
            int period = Period % 2 == 0 ? Period - 1 : Period;
            int middleIndex = index - period / 2;
            double middleValue = Bars.HighPrices[middleIndex];

            bool up = true;

            for (int i = 0; i < period; i++)
            {
                if (middleValue < Bars.HighPrices[index - i])
                {
                    up = false;
                    break;
                }
            }
            if (up)
                UpFractal[middleIndex] = middleValue;

        }

        private void DrawDownFractal(int index)
        {
            int period = Period % 2 == 0 ? Period - 1 : Period;
            int middleIndex = index - period / 2;
            double middleValue = Bars.LowPrices[middleIndex];
            bool down = true;

            for (int i = 0; i < period; i++)
            {
                if (middleValue > Bars.LowPrices[index - i])
                {
                    down = false;
                    break;
                }
            }
            if (down)
                DownFractal[middleIndex] = middleValue;

        }


    }
}

 

Your help and advice is greatly appreciated, thanks.


@waym77

amusleh
17 Sep 2021, 10:23

Hi,

I tired a lot to fix this issue but I couldn't, this indicator keep changing its past data and even if you wait few more bars than Fractals defined periods the indicator data can change.

 


@amusleh