Tiger.com Windows Wiki
Русский
Русский
  • 👋Добро пожаловать
  • ⭐C чего начать?
    • Рекомендуемые системные требования
    • Регистрация и установка
    • Лицензии и логин
  • ⚙️Настройки
    • Рабочее пространство
    • Режимы торговли
    • Подключения
      • Криптобиржи
        • TigerX
        • Binance via Tiger.com Broker
        • Bybit via Tiger.com Broker
        • Binance
        • Bitfinex
        • BitMEX
        • Bybit
        • OKX
        • Gate.io
        • MEXC
      • Торговые терминалы
        • DataFeed
        • MetaTrader 5
        • OEC Trader (GAIN Capital)
        • Rithmic
        • QUIK
        • SmartCOM
        • Trader WorkStation (Interactive Brokers)
        • Transaq Connector
      • Прокси
        • Настройка прокси
        • Подключение сервисов терминала через прокси
    • Основные действия
      • Выбор инструмента
      • Выбор периода (таймфрейма)
      • Линковка окон
      • Установка сигнальных уровней
    • Терминал
      • Конфигурация
      • Основные настройки
      • Настройки стакана
      • Горячие клавиши
      • Звуковые сигналы
      • Параметры Telegram
      • Параметры почты
      • Инструменты
  • 📈Торговля
    • Выбор торгового счета
    • Размеры ордеров по умолчанию
    • Выбор объема заявки
    • Какие типы ордеров доступны в Tiger.com?
    • Работа с торговым модулем
    • Параметры защитной стратегии
    • Настройка отступов
    • Спотовая торговля в терминале Tiger.com
    • Как настроить отображение ордеров и позиций в валюте котирования?
  • 🖥️Окна
    • График
      • Чем отличается загрузка графиков с биржи и с серверов Tiger.com?
      • Настройка панелей
      • Тема Графика
      • Параметры Графика
      • Масштабирование и перемещение графика
      • Кластеры
      • Кластерные пресеты
      • Графические объекты в окне График
        • Текст
        • Линейка
        • Профиль объёма
        • Угол тренда
        • Elliott Correction Wave
        • Elliott Impulse Wave
        • Fibonacci Fan
        • Fibonacci Extensions
        • Fibonacci Retracement
        • Fibonacci Time Zones
        • Linear Regression
      • Основные индикаторы окна График
        • Bar Search
        • Bar Timer
        • Bid Ask
        • Big Trades
        • BW MFI
        • Cluster Search
        • Cluster Statistic
        • Cumulative Delta
        • Delta
        • Depth Of Market
        • Dynamic Levels
        • Elders Force Index
        • External Chart
        • Gradient
        • Heatmap
        • High Low
        • Histogram
        • Ichimoku
        • Margin Zones
        • Maximum Levels
        • Open Interest
        • Price
        • Session Color
        • Trades Flow
        • Volume
        • Volume Profiles
        • VWAP
        • Weis Wave Volume
        • ZigZag
    • Стакан
      • Выбор торгового счёта
      • Линейка
      • Мультипликатор
      • Параметры окна стакан
        • Основные
        • Кластер
        • Торговля
      • Стоп-лосс
      • Тейк-профит
      • Триггерные заявки
    • Котировки
      • Фильтрация котировок
    • Лента сделок
    • Статистика
    • Поиск объема
    • Все цены
    • Доска опционов
    • Крипто скринер
  • 📋Таблицы
    • Заявки
    • Сделки
    • Позиции
    • Позиции ТТ
    • Счета
    • Лимиты
    • Плеер
    • Сигналы
    • Журнал
    • Серверные алерты
  • 📽️Обучающие видео
    • Основы работы с терминалом
    • Графики и технический анализ
    • Стакан, Лента сделок и Плеер
    • Торговля через терминал
  • 💡Версии терминала
    • Версия 7.0 Beta
    • Версия 6.9
    • Версия 6.8
    • Версия 6.7.1
    • Версия 6.7
    • Версия 6.6
    • Версия 6.5
    • Версия 6.4
    • Версия 6.3
    • Версия 6.2
    • Версия 6.1
    • Версия 6.0.2
    • Версия 6.0.1
    • Версия 6.0
    • Версия 5.0.7
    • Версия 4.5.15
    • Версия 4.4.7
    • Версия 4.4.1
    • Версия 4.3.1
    • Версия 4.2.1
    • Версия 4.1.2
    • Версия 4.1.1
    • Версия 4.1
    • Версия 4.0.5
    • Версия 4.0.4
    • Версия 4.0.3
    • Версия 4.0.2
    • Версия 4.0.1
    • Версия 4.0
    • Версия 3.0.5
    • Версия 3.0.4
    • Версия 3.0.3
    • Версия 3.0.2
    • Версия 3.0.1
  • ⌨️Разработка для Tiger.com Windows
    • Примеры индикаторов
      • Trades Flow
      • Depth Of Market
      • Volume Profiles
      • Cluster Search
      • Bar Search
      • Bar Timer
      • VWAP
      • Volume
      • Trades
      • Session Color
      • Open Interest
      • Dynamic Levels
      • Delta
      • Cumulative Delta
      • Cluster Statistic
      • Bid Ask
      • External Chart
      • High Low
      • Histogram
    • Примеры источников
      • Moving Average
      • Stock
    • Примеры графических объектов
      • Fibonacci Extensions
      • Fibonacci Retracement
      • Вертикальная линия
      • Горизонтальная линия
      • Профиль объёма
      • Прямоугольник
  • ❓Часто задаваемые вопросы
    • Вопросы по лицензиям
    • Вопросы по индикаторам
    • Вопросы по подключениям
    • Вопросы по торговле
    • Ошибка выставления заявки
    • Как стабилизировать подключение к бирже?
    • Зачем настраивать комиссию в терминале?
    • Как оптимизировать терминал для улучшения производительности?
    • Как воспользоваться криптовалютной лицензией для торговли на Binance?
    • Как настроить автообновление графиков при подключении к QUIK?
    • Как работает автовыбор типа данных?
    • Не получается установить терминал
    • Подойдёт ли моя система для установки терминала?
    • Как настроить соединение с отправкой через прокси только ордеров без потока биржевых данных?
    • Как предоставить протоколы работы терминала Tiger.com для исследования нашей командой?
    • Как настроить DNS-сервер для более стабильного соединения?
    • Как работает определение жизни плотностей в стакане?
    • Ошибка "Нет соединения" при запуске терминала
    • Как настроить отображение стакана в валюте котирования?
  • 📬Техническая поддержка
  • 💭Предложить улучшение
Powered by GitBook
On this page
  1. Разработка для Tiger.com Windows
  2. Примеры индикаторов

Dynamic Levels

//--------------------------------------------------------------------------------
//
// Индикатор DynamicLevels. 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.Media;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Base.Enums;
using TigerTrade.Chart.Data;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Indicators.Drawings;
using TigerTrade.Chart.Indicators.Drawings.Enums;
using TigerTrade.Chart.Indicators.Enums;
using TigerTrade.Core.UI.Converters;
using TigerTrade.Core.Utils.Time;
using TigerTrade.Dx;
 
namespace TigerTrade.Chart.Indicators.Custom
{
    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    [DataContract(Name = "DynamicLevelsPeriodType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    public enum DynamicLevelsPeriodType
    {
        [EnumMember(Value = "Hour"), Description("Час")]
        Hour,
        [EnumMember(Value = "Day"), Description("День")]
        Day,
        [EnumMember(Value = "Week"), Description("Неделя")]
        Week,
        [EnumMember(Value = "Month"), Description("Месяц")]
        Month,
        [EnumMember(Value = "AllBars"), Description("Все бары")]
        AllBars,
    }
 
    [DataContract(Name = "DynamicLevelsIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("X_DynamicLevels", "*DynamicLevels", true, Type = typeof(DynamicLevelsIndicator))]
    internal sealed class DynamicLevelsIndicator : IndicatorBase
    {
        private DynamicLevelsPeriodType _period;
 
        [DataMember(Name = "Period")]
        [Category("Параметры"), DisplayName("Период")]
        public DynamicLevelsPeriodType Period
        {
            get => _period;
            set
            {
                if (value == _period)
                {
                    return;
                }
 
                _period = value;
 
                _lastDataWrapper?.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private bool _showValueArea;
 
        [DataMember(Name = "ShowValueArea")]
        [Category("ChartIndicatorsValueArea"), DisplayName("Отображать Value Area")]
        public bool ShowValueArea
        {
            get => _showValueArea;
            set
            {
                if (value == _showValueArea)
                {
                    return;
                }
 
                _showValueArea = value;
 
                _lastDataWrapper?.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private int _valueAreaPercent;
 
        [DataMember(Name = "ValueAreaPercent")]
        [Category("ChartIndicatorsValueArea"), DisplayName("ValueArea %")]
        public int ValueAreaPercent
        {
            get => _valueAreaPercent;
            set
            {
                value = Math.Max(0, Math.Min(100, value));
 
                if (value == 0)
                {
                    value = 70;
                }
 
                if (value == _valueAreaPercent)
                {
                    return;
                }
 
                _valueAreaPercent = value;
 
                _lastDataWrapper?.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private XColor _valueAreaBackColor;
 
        [DataMember(Name = "ValueAreaBackColor")]
        [Category("ChartIndicatorsValueArea"), DisplayName("Цвет фона")]
        public XColor ValueAreaBackColor
        {
            get => _valueAreaBackColor;
            set
            {
                if (value == _valueAreaBackColor)
                {
                    return;
                }
 
                _valueAreaBackColor = value;
 
                OnPropertyChanged();
            }
        }
 
        private XColor _valueAreaBorderColor;
 
        [DataMember(Name = "ValueAreaBorderColor")]
        [Category("ChartIndicatorsValueArea"), DisplayName("Цвет границы")]
        public XColor ValueAreaBorderColor
        {
            get => _valueAreaBorderColor;
            set
            {
                if (value == _valueAreaBorderColor)
                {
                    return;
                }
 
                _valueAreaBorderColor = value;
 
                OnPropertyChanged();
            }
        }
 
        private int _valueAreaBorderWidth;
 
        [DataMember(Name = "ValueAreaBorderWidth")]
        [Category("ChartIndicatorsValueArea"), DisplayName("Ширина границы")]
        public int ValueAreaBorderWidth
        {
            get => _valueAreaBorderWidth;
            set
            {
                value = Math.Max(0, Math.Min(10, value));
 
                if (value == _valueAreaBorderWidth)
                {
                    return;
                }
 
                _valueAreaBorderWidth = value;
 
                OnPropertyChanged();
            }
        }
 
        private bool _showPoc;
 
        [DataMember(Name = "ShowPoc")]
        [Category("ChartIndicatorsPoc"), DisplayName("Отображать POC")]
        public bool ShowPoc
        {
            get => _showPoc;
            set
            {
                if (value == _showPoc)
                {
                    return;
                }
 
                _showPoc = value;
 
                OnPropertyChanged();
            }
        }
 
        private XColor _pocLineColor;
 
        [DataMember(Name = "PocLineColor")]
        [Category("ChartIndicatorsPoc"), DisplayName("Цвет линии")]
        public XColor PocLineColor
        {
            get => _pocLineColor;
            set
            {
                if (value == _pocLineColor)
                {
                    return;
                }
 
                _pocLineColor = value;
 
                OnPropertyChanged();
            }
        }
 
        private int _pocLineWidth;
 
        [DataMember(Name = "PocLineWidth")]
        [Category("ChartIndicatorsPoc"), DisplayName("Толщина линии")]
        public int PocLineWidth
        {
            get => _pocLineWidth;
            set
            {
                value = Math.Max(1, Math.Min(10, value));
 
                if (value == _pocLineWidth)
                {
                    return;
                }
 
                _pocLineWidth = value;
 
                OnPropertyChanged();
            }
        }
 
        [Browsable(false)]
        public override IndicatorCalculation Calculation => IndicatorCalculation.OnBarClose;
 
        public DynamicLevelsIndicator()
        {
            Period = DynamicLevelsPeriodType.Day;
 
            ShowValueArea = true;
            ValueAreaPercent = 70;
 
            ValueAreaBackColor = Color.FromArgb(50, 255, 255, 255);
            ValueAreaBorderColor = Colors.Black;
            ValueAreaBorderWidth = 1;
 
            ShowPoc = true;
 
            PocLineColor = Colors.Black;
            PocLineWidth = 1;
        }
 
        private class LastDataWrapper
        {
            public double[] Vah;
            public double[] Val;
            public double[] Poc;
 
            public bool[] Splits;
 
            public int LastSequence;
            public int LastIndex;
            public int LastCount;
 
            public readonly List<DynamicCluster> Clusters = new List<DynamicCluster>();
 
            public LastDataWrapper()
            {
                Clear();
            }
 
            public void Clear()
            {
                LastSequence = -1;
                LastIndex = 0;
                LastCount = 0;
 
                Vah = new double[0];
                Val = new double[0];
                Poc = new double[0];
 
                Splits = new bool[0];
 
                Clusters.Clear();
            }
 
            public void Prepare(int count, double step)
            {
                LastIndex = Math.Max(0, count - 1);
                LastCount = count;
 
                Vah = new double[count];
                Val = new double[count];
                Poc = new double[count];
 
                Splits = new bool[count];
 
                for (var i = 0; i < count - 1; i++)
                {
                    var cluster = Clusters[i];
 
                    Vah[i] = cluster.Vah * step;
                    Val[i] = cluster.Val * step;
                    Poc[i] = cluster.Poc * step;
 
                    Splits[i] = cluster.Split;
                }
 
                if (count > 1)
                {
                    Vah[count - 1] = Vah[count - 2];
                    Val[count - 1] = Val[count - 2];
                    Poc[count - 1] = Poc[count - 2];
                }
            }
        }
 
        private LastDataWrapper _lastDataWrapper;
 
        protected override void Execute()
        {
            if (ClearData)
            {
                _lastDataWrapper = null;
            }
 
            if (_lastDataWrapper == null)
            {
                _lastDataWrapper = new LastDataWrapper();
            }
 
            var date = Helper.Date;
 
            var timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
 
            if (date.Length > _lastDataWrapper.LastCount)
            {
                for (var i = _lastDataWrapper.LastIndex; i < date.Length - 1; i++)
                {
                    var sequence = -1;
 
                    switch (Period)
                    {
                        case DynamicLevelsPeriodType.Hour:
 
                            sequence = DataProvider.Period.GetSequence(ChartPeriodType.Hour, 1, date[i], timeOffset);
 
                            break;
 
                        case DynamicLevelsPeriodType.Day:
 
                            sequence = DataProvider.Period.GetSequence(ChartPeriodType.Day, 1, date[i], timeOffset);
 
                            break;
 
                        case DynamicLevelsPeriodType.Week:
 
                            sequence = DataProvider.Period.GetSequence(ChartPeriodType.Week, 1, date[i], timeOffset);
 
                            break;
 
                        case DynamicLevelsPeriodType.Month:
 
                            sequence = DataProvider.Period.GetSequence(ChartPeriodType.Month, 1, date[i], timeOffset);
 
                            break;
                    }
 
                    var currCluster = DataProvider.GetRawCluster(i);
 
                    var prevCluster = i > 0 ? _lastDataWrapper.Clusters[i - 1] : null;
 
                    var split = false;
 
                    if (sequence != _lastDataWrapper.LastSequence)
                    {
                        prevCluster = null;
 
                        _lastDataWrapper.LastSequence = sequence;
 
                        split = true;
                    }
 
                    var newCluster = new DynamicCluster(prevCluster)
                    {
                        Split = split
                    };
 
                    newCluster.AddCluster(currCluster);
 
                    newCluster.UpdateData();
 
                    if (ShowValueArea)
                    {
                        newCluster.UpdateValueArea(ValueAreaPercent / 100.0);
                    }
 
                    if (_lastDataWrapper.Clusters.Count == date.Length)
                    {
                        _lastDataWrapper.Clusters[i] = newCluster;
                    }
                    else
                    {
                        _lastDataWrapper.Clusters.Add(newCluster);
 
                        if (_lastDataWrapper.Clusters.Count > 1)
                        {
                            _lastDataWrapper.Clusters[_lastDataWrapper.Clusters.Count - 2].ClearItems();
                        }
                    }
                }
 
                _lastDataWrapper.Prepare(date.Length, DataProvider.Step);
            }
 
            if (ShowValueArea)
            {
                var vaData = new IndicatorSeriesData(_lastDataWrapper.Vah, new ChartRegion(ValueAreaBackColor))
                {
                    Style = { DisableMinMax = true },
                    ["L"] = _lastDataWrapper.Val
                };
 
                Series.Add(vaData);
 
                if (ValueAreaBorderWidth > 0)
                {
                    var vahData = new IndicatorSeriesData(_lastDataWrapper.Vah,
                        new ChartSeries(ChartSeriesType.Line, ValueAreaBorderColor)
                        {
                            Width = ValueAreaBorderWidth
                        })
                    {
                        Style =
                        {
                            DisableMinMax = true
                        }
                    };
 
                    var valData = new IndicatorSeriesData(_lastDataWrapper.Val,
                        new ChartSeries(ChartSeriesType.Line, ValueAreaBorderColor)
                        {
                            Width = ValueAreaBorderWidth
                        })
                    {
                        Style =
                        {
                            DisableMinMax = true
                        }
                    };
 
                    Series.Add(vahData, valData);
                }
            }
 
            if (ShowPoc)
            {
                var pocData = new IndicatorSeriesData(_lastDataWrapper.Poc,
                    new ChartSeries(ChartSeriesType.Line, PocLineColor))
                {
                    Style =
                    {
                        DisableMinMax = true,
                        StraightLine = true,
                        LineWidth = PocLineWidth
                    }
                };
 
                Series.Add(pocData);
            }
 
            foreach (var series in Series)
            {
                series.UserData["S"] = _lastDataWrapper.Splits;
                series.UserData["SE"] = true;
            }
        }
 
        public override void ApplyColors(IChartTheme theme)
        {
            ValueAreaBorderColor = theme.GetNextColor();
 
            ValueAreaBackColor = new XColor(50, ValueAreaBorderColor);
 
            PocLineColor = theme.GetNextColor();
 
            base.ApplyColors(theme);
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (DynamicLevelsIndicator)indicator;
 
            Period = i.Period;
 
            ShowValueArea = i.ShowValueArea;
            ValueAreaPercent = i.ValueAreaPercent;
 
            ValueAreaBackColor = i.ValueAreaBackColor;
            ValueAreaBorderColor = i.ValueAreaBorderColor;
            ValueAreaBorderWidth = i.ValueAreaBorderWidth;
 
            ShowPoc = i.ShowPoc;
 
            PocLineColor = i.PocLineColor;
            PocLineWidth = i.PocLineWidth;
 
            base.CopyTemplate(indicator, style);
        }
 
        internal sealed class DynamicCluster
        {
            public DateTime Time;
 
            public long High;
            public long Low;
 
            public long Volume;
            public long MaxVolume;
 
            public long Poc;
            public long Vah;
            public long Val;
 
            public bool Split;
 
            private readonly Dictionary<long, long> _items = new Dictionary<long, long>();
 
            public DynamicCluster(DynamicCluster cluster)
            {
                if (cluster == null)
                {
                    return;
                }
 
                Time = cluster.Time;
 
                _items = new Dictionary<long, long>(cluster._items.Count);
 
                foreach (var item in cluster._items)
                {
                    _items.Add(item.Key, item.Value);
                }
 
                High = cluster.High;
                Low = cluster.Low;
 
                Volume = cluster.Volume;
            }
 
            public void AddCluster(IRawCluster cluster)
            {
                Time = cluster.Time;
 
                foreach (var item in cluster.Items)
                {
                    if (!_items.ContainsKey(item.Price))
                    {
                        _items.Add(item.Price, 0);
                    }
 
                    _items[item.Price] += item.Volume;
                }
 
                High = High == 0 ? cluster.High : Math.Max(High, cluster.High);
                Low = Low == 0 ? cluster.Low : Math.Min(Low, cluster.Low);
 
                Volume += cluster.Volume;
            }
 
            public void UpdateData()
            {
                MaxVolume = 0;
                Poc = 0;
 
                foreach (var item in _items)
                {
                    if (item.Value <= MaxVolume)
                    {
                        continue;
                    }
 
                    MaxVolume = item.Value;
 
                    Poc = item.Key;
                }
            }
 
            public void UpdateValueArea(double valueArea)
            {
                if (_items.Count == 0)
                {
                    return;
                }
 
                if (High - Low > 100000)
                {
                    return;
                }
 
                if (valueArea < 0.01)
                {
                    Vah = Poc;
                    Val = Poc;
 
                    return;
                }
 
                if (valueArea > 0.99)
                {
                    Vah = High;
                    Val = Low;
 
                    return;
                }
 
                var vah = 0L;
                var val = 0L;
 
                if (High != 0 && Low != 0)
                {
                    vah = Poc;
                    val = Poc;
 
                    var vol = MaxVolume;
 
                    var areaVol = Volume * valueArea;
 
                    while (vol < areaVol)
                    {
                        if (vah >= High && val <= Low)
                        {
                            break;
                        }
 
                        var currentVahVol = 0L;
                        var currentValVol = 0L;
                        var currentVah = vah;
                        var currentVal = val;
 
                        for (var i = 0; i <= 1; i++)
                        {
                            if (High >= currentVah + 1)
                            {
                                currentVah++;
 
                                if (_items.ContainsKey(currentVah))
                                {
                                    currentVahVol += _items[currentVah];
                                }
                            }
                        }
 
                        for (var j = 0; j <= 1; j++)
                        {
                            if (Low <= currentVal - 1)
                            {
                                currentVal--;
 
                                if (_items.ContainsKey(currentVal))
                                {
                                    currentValVol += _items[currentVal];
                                }
                            }
                        }
 
                        if (currentVahVol == currentValVol && currentVahVol == 0)
                        {
                            if (High == currentVah)
                            {
                                val = currentVal;
                            }
 
                            if (Low == currentVal)
                            {
                                vah = currentVah;
                            }
                        }
 
                        if (currentVahVol >= currentValVol)
                        {
                            vah = currentVah;
                            vol += currentVahVol;
                        }
                        else
                        {
                            val = currentVal;
                            vol += currentValVol;
                        }
 
                        if (vol >= areaVol)
                        {
                            break;
                        }
                    }
                }
 
                Vah = vah;
                Val = val;
            }
 
            public void ClearItems()
            {
                _items.Clear();
            }
        }
    }
}
PreviousOpen InterestNextDelta

Last updated 2 years ago

⌨️