Tiger.com Windows Wiki
English
English
  • 👋Welcome!
  • ⭐How to start?
    • Recommended system requirements
    • Register and setup
    • Licenses and login
  • ⚙️Settings
    • Workspace
    • Trading modes
    • Connections
      • Crypto exchanges
        • TigerX
        • Binance via Tiger.com Broker
        • Bybit via Tiger.com Broker
        • Binance
        • Bitfinex
        • BitMEX
        • Bybit
        • OKX
        • Gate.io
        • MEXC
      • Trading terminals
        • DataFeed
        • MetaTrader 5
        • OEC Trader (GAIN Capital)
        • Rithmic
        • QUIK
        • SmartCOM
        • Trader WorkStation (Interactive Brokers)
        • Transaq Connector
    • Basic setup
      • Selecting a symbol
      • Selecting a timeframe
      • Linking windows
      • Setting up exit strategies
      • Setting offsets
    • Terminal
      • Order volumes preset
      • Configuration
        • How to create public configuration
      • General settings
      • Email notifications
      • Telegram alerts
      • Hotkeys Manager
      • Sound alerts
      • Symbols manager
  • 🖥️Windows
    • Chart
      • Chart trading
      • Toolbar setup
      • Chart theme
      • Chart settings
      • Scaling and moving the chart
      • Cluster chart
      • Cluster presets
      • Graphical objects in Chart window
        • Text
        • Ruler
        • Volume profile
        • Trend angle
        • Elliott Correction Wave
        • Elliott Impulse Wave
        • Fibonacci Fan
        • Fibonacci Extensions
        • Fibonacci Retracement
        • Fibonacci Time Zones
        • Linear Regression
      • Main indicators in Chart window
        • 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 Profile
        • VWAP
        • Weis Wave Volume
        • ZigZag
    • DOM
      • Selecting a trading account
      • Ruler
      • Multiplier
      • DOM settings
        • Main
        • Cluster
        • Trading
      • Stop Loss
      • Take Profit
      • Trigger orders
    • Watchlist
      • How to filter watchlist
    • SmartTape
    • Statistics
    • Volume search
    • All prices
    • Options board
  • 📋Tables
    • Orders
    • Executions
    • Positions
    • XPositions
    • Accounts
    • Limits
    • Player
    • Signals
    • Log
  • 🔍Video Tutorials
    • Terminal Basics
    • Charts and technical analysis
    • Charts, Trade Tape and Player
    • Trading in Tiger.com Windows
  • 💡Platform Updates
    • Version 7.0 Beta
    • Version 6.9
    • Version 6.8
    • Version 6.7
    • Version 6.6
    • Version 6.5
    • Version 6.4
    • Version 6.3
    • Version 6.2
    • Version 6.1
    • Version 6.0.2
    • Version 6.0.1
    • Version 6.0.0
    • Version 5.0.7
    • Version 4.5.15
  • ⌨️Development for Tiger.com Windows
    • Indicator examples
      • DepthOfMarket
      • Trades Flow
      • Volume Profiles
      • Cluster Search
      • Bar Search
      • VWAP
      • Bar Timer
      • Volume
      • Trades
      • Session color
      • Open Interest
      • Dynamic Levels
      • Delta
      • Cumulative Delta
      • Cluster Statistic
      • Bid Ask
      • External Chart
      • High Low
      • Histogram
    • Source examples
      • Moving Average
      • Stock
    • Examples of graphical objects
      • Fibonacci Extensions
      • Fibonacci Retracement
      • Vertical Line
      • Horizontal Line
      • Volume Profile
      • Rectangle
  • ❓Frequently Asked Questions
    • Questions about licenses
    • Questions about indicators
    • Questions about connections
    • Questions about trading
    • Error "Connection lost" when launching the terminal
    • Why do I need to set commission in the terminal?
    • How does automatic account selection work?
    • How do I optimize the terminal to improve performance?
    • How to use the Crypto license to trade on Binance
    • Which order types are available in Tiger.com?
    • How to set up chart auto-refresh for QUIK connection?
    • How do I enable Take Profit orders on Binance?
    • How does autoselection of data type work?
    • Troubles installing the terminal
    • What are the system requirements for the terminal?
    • How to provide Tiger.com Windows app logs for investigation?
    • Fixing Network Issues: How to Adjust DNS Settings
  • 📬Technical support
  • 💭Suggest an improvement
Powered by GitBook
On this page
  1. Development for Tiger.com Windows
  2. Indicator examples

External Chart

/--------------------------------------------------------------------------------
//
// Indicator ExternalChart. 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.Base.Enums;
using TigerTrade.Chart.Data;
using TigerTrade.Chart.Indicators.Common;
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 = "ExternalChartPeriodType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    public enum ExternalChartPeriodType
    {
        [EnumMember(Value = "Minute"), Description("Минута")]
        Minute,
        [EnumMember(Value = "Hour"), Description("Час")]
        Hour,
        [EnumMember(Value = "Day"), Description("День")]
        Day,
        [EnumMember(Value = "Week"), Description("Неделя")]
        Week,
        [EnumMember(Value = "Month"), Description("Месяц")]
        Month
    }
 
    [DataContract(Name = "ExternalChartBorderType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ExternalChartBorderType
    {
        [EnumMember(Value = "None"), Description("Скрыть")]
        None,
        [EnumMember(Value = "Box"), Description("Коробка")]
        Box,
        [EnumMember(Value = "ColoredBox"), Description("Коробка с раскраской")]
        ColoredBox,
        [EnumMember(Value = "Candle"), Description("Свеча")]
        Candle,
        [EnumMember(Value = "ColoredCandle"), Description("Свеча с раскраской")]
        ColoredCandle
    }
 
    [DataContract(Name = "ExternalChartIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("Z_ExternalChart", "*ExternalChart", true, Type = typeof(ExternalChartIndicator))]
    internal sealed class ExternalChartIndicator : IndicatorBase
    {
        private ExternalChartPeriodType _periodType;
 
        [DataMember(Name = "PeriodType")]
        [Category("Период"), DisplayName("Интервал")]
        public ExternalChartPeriodType PeriodType
        {
            get => _periodType;
            set
            {
                if (value == _periodType)
                {
                    return;
                }
 
                _periodType = value;
 
                _periodValue = _periodType == ExternalChartPeriodType.Minute ? 15 : 1;
 
                Clear();
 
                OnPropertyChanged();
                OnPropertyChanged(nameof(PeriodValue));
            }
        }
 
        private int _periodValue;
 
        [DataMember(Name = "PeriodValue")]
        [Category("Период"), DisplayName("Значение")]
        public int PeriodValue
        {
            get => _periodValue;
            set
            {
                value = Math.Max(1, value);
 
                if (value == _periodValue)
                {
                    return;
                }
 
                _periodValue = value;
 
                Clear();
 
                OnPropertyChanged();
            }
        }
 
        private bool _showBack;
 
        [DataMember(Name = "ShowBack")]
        [Category("Фон"), DisplayName("Отображать фон")]
        public bool ShowBack
        {
            get => _showBack;
            set
            {
                if (value == _showBack)
                {
                    return;
                }
 
                _showBack = value;
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _backBrush;
 
        private XColor _backColor;
 
        [DataMember(Name = "BackColor")]
        [Category("Фон"), DisplayName("Цвет фона")]
        public XColor BackColor
        {
            get => _backColor;
            set
            {
                if (value == _backColor)
                {
                    return;
                }
 
                _backColor = value;
 
                _backBrush = new XBrush(_backColor);
 
                OnPropertyChanged();
            }
        }
 
        private bool _showGrid;
 
        [DataMember(Name = "ShowGrid")]
        [Category("Сетка"), DisplayName("Отображать сетку")]
        public bool ShowGrid
        {
            get => _showGrid;
            set
            {
                if (value == _showGrid)
                {
                    return;
                }
 
                _showGrid = value;
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _gridBrush;
 
        private XPen _gridPen;
 
        private XColor _gridColor;
 
        [DataMember(Name = "GridColor")]
        [Category("Сетка"), DisplayName("Цвет Сетки")]
        public XColor GridColor
        {
            get => _gridColor;
            set
            {
                if (value == _gridColor)
                {
                    return;
                }
 
                _gridColor = value;
 
                _gridBrush = new XBrush(_gridColor);
 
                _gridPen = new XPen(_gridBrush, 1);
 
                OnPropertyChanged();
            }
        }
 
        private ExternalChartBorderType _borderType;
 
        [DataMember(Name = "BorderType")]
        [Category("Граница"), DisplayName("Тип границы")]
        public ExternalChartBorderType BorderType
        {
            get => _borderType;
            set
            {
                if (value == _borderType)
                {
                    return;
                }
 
                _borderType = value;
 
                OnPropertyChanged();
            }
        }
 
        private int _borderWidth;
 
        [DataMember(Name = "BorderWidth")]
        [Category("Граница"), DisplayName("Ширина границы")]
        public int BorderWidth
        {
            get => _borderWidth;
            set
            {
                value = Math.Max(1, value);
 
                if (value == _borderWidth)
                {
                    return;
                }
 
                _borderWidth = value;
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _borderBrush;
 
        private XColor _borderColor;
 
        [DataMember(Name = "BorderColor")]
        [Category("Граница"), DisplayName("Цвет границы")]
        public XColor BorderColor
        {
            get => _borderColor;
            set
            {
                if (value == _borderColor)
                {
                    return;
                }
 
                _borderColor = value;
 
                _borderBrush = new XBrush(_borderColor);
 
                OnPropertyChanged();
            }
        }
 
        [Browsable(false)]
        public override bool ShowIndicatorValues => false;
 
        [Browsable(false)]
        public override bool ShowIndicatorLabels => false;
 
        [Browsable(false)]
        public override IndicatorCalculation Calculation => IndicatorCalculation.OnPriceChange;
 
        private List<ExternalBar> _bars;
 
        private List<ExternalBar> Bars => _bars ?? (_bars = new List<ExternalBar>());
 
        public ExternalChartIndicator()
        {
            ShowIndicatorTitle = false;
 
            PeriodType = ExternalChartPeriodType.Hour;
            PeriodValue = 1;
 
            ShowBack = true;
            BackColor = Color.FromArgb(30, 70, 130, 180);
 
            ShowGrid = false;
            GridColor = Color.FromArgb(255, 70, 130, 180);
 
            BorderType = ExternalChartBorderType.ColoredBox;
            BorderWidth = 1;
            BorderColor = Color.FromArgb(255, 120, 120, 120);
        }
 
        private int _lastFullID;
 
        private void Clear()
        {
            _lastFullID = 0;
 
            Bars.Clear();
        }
 
        private int GetSequence(DateTime date, double offset)
        {
            var periodType = ChartPeriodType.Hour;
 
            switch (PeriodType)
            {
                case ExternalChartPeriodType.Minute:
 
                    periodType = ChartPeriodType.Minute;
 
                    break;
 
                case ExternalChartPeriodType.Hour:
 
                    periodType = ChartPeriodType.Hour;
 
                    break;
 
                case ExternalChartPeriodType.Day:
 
                    periodType = ChartPeriodType.Day;
 
                    break;
 
                case ExternalChartPeriodType.Week:
 
                    periodType = ChartPeriodType.Week;
 
                    break;
 
                case ExternalChartPeriodType.Month:
 
                    periodType = ChartPeriodType.Month;
 
                    break;
            }
 
            return DataProvider.Period.GetSequence(periodType, PeriodValue, date, offset);
        }
 
        protected override void Execute()
        {
            if (ClearData)
            {
                Clear();
            }
 
            if (Bars.Count > 0 && !Bars[Bars.Count - 1].Completed)
            {
                Bars.RemoveAt(Bars.Count - 1);
            }
 
            var timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
 
            var lastSequence = -1;
 
            for (var i = _lastFullID; i < DataProvider.Count; i++)
            {
                var cluster = DataProvider.GetCluster(i);
 
                var currSequence = GetSequence(cluster.Time, timeOffset);
 
                if (Bars.Count == 0 || currSequence != lastSequence)
                {
                    lastSequence = currSequence;
 
                    if (Bars.Count > 0 && i > _lastFullID)
                    {
                        _lastFullID = i;
 
                        Bars[Bars.Count - 1].Completed = true;
                    }
 
                    Bars.Add(new ExternalBar(i));
                }
 
                Bars[Bars.Count - 1].Update(cluster, i);
            }
        }
 
        public override void Render(DxVisualQueue visual)
        {
            if (Bars.Count == 0)
            {
                return;
            }
 
            var startIndex = Canvas.Stop;
            var endIndex = Canvas.Stop + Canvas.Count;
 
            var step = (decimal)DataProvider.Step;
 
            var columnWidth2 = Canvas.ColumnWidth / 2.0;
 
            var prevRight = int.MinValue;
 
            foreach (var bar in Bars)
            {
                if (bar.EndBar < startIndex || bar.StartBar > endIndex)
                {
                    continue;
                }
 
                var x1 = Canvas.GetX(bar.StartBar);
                var x2 = Canvas.GetX(bar.EndBar);
 
                var left = (int)(x1 - columnWidth2);
                var right = (int)(x2 + columnWidth2 - 1);
 
                if (prevRight != int.MinValue)
                {
                    left = prevRight;
                }
 
                prevRight = right;
 
                var centerX = (int)((x1 + x2) / 2.0);
 
                var isUp = bar.Open < bar.Close;
 
                var highY = (int)GetY(bar.High + step / 2m);
                var lowY = (int)GetY(bar.Low - step / 2m);
 
                var bodyHighY = isUp
                    ? (int)GetY(bar.Close + step / 2m)
                    : (int)GetY(bar.Open + step / 2m);
 
                var bodyLowY = !isUp
                    ? (int)GetY(bar.Close - step / 2m)
                    : (int)GetY(bar.Open - step / 2m);
 
                if (ShowBack)
                {
                    visual.FillRectangle(_backBrush,
                        new Rect(new Point(left, highY - 1), new Point(right, lowY)));
                }
 
                if (ShowGrid)
                {
                    for (var j = bar.High + step; j >= bar.Low; j -= step)
                    {
                        var currY = (int)GetY(j - step / 2m) - 1;
 
                        visual.DrawLine(_gridPen, new Point(left, currY), new Point(right, currY));
                    }
 
                    for (var j = bar.StartBar; j <= bar.EndBar; j++)
                    {
                        var barLeft = j == bar.StartBar ? left : Canvas.GetX(j) - columnWidth2 - 1;
 
                        visual.DrawLine(_gridPen, new Point(barLeft, highY - 1), new Point(barLeft, lowY));
 
                        if (j == bar.EndBar)
                        {
                            visual.DrawLine(_gridPen, new Point(right, highY - 1), new Point(right, lowY));
                        }
                    }
                }
 
                if (BorderType != ExternalChartBorderType.None)
                {
                    var borderBrush = _borderBrush;
 
                    if (BorderType == ExternalChartBorderType.ColoredCandle ||
                        BorderType == ExternalChartBorderType.ColoredBox)
                    {
                        borderBrush = new XBrush(isUp ? Canvas.Theme.ClusterUpBarColor : Canvas.Theme.ClusterDownBarColor);
                    }
 
                    var borderPen = new XPen(borderBrush, BorderWidth);
 
                    if (BorderType == ExternalChartBorderType.Candle ||
                        BorderType == ExternalChartBorderType.ColoredCandle)
                    {
                        var correct = (int)Math.Ceiling(_borderWidth / 2.0);
 
                        visual.DrawRectangle(borderPen, new Rect(new Point(left + correct, bodyHighY), new Point(right - correct, bodyLowY)));
 
                        visual.DrawLine(borderPen, new Point(centerX, highY), new Point(centerX, bodyHighY));
 
                        visual.DrawLine(borderPen, new Point(centerX, bodyLowY), new Point(centerX, lowY));
                    }
                    else if (BorderType == ExternalChartBorderType.Box ||
                             BorderType == ExternalChartBorderType.ColoredBox)
                    {
                        var correct = (int)Math.Ceiling(_borderWidth / 2.0);
 
                        visual.DrawRectangle(borderPen, new Rect(new Point(left + correct, highY), new Point(right - correct, lowY)));
                    }
                }
            }
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (ExternalChartIndicator)indicator;
 
            PeriodType = i.PeriodType;
            PeriodValue = i.PeriodValue;
 
            ShowBack = i.ShowBack;
            BackColor = i.BackColor;
 
            ShowGrid = i.ShowGrid;
            GridColor = i.GridColor;
 
            BorderType = i.BorderType;
            BorderWidth = i.BorderWidth;
            BackColor = i.BorderColor;
 
            base.CopyTemplate(indicator, style);
        }
 
        private class ExternalBar
        {
            public readonly int StartBar;
            public int EndBar;
            public bool Completed;
 
            public decimal Open;
            public decimal High;
            public decimal Low;
            public decimal Close;
 
            private bool _new;
 
            public ExternalBar(int startBar)
            {
                StartBar = startBar;
 
                _new = true;
            }
 
            public void Update(IChartCluster cluster, int bar)
            {
                if (_new)
                {
                    Open = cluster.Open;
                    High = cluster.High;
                    Low = cluster.Low;
 
                    _new = false;
                }
                else
                {
                    High = Math.Max(High, cluster.High);
                    Low = Math.Min(Low, cluster.Low);
                }
 
                Close = cluster.Close;
 
                EndBar = bar;
            }
        }
    }
}
PreviousBid AskNextHigh Low

Last updated 2 years ago

⌨️