High Low

//------------------------------------------------------------------------------
//
// Indicator HighLow. Copyright (c) 2023 Tiger Trade Capital AG. All rights reserved.
//
//------------------------------------------------------------------------------
 
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Base.Enums;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Indicators.Drawings;
using TigerTrade.Chart.Indicators.Enums;
using TigerTrade.Core.Utils.Time;
using TigerTrade.Dx.Enums;
 
namespace TigerTrade.Chart.Indicators.Custom
{
    [DataContract(Name = "HighLowIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("Z_HighLow", "*HighLow", true, Type = typeof(HighLowIndicator))]
    internal sealed class HighLowIndicator : IndicatorBase
    {
        private IndicatorPeriodType _period;
 
        [DataMember(Name = "Period")]
        [Category("Параметры"), DisplayName("Период")]
        public IndicatorPeriodType Period
        {
            get => _period;
            set
            {
                if (value == _period)
                {
                    return;
                }
 
                _period = value;
 
                OnPropertyChanged();
            }
        }
 
        private ChartLine _highLowSeries;
 
        [DataMember(Name = "HighLow")]
        [Category("Графики"), DisplayName("High/Low")]
        public ChartLine HighLowSeries
        {
            get => _highLowSeries ?? (_highLowSeries = new ChartLine());
            private set
            {
                if (Equals(value, _highLowSeries))
                {
                    return;
                }
 
                _highLowSeries = value;
 
                OnPropertyChanged();
            }
        }
 
        private ChartLine _medianSeries;
 
        [DataMember(Name = "Median")]
        [Category("Графики"), DisplayName("Median")]
        public ChartLine MedianSeries
        {
            get => _medianSeries ?? (_medianSeries = new ChartLine());
            private set
            {
                if (Equals(value, _medianSeries))
                {
                    return;
                }
 
                _medianSeries = value;
 
                OnPropertyChanged();
            }
        }
 
        private ChartLine _prevMedianSeries;
 
        [DataMember(Name = "PrevMedian")]
        [Category("Графики"), DisplayName("PrevMedian")]
        public ChartLine PrevMedianSeries
        {
            get => _prevMedianSeries ?? (_prevMedianSeries = new ChartLine
            {
                Style = XDashStyle.Dash
            });
            private set
            {
                if (Equals(value, _prevMedianSeries))
                {
                    return;
                }
 
                _prevMedianSeries = value;
 
                OnPropertyChanged();
            }
        }
 
        [Browsable(false)]
        public override IndicatorCalculation DefaultCalculation => IndicatorCalculation.OnBarClose;
 
        public HighLowIndicator()
        {
            Period = IndicatorPeriodType.Day;
        }
 
        protected override void Execute()
        {
            var date = Helper.Date;
            var high = Helper.High;
            var low = Helper.Low;
 
            var highData = new double[date.Length];
            var lowData = new double[date.Length];
            var medianData = new double[date.Length];
            var prevMedianData = new double[date.Length];
 
            var splits = new bool[date.Length];
 
            var lastSequence = -1;
 
            var highValue = 0.0;
            var lowValue = 0.0;
 
            var prevMedian = double.NaN;
 
            var timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
 
            for (var i = 0; i < date.Length; i++)
            {
                var sequence = 1;
 
                switch (Period)
                {
                    case IndicatorPeriodType.Day:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Day, 1, date[i], timeOffset);
 
                        break;
 
                    case IndicatorPeriodType.Week:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Week, 1, date[i], timeOffset);
 
                        break;
 
                    case IndicatorPeriodType.Month:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Month, 1, date[i], timeOffset);
 
                        break;
                }
 
                if (sequence != lastSequence)
                {
                    lastSequence = sequence;
 
                    highValue = high[i];
                    lowValue = low[i];
 
                    if (i > 0 && medianData.Length > i)
                    {
                        prevMedian = medianData[i - 1];
                    }
 
                    splits[i] = true;
                }
 
                highValue = Math.Max(highValue, high[i]);
                lowValue = Math.Min(lowValue, low[i]);
 
                highData[i] = highValue;
                lowData[i] = lowValue;
 
                medianData[i] = (highValue + lowValue) / 2.0;
                prevMedianData[i] = prevMedian;
            }
 
            Series.Add(new IndicatorSeriesData(prevMedianData, PrevMedianSeries)
            {
                Style =
                {
                    DisableMinMax = true,
                    StraightLine = true
                },
 
            }, new IndicatorSeriesData(highData, HighLowSeries)
            {
                Style =
                {
                    DisableMinMax = true,
                    StraightLine = true
                }
            }, new IndicatorSeriesData(lowData, HighLowSeries)
            {
                Style =
                {
                    DisableMinMax = true,
                    StraightLine = true
                }
            }, new IndicatorSeriesData(medianData, MedianSeries)
            {
                Style =
                {
                    DisableMinMax = true,
                    StraightLine = true
                }
            });
 
            foreach (var series in Series)
            {
                series.UserData["S"] = splits;
                series.UserData["SE"] = true;
            }
        }
 
        public override void ApplyColors(IChartTheme theme)
        {
            HighLowSeries.Color = theme.GetNextColor();
            MedianSeries.Color = theme.GetNextColor();
            PrevMedianSeries.Color = theme.GetNextColor();
 
            base.ApplyColors(theme);
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (HighLowIndicator)indicator;
 
            Period = i.Period;
 
            HighLowSeries.CopyTheme(i.HighLowSeries);
            MedianSeries.CopyTheme(i.MedianSeries);
            PrevMedianSeries.CopyTheme(i.PrevMedianSeries);
 
            base.CopyTemplate(indicator, style);
        }
 
        public override string ToString()
        {
            return $"{Name} ({Period})";
        }
    }
}

Last updated