Category Other  Published on 29/10/2019

Auto Drawings

Description

How to use:
1) Select bars using Ctrl + Mouse 
2) Choose desired drawing in selected area: fibonacci, min/max price level, or support/resistance trend line.

 

Algorhitm to place trend lines is pretty dumb. It simply draw a line between left and right extremums (when high or low exceed its neigbours).
If you know better ideas, please advice.

Please share your ideas, what to add to this indicator.


using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Collections.Generic;
using System.Linq;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class AutoDrawings : Indicator
    {
        [Parameter("Drawings Color", DefaultValue = "99DFF9")]
        public string DrawingsColor { get; set; }

        [Parameter("Selection Color", DefaultValue = "2F68D0F7")]
        public string SelectionleColor { get; set; }

        ChartRectangle SelectRectangle;
        int SelectedStartBarIndex;
        int SelectedEndBarIndex;
        decimal[] DefaultFiboLevels = new[] 
        {
            0.0m,
            23.6m,
            38.2m,
            50.0m,
            61.8m,
            100.0m
        };

        ControlBase DrawingDialog;

        protected override void Initialize()
        {
            Chart.MouseDown += Chart_MouseDown;
            Chart.MouseUp += Chart_MouseUp;
            Chart.MouseMove += Chart_MouseMove;

            CreateDrawingDialog();
        }

        private void CreateDrawingDialog()
        {
            var stackPanel = new StackPanel 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Left,
                Orientation = Orientation.Vertical,
                IsVisible = false,
                Width = 160,
                BackgroundColor = "#707070"
            };

            var fibonacciRetracementButton = new Button 
            {
                Text = "Fibonacci Retracement",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };

            var supportTrendLineButton = new Button 
            {
                Text = "Support Trend Line",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };

            var resistanceTrendLineButton = new Button 
            {
                Text = "Resistance Trend Line",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };

            var supportLevelButton = new Button 
            {
                Text = "Support Level",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };

            var resistanceLevelButton = new Button 
            {
                Text = "Resistance Level",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };

            fibonacciRetracementButton.Click += FibonacciRetracementButton_Click;
            supportTrendLineButton.Click += SupportTrendLineButton_Click;
            resistanceTrendLineButton.Click += ResistanceTrendLineButton_Click;
            supportLevelButton.Click += SupportLevelButton_Click;
            resistanceLevelButton.Click += ResistanceLevelButton_Click;

            stackPanel.AddChild(fibonacciRetracementButton);
            stackPanel.AddChild(supportTrendLineButton);
            stackPanel.AddChild(resistanceTrendLineButton);
            stackPanel.AddChild(supportLevelButton);
            stackPanel.AddChild(resistanceLevelButton);

            DrawingDialog = stackPanel;
            Chart.AddControl(DrawingDialog);
        }

        private void FibonacciRetracementButton_Click(ButtonClickEventArgs obj)
        {
            var extremums = GetHighLowInSelection();
            var name = string.Format("Fibonacci Retracement [Auto Drawing] {0}", DateTime.Now.ToString("dd.MM.yy HH:mm:ss.zzz"));
            var point1 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point1 : extremums.Point2;
            var point2 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point2 : extremums.Point1;
            var fibo = Chart.DrawFibonacciRetracement(name, point1.BarIndex, point1.Price, point2.BarIndex, point2.Price, DrawingsColor);
            fibo.IsInteractive = true;
            fibo.DisplayPrices = false;
            SetDefaultFiboLevels(fibo.FibonacciLevels);
            CloseDrawingDialog();
        }

        private void SetDefaultFiboLevels(IEnumerable<FibonacciLevel> levels)
        {
            foreach (var level in levels)
            {
                level.IsVisible = Array.IndexOf(DefaultFiboLevels, (decimal)level.PercentLevel) > -1;
            }
        }

        private void ResistanceTrendLineButton_Click(ButtonClickEventArgs obj)
        {
            var extremums = GetFirstLastHighExtremumsInSelection();
            var point1 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point1 : extremums.Point2;
            var point2 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point2 : extremums.Point1;
            var name = string.Format("Resistance Trend Line [Auto Drawing] {0}", DateTime.Now.ToString("dd.MM.yy HH:mm:ss.zzz"));
            var line = Chart.DrawTrendLine(name, point1.BarIndex, point1.Price, point2.BarIndex, point2.Price, DrawingsColor);
            line.IsInteractive = true;
            line.ExtendToInfinity = true;
            CloseDrawingDialog();
        }

        private void SupportTrendLineButton_Click(ButtonClickEventArgs obj)
        {
            var extremums = GetFirstLastLowExtremumsInSelection();
            var point1 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point1 : extremums.Point2;
            var point2 = extremums.Point1.BarIndex < extremums.Point2.BarIndex ? extremums.Point2 : extremums.Point1;
            var name = string.Format("Support Trend Line [Auto Drawing] {0}", DateTime.Now.ToString("dd.MM.yy HH:mm:ss.zzz"));
            var line = Chart.DrawTrendLine(name, point1.BarIndex, point1.Price, point2.BarIndex, point2.Price, DrawingsColor);
            line.IsInteractive = true;
            line.ExtendToInfinity = true;
            CloseDrawingDialog();
        }

        private void ResistanceLevelButton_Click(ButtonClickEventArgs obj)
        {
            var maximum = GetMaximumInSelection();
            var name = string.Format("Resistance Level [Auto Drawing] {0}", DateTime.Now.ToString("dd.MM.yy HH:mm:ss.zzz"));
            var line = Chart.DrawHorizontalLine(name, maximum.Price, DrawingsColor);
            line.IsInteractive = true;
            CloseDrawingDialog();
        }

        private void SupportLevelButton_Click(ButtonClickEventArgs obj)
        {
            var minimum = GetMinimumInSelection();
            var name = string.Format("Support Level [Auto Drawing] {0}", DateTime.Now.ToString("dd.MM.yy HH:mm:ss.zzz"));
            var line = Chart.DrawHorizontalLine(name, minimum.Price, DrawingsColor);
            line.IsInteractive = true;
            CloseDrawingDialog();
        }

        private ChartPoint GetMaximumInSelection()
        {
            var priceMax = double.MinValue;
            int barIndexMax = -1;
            for (int i = SelectedStartBarIndex; i <= SelectedEndBarIndex; i++)
            {
                var high = MarketSeries.High[i];
                if (high > priceMax)
                {
                    priceMax = high;
                    barIndexMax = i;
                }
            }
            return new ChartPoint(barIndexMax, priceMax);
        }

        private ChartPoint GetMinimumInSelection()
        {
            var priceMin = double.MaxValue;
            int barIndexMin = -1;
            for (int i = SelectedStartBarIndex; i <= SelectedEndBarIndex; i++)
            {
                var low = MarketSeries.Low[i];
                if (low < priceMin)
                {
                    priceMin = low;
                    barIndexMin = i;
                }
            }
            return new ChartPoint(barIndexMin, priceMin);
        }

        private ChartPoints GetHighLowInSelection()
        {
            var priceMax = double.MinValue;
            var priceMin = double.MaxValue;
            int barIndexMin = -1;
            int barIndexMax = -1;
            for (int i = SelectedStartBarIndex; i <= SelectedEndBarIndex; i++)
            {
                var high = MarketSeries.High[i];
                var low = MarketSeries.Low[i];
                if (high > priceMax)
                {
                    priceMax = high;
                    barIndexMax = i;
                }
                if (low < priceMin)
                {
                    priceMin = low;
                    barIndexMin = i;
                }
            }

            var maximum = new ChartPoint(barIndexMax, priceMax);
            var minimum = new ChartPoint(barIndexMin, priceMin);
            return new ChartPoints(minimum, maximum);
        }

        private ChartPoints GetFirstLastHighExtremumsInSelection()
        {
            var highExtremums = new List<ChartPoint>();
            for (int i = SelectedStartBarIndex; i <= SelectedEndBarIndex; i++)
            {
                bool isExtremum = false;
                var currHigh = MarketSeries.High[i];

                if (i == 0 || i == MarketSeries.Close.Count - 1)
                {
                    isExtremum = true;
                }
                else
                {
                    var nextHigh = MarketSeries.High[i + 1];
                    var prevHigh = MarketSeries.High[i - 1];
                    isExtremum = currHigh > nextHigh && currHigh > prevHigh;
                }

                if (isExtremum)
                    highExtremums.Add(new ChartPoint(i, currHigh));
            }
            if (highExtremums.Count < 2)
                return null;

            return new ChartPoints(highExtremums.First(), highExtremums.Last());
        }

        private ChartPoints GetFirstLastLowExtremumsInSelection()
        {
            var lowExtremums = new List<ChartPoint>();
            for (int i = SelectedStartBarIndex; i <= SelectedEndBarIndex; i++)
            {
                bool isExtremum = false;
                var currLow = MarketSeries.Low[i];

                if (i == 0 || i == MarketSeries.Close.Count - 1)
                {
                    isExtremum = true;
                }
                else
                {
                    var nextLow = MarketSeries.Low[i + 1];
                    var prevLow = MarketSeries.Low[i - 1];
                    isExtremum = currLow < nextLow && currLow < prevLow;
                }

                if (isExtremum)
                    lowExtremums.Add(new ChartPoint(i, currLow));
            }
            if (lowExtremums.Count < 2)
                return null;

            return new ChartPoints(lowExtremums.First(), lowExtremums.Last());

        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            if (SelectRectangle == null)
                return;

            SelectRectangle.Time2 = obj.TimeValue;
        }

        private void Chart_MouseDown(ChartMouseEventArgs obj)
        {
            if (DrawingDialog.IsVisible)
            {
                CloseDrawingDialog();
            }

            if (obj.CtrlKey == false)
                return;

            Chart.IsScrollingEnabled = false;
            SelectRectangle = CreateDragRectangle(obj.TimeValue);
        }

        private void Chart_MouseUp(ChartMouseEventArgs obj)
        {
            Chart.IsScrollingEnabled = true;

            if (SelectRectangle != null)
            {
                SetSelectedStartEndIndex(SelectRectangle);
                Chart.RemoveObject(SelectRectangle.Name);
                SelectRectangle = null;

                if (SelectedStartBarIndex >= 0 && SelectedEndBarIndex >= 0)
                {
                    OpenDrawingDialog(obj.MouseX, obj.MouseY);
                }
            }
        }

        private void SetSelectedStartEndIndex(ChartRectangle rectangle)
        {
            var index1 = MarketSeries.OpenTime.GetIndexByTime(rectangle.Time1);
            var index2 = MarketSeries.OpenTime.GetIndexByTime(rectangle.Time2);
            SelectedStartBarIndex = Math.Min(index1, index2);
            SelectedEndBarIndex = Math.Max(index1, index2);
        }

        private void OpenDrawingDialog(double mouseX, double mouseY)
        {
            DrawingDialog.IsVisible = true;
            var left = Chart.Width - mouseX > 160 ? mouseX : mouseX - 160;
            var right = Chart.Height - mouseY > 100 ? mouseY : mouseY - 100;
            DrawingDialog.Margin = new Thickness(left, right, 0, 0);

        }

        private void CloseDrawingDialog()
        {
            DrawingDialog.IsVisible = false;
        }

        private ChartRectangle CreateDragRectangle(DateTime time)
        {
            var rect = Chart.DrawRectangle("DragRectangle", time, Chart.TopY, time, Chart.BottomY, SelectionleColor);
            rect.IsFilled = true;
            return rect;
        }

        public override void Calculate(int index)
        {
        }
    }

    class ChartPoint
    {
        public ChartPoint(int barIndex, double price)
        {
            BarIndex = barIndex;
            Price = price;
        }

        public int BarIndex { get; private set; }
        public double Price { get; private set; }
    }

    class ChartPoints
    {
        public ChartPoints(ChartPoint point1, ChartPoint point2)
        {
            Point1 = point1;
            Point2 = point2;
        }

        public ChartPoint Point1 { get; private set; }
        public ChartPoint Point2 { get; private set; }
    }
}


bart1's avatar
bart1

Joined on 03.08.2017

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Auto Drawings.algo
  • Rating: 5
  • Installs: 3955
Comments
Log in to add a comment.
TI
Timoor · 8 months ago

Thank you, good, nice and fast, but needs an update

HG
hgrams · 2 years ago

Very cooooollll!

would it be possible to choose the fibo level that will be drawn at the top or bottom to use as a target?

Very thanks!

NE
newbee · 2 years ago

Hello, any chance you can add fib levels -27.2%, -61.8% & -161.8% please?

 

XE
xeulav · 3 years ago

could you please contact me on telegram (username: xeulav) ?

thanks !

CT
ctid471531 · 3 years ago

Hi .Could you add another option to draw rectangle something like Rectangle Extender?

JE
JeffMouller · 4 years ago

hi dear

i now use your product.

its very well.

please insert all fibos - shapes - price channel - pitchfork .

please insert api for color setting.

goodluck.

FA
farzadmontazer · 4 years ago

It's great but I have a problem with Fib Levels. Is it possible to change Fib Levels to optional values?

YU
yuri · 4 years ago

This is super cool!

bart1's avatar
bart1 · 4 years ago

Probably your broker has cTrader version 3.5. This indicator use custom UI from  the new version 3.6.

You can try it with Spotware cTrader
https://spotware.com/beta/

massimiliano.quarti's avatar
massimiliano.quarti · 4 years ago

Not working for me, ctrl mouse is scrolling.

Which libraries are referenced?