Category Trend  Published on 22/01/2022

King Market Structure

Description

This indicator shows the trend direction based on major swing levels (higher lows on uptrend, lower highs on down trend) and switches direction when they get broken. A pullback starts when price went at least a certain amount back (ATR x multi) and lasts for a minimum of bars.


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

namespace cAlgo
{
    [Cloud("Continuation", "Stop", Opacity = 0.1, FirstColor = "Green", SecondColor = "Red")]
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class KingMarketStructure : Indicator
    {
        [Parameter("ATR Period", DefaultValue = 14)]
        public int ATRPeriod { get; set; }

        [Parameter("ATR Multiplier", DefaultValue = 2.0)]
        public double ATRMulti { get; set; }

        [Parameter("ATR MA Type", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType ATRMaType { get; set; }

        [Parameter("Min Pullback Bars", DefaultValue = 5)]
        public int MinPullbackBars { get; set; }

        [Parameter("Colorize Bars", DefaultValue = true)]
        public bool ColorizeBars { get; set; }



        [Output("Continuation", LineColor = "Blue", Thickness = 2)]
        public IndicatorDataSeries Continuation { get; set; }

        [Output("Middle", LineColor = "Gray", Thickness = 2)]
        public IndicatorDataSeries Middle { get; set; }

        [Output("Stop", LineColor = "Red", Thickness = 2)]
        public IndicatorDataSeries Stop { get; set; }

        [Output("ZigZag", LineColor = "Yellow", Thickness = 3)]
        public IndicatorDataSeries ZigZag { get; set; }



        private enum Direction
        {
            Up,
            Down,
            Pullback,
            Undefined
        }



        private double lastLow, lastHigh;
        private int lastLowIndex, lastHighIndex;
        private Direction direction, lastDir;
        private AverageTrueRange atr;



        protected override void Initialize()
        {
            lastLow = double.MaxValue;
            lastLowIndex = 0;
            lastHigh = double.MinValue;
            lastHighIndex = 0;
            direction = Direction.Undefined;
            lastDir = Direction.Undefined;

            atr = Indicators.AverageTrueRange(ATRPeriod, ATRMaType);
        }

        public override void Calculate(int index)
        {
            if (index > 50)
            {
                Continuation[index] = Continuation[index - 1];
                Stop[index] = Stop[index - 1];

                double high = Bars.HighPrices[index];
                double low = Bars.LowPrices[index];

                double close = Bars.ClosePrices[index];
                double open = Bars.OpenPrices[index];

                double deviationUp = lastLow + atr.Result[index] * ATRMulti;
                double deviationDown = lastHigh - atr.Result[index] * ATRMulti;

                if (direction == Direction.Up)
                {
                    if (lastDir == Direction.Down)
                    {
                        double temp = Continuation[index];
                        Continuation[index] = Stop[index];
                        Stop[index] = temp;
                    }

                    lastDir = Direction.Up;
                    if (high > lastHigh)
                    {
                        if (lastHighIndex > lastLowIndex)
                        {
                            ZigZag[lastHighIndex] = double.NaN;
                        }
                        ZigZag[index] = high;

                        lastHighIndex = index;
                        lastHigh = high;
                    }
                    else if (close <= deviationDown)
                    {
                        direction = Direction.Pullback;
                        Continuation[index] = lastHigh;
                        ZigZag[index] = low;

                        lastLowIndex = index;
                        lastLow = low;
                    }
                    else if (close < Stop[index])
                    {
                        direction = Direction.Down;

                        Continuation[index] = Stop[index];
                        Stop[index] = lastHigh;
                    }
                }
                else if (direction == Direction.Down)
                {
                    if (lastDir == Direction.Up)
                    {
                        double temp = Continuation[index];
                        Continuation[index] = Stop[index];
                        Stop[index] = temp;
                    }

                    lastDir = Direction.Down;
                    if (low < lastLow)
                    {
                        if (lastLowIndex > lastHighIndex)
                        {
                            ZigZag[lastLowIndex] = double.NaN;
                        }
                        ZigZag[index] = low;

                        lastLowIndex = index;
                        lastLow = low;
                    }
                    else if (close >= deviationUp)
                    {
                        direction = Direction.Pullback;
                        Continuation[index] = lastLow;
                        ZigZag[index] = high;

                        lastHighIndex = index;
                        lastHigh = high;
                    }
                    else if (close > Stop[index])
                    {
                        direction = Direction.Up;
                    }
                }

                if (direction == Direction.Pullback)
                {
                    if (high > lastHigh && lastDir == Direction.Down)
                    {
                        ZigZag[lastHighIndex] = double.NaN;
                        ZigZag[index] = high;

                        lastHighIndex = index;
                        lastHigh = high;
                    }
                    else if (low < lastLow && lastDir == Direction.Up)
                    {
                        ZigZag[lastLowIndex] = double.NaN;
                        ZigZag[index] = low;

                        lastLowIndex = index;
                        lastLow = low;
                    }

                    if (close < Stop[index] && lastDir == Direction.Up || close < Continuation[index] && lastDir == Direction.Down)
                    {
                        direction = Direction.Down;

                        if (lastHighIndex > lastLowIndex)
                        {
                            if (index - lastLowIndex > MinPullbackBars)
                            {
                                Stop[index] = lastHigh;
                            }
                            else
                            {
                                ZigZag[lastLowIndex] = double.NaN;
                                ZigZag[lastHighIndex] = double.NaN;
                            }

                            if (low < lastLow)
                            {
                                ZigZag[index] = low;

                                lastLowIndex = index;
                                lastLow = low;
                            }
                        }
                    }
                    else if (close > Stop[index] && lastDir == Direction.Down || close > Continuation[index] && lastDir == Direction.Up)
                    {
                        direction = Direction.Up;

                        if (lastLowIndex > lastHighIndex)
                        {
                            if (index - lastHighIndex > MinPullbackBars)
                            {
                                Stop[index] = lastLow;
                            }
                            else
                            {
                                ZigZag[lastLowIndex] = double.NaN;
                                ZigZag[lastHighIndex] = double.NaN;
                            }

                            if (high > lastHigh)
                            {
                                ZigZag[index] = high;

                                lastHighIndex = index;
                                lastHigh = high;
                            }
                        }
                    }
                }
                else
                {
                    if (close > lastHigh)
                    {
                        direction = Direction.Up;
                        Continuation[index] = lastHigh;
                        Stop[index] = lastLow;
                    }
                    else if (close < lastLow)
                    {
                        direction = Direction.Down;
                        Continuation[index] = lastLow;
                        Stop[index] = lastHigh;
                    }
                }

                Middle[index] = (Continuation[index] + Stop[index]) / 2.0;

                if (ColorizeBars && RunningMode != RunningMode.Optimization)
                {
                    bool up = close > open;
                    switch (direction)
                    {
                        case Direction.Up:
                            if (up)
                                Chart.SetBarColor(index, Color.LimeGreen);
                            else if (!up)
                                Chart.SetBarColor(index, Color.DarkGreen);
                            break;
                        case Direction.Down:
                            if (!up)
                                Chart.SetBarColor(index, Color.Crimson);
                            else if (up)
                                Chart.SetBarColor(index, Color.Tomato);
                            break;
                        case Direction.Pullback:
                            if (lastDir == Direction.Up && up)
                                Chart.SetBarColor(index, Color.LimeGreen);
                            else if (lastDir == Direction.Up && !up)
                                Chart.SetBarColor(index, Color.DarkGreen);
                            else if (lastDir == Direction.Down && !up)
                                Chart.SetBarColor(index, Color.Crimson);
                            else if (lastDir == Direction.Down && up)
                                Chart.SetBarColor(index, Color.Tomato);
                            break;
                    }
                }
            }
            else
            {
                double high = Bars.HighPrices[index];
                double low = Bars.LowPrices[index];

                Continuation[index] = Continuation[index - 1];
                Stop[index] = Stop[index - 1];

                if (lastLow > low)
                {
                    lastLow = low;
                    lastLowIndex = index;
                }

                if (lastHigh < high)
                {
                    lastHigh = high;
                    lastHighIndex = index;
                }
            }
        }

        private int getLowest(int startIndex, int endIndex, DataSeries series)
        {
            double min = series[startIndex];
            int index = startIndex;
            for (int i = startIndex + 1; i <= endIndex; i++)
            {
                if (series[i] < min)
                {
                    min = series[i];
                    index = i;
                }
            }
            return index;
        }

        private int getHighest(int startIndex, int endIndex, DataSeries series)
        {
            double max = series[startIndex];
            int index = startIndex;
            for (int i = startIndex + 1; i <= endIndex; i++)
            {
                if (series[i] > max)
                {
                    max = series[i];
                    index = i;
                }
            }
            return index;
        }
    }
}


CW
cW22Trader

Joined on 16.03.2021

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: King Market Structure.algo
  • Rating: 5
  • Installs: 2856
  • Modified: 22/01/2022 16:18
Comments
Log in to add a comment.
YE
YesOrNot · 1 year ago

I forget to say “Champion” !

YE
YesOrNot · 1 year ago

Hi, Collaboration ? 

IA
iafm22 · 2 years ago

Could you put an example using the indicator in a cBot? I am trying to do that but I can´t. Thank you!

SH
shamsulzoha5 · 2 years ago

Absolutely great for traders who dwell on price action trading. I had a hard time determining the market trend before I found this indicator. The added ATR functionality helps in increasing the overall profitability. Recommended.