Maximum Levels

namespace ATAS.Indicators.Technical
{
    using System;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Drawing;

    using ATAS.Indicators.Properties;

    using OFT.Rendering.Context;
    using OFT.Rendering.Tools;

    using Utils.Common.Attributes;
    using Utils.Common.Localization;

    [DisplayName("Maximum Levels")]
    [Category("Clusters, Profiles, Levels")]
    public class MaxLevels : Indicator
    {
        #region Nested types

        public enum MaxLevelType
        {
            Bid,

            Ask,

            PositiveDelta,

            NegativeDelta,

            Volume,

            Tick,

            Time
        };

        #endregion

        #region Private

        private RenderStringFormat _stringRightFormat = new RenderStringFormat
        {
            Alignment = StringAlignment.Far,
            LineAlignment = StringAlignment.Center,
            Trimming = StringTrimming.EllipsisCharacter,
            FormatFlags = StringFormatFlags.NoWrap
        };

        private bool _candleRequested;
        private IndicatorCandle _candle;
        private Color _lineColor = System.Drawing.Color.CornflowerBlue;
        private Color _axisTextColor = System.Drawing.Color.White;
        private Color _textColor = System.Drawing.Color.Black;
        private RenderPen _renderPen = new RenderPen(System.Drawing.Color.CornflowerBlue, 2);
        private int _width = 2;
        private FixedProfilePeriods _period = FixedProfilePeriods.CurrentDay;
        private RenderFont _font = new RenderFont("Arial", 8);
        private string _description = "Current Day";

        #endregion

        #region Properties

        public FixedProfilePeriods Period
        {
            get => _period;
            set
            {
                _period = value;
                _description = GetPeriodDescription(_period);
                RecalculateValues();
            }
        }

        
        public MaxLevelType Type { get; set; } = MaxLevelType.Volume;

        public System.Windows.Media.Color Color
        {
            get => _lineColor.Convert();
            set
            {
                _lineColor = value.Convert();
                _renderPen = new RenderPen(_lineColor, _width);
            }
        }

        public int Width
        {
            get => _width;
            set
            {
                _width = Math.Max(1, value);
                _renderPen = new RenderPen(_lineColor, _width);
            }
        }

        public System.Windows.Media.Color AxisTextColor
        {
            get => _axisTextColor.Convert();
            set => _axisTextColor = value.Convert();
        }

        public bool ShowText { get; set; } = true;

        public System.Windows.Media.Color TextColor
        {
            get => _textColor.Convert();
            set => _textColor = value.Convert();
        }

        public int FontSize
        {
            get => (int)_font.Size;
            set => _font = new RenderFont("Arial", Math.Max(7, value));
        }

        #endregion

        public MaxLevels()
            : base(true)
        {
            DataSeries[0].IsHidden = true;
            DenyToChangePanel = true;
            EnableCustomDrawing = true;
            SubscribeToDrawingEvents(DrawingLayouts.LatestBar);
            DrawAbovePrice = true;
            Width = Width;
        }

        #region Overrides of BaseIndicator

        protected override void OnCalculate(int bar, decimal value)
        {
            if (bar == 0)
                _candleRequested = false;

            if (!_candleRequested && bar == CurrentBar - 1)
            {
                _candleRequested = true;
                GetFixedProfile(new FixedProfileRequest(Period));
            }
        }

        protected override void OnFixedProfilesResponse(IndicatorCandle fixedProfile, FixedProfilePeriods period)
        {
            _candle = fixedProfile;
            RedrawChart();
        }

        protected override void OnRender(RenderContext context, DrawingLayouts layout)
        {
            if (_candle == null)
                return;

            var priceInfo = GetPriceVolumeInfo(_candle, Type);

            if (priceInfo == null)
                return;

            var y = ChartInfo.GetYByPrice(priceInfo.Price);
            var firstX = ChartInfo.PriceChartContainer.Region.Width / 2;
            var secondX = ChartInfo.PriceChartContainer.Region.Width;

            context.DrawLine(_renderPen, firstX, y, secondX, y);

            if (ShowText)
            {
                var size = context.MeasureString(_description, _font);
                var textRect = new Rectangle(new Point(ChartInfo.PriceChartContainer.Region.Width - (int)size.Width - 20, y - (int)size.Height - Width / 2),
                                             new Size((int)size.Width + 20, (int)size.Height));
                context.DrawString(_description, _font, _textColor, textRect, _stringRightFormat);
            }

            this.DrawLabelOnPriceAxis(context, string.Format(ChartInfo.StringFormat, priceInfo.Price), y, _font, _lineColor, _axisTextColor);
        }

        #endregion

        private string GetPeriodDescription(FixedProfilePeriods period)
        {
            switch (period)
            {
                case FixedProfilePeriods.CurrentDay:
                    return "Current Day";
                case FixedProfilePeriods.LastDay:
                    return "Last Day";
                case FixedProfilePeriods.CurrentWeek:
                    return "Current Week";
                case FixedProfilePeriods.LastWeek:
                    return "Last Week";
                case FixedProfilePeriods.CurrentMonth:
                    return "Current Month";
                case FixedProfilePeriods.LastMonth:
                    return "Last Month";
                case FixedProfilePeriods.Contract:
                    return "Contract";
                default:
                    throw new ArgumentOutOfRangeException(nameof(period), period, null);
            }
        }

        private PriceVolumeInfo GetPriceVolumeInfo(IndicatorCandle candle, MaxLevelType levelType)
        {
            switch (Type)
            {
                case MaxLevelType.Bid:
                {
                    return _candle.MaxBidPriceInfo;
                }
                case MaxLevelType.Ask:
                {
                    return _candle.MaxAskPriceInfo;
                }
                case MaxLevelType.PositiveDelta:
                {
                    return _candle.MaxPositiveDeltaPriceInfo;
                }
                case MaxLevelType.NegativeDelta:
                {
                    return _candle.MaxNegativeDeltaPriceInfo;
                }
                case MaxLevelType.Volume:
                {
                    return _candle.MaxVolumePriceInfo;
                }
                case MaxLevelType.Tick:
                {
                    return _candle.MaxTickPriceInfo;
                }
                case MaxLevelType.Time:
                {
                    return _candle.MaxTimePriceInfo;
                }
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}

Is this article helpful for you?