Overlaying indicator on lower panel(s)

Created at 30 Sep 2023, 23:18
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!
PG

pgrant71

Joined 10.09.2023

Overlaying indicator on lower panel(s)
30 Sep 2023, 23:18


Hi,

I have a market hours indicator that displays fine when plotting on a chart using Chart.DrawTrendLine, Chart.DrawText, and [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]:



But I cannot get it to display/overlay on a lower panel like this similar indicator:



What is the best approach to achieve this please?


@pgrant71
Replies

PanagiotisChar
02 Oct 2023, 06:06 ( Updated at: 02 Oct 2023, 06:09 )

Hi there,

You need to draw your lines in the IndicatorArea instead.


@PanagiotisChar

pgrant71
03 Oct 2023, 00:56 ( Updated at: 03 Oct 2023, 05:25 )

RE: Overlaying indicator on lower panel(s)

PanagiotisChar said: 

Hi there,

You need to draw your lines in the IndicatorArea instead.

Thank you.

I tried that and the lines just disappear whether I put the indicator on the Chart or a lower panel:

Old
Chart.DrawTrendLine(objNameSydney  + "_Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );

New
IndicatorArea.DrawTrendLine(objNameSydney  + " Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );

Any other thoughts?


@pgrant71

PanagiotisChar
03 Oct 2023, 05:46 ( Updated at: 03 Oct 2023, 10:59 )

Can you share the complete indicator code?


@PanagiotisChar

pgrant71
03 Oct 2023, 21:29

RE: Overlaying indicator on lower panel(s)

PanagiotisChar said: 

Can you share the complete indicator code?

using cAlgo.API;
using System;
using System.Globalization;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    
    public class TradingTimePeriods : Indicator
    {
        private readonly string _name = "MarketHours";

        private TimeSpan _startTimeSydney , _endTimeSydney ;
        private TimeSpan _startTimeTokyo  , _endTimeTokyo  ;
        private TimeSpan _startTimeLondon , _endTimeLondon ;
        private TimeSpan _startTimeNewYork, _endTimeNewYork;

        private bool _isLinesPlotted;
        
        

        [Parameter("Start Local Time", DefaultValue = "07:00", Group = "Sydney")]
        public string StartTimeSydney { get; set; }

        [Parameter("End Local Time", DefaultValue = "16:00", Group = "Sydney")]
        public string EndTimeSydney { get; set; }

        [Parameter("Color", DefaultValue = "FF008000", Group = "Sydney")]
        public Color ColorSydney { get; set; }

        [Parameter("Transparency", DefaultValue = 50, MaxValue = 255, MinValue = 0, Group = "Sydney")]
        public int TransparencySydney { get; set; }

        [Parameter("Thickness", DefaultValue = 3, Group = "Sydney")]
        public int LinesThicknessSydney { get; set; }

        [Parameter("Style", DefaultValue = LineStyle.Dots, Group = "Sydney")]
        public LineStyle LinesStyleSydney { get; set; }



        [Parameter("Start Local Time", DefaultValue = "10:00", Group = "Tokyo")]
        public string StartTimeTokyo { get; set; }

        [Parameter("End Local Time", DefaultValue = "19:00", Group = "Tokyo")]
        public string EndTimeTokyo { get; set; }

        [Parameter("Color", DefaultValue = "FF0070C0", Group = "Tokyo")]
        public Color ColorTokyo { get; set; }

        [Parameter("Transparency", DefaultValue = 50, MaxValue = 255, MinValue = 0, Group = "Tokyo")]
        public int TransparencyTokyo { get; set; }

        [Parameter("Thickness", DefaultValue = 3, Group = "Tokyo")]
        public int LinesThicknessTokyo { get; set; }

        [Parameter("Style", DefaultValue = LineStyle.Dots, Group = "Tokyo")]
        public LineStyle LinesStyleTokyo { get; set; }



        [Parameter("Start Local Time", DefaultValue = "17:00", Group = "London")]
        public string StartTimeLondon { get; set; }

        [Parameter("End Local Time", DefaultValue = "2:00", Group = "London")]
        public string EndTimeLondon { get; set; }

        [Parameter("Color", DefaultValue = "FFB3B3B3", Group = "London")]
        public Color ColorLondon { get; set; }

        [Parameter("Transparency", DefaultValue = 50, MaxValue = 255, MinValue = 0, Group = "London")]
        public int TransparencyLondon { get; set; }

        [Parameter("Thickness", DefaultValue = 3, Group = "London")]
        public int LinesThicknessLondon { get; set; }

        [Parameter("Style", DefaultValue = LineStyle.Dots, Group = "London")]
        public LineStyle LinesStyleLondon { get; set; }



        [Parameter("Start Local Time", DefaultValue = "22:00", Group = "New York")]
        public string StartTimeNewYork { get; set; }

        [Parameter("End Local Time", DefaultValue = "7:00", Group = "New York")]
        public string EndTimeNewYork { get; set; }

        [Parameter("Color", DefaultValue = "FFFF3334", Group = "New York")]
        public Color ColorNewYork { get; set; }

        [Parameter("Transparency", DefaultValue = 50, MaxValue = 255, MinValue = 0, Group = "New York")]
        public int TransparencyNewYork { get; set; }

        [Parameter("Thickness", DefaultValue = 3, Group = "New York")]
        public int LinesThicknessNewYork { get; set; }

        [Parameter("Style", DefaultValue = LineStyle.Dots, Group = "New York")]
        public LineStyle LinesStyleNewYork { get; set; }



        protected override void Initialize()
        {
            // Ensure the time formats are valid (HH:mm)
            if (!IsValidTimeFormat(StartTimeSydney ) || !IsValidTimeFormat(EndTimeSydney ) ||
                !IsValidTimeFormat(StartTimeTokyo  ) || !IsValidTimeFormat(EndTimeTokyo  ) ||
                !IsValidTimeFormat(StartTimeLondon ) || !IsValidTimeFormat(EndTimeLondon ) ||
                !IsValidTimeFormat(StartTimeNewYork) || !IsValidTimeFormat(EndTimeNewYork))
            {
                Print("Invalid time format. Please use HH:mm format.");
                return;
            }
            
            Chart.SizeChanged += Chart_SizeChanged;
            
            ParseTimes();

            Application.UserTimeOffsetChanged += Application_UserTimeOffsetChanged;
        }



        private void Chart_SizeChanged(ChartSizeEventArgs obj)
        {
            _isLinesPlotted = false;
        }
        
        
        
        public override void Calculate(int index)
        {
            if (!IsLastBar || _isLinesPlotted) return;

            _isLinesPlotted = true;

            // Y position
            double topY     = Math.Round(Chart.TopY   , Symbol.Digits);
            double bottomY  = Math.Round(Chart.BottomY, Symbol.Digits);
            // double topY     = IndicatorArea.TopY   ;
            // double bottomY  = IndicatorArea.BottomY;
            
            double ySydney  = bottomY + (topY - bottomY) / 5 * 4;
            double yTokyo   = bottomY + (topY - bottomY) / 5 * 3;
            double yLondon  = bottomY + (topY - bottomY) / 5 * 2;
            double yNewYork = bottomY + (topY - bottomY) / 5 * 1;

            TimeSpan t = new TimeSpan(1, 0, 0, 0);
            if (_endTimeSydney < _startTimeSydney)
                _endTimeSydney += t;
            if (_endTimeTokyo < _startTimeTokyo)
                _endTimeTokyo += t;
            if (_endTimeLondon < _startTimeLondon)
                _endTimeLondon += t;
            if (_endTimeNewYork < _startTimeNewYork)
                _endTimeNewYork += t;
            
            for (DateTime currentTime = Bars.OpenTimes[0].Date; currentTime <= Bars.Last(0).OpenTime.Date.AddDays(1); currentTime = currentTime.AddDays(1))
            {
                if (currentTime.DayOfWeek == DayOfWeek.Saturday || currentTime.DayOfWeek == DayOfWeek.Sunday) continue;
            
                string objNameSydney  = string.Format("{0}_{1}_{2:yyyyMMdd}", _name, "Sydney" , currentTime);
                string objNameTokyo   = string.Format("{0}_{1}_{2:yyyyMMdd}", _name, "Tokyo"  , currentTime);
                string objNameLondon  = string.Format("{0}_{1}_{2:yyyyMMdd}", _name, "London" , currentTime);
                string objNameNewYork = string.Format("{0}_{1}_{2:yyyyMMdd}", _name, "NewYork", currentTime);
                
                DateTime startTimeSydney  = currentTime.Add(_startTimeSydney );
                DateTime startTimeTokyo   = currentTime.Add(_startTimeTokyo  );
                DateTime startTimeLondon  = currentTime.Add(_startTimeLondon );
                DateTime startTimeNewYork = currentTime.Add(_startTimeNewYork);
                
                DateTime endTimeSydney  = currentTime.Add(_endTimeSydney );
                DateTime endTimeTokyo   = currentTime.Add(_endTimeTokyo  );
                DateTime endTimeLondon  = currentTime.Add(_endTimeLondon );
                DateTime endTimeNewYork = currentTime.Add(_endTimeNewYork);
                
                /*
                IndicatorArea.DrawTrendLine(objNameSydney  + "_Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );
                IndicatorArea.DrawTrendLine(objNameTokyo   + "_Line", startTimeTokyo  , yTokyo  , endTimeTokyo  , yTokyo  , ColorTokyo  , LinesThicknessTokyo  , LinesStyleTokyo  );
                IndicatorArea.DrawTrendLine(objNameLondon  + "_Line", startTimeLondon , yLondon , endTimeLondon , yLondon , ColorLondon , LinesThicknessLondon , LinesStyleLondon );
                IndicatorArea.DrawTrendLine(objNameNewYork + "_Line", startTimeNewYork, yNewYork, endTimeNewYork, yNewYork, ColorNewYork, LinesThicknessNewYork, LinesStyleNewYork);
                */

                Chart.DrawTrendLine(objNameSydney  + "_Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );
                Chart.DrawTrendLine(objNameTokyo   + "_Line", startTimeTokyo  , yTokyo  , endTimeTokyo  , yTokyo  , ColorTokyo  , LinesThicknessTokyo  , LinesStyleTokyo  );
                Chart.DrawTrendLine(objNameLondon  + "_Line", startTimeLondon , yLondon , endTimeLondon , yLondon , ColorLondon , LinesThicknessLondon , LinesStyleLondon );
                Chart.DrawTrendLine(objNameNewYork + "_Line", startTimeNewYork, yNewYork, endTimeNewYork, yNewYork, ColorNewYork, LinesThicknessNewYork, LinesStyleNewYork);

                /*
                IndicatorArea.DrawText(objNameSydney  + "StartLabelSydney" , "Sydney" , startTimeSydney , ySydney , ColorSydney );
                IndicatorArea.DrawText(objNameTokyo   + "StartLabelTokyo"  , "Tokyo"  , startTimeTokyo  , yTokyo  , ColorTokyo  );
                IndicatorArea.DrawText(objNameLondon  + "StartLabelLondon" , "London" , startTimeLondon , yLondon , ColorLondon );
                IndicatorArea.DrawText(objNameNewYork + "StartLabelNewYork", "NewYork", startTimeNewYork, yNewYork, ColorNewYork);
                */

                Chart.DrawText(objNameSydney  + "_Label", "Sydney" , startTimeSydney , ySydney , ColorSydney );
                Chart.DrawText(objNameTokyo   + "_Label", "Tokyo"  , startTimeTokyo  , yTokyo  , ColorTokyo  );
                Chart.DrawText(objNameLondon  + "_Label", "London" , startTimeLondon , yLondon , ColorLondon );
                Chart.DrawText(objNameNewYork + "_Label", "NewYork", startTimeNewYork, yNewYork, ColorNewYork);
            }
        }
        
        
        
        private void Application_UserTimeOffsetChanged(UserTimeOffsetChangedEventArgs obj)
        {
            ParseTimes();

            _isLinesPlotted = false;
        }



        private void ParseTimes()
        {
            // Start times
            if (TimeSpan.TryParse(StartTimeSydney, CultureInfo.InvariantCulture, out _startTimeSydney))
                _startTimeSydney = _startTimeSydney.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(StartTimeTokyo, CultureInfo.InvariantCulture, out _startTimeTokyo))
                _startTimeTokyo = _startTimeTokyo.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(StartTimeLondon, CultureInfo.InvariantCulture, out _startTimeLondon))
                _startTimeLondon = _startTimeLondon.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(StartTimeNewYork, CultureInfo.InvariantCulture, out _startTimeNewYork))
                _startTimeNewYork = _startTimeNewYork.Add(-Application.UserTimeOffset);
                
            // End times
            if (TimeSpan.TryParse(EndTimeSydney, CultureInfo.InvariantCulture, out _endTimeSydney))
                _endTimeSydney = _endTimeSydney.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(EndTimeTokyo, CultureInfo.InvariantCulture, out _endTimeTokyo))
                _endTimeTokyo = _endTimeTokyo.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(EndTimeLondon, CultureInfo.InvariantCulture, out _endTimeLondon))
                _endTimeLondon = _endTimeLondon.Add(-Application.UserTimeOffset);

            if (TimeSpan.TryParse(EndTimeNewYork, CultureInfo.InvariantCulture, out _endTimeNewYork))
                _endTimeNewYork = _endTimeNewYork.Add(-Application.UserTimeOffset);
        }


        
        private bool IsValidTimeFormat(string time)
        {
            // Validate that the time string has the format HH:mm
            return System.Text.RegularExpressions.Regex.IsMatch(time, @"^([01]?[0-9]|2[0-3]):[0-5][0-9]$");
        }
        
        
        
    }
}
 

@pgrant71

PanagiotisChar
04 Oct 2023, 05:57 ( Updated at: 21 Dec 2023, 09:23 )

Here is an example of drawing one of the lines on the lower panel

                Chart.DrawTrendLine(objNameSydney  + "_Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );
               Chart.DrawTrendLine(objNameTokyo   + "_Line", startTimeTokyo  , yTokyo  , endTimeTokyo  , yTokyo  , ColorTokyo  , LinesThicknessTokyo  , LinesStyleTokyo  );
               Chart.DrawTrendLine(objNameLondon  + "_Line", startTimeLondon , yLondon , endTimeLondon , yLondon , ColorLondon , LinesThicknessLondon , LinesStyleLondon );
               Chart.DrawTrendLine(objNameNewYork + "_Line", startTimeNewYork, yNewYork, endTimeNewYork, yNewYork, ColorNewYork, LinesThicknessNewYork, LinesStyleNewYork);

               if (Chart.IndicatorAreas.Count > 0)
               {
                   foreach(var area in Chart.IndicatorAreas) 
                   {
                       double areaTopY = Math.Round(area.TopY, Symbol.Digits);
                       double areaBottomY = Math.Round(area.BottomY, Symbol.Digits);
                       double areaYSydney = areaBottomY + (areaTopY - areaBottomY) / 5 * 4;
                       area.DrawTrendLine(objNameSydney + "_Line", startTimeSydney, areaYSydney, endTimeSydney, areaYSydney, ColorSydney, LinesThicknessSydney, LinesStyleSydney);
                   }
               }

 


@PanagiotisChar

pgrant71
04 Oct 2023, 06:31 ( Updated at: 21 Dec 2023, 09:23 )

RE: Overlaying indicator on lower panel(s)

PanagiotisChar said: 

Here is an example of drawing one of the lines on the lower panel

                Chart.DrawTrendLine(objNameSydney  + "_Line", startTimeSydney , ySydney , endTimeSydney , ySydney , ColorSydney , LinesThicknessSydney , LinesStyleSydney );
               Chart.DrawTrendLine(objNameTokyo   + "_Line", startTimeTokyo  , yTokyo  , endTimeTokyo  , yTokyo  , ColorTokyo  , LinesThicknessTokyo  , LinesStyleTokyo  );
               Chart.DrawTrendLine(objNameLondon  + "_Line", startTimeLondon , yLondon , endTimeLondon , yLondon , ColorLondon , LinesThicknessLondon , LinesStyleLondon );
               Chart.DrawTrendLine(objNameNewYork + "_Line", startTimeNewYork, yNewYork, endTimeNewYork, yNewYork, ColorNewYork, LinesThicknessNewYork, LinesStyleNewYork);

               if (Chart.IndicatorAreas.Count > 0)
               {
                   foreach(var area in Chart.IndicatorAreas) 
                   {
                       double areaTopY = Math.Round(area.TopY, Symbol.Digits);
                       double areaBottomY = Math.Round(area.BottomY, Symbol.Digits);
                       double areaYSydney = areaBottomY + (areaTopY - areaBottomY) / 5 * 4;
                       area.DrawTrendLine(objNameSydney + "_Line", startTimeSydney, areaYSydney, endTimeSydney, areaYSydney, ColorSydney, LinesThicknessSydney, LinesStyleSydney);
                   }
               }

 

Thanks very much!

Is there way to access this property:

…to avoid this:

It should appear only in the panel selected but I can't find a way to determine which panel is selected.


@pgrant71

PanagiotisChar
05 Oct 2023, 06:01 ( Updated at: 05 Oct 2023, 06:09 )

Unfortunately there isn't such an option


@PanagiotisChar

pgrant71
05 Oct 2023, 08:19

RE: Overlaying indicator on lower panel(s)

PanagiotisChar said: 

Unfortunately there isn't such an option

Thank you again. So how is an indicator of the nature of this one placed on the selected panel only please?


@pgrant71

PanagiotisChar
06 Oct 2023, 05:37

I am not aware of any way to do this


@PanagiotisChar