Transform Indicator to Bot

Created at 11 Nov 2020, 14:39
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!
LA

lazaromg

Joined 11.11.2020

Transform Indicator to Bot
11 Nov 2020, 14:39


Hi, 

I am a great layman in programming and would like to help transform this wonderful indicator into a robot.
To automatically open orders, you have control over the size of the orders you are going to execute, trailing stop and time control for work.
Could anyone help with this transformation? Thanks!

This is the code:

 

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;
        }
    }
}


@lazaromg