# Trades

```
//------------------------------------------------------------------------------
//
// Индикатор Trades. Copyright (c) 2023 Tiger Trade Capital AG. All rights reserved.
//
//------------------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Media;
using TigerTrade.Chart.Alerts;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Indicators.Enums;
using TigerTrade.Dx;
 
namespace TigerTrade.Chart.Indicators.Custom
{
    [DataContract(Name = "TradesIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("X_Trades", "*Trades", false, Type = typeof(TradesIndicator))]
    internal sealed class TradesIndicator : IndicatorBase
    {
        private XBrush _upBackBrush;
 
        private XPen _upBackPen;
 
        private XColor _upBackColor;
 
        [DataMember(Name = "UpColor")]
        [Category("Стиль"), DisplayName("Цвет при росте")]
        public XColor UpColor
        {
            get => _upBackColor;
            set
            {
                if (value == _upBackColor)
                {
                    return;
                }
 
                _upBackColor = value;
 
                _upBackBrush = new XBrush(_upBackColor);
                _upBackPen = new XPen(_upBackBrush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _downBackBrush;
 
        private XPen _downBackPen;
 
        private XColor _downBackColor;
 
        [DataMember(Name = "DownColor")]
        [Category("Стиль"), DisplayName("Цвет при падении")]
        public XColor DownColor
        {
            get => _downBackColor;
            set
            {
                if (value == _downBackColor)
                {
                    return;
                }
 
                _downBackColor = value;
 
                _downBackBrush = new XBrush(_downBackColor);
                _downBackPen = new XPen(_downBackBrush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private bool _deltaColored;
 
        [DataMember(Name = "DeltaColored")]
        [Category("Параметры"), DisplayName("Раскраска по дельте")]
        public bool DeltaColored
        {
            get => _deltaColored;
            set
            {
                if (value == _deltaColored)
                {
                    return;
                }
 
                _deltaColored = value;
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _maxTradesParam;
 
        [DataMember(Name = "MaxTradesParam")]
        public IndicatorNullIntParam MaxTradesParam
        {
            get => _maxTradesParam ?? (_maxTradesParam = new IndicatorNullIntParam(null));
            set => _maxTradesParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Параметры"), DisplayName("Макс. значение")]
        public int? MaxTrades
        {
            get => MaxTradesParam.Get(SettingsLongKey);
            set
            {
                if (!MaxTradesParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter1MinParam;
 
        [DataMember(Name = "Filter1MinParam")]
        public IndicatorNullIntParam Filter1MinParam
        {
            get => _filter1MinParam ?? (_filter1MinParam = new IndicatorNullIntParam(null));
            set => _filter1MinParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 1"), DisplayName("Минимум")]
        public int? Filter1Min
        {
            get => Filter1MinParam.Get(SettingsLongKey);
            set
            {
                if (!Filter1MinParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter1MaxParam;
 
        [DataMember(Name = "Filter1MaxParam")]
        public IndicatorNullIntParam Filter1MaxParam
        {
            get => _filter1MaxParam ?? (_filter1MaxParam = new IndicatorNullIntParam(null));
            set => _filter1MaxParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 1"), DisplayName("Максимум")]
        public int? Filter1Max
        {
            get => Filter1MaxParam.Get(SettingsLongKey);
            set
            {
                if (!Filter1MaxParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _filter1Brush;
 
        private XPen _filter1Pen;
 
        private XColor _filter1Color;
 
        [DataMember(Name = "Filter1Color")]
        [Category("Фильтр 1"), DisplayName("Цвет")]
        public XColor Filter1Color
        {
            get => _filter1Color;
            set
            {
                if (value == _filter1Color)
                {
                    return;
                }
 
                _filter1Color = value;
 
                _filter1Brush = new XBrush(_filter1Color);
                _filter1Pen = new XPen(_filter1Brush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private ChartAlertSettings _filter1Alert;
 
        [DataMember(Name = "Filter1Alert")]
        [Category("Фильтр 1"), DisplayName("Оповещение")]
        public ChartAlertSettings Filter1Alert
        {
            get => _filter1Alert ?? (_filter1Alert = new ChartAlertSettings());
            set
            {
                if (Equals(value, _filter1Alert))
                {
                    return;
                }
 
                _filter1Alert = value;
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter2MinParam;
 
        [DataMember(Name = "Filter2MinParam")]
        public IndicatorNullIntParam Filter2MinParam
        {
            get => _filter2MinParam ?? (_filter2MinParam = new IndicatorNullIntParam(null));
            set => _filter2MinParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 2"), DisplayName("Минимум")]
        public int? Filter2Min
        {
            get => Filter2MinParam.Get(SettingsLongKey);
            set
            {
                if (!Filter2MinParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter2MaxParam;
 
        [DataMember(Name = "Filter2MaxParam")]
        public IndicatorNullIntParam Filter2MaxParam
        {
            get => _filter2MaxParam ?? (_filter2MaxParam = new IndicatorNullIntParam(null));
            set => _filter2MaxParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 2"), DisplayName("Максимум")]
        public int? Filter2Max
        {
            get => Filter2MaxParam.Get(SettingsLongKey);
            set
            {
                if (!Filter2MaxParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _filter2Brush;
 
        private XPen _filter2Pen;
 
        private XColor _filter2Color;
 
        [DataMember(Name = "Filter2Color")]
        [Category("Фильтр 2"), DisplayName("Цвет")]
        public XColor Filter2Color
        {
            get => _filter2Color;
            set
            {
                if (value == _filter2Color)
                {
                    return;
                }
 
                _filter2Color = value;
 
                _filter2Brush = new XBrush(_filter2Color);
                _filter2Pen = new XPen(_filter2Brush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private ChartAlertSettings _filter2Alert;
 
        [DataMember(Name = "Filter2Alert")]
        [Category("Фильтр 2"), DisplayName("Оповещение")]
        public ChartAlertSettings Filter2Alert
        {
            get => _filter2Alert ?? (_filter2Alert = new ChartAlertSettings());
            set
            {
                if (Equals(value, _filter2Alert))
                {
                    return;
                }
 
                _filter2Alert = value;
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter3MinParam;
 
        [DataMember(Name = "Filter3MinParam")]
        public IndicatorNullIntParam Filter3MinParam
        {
            get => _filter3MinParam ?? (_filter3MinParam = new IndicatorNullIntParam(null));
            set => _filter3MinParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 3"), DisplayName("Минимум")]
        public int? Filter3Min
        {
            get => Filter3MinParam.Get(SettingsLongKey);
            set
            {
                if (!Filter3MinParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _filter3MaxParam;
 
        [DataMember(Name = "Filter3MaxParam")]
        public IndicatorNullIntParam Filter3MaxParam
        {
            get => _filter3MaxParam ?? (_filter3MaxParam = new IndicatorNullIntParam(null));
            set => _filter3MaxParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Фильтр 3"), DisplayName("Максимум")]
        public int? Filter3Max
        {
            get => Filter3MaxParam.Get(SettingsLongKey);
            set
            {
                if (!Filter3MaxParam.Set(SettingsLongKey, value, 0))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _filter3Brush;
 
        private XPen _filter3Pen;
 
        private XColor _filter3Color;
 
        [DataMember(Name = "Filter3Color")]
        [Category("Фильтр 3"), DisplayName("Цвет")]
        public XColor Filter3Color
        {
            get => _filter3Color;
            set
            {
                if (value == _filter3Color)
                {
                    return;
                }
 
                _filter3Color = value;
 
                _filter3Brush = new XBrush(_filter3Color);
                _filter3Pen = new XPen(_filter3Brush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private ChartAlertSettings _filter3Alert;
 
        [DataMember(Name = "Filter3Alert")]
        [Category("Фильтр 3"), DisplayName("Оповещение")]
        public ChartAlertSettings Filter3Alert
        {
            get => _filter3Alert ?? (_filter3Alert = new ChartAlertSettings());
            set
            {
                if (Equals(value, _filter3Alert))
                {
                    return;
                }
 
                _filter3Alert = value;
 
                OnPropertyChanged();
            }
        }
 
        [Browsable(false)]
        public override IndicatorCalculation Calculation => IndicatorCalculation.OnEachTick;
 
        public override bool IntegerValues => true;
 
        private int _filter1SignalIndex;
        private int _filter2SignalIndex;
        private int _filter3SignalIndex;
 
        private double _max;
 
        public TradesIndicator()
        {
            UpColor = Color.FromArgb(255, 30, 144, 255);
            DownColor = Color.FromArgb(255, 178, 34, 34);
 
            DeltaColored = false;
 
            Filter1Color = Colors.Orange;
            Filter2Color = Colors.Orange;
            Filter3Color = Colors.Orange;
 
            _filter1SignalIndex = -1;
            _filter2SignalIndex = -1;
            _filter3SignalIndex = -1;
        }
 
        protected override void Execute()
        {
            if (ClearData)
            {
                _filter1SignalIndex = -1;
                _filter2SignalIndex = -1;
                _filter3SignalIndex = -1;
            }
 
            var index = DataProvider.Count;
 
            var cluster = DataProvider.GetCluster(index - 1);
 
            if (cluster == null)
            {
                return;
            }
 
            var trades = cluster.Trades;
 
            if (Filter1Alert.IsActive && _filter1SignalIndex < index)
            {
                var min = Filter1Min ?? -1;
                var max = Filter1Max ?? -1;
 
                if (min >= 0 && trades >= min && (max < 0 || trades <= max))
                {
                    _filter1SignalIndex = index;
 
                    AddAlert(Filter1Alert,
                        $"Trades: фильтр 1, значение {DataProvider.Symbol.FormatTrades(trades)}.");
                }
            }
 
            if (Filter2Alert.IsActive && _filter2SignalIndex < index)
            {
                var min = Filter2Min ?? -1;
                var max = Filter2Max ?? -1;
 
                if (min >= 0 && trades >= min && (max < 0 || trades <= max))
                {
                    _filter2SignalIndex = index;
 
                    AddAlert(Filter2Alert,
                        $"Trades: фильтр 2, значение {DataProvider.Symbol.FormatTrades(trades)}.");
                }
            }
 
            if (Filter3Alert.IsActive && _filter3SignalIndex < index)
            {
                var min = Filter3Min ?? -1;
                var max = Filter3Max ?? -1;
 
                if (min >= 0 && trades >= min && (max < 0 || trades <= max))
                {
                    _filter3SignalIndex = index;
 
                    AddAlert(Filter3Alert,
                        $"Trades: фильтр 3, значение {DataProvider.Symbol.FormatTrades(trades)}.");
                }
            }
        }
 
        public override bool GetMinMax(out double min, out double max)
        {
            min = 0.0;
            max = 0.0;
 
            if (Canvas.IsStock)
            {
                return false;
            }
 
            for (var i = 0; i < Canvas.Count; i++)
            {
                var index = Canvas.GetIndex(i);
 
                var cluster = DataProvider.GetCluster(index);
 
                if (cluster == null)
                {
                    continue;
                }
 
                var trades = (double)cluster.Trades;
 
                if (max < trades)
                {
                    max = trades;
                }
            }
 
            var maxTrades = MaxTrades ?? -1;
 
            if (maxTrades >= 0 && max > maxTrades)
            {
                max = maxTrades;
            }
 
            return true;
        }
 
        private double GetMax()
        {
            var max = 0.0;
 
            for (var i = 0; i < Canvas.Count; i++)
            {
                var index = Canvas.GetIndex(i);
 
                var cluster = DataProvider.GetCluster(index);
 
                if (cluster == null)
                {
                    continue;
                }
 
                var trades = (double)cluster.Trades;
 
                if (max < trades)
                {
                    max = trades;
                }
            }
 
            var maxTrades = MaxTrades ?? -1;
 
            if (maxTrades >= 0 && max > maxTrades)
            {
                max = maxTrades;
            }
 
            return max;
        }
 
        public override void Render(DxVisualQueue visual)
        {
            if (Canvas.IsStock)
            {
                RenderOnMain(visual);
 
                return;
            }
 
            var min1 = Filter1Min ?? -1;
            var max1 = Filter1Max ?? -1;
            var min2 = Filter2Min ?? -1;
            var max2 = Filter2Max ?? -1;
            var min3 = Filter3Min ?? -1;
            var max3 = Filter3Max ?? -1;
 
            var maxTrades = MaxTrades ?? -1;
            var maxPoint = GetY((double)maxTrades);
 
            var zeroPoint = GetY(0.0);
 
            var width = Math.Max(Canvas.ColumnWidth - 1, 1);
 
            for (var i = 0; i < Canvas.Count; i++)
            {
                var index = Canvas.GetIndex(i);
 
                var cluster = DataProvider.GetCluster(index);
 
                if (cluster == null)
                {
                    continue;
                }
 
                var x = Canvas.GetX(index);
                var y = GetY((double)cluster.Trades);
 
                if (maxTrades >= 0)
                {
                    y = Math.Max(y, maxPoint);
                }
 
                var h = (int)zeroPoint - (int)y;
 
                if (h < 0)
                {
                    continue;
                }
 
                if (h < 1)
                {
                    y = (int)zeroPoint - 1;
                    h = 1;
                }
 
                var isUp = DeltaColored ? cluster.Delta > 0 : cluster.IsUp;
 
                XBrush filterBrush = null;
                XPen filterPen = null;
 
                if (min1 >= 0 && cluster.Trades >= min1 && (max1 < 0 || cluster.Trades <= max1))
                {
                    filterBrush = _filter1Brush;
                    filterPen = _filter1Pen;
                }
                else if (min2 >= 0 && cluster.Trades >= min2 && (max2 < 0 || cluster.Trades <= max2))
                {
                    filterBrush = _filter2Brush;
                    filterPen = _filter2Pen;
                }
                else if (min3 >= 0 && cluster.Trades >= min3 && (max3 < 0 || cluster.Trades <= max3))
                {
                    filterBrush = _filter3Brush;
                    filterPen = _filter3Pen;
                }
 
                if (width > 1)
                {
                    if (filterBrush != null)
                    {
                        visual.FillRectangle(filterBrush, new Rect(x - width / 2.0, y, width, h));
                    }
                    else
                    {
                        visual.FillRectangle(isUp
                            ? _upBackBrush
                            : _downBackBrush, new Rect(x - width / 2.0, y, width, h));
                    }
                }
                else
                {
                    if (filterPen != null)
                    {
                        visual.DrawLine(filterPen, new Point(x, y), new Point(x, y + h));
                    }
                    else
                    {
                        visual.DrawLine(isUp
                            ? _upBackPen
                            : _downBackPen, new Point(x, y), new Point(x, y + h));
                    }
                }
            }
        }
 
        public void RenderOnMain(DxVisualQueue visual)
        {
            var min1 = Filter1Min ?? -1;
            var max1 = Filter1Max ?? -1;
            var min2 = Filter2Min ?? -1;
            var max2 = Filter2Max ?? -1;
            var min3 = Filter3Min ?? -1;
            var max3 = Filter3Max ?? -1;
 
            var maxTrades = MaxTrades ?? -1;
 
            var height = Canvas.Rect.Height * 0.2;
            var minPoint = Canvas.Rect.Bottom - 2;
            var maxPoint = minPoint - height;
 
            var width = Math.Max(Canvas.ColumnWidth - 1, 1);
 
            _max = GetMax();
 
            for (var i = 0; i < Canvas.Count; i++)
            {
                var index = Canvas.GetIndex(i);
 
                var cluster = DataProvider.GetCluster(index);
 
                if (cluster == null)
                {
                    continue;
                }
 
                var x = Canvas.GetX(index);
                var y = minPoint - height * cluster.Trades / _max;
 
                if (maxTrades >= 0)
                {
                    y = Math.Max(y, maxPoint);
                }
 
                var h = (int)minPoint - (int)y;
 
                if (h < 0)
                {
                    continue;
                }
 
                var isUp = DeltaColored ? cluster.Delta > 0 : cluster.IsUp;
 
                XBrush filterBrush = null;
                XPen filterPen = null;
 
                if (min1 >= 0 && cluster.Trades >= min1 && (max1 < 0 || cluster.Trades <= max1))
                {
                    filterBrush = _filter1Brush;
                    filterPen = _filter1Pen;
                }
                else if (min2 >= 0 && cluster.Trades >= min2 && (max2 < 0 || cluster.Trades <= max2))
                {
                    filterBrush = _filter2Brush;
                    filterPen = _filter2Pen;
                }
                else if (min3 >= 0 && cluster.Trades >= min3 && (max3 < 0 || cluster.Trades <= max3))
                {
                    filterBrush = _filter3Brush;
                    filterPen = _filter3Pen;
                }
 
                if (width > 1)
                {
                    if (filterBrush != null)
                    {
                        visual.FillRectangle(filterBrush, new Rect(x - width / 2.0, y, width, h));
                    }
                    else
                    {
                        visual.FillRectangle(isUp
                            ? _upBackBrush
                            : _downBackBrush, new Rect(x - width / 2.0, y, width, h));
                    }
                }
                else
                {
                    if (filterPen != null)
                    {
                        visual.DrawLine(filterPen, new Point(x, y), new Point(x, y + h));
                    }
                    else
                    {
                        visual.DrawLine(isUp
                            ? _upBackPen
                            : _downBackPen, new Point(x, y), new Point(x, y + h));
                    }
                }
            }
        }
 
        public override List<IndicatorValueInfo> GetValues(int cursorPos)
        {
            var info = new List<IndicatorValueInfo>();
 
            var cluster = DataProvider.GetCluster(cursorPos);
 
            if (cluster == null)
            {
                return info;
            }
 
            var s = Canvas.FormatValue((double)cluster.Trades);
 
            if (Canvas.IsStock)
            {
                s = DataProvider.Symbol.FormatSizeShort(cluster.Trades);
            }
 
            info.Add(new IndicatorValueInfo(s,
                new XBrush(cluster.IsUp ? _upBackColor : _downBackColor)));
 
            return info;
        }
 
        public override void GetLabels(ref List<IndicatorLabelInfo> labels)
        {
            if (DataProvider.Count <= Canvas.Start)
            {
                return;
            }
 
            var cluster = DataProvider.GetCluster(DataProvider.Count - 1 - Canvas.Start);
 
            if (cluster == null)
            {
                return;
            }
 
            double? position = null;
 
            if (Canvas.IsStock)
            {
                position = Canvas.Rect.Bottom -
                           Canvas.Rect.Height * 0.2 * cluster.Trades / _max;
            }
 
            labels.Add(new IndicatorLabelInfo(cluster.Trades,
                cluster.IsUp ? _upBackColor : _downBackColor, position));
        }
 
        public override bool CheckAlert(double value, int distance, ref int lastIndex, ref double lastValue)
        {
            if (Canvas.IsStock)
            {
                return false;
            }
 
            if (DataProvider.Count == lastIndex && value == lastValue)
            {
                return false;
            }
 
            var cluster = DataProvider.GetCluster(DataProvider.Count - 1);
 
            if (cluster == null)
            {
                return false;
            }
 
            if (cluster.Trades < value - distance)
            {
                return false;
            }
 
            lastIndex = DataProvider.Count;
            lastValue = value;
 
            return true;
        }
 
        public override void ApplyColors(IChartTheme theme)
        {
            UpColor = theme.PaletteColor6;
            DownColor = theme.PaletteColor7;
 
            base.ApplyColors(theme);
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (TradesIndicator)indicator;
 
            UpColor = i.UpColor;
            DownColor = i.DownColor;
 
            DeltaColored = i.DeltaColored;
 
            MaxTradesParam.Copy(i.MaxTradesParam);
 
            Filter1MinParam.Copy(i.Filter1MinParam);
            Filter1MaxParam.Copy(i.Filter1MaxParam);
 
            OnPropertyChanged(nameof(Filter1Min));
            OnPropertyChanged(nameof(Filter1Max));
 
            Filter1Color = i.Filter1Color;
 
            Filter1Alert.Copy(i.Filter1Alert, !style);
 
            OnPropertyChanged(nameof(Filter1Alert));
 
            Filter2MinParam.Copy(i.Filter2MinParam);
            Filter2MaxParam.Copy(i.Filter2MaxParam);
 
            OnPropertyChanged(nameof(Filter2Min));
            OnPropertyChanged(nameof(Filter2Max));
 
            Filter2Color = i.Filter2Color;
 
            Filter2Alert.Copy(i.Filter2Alert, !style);
 
            OnPropertyChanged(nameof(Filter2Alert));
 
            Filter3MinParam.Copy(i.Filter3MinParam);
            Filter3MaxParam.Copy(i.Filter3MaxParam);
 
            OnPropertyChanged(nameof(Filter3Min));
            OnPropertyChanged(nameof(Filter3Max));
 
            Filter3Color = i.Filter3Color;
 
            Filter3Alert.Copy(i.Filter3Alert, !style);
 
            OnPropertyChanged(nameof(Filter3Alert));
 
            base.CopyTemplate(indicator, style);
        }
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://support.tiger.com/razrabotka-dlya-tiger.trade-windows/primery-indikatorov/trades.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
