Trades Indicator Code
//------------------------------------------------------------------------------ // // Trades. Copyright (c) 2019 Ilya Smirnov. 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); } } }