*** 3 EMA Cross. Indicator (Bot avail.) free

by NiLo in category Trend at 25/08/2020
Description

I just released my latest creation. The EMA3 Crossing indicator.

This indicator is based on the well-known EMA3 crossing strategy. This indicator shows the 3 EMA lines and also indicates when there is confirmation. On confirmation you want to open a trade. This indicator tells you to go long or short (depending on direction). This indicator also provides a suggestion for the stoploss and takeprofit. This strategy works in many markets and timeframes. The indicator will draw all lines as in the sample picture below. Just install this one and you're set to go.

I'll explain the indicator in this Youtube video:
 

 

Would you be so kind to give a thumbs up if you download this indicator?
That will keep me motivated to create more of these awesome indicators.
Thank you!

 

Version history
Aug 25, 2020 -> version 2.2 (minor updates)
July 22, 2020 -> Auto tradingbot released on cTrader 
(https://ctrader.com/algos/cbots/show/2309)
July 9, 2020 -> version 2.1 (cosmetic updates)
July 8, 2020 -> version 2.0 (bugfix)
July 8, 2020 -> version 1.0 (initial version)

 

NOW AVAILABLE - Fully automated tradingbot based on this strategy (https://ctrader.com/algos/cbots/show/2309)
Today I have released a bot that you can easily activate in your own cTrader software so that the bot takes all the work out of your hands to trade with this profitable strategy. The bot will watch all activated markets and timeframes automatically and will set the correct stop loss and takeprofit for you. I will explain in the instructionvide how you can set up your own cTrader software in a few minutes to have this bot traded optimized per market, timeframe and period via this strategy. This bot works in all markets, as long as the market is open.

Always use appropriate risk management!!
Use at your own risk!!

 

 

 

My other cTrader products:
EMA 3 Crossing autotrading Bot (https://ctrader.com/algos/cbots/show/2309)
EMA 3 Crossing indicator (https://ctrader.com/algos/indicators/show/2286)
FractalBreak autotrading Bot (https://ctrader.com/algos/cbots/show/2282)
FractalBreak indicator (https://ctrader.com/algos/indicators/show/2274)

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: cAlgocTrader
´╗┐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 Ema3Indicator : Indicator
    {
        private Color _textcolor;
        private ExponentialMovingAverage _emaFast;
        private ExponentialMovingAverage _emaSlow;
        private ExponentialMovingAverage _emaTrend;

        [Parameter("Fast EMA (periods)", Group = "Trading", DefaultValue = 9, MinValue = 1, MaxValue = 100, Step = 1)]
        public int EmaPeriodsFast { get; set; }

        [Parameter("Slow EMA (periods)", Group = "Trading", DefaultValue = 21, MinValue = 1, MaxValue = 100, Step = 1)]
        public int EmaPeriodsSlow { get; set; }

        [Parameter("Trend EMA (periods)", Group = "Trading", DefaultValue = 55, MinValue = 1, MaxValue = 100, Step = 1)]
        public int EmaPeriodsTrend { get; set; }

        [Parameter("Source", Group = "Trading")]
        public DataSeries Source { get; set; }

        [Output("EMA Fast", LineColor = "Turquoise", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries EMAFast { get; set; }

        [Output("EMA Slow", LineColor = "Orange", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries EMASlow { get; set; }

        [Output("EMA Trend", LineColor = "Green", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries EMATrend { get; set; }

        [Output("Stoploss Level", LineColor = "#FE0000", PlotType = PlotType.DiscontinuousLine, Thickness = 1)]
        public IndicatorDataSeries StoplossLevel { get; set; }

        [Output("Takeprofit Level", LineColor = "#01FF01", PlotType = PlotType.DiscontinuousLine, Thickness = 1)]
        public IndicatorDataSeries TakeProfitLevel { get; set; }

        protected override void Initialize()
        {
            // Initialize and create nested indicators
            _emaFast = Indicators.ExponentialMovingAverage(Source, EmaPeriodsFast);
            _emaSlow = Indicators.ExponentialMovingAverage(Source, EmaPeriodsSlow);
            _emaTrend = Indicators.ExponentialMovingAverage(Source, EmaPeriodsTrend);
        }

        public override void Calculate(int index)
        {
            try
            {
                // Set textcolor based on selected theme
                if (this.Application.ColorTheme == ColorTheme.Dark)
                    _textcolor = Color.FromHex("#E3D5EC");
                else if (this.Application.ColorTheme == ColorTheme.Light)
                    _textcolor = Color.Black;

                // Clear all visuals
                ClearAllVisuals();

                // Calculate ema results
                _emaFast.Calculate(index);
                _emaSlow.Calculate(index);
                _emaTrend.Calculate(index);

                // Save calculated results
                EMAFast[index] = _emaFast.Result[index];
                EMASlow[index] = _emaSlow.Result[index];
                EMATrend[index] = _emaTrend.Result[index];

                // Determine if we need to check for bullish or bearish setup
                int? bearishSetupIndex = FindBearishSetupIndex(index);
                int? bullishSetupIndex = FindBullishSetupIndex(index);

                if (bearishSetupIndex != null && bullishSetupIndex != null)
                {
                    // Find most recent bullish setup
                    if (bullishSetupIndex.Value > bearishSetupIndex.Value)
                        FindLastBullishSetup(index);
                    else
                        FindLastBearishSetup(index);
                }
            } catch (Exception ex)
            {
                Print("There was an exception in the EMA3 indicator: {0}", ex.Message);
            }
        }

        private void ClearAllVisuals()
        {
            // Clear all drawings
            Chart.DrawText("ema3_trade", "", 0, 0, _textcolor);
            Chart.DrawText("ema3_swingHighLowIndex", "", 0, 0, _textcolor);
            Chart.DrawTrendLine("ema3_longPosition", 0, 0, 0, 0, _textcolor);
            Chart.DrawText("ema3_trade_pips", "", 0, 0, _textcolor);
            Chart.DrawText("ema3_tp", "", 0, 0, _textcolor);
            Chart.DrawText("ema3_sl", "", 0, 0, _textcolor);
            Chart.DrawTrendLine("ema3_swing_highlow", 0, 0, 0, 0, _textcolor);

            // Clear all visualized data series
            for (int i = 0; i < Bars.Count; i++)
            {
                StoplossLevel[i] = double.NaN;
                TakeProfitLevel[i] = double.NaN;
            }
        }

        private int? FindBearishSetupIndex(int index)
        {
            for (int i = index; i > 0; i--)
            {
                // Test if EMA's are aligned in the same direction in order of 9, 21 55
                if ((_emaFast.Result[i - 1] > _emaSlow.Result[i - 1] || _emaSlow.Result[i - 1] > _emaTrend.Result[i - 1]) && _emaFast.Result[i] < _emaSlow.Result[i] && _emaSlow.Result[i] < _emaTrend.Result[i])
                    return i;
            }
            return null;
        }

        private int? FindBullishSetupIndex(int index)
        {
            for (int i = index; i > 0; i--)
            {
                // Test if EMA's are aligned in the same direction in order of 9, 21 55
                if ((_emaFast.Result[i - 1] < _emaSlow.Result[i - 1] || _emaSlow.Result[i - 1] < _emaTrend.Result[i - 1]) && _emaFast.Result[i] > _emaSlow.Result[i] && _emaSlow.Result[i] > _emaTrend.Result[i])
                    return i;
            }
            return null;
        }

        private void FindLastBearishSetup(int index)
        {
            Chart.DrawText("ema3_trade", "", index, Bars[index].Low, _textcolor);

            double? waitForPriceLevelBreak = null;
            int? swingLowIndex = null;
            int emaAlignedIndex = index;
            int? bullFractalIndex = null;

            for (; emaAlignedIndex > 0; emaAlignedIndex--)
            {
                // Test if EMA's are aligned in the same direction in order of 9, 21 55
                if ((_emaFast.Result[emaAlignedIndex - 1] > _emaSlow.Result[emaAlignedIndex - 1] || _emaSlow.Result[emaAlignedIndex - 1] > _emaTrend.Result[emaAlignedIndex - 1]) && _emaFast.Result[emaAlignedIndex] < _emaSlow.Result[emaAlignedIndex] && _emaSlow.Result[emaAlignedIndex] < _emaTrend.Result[emaAlignedIndex])
                {
                    // Chart.DrawIcon("EMAsAligned", ChartIconType.DownArrow, emaAlignedIndex, Bars[emaAlignedIndex].Low, Color.Yellow);

                    // Find the last swing low
                    double swingLowLevel = (Bars[emaAlignedIndex].Low + Bars[emaAlignedIndex].High) / 2;
                    swingLowIndex = FindLastSwingLow(swingLowLevel, emaAlignedIndex);
                    if (swingLowIndex != null)
                    {
                        waitForPriceLevelBreak = Bars[swingLowIndex.Value].Low;
                        Chart.DrawText("ema3_swingHighLowIndex", "SL (WAITING FOR TREND CONFIRMATION)", swingLowIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
                        Chart.DrawTrendLine("ema3_swing_highlow", swingLowIndex.Value, waitForPriceLevelBreak.Value, emaAlignedIndex, waitForPriceLevelBreak.Value, _textcolor);

                        break;
                    }
                }
            }

            if (waitForPriceLevelBreak != null)
            {
                double stoplossLevel = 0;
                double takeProfitLevel = 0;

                int? positionOpenIndex = null;
                for (int i = emaAlignedIndex; i <= index; i++)
                {
                    Chart.DrawTrendLine("ema3_swing_highlow", swingLowIndex.Value, waitForPriceLevelBreak.Value, i, waitForPriceLevelBreak.Value, _textcolor);
                    if (Bars[i].Close <= waitForPriceLevelBreak.Value)
                    {
                        bullFractalIndex = FindLastBullFractal(i);
                        if (bullFractalIndex != null)
                        {
                            stoplossLevel = Bars[bullFractalIndex.Value].High + (5 * Symbol.PipSize);
                            takeProfitLevel = Bars[i].Close - Math.Abs(Bars[bullFractalIndex.Value].High - Bars[i].Close);
                            positionOpenIndex = i;

                            // SHORT
                            Chart.DrawText("ema3_swingHighLowIndex", "SL (TREND CONFIRMED)", swingLowIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
                            Chart.DrawText("ema3_trade", "SHORT", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Low, _textcolor);
                        }
                        break;
                    }
                }

                if (positionOpenIndex != null)
                {
                    for (int i = positionOpenIndex.Value; i <= index; i++)
                    {
                        double pips = 0;
                        double trendlineEndPrice = 0;
                        if (Bars[i].Low > takeProfitLevel && Bars[i].High < stoplossLevel)
                        {
                            pips = (Bars[positionOpenIndex.Value].Close - Bars[i].Close) / Symbol.PipSize;
                            trendlineEndPrice = Bars[i].Close;

                            UpdateBearPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
                        }
                        else
                        {
                            if (Bars[i].Low <= takeProfitLevel)
                            {
                                pips = (Bars[positionOpenIndex.Value].Close - takeProfitLevel) / Symbol.PipSize;
                                trendlineEndPrice = takeProfitLevel;
                            }
                            else if (Bars[i].High >= stoplossLevel)
                            {
                                pips = (Bars[positionOpenIndex.Value].Close - stoplossLevel) / Symbol.PipSize;
                                trendlineEndPrice = stoplossLevel;
                            }

                            UpdateBearPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
                            break;
                        }
                    }
                }
            }
        }

        private void FindLastBullishSetup(int index)
        {
            Chart.DrawText("ema3_trade", "", index, Bars[index].High, _textcolor);

            double? waitForPriceLevelBreak = null;
            int? swingHighIndex = null;
            int emaAlignedIndex = index;
            int? bearFractalIndex = null;

            for (; emaAlignedIndex > 0; emaAlignedIndex--)
            {
                // Test if EMA's are aligned in the same direction in order of 9, 21 55
                if ((_emaFast.Result[emaAlignedIndex - 1] < _emaSlow.Result[emaAlignedIndex - 1] || _emaSlow.Result[emaAlignedIndex - 1] < _emaTrend.Result[emaAlignedIndex - 1]) && _emaFast.Result[emaAlignedIndex] > _emaSlow.Result[emaAlignedIndex] && _emaSlow.Result[emaAlignedIndex] > _emaTrend.Result[emaAlignedIndex])
                {
                    // Chart.DrawIcon("EMAsAligned", ChartIconType.DownArrow, emaAlignedIndex, Bars[emaAlignedIndex].High * 1.0008, Color.Blue);

                    // Find the last swing high
                    double swingHighLevel = (Bars[emaAlignedIndex].Low + Bars[emaAlignedIndex].High) / 2;
                    swingHighIndex = FindLastSwingHigh(swingHighLevel, emaAlignedIndex);
                    if (swingHighIndex != null)
                    {
                        waitForPriceLevelBreak = Bars[swingHighIndex.Value].High;
                        Chart.DrawText("ema3_swingHighLowIndex", "SH (WAITING FOR TREND CONFIRMATION)", swingHighIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
                        Chart.DrawTrendLine("ema3_swing_highlow", swingHighIndex.Value, waitForPriceLevelBreak.Value, emaAlignedIndex, waitForPriceLevelBreak.Value, _textcolor);

                        break;
                    }
                }
            }

            if (waitForPriceLevelBreak != null)
            {
                double stoplossLevel = 0;
                double takeProfitLevel = 0;

                int? positionOpenIndex = null;
                for (int i = emaAlignedIndex; i <= index; i++)
                {
                    Chart.DrawTrendLine("ema3_swing_highlow", swingHighIndex.Value, waitForPriceLevelBreak.Value, i, waitForPriceLevelBreak.Value, _textcolor);

                    if (Bars[i].Close >= waitForPriceLevelBreak.Value)
                    {
                        bearFractalIndex = FindLastBearFractal(i);
                        if (bearFractalIndex != null)
                        {
                            stoplossLevel = Bars[bearFractalIndex.Value].Low - (5 * Symbol.PipSize);
                            takeProfitLevel = Bars[i].Close + Math.Abs(Bars[i].Close - Bars[bearFractalIndex.Value].Low);
                            positionOpenIndex = i;

                            // LONG
                            Chart.DrawText("ema3_swingHighLowIndex", "SH (TREND CONFIRMED)", swingHighIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
                            Chart.DrawText("ema3_trade", "LONG", positionOpenIndex.Value, Bars[positionOpenIndex.Value].High, _textcolor);
                        }
                        break;
                    }
                }

                if (positionOpenIndex != null)
                {
                    for (int i = positionOpenIndex.Value; i <= index; i++)
                    {
                        double pips = 0;
                        double trendlineEndPrice = 0;
                        if (Bars[i].High < takeProfitLevel && Bars[i].Low > stoplossLevel)
                        {
                            pips = (Bars[i].Close - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
                            trendlineEndPrice = Bars[i].Close;

                            UpdateBullPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
                        }
                        else
                        {
                            if (Bars[i].High >= takeProfitLevel)
                            {
                                pips = (takeProfitLevel - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
                                trendlineEndPrice = takeProfitLevel;
                            }
                            else if (Bars[i].Low <= stoplossLevel)
                            {
                                pips = (stoplossLevel - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
                                trendlineEndPrice = stoplossLevel;
                            }

                            UpdateBullPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
                            break;
                        }
                    }
                }
            }
        }

        private void UpdateBearPositionVisuals(int? bullFractalIndex, double stoplossLevel, double takeProfitLevel, int? positionOpenIndex, int trendlineEndIndex, double pips, double trendlineEndPrice)
        {
            Chart.DrawTrendLine("ema3_longPosition", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Close, trendlineEndIndex, trendlineEndPrice, _textcolor);
            Chart.DrawText("ema3_trade_pips", pips.ToString("N1") + " PIPS" + (trendlineEndIndex < Bars.Count - 1 ? "\r\nCLOSED" : ""), trendlineEndIndex, trendlineEndPrice, _textcolor);

            Chart.DrawText("ema3_tp", "TP", bullFractalIndex.Value, takeProfitLevel, Color.FromHex("#01FF01"));
            Chart.DrawText("ema3_sl", "SL", bullFractalIndex.Value, stoplossLevel, Color.FromHex("#FE0000"));

            for (int j = 0; j <= trendlineEndIndex; j++)
                StoplossLevel[j] = double.NaN;

            for (int j = bullFractalIndex.Value; j <= trendlineEndIndex; j++)
                StoplossLevel[j] = stoplossLevel;

            for (int j = 0; j <= trendlineEndIndex; j++)
                TakeProfitLevel[j] = double.NaN;

            for (int j = bullFractalIndex.Value; j <= trendlineEndIndex; j++)
                TakeProfitLevel[j] = takeProfitLevel;
        }

        private void UpdateBullPositionVisuals(int? bearFractalIndex, double stoplossLevel, double takeProfitLevel, int? positionOpenIndex, int trendlineEndIndex, double pips, double trendlineEndPrice)
        {
            Chart.DrawTrendLine("ema3_longPosition", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Close, trendlineEndIndex, trendlineEndPrice, _textcolor);
            Chart.DrawText("ema3_trade_pips", pips.ToString("N1") + " PIPS" + (trendlineEndIndex < Bars.Count - 1 ? "\r\nCLOSED" : ""), trendlineEndIndex, trendlineEndPrice, _textcolor);

            Chart.DrawText("ema3_tp", "TP", bearFractalIndex.Value, takeProfitLevel, Color.FromHex("#01FF01"));
            Chart.DrawText("ema3_sl", "SL", bearFractalIndex.Value, stoplossLevel, Color.FromHex("#FE0000"));

            for (int j = 0; j <= trendlineEndIndex; j++)
                StoplossLevel[j] = double.NaN;

            for (int j = bearFractalIndex.Value; j <= trendlineEndIndex; j++)
                StoplossLevel[j] = stoplossLevel;

            for (int j = 0; j <= trendlineEndIndex; j++)
                TakeProfitLevel[j] = double.NaN;

            for (int j = bearFractalIndex.Value; j <= trendlineEndIndex; j++)
                TakeProfitLevel[j] = takeProfitLevel;
        }

        private int? FindLastSwingLow(double swingLowLevel, int startIndex)
        {
            // Find the start of the current swing
            int startOfCurrentSwing = startIndex;
            for (; startOfCurrentSwing >= 0; startOfCurrentSwing--)
            {
                if (Bars[startOfCurrentSwing].High > _emaFast.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].High > _emaSlow.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].High > _emaTrend.Result[startOfCurrentSwing])
                    break;
            }
            // Chart.DrawIcon("StartOfCurrentSwingIndex", ChartIconType.DownArrow, startOfCurrentSwing, Bars[startOfCurrentSwing].High * 1.0008, Color.Magenta);

            // Find the previous candle that touches the swinghigh level
            int previousSwing = startOfCurrentSwing;
            for (; previousSwing >= 0; previousSwing--)
            {
                if (Bars[previousSwing].High >= swingLowLevel && Bars[previousSwing].Low <= swingLowLevel)
                {
                    break;
                }
            }
            //Chart.DrawIcon("StartOfPreviousSwingIndex", ChartIconType.DownArrow, previousSwing, Bars[previousSwing].High * 1.0008, Color.Yellow);

            // Find the last bull fractal (=SH). The found previousSwing index will very often be the SH itself, so set the offset to 2, so that this SH can be found
            return FindLastBearFractal(Math.Min(previousSwing + 2, Bars.Count - 1));
        }

        private int? FindLastSwingHigh(double swingHighLevel, int startIndex)
        {
            // Find the start of the current swing
            int startOfCurrentSwing = startIndex;
            for (; startOfCurrentSwing >= 0; startOfCurrentSwing--)
            {
                if (Bars[startOfCurrentSwing].Low < _emaFast.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].Low < _emaSlow.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].Low < _emaTrend.Result[startOfCurrentSwing])
                    break;
            }
            // Chart.DrawIcon("StartOfCurrentSwingIndex", ChartIconType.DownArrow, startOfCurrentSwing, Bars[startOfCurrentSwing].High * 1.0008, Color.Magenta);

            // Find the previous candle that touches the swinghigh level
            int previousSwing = startOfCurrentSwing;
            for (; previousSwing >= 0; previousSwing--)
            {
                if (Bars[previousSwing].Low <= swingHighLevel && Bars[previousSwing].High >= swingHighLevel)
                {
                    break;
                }
            }
            //Chart.DrawIcon("StartOfPreviousSwingIndex", ChartIconType.DownArrow, previousSwing, Bars[previousSwing].High * 1.0008, Color.Yellow);

            // Find the last bull fractal (=SH). The found previousSwing index will very often be the SH itself, so set the offset to 2, so that this SH can be found
            return FindLastBullFractal(Math.Min(previousSwing + 2, Bars.Count - 1));
        }

        private int? FindLastBearFractal(int startIndex)
        {
            for (int i = startIndex; i >= 4; i--)
            {
                if (this.Bars[i].Low > this.Bars[i - 2].Low && this.Bars[i - 1].Low > this.Bars[i - 2].Low && this.Bars[i - 3].Low > this.Bars[i - 2].Low && this.Bars[i - 4].Low > this.Bars[i - 2].Low)

                    return i - 2;
            }

            return null;
        }

        private int? FindLastBullFractal(int startIndex)
        {
            for (int i = startIndex; i >= 4; i--)
            {
                if (this.Bars[i].High < this.Bars[i - 2].High && this.Bars[i - 1].High < this.Bars[i - 2].High && this.Bars[i - 3].High < this.Bars[i - 2].High && this.Bars[i - 4].High < this.Bars[i - 2].High)

                    return i - 2;
            }

            return null;
        }
    }
}
Comments
0