Maximum Levels

Modified on Fri, 04 Aug 2023 at 01:55 PM

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

 

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select atleast one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article