Feature Request - Fibonacci Setting: "Extend to Infinity"

Created at 21 Feb 2024, 19:34
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!
BO

Bourbaba

Joined 27.12.2022

Feature Request - Fibonacci Setting: "Extend to Infinity"
21 Feb 2024, 19:34


Dear cTrader Developer Team,

I hope this message finds you well. I am writing to express my appreciation for the excellent trading platform you provide and to suggest an enhancement that I believe could significantly benefit users like myself.

I have been using the Fibonacci tool extensively on cTrader, and it has proven to be an invaluable asset in my technical analysis. However, I have often found myself wishing for a feature that would enhance the functionality of the Fibonacci tool even further.

Specifically, I would like to propose the addition of a new setting called "Extend to Infinity" in the Fibonacci tool. This feature would allow users to extend Fibonacci retracement and extension levels indefinitely to the right, providing a more comprehensive view of potential support and resistance zones.

The ability to extend Fibonacci levels beyond the current chart boundaries would greatly assist traders in identifying key price levels that may come into play in the future. This feature would be particularly beneficial for long-term traders and investors who rely on Fibonacci analysis for strategic decision-making.

I understand that development decisions are complex, and resources may be allocated based on various factors. However, I wanted to share this suggestion with you as I believe it aligns with cTrader's commitment to providing a cutting-edge and user-friendly trading experience.

Thank you for considering my request. I look forward to any updates on this matter and appreciate the continuous efforts of the cTrader team in making the platform even more robust.

Best regards,

[Bourbaba]


@Bourbaba
Replies

PanagiotisCharalampous
22 Feb 2024, 07:51

Hi Bourbara,

Thank you for your encouraging feedback. Feel free to post your suggestion in the correct section

https://ctrader.com/forum/suggestions

Best regards,

Panagiotis

 


@PanagiotisCharalampous

RJM1
24 Feb 2024, 05:56 ( Updated at: 24 Feb 2024, 05:58 )

Hello,

Maybe this will help you, press ctrl, click and drag your mouse to select the area you want. The indicator will then choose the highest high and lowest low in your selection area and produce a Fib Retracement. If you want to reset, press ctrl and click and you will see the option to Reset Fib. Because it is an indicator, it's a visual overlay and you will not be able to click the Fib as you normally would after drawing it, and it will vanish if you change timeframes. 

I added 500 candles back and forward, hopefully this will assist you. 

—> Copy the script below into a new indicator, then load the indicator like any other.

 

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 = "Black")]
        public string DrawingsColor { get; set; }

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

        ChartRectangle SelectRectangle;
        int SelectedStartBarIndex;
        int SelectedEndBarIndex;
        List<double> DefaultFiboLevels = new List<double> 
        {
            -23.6,
            0.0,
            23.6,
            38.0,
            50.0,
            61.8,
            78.6,
            100,
            123.6
        };


        ControlBase DrawingDialog;
        List<string> drawnFibObjects = new List<string>();


        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 resetButton = new Button 
            {
                Text = "Reset Fibonacci",
                HorizontalContentAlignment = HorizontalAlignment.Left
            };
            resetButton.Click += ResetButton_Click;
            stackPanel.AddChild(resetButton);

            fibonacciRetracementButton.Click += FibonacciRetracementButton_Click;


            stackPanel.AddChild(fibonacciRetracementButton);


            DrawingDialog = stackPanel;
            Chart.AddControl(DrawingDialog);
        }
         private void ResetButton_Click(ButtonClickEventArgs obj)
        {
            foreach (var objectName in drawnFibObjects)
            {
                Chart.RemoveObject(objectName);
            }
            drawnFibObjects.Clear();
        }

        private void FibonacciRetracementButton_Click(ButtonClickEventArgs obj)
        {
            var extremums = GetHighLowInSelection();
            var name = $"Fibonacci Retracement [Auto Drawing] {DateTime.Now: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;
        
            double distance = Math.Abs(point2.Price - point1.Price);
        
            // Extend lines far to the left and right
            int extendToLeftBarIndex = 0;
            int extendToRightBarIndex = Bars.ClosePrices.Count + 500; 
        
            bool isLowToHigh = point1.Price < point2.Price;
        
            foreach (var lev in DefaultFiboLevels)
            {
                double dev;
                if (isLowToHigh)
                {
                    dev = point1.Price + (1 - lev / 100) * distance;
                }
                else
                {
                    dev = point2.Price + lev / 100 * distance;
                }
                
                var lineName = name + lev + "%";
                var textName = name + lev + "% text";
                
                // Adjust the drawing to extend left and right
                var line = Chart.DrawTrendLine(lineName, extendToLeftBarIndex, dev, extendToRightBarIndex, dev, DrawingsColor);
                line.LineStyle = LineStyle.Dots;
                
                // Optionally, adjust label positions if needed
                Chart.DrawText(textName, lev + "%", point2.BarIndex + 10, dev, DrawingsColor);
                
                drawnFibObjects.Add(lineName);
                drawnFibObjects.Add(textName);
            }
            
            CloseDrawingDialog();
        }

        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 = Bars.HighPrices[i];
                var low = Bars.LowPrices[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 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 = Bars.OpenTimes.GetIndexByTime(rectangle.Time1);
            var index2 = Bars.OpenTimes.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; }
    }
}


@RJM1