Warning! This section will be deprecated on February 1st 2025. Please move all your Indicators to the cTrader Store catalogue.
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: 2942
- Modified: 22/01/2022 16:18
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
YE
Hi, Collaboration ?
IA
Could you put an example using the indicator in a cBot? I am trying to do that but I can´t. Thank you!
SH
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.
I forget to say “Champion” !