# Depth Of Market

```
//------------------------------------------------------------------------------
//
// Индикатор DepthOfMarket. Copyright (c) 2023 Tiger Trade Capital AG. All rights reserved.
//
//------------------------------------------------------------------------------
 
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Media;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Indicators.Enums;
using TigerTrade.Core.UI.Converters;
using TigerTrade.Dx;
using TigerTrade.Dx.Enums;
 
namespace TigerTrade.Chart.Indicators.Custom
{
    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    [DataContract(Name = "DepthOfMarketScaleAlignment", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    public enum DepthOfMarketScaleAlignment
    {
        [EnumMember(Value = "Left"), Description("Слева")]
        Left,
        [EnumMember(Value = "Right"), Description("Справа")]
        Right
    }
 
    [DataContract(Name = "DepthOfMarketIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("X_DepthOfMarket", "*DepthOfMarket", true, Type = typeof(DepthOfMarketIndicator))]
    internal sealed class DepthOfMarketIndicator : IndicatorBase
    {
        private int _scaleWidth;
 
        [DataMember(Name = "ScaleWidth")]
        [Category("Параметры"), DisplayName("Ширина шкалы")]
        public int ScaleWidth
        {
            get => _scaleWidth;
            set
            {
                value = Math.Max(0, value);
 
                if (value == _scaleWidth)
                {
                    return;
                }
 
                _scaleWidth = value;
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorNullIntParam _scaleVolumeParam;
 
        [DataMember(Name = "ScaleVolumeParam")]
        public IndicatorNullIntParam ScaleVolumeParam
        {
            get => _scaleVolumeParam ?? (_scaleVolumeParam = new IndicatorNullIntParam(null));
            set => _scaleVolumeParam = value;
        }
 
        [DefaultValue(null)]
        [Category("Параметры"), DisplayName("Объём шкалы")]
        public int? ScaleVolume
        {
            get => ScaleVolumeParam.Get(SettingsShortKey);
            set
            {
                if (!ScaleVolumeParam.Set(SettingsShortKey, value, 1))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private DepthOfMarketScaleAlignment _scaleAlignment;
     
        [DataMember(Name = "DepthOfMarketScaleAlignment")]
        [Category("Параметры"), DisplayName("Расположение шкалы")]
        public DepthOfMarketScaleAlignment ScaleAlignment
        {
            get => _scaleAlignment;
            set
            {
                if (value == _scaleAlignment)
                {
                    return;
                }
 
                _scaleAlignment = value;
 
                OnPropertyChanged();
            }
        }
 
        private bool _addMargins;
     
        [DataMember(Name = "AddMargins")]
        [Category("Параметры"), DisplayName("Добавить отступы")]
        public bool AddMargins
        {
            get => _addMargins;
            set
            {
                if (value == _addMargins)
                {
                    return;
                }
 
                _addMargins = value;
 
                OnPropertyChanged();
            }
        }
 
        private bool _showValues;
 
        [DataMember(Name = "ShowValues")]
        [Category("Параметры"), DisplayName("Отображать значения")]
        public bool ShowValues
        {
            get => _showValues;
            set
            {
                if (value == _showValues)
                {
                    return;
                }
 
                _showValues = value;
 
                OnPropertyChanged();
            }
        }
 
        private bool _minimizeValues;
 
        [DataMember(Name = "MinimizeValues")]
        [Category("Параметры"), DisplayName("Минимизировать значения")]
        public bool MinimizeValues
        {
            get => _minimizeValues;
            set
            {
                if (value == _minimizeValues)
                {
                    return;
                }
 
                _minimizeValues = value;
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorIntParam _roundValueParam;
 
        [DataMember(Name = "RoundValueParam")]
        public IndicatorIntParam RoundValuesParam
        {
            get => _roundValueParam ?? (_roundValueParam = new IndicatorIntParam(0));
            set => _roundValueParam = value;
        }
 
        [DefaultValue(0)]
        [Category("Параметры"), DisplayName("Округлять значения")]
        public int RoundValues
        {
            get => RoundValuesParam.Get(SettingsLongKey);
            set
            {
                if (!RoundValuesParam.Set(SettingsLongKey, value, -4, 4))
                {
                    return;
                }
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _bidQuoteBrush;
 
        private XColor _quoteBuyColor;
 
        [DataMember(Name = "BidQuoteColor")]
        [Category("Стиль"), DisplayName("Заявка на покупку")]
        public XColor BidQuoteColor
        {
            get => _quoteBuyColor;
            set
            {
                if (_quoteBuyColor == value)
                {
                    return;
                }
 
                _quoteBuyColor = value;
 
                _bidQuoteBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _bestBidQuoteBrush;
 
        private XColor _quoteBestBuyColor;
 
        [DataMember(Name = "BestBidQuoteColor")]
        [Category("Стиль"), DisplayName("Лучшая заявка на покупку")]
        public XColor BestBidQuoteColor
        {
            get => _quoteBestBuyColor;
            set
            {
                if (_quoteBestBuyColor == value)
                {
                    return;
                }
 
                _quoteBestBuyColor = value;
 
                _bestBidQuoteBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _askQuoteBrush;
 
        private XColor _quoteSellColor;
 
        [DataMember(Name = "AskQuoteColor")]
        [Category("Стиль"), DisplayName("Заявка на продажу")]
        public XColor AskQuoteColor
        {
            get => _quoteSellColor;
            set
            {
                if (_quoteSellColor == value)
                {
                    return;
                }
 
                _quoteSellColor = value;
 
                _askQuoteBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _bestAskQuoteBrush;
 
        private XColor _quoteBestSellColor;
 
        [DataMember(Name = "BestAskQuoteColor")]
        [Category("Стиль"), DisplayName("Лучшая заявка на прдажу")]
        public XColor BestAskQuoteColor
        {
            get => _quoteBestSellColor;
            set
            {
                if (_quoteBestSellColor == value)
                {
                    return;
                }
 
                _quoteBestSellColor = value;
 
                _bestAskQuoteBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _emptyQuoteBrush;
 
        private XColor _quoteEmptyColor;
 
        [Browsable(false)]
        [DataMember(Name = "EmptyQuoteColor")]
        [Category("Стиль"), DisplayName("Цена без заявок")]
        public XColor EmptyQuoteColor
        {
            get => _quoteEmptyColor;
            set
            {
                if (_quoteEmptyColor == value)
                {
                    return;
                }
 
                _quoteEmptyColor = value;
 
                _emptyQuoteBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _bidVolumeBrush;
 
        private XColor _quoteBuyVolumeColor;
 
        [DataMember(Name = "BidVolumeColor")]
        [Category("Стиль"), DisplayName("Шкала покупок")]
        public XColor BidVolumeColor
        {
            get => _quoteBuyVolumeColor;
            set
            {
                if (_quoteBuyVolumeColor == value)
                {
                    return;
                }
 
                _quoteBuyVolumeColor = value;
 
                _bidVolumeBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _askVolumeBrush;
 
        private XColor _quoteSellVolumeColor;
 
        [DataMember(Name = "AskVolumeColor")]
        [Category("Стиль"), DisplayName("Шкала продаж")]
        public XColor AskVolumeColor
        {
            get => _quoteSellVolumeColor;
            set
            {
                if (_quoteSellVolumeColor == value)
                {
                    return;
                }
 
                _quoteSellVolumeColor = value;
 
                _askVolumeBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _textBrush;
 
        private XColor _textColor;
 
        [DataMember(Name = "TextColor")]
        [Category("Стиль"), DisplayName("Цвет текста")]
        public XColor TextColor
        {
            get => _textColor;
            set
            {
                if (_textColor == value)
                {
                    return;
                }
 
                _textColor = value;
 
                _textBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _backBrush;
 
        private XColor _backColor;
 
        [DataMember(Name = "BackColor")]
        [Category("Стиль"), DisplayName("Цвет фона")]
        public XColor BackColor
        {
            get => _backColor;
            set
            {
                if (_backColor == value)
                {
                    return;
                }
 
                _backColor = value;
 
                _backBrush = new XBrush(value);
 
                OnPropertyChanged();
            }
        }
 
        [Browsable(false)]
        public override bool ShowIndicatorValues => false;
 
        [Browsable(false)]
        public override bool ShowIndicatorLabels => false;
 
        [Browsable(false)]
        public override IndicatorCalculation Calculation => IndicatorCalculation.OnEachTick;
 
        public DepthOfMarketIndicator()
        {
            ShowIndicatorTitle = false;
 
            ScaleWidth = 0;
            ScaleAlignment = DepthOfMarketScaleAlignment.Right;
            AddMargins = false;
            ShowValues = true;
            MinimizeValues = false;
 
            BidQuoteColor = Colors.Transparent;
            BestBidQuoteColor = Colors.Transparent;
            AskQuoteColor = Colors.Transparent;
            BestAskQuoteColor = Colors.Transparent;
            EmptyQuoteColor = Colors.Transparent;
            BidVolumeColor = Color.FromArgb(255, 30, 144, 255);
            AskVolumeColor = Color.FromArgb(255, 178, 34, 34);
            TextColor = Colors.White;
            BackColor = Colors.Transparent;
        }
 
        protected override void Execute()
        {
        }
 
        public override void Render(DxVisualQueue visual)
        {
            var dp = DataProvider;
            var step = dp.Step;
            var symbol = dp.Symbol;
 
            var md = dp.GetRawMarketDepth();
 
            var r = Canvas.Rect;
 
            var maxWidth = ScaleWidth > 0 ? ScaleWidth : r.Width * 0.1;
            var maxVolume = ScaleVolume > 0 ? symbol.CorrectSizeFilter(ScaleVolume.Value) : md.MaxSize;
 
            if (maxWidth < 5 || maxVolume < 1)
            {
                return;
            }
 
            var heightCorrect = AddMargins ? -1 : 0;
 
            var height = Math.Max(GetY(0.0) - GetY(step), 1);
 
            var fontSize = Math.Min(height + heightCorrect - 2, 18) * 96.0 / 72.0;
 
            fontSize = Math.Min(fontSize, Canvas.ChartFont.Size);
 
            var textFont = new XFont(Canvas.ChartFont.Name, fontSize);
 
            visual.FillRectangle(_backBrush, new Rect(r.Right - maxWidth, r.Y, maxWidth, r.Height));
 
            var asksY1 = (int)GetY(md.MaxAskPrice * step + step / 2.0);
            var asksY2 = (int)GetY(md.MinAskPrice * step + step / 2.0);
 
            visual.FillRectangle(_askQuoteBrush,
                new Rect(new Point(r.Right - maxWidth, asksY1), new Point(r.Right, asksY2)));
 
            var bidsY1 = (int)GetY(md.MaxBidPrice * step - step / 2.0);
            var bidsY2 = (int)GetY(md.MinBidPrice * step - step / 2.0);
 
            visual.FillRectangle(_bidQuoteBrush,
                new Rect(new Point(r.Right - maxWidth, bidsY1), new Point(r.Right, bidsY2)));
 
            var prevY = (int)GetY(md.MaxAskPrice * step + step / 2.0);
 
            var maxPrice = Math.Min((long)Math.Round(Canvas.GetValue(r.Top) / step), md.MaxAskPrice);
            var minPrice = Math.Max((long)Math.Round(Canvas.GetValue(r.Bottom) / step), md.MinAskPrice);
 
            if (maxPrice - minPrice > 5000)
            {
                return;
            }
 
            var roundValues = RoundValues;
 
            for (var price = maxPrice; price >= minPrice; price--)
            {
                var currY = (int)GetY(price * step - step / 2.0);
 
                var currHeight = Math.Max(currY - prevY, 1);
 
                var y = prevY;
 
                prevY = currY;
 
                if (!md.AskQuotes.ContainsKey(price) || currY < r.Top)
                {
                    continue;
                }
 
                if (price == md.MinAskPrice)
                {
                    var quoteRect = new Rect(new Point(r.Right - maxWidth, y), new Point(r.Right, y + currHeight));
 
                    visual.FillRectangle(_bestAskQuoteBrush, quoteRect);
                }
 
                var volume = md.AskQuotes[price];
 
                var text = symbol.FormatRawSize(volume, roundValues, MinimizeValues);
                var textWidth = textFont.GetWidth(text);
 
                var width = (int)Math.Min(volume * maxWidth / maxVolume, maxWidth);
 
                if (ShowValues && height > 8)
                {
                    width = (int)Math.Min(Math.Max(width, textWidth), maxWidth);
                }
 
                var volumeRect = ScaleAlignment == DepthOfMarketScaleAlignment.Right
                    ? new Rect(new Point(r.Right - width, y),
                        new Point(r.Right, y + Math.Max(currHeight + heightCorrect, 1)))
                    : new Rect(new Point(r.Right - maxWidth, y),
                        new Point(r.Right - (maxWidth - width), y + Math.Max(currHeight + heightCorrect, 1)));
 
                visual.FillRectangle(_askVolumeBrush, volumeRect);
 
                if (ShowValues && height > 8)
                {
                    visual.DrawString(text, textFont, _textBrush, volumeRect,
                        ScaleAlignment == DepthOfMarketScaleAlignment.Right ? XTextAlignment.Right : XTextAlignment.Left);
                }
            }
 
            prevY = (int)GetY(md.MaxBidPrice * step + step / 2.0);
 
            maxPrice = Math.Min((long)Math.Round(Canvas.GetValue(r.Top) / step), md.MaxBidPrice);
            minPrice = Math.Max((long)Math.Round(Canvas.GetValue(r.Bottom) / step), md.MinBidPrice);
 
            if (maxPrice - minPrice > 5000)
            {
                return;
            }
 
            for (var price = maxPrice; price >= minPrice; price--)
            {
                var currY = (int)GetY(price * step - step / 2.0);
 
                var currHeight = Math.Max((currY - prevY), 1);
 
                var y = prevY;
 
                prevY = currY;
 
                if (!md.BidQuotes.ContainsKey(price) || y > r.Bottom)
                {
                    continue;
                }
 
                if (price == md.MaxBidPrice)
                {
                    var quoteRect = new Rect(new Point(r.Right - maxWidth, y), new Point(r.Right, y + currHeight));
 
                    visual.FillRectangle(_bestBidQuoteBrush, quoteRect);
                }
 
                var volume = md.BidQuotes[price];
 
                var text = symbol.FormatRawSize(volume, roundValues, MinimizeValues);
                var textWidth = textFont.GetWidth(text);
 
                var width = (int)Math.Min(volume * maxWidth / maxVolume, maxWidth);
 
                if (ShowValues && height > 8)
                {
                    width = (int)Math.Min(Math.Max(width, textWidth), maxWidth);
                }
 
                var volumeRect = ScaleAlignment == DepthOfMarketScaleAlignment.Right
                    ? new Rect(new Point(r.Right - width, y),
                        new Point(r.Right, y + Math.Max(currHeight + heightCorrect, 1)))
                    : new Rect(new Point(r.Right - maxWidth, y),
                        new Point(r.Right - (maxWidth - width), y + Math.Max(currHeight + heightCorrect, 1)));
 
                visual.FillRectangle(_bidVolumeBrush, volumeRect);
 
                if (ShowValues && height > 8)
                {
                    visual.DrawString(text, textFont, _textBrush, volumeRect,
                        ScaleAlignment == DepthOfMarketScaleAlignment.Right ? XTextAlignment.Right : XTextAlignment.Left);
                }
            }
        }
 
        public override void ApplyColors(IChartTheme theme)
        {
            BidVolumeColor = theme.PaletteColor6;
            AskVolumeColor = theme.PaletteColor7;
            TextColor = theme.ChartFontColor;
 
            base.ApplyColors(theme);
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (DepthOfMarketIndicator)indicator;
 
            ScaleWidth = i.ScaleWidth;
            ScaleAlignment = i.ScaleAlignment;
            AddMargins = i.AddMargins;
            ShowValues = i.ShowValues;
            MinimizeValues = i.MinimizeValues;
 
            ScaleVolumeParam.Copy(i.ScaleVolumeParam);
            RoundValuesParam.Copy(i.RoundValuesParam);
 
            BidQuoteColor = i.BidQuoteColor;
            BestBidQuoteColor = i.BestBidQuoteColor;
            AskQuoteColor = i.AskQuoteColor;
            BestAskQuoteColor = i.BestAskQuoteColor;
            EmptyQuoteColor = i.EmptyQuoteColor;
            BidVolumeColor = i.BidVolumeColor;
            AskVolumeColor = i.AskVolumeColor;
            TextColor = i.TextColor;
            BackColor = i.BackColor;
 
            OnPropertyChanged(nameof(ScaleVolume));
 
            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/depth-of-market.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.
