ExternalChart

Тема в разделе "Примеры индикаторов", создана пользователем Support, 3 июл 2019.

  1. Support

    Support Администратор
    Команда форума

    Регистрация:
    5 сен 2015
    Сообщения:
    984
    Симпатии:
    185
    Код индикатора ExternalChart
    1. //--------------------------------------------------------------------------------
    2. //
    3. // Индикатор ExternalChart. Copyright (c) 2019 Ilya Smirnov. All rights reserved.
    4. //
    5. //--------------------------------------------------------------------------------
    6.  
    7. using System;
    8. using System.Collections.Generic;
    9. using System.ComponentModel;
    10. using System.Runtime.Serialization;
    11. using System.Windows;
    12. using System.Windows.Media;
    13. using TigerTrade.Chart.Base.Enums;
    14. using TigerTrade.Chart.Data;
    15. using TigerTrade.Chart.Indicators.Common;
    16. using TigerTrade.Chart.Indicators.Enums;
    17. using TigerTrade.Core.UI.Converters;
    18. using TigerTrade.Core.Utils.Time;
    19. using TigerTrade.Dx;
    20.  
    21. namespace TigerTrade.Chart.Indicators.Custom
    22. {
    23.     [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    24.     [DataContract(Name = "ExternalChartPeriodType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    25.     public enum ExternalChartPeriodType
    26.     {
    27.         [EnumMember(Value = "Minute"), Description("Минута")]
    28.         Minute,
    29.         [EnumMember(Value = "Hour"), Description("Час")]
    30.         Hour,
    31.         [EnumMember(Value = "Day"), Description("День")]
    32.         Day,
    33.         [EnumMember(Value = "Week"), Description("Неделя")]
    34.         Week,
    35.         [EnumMember(Value = "Month"), Description("Месяц")]
    36.         Month
    37.     }
    38.  
    39.     [DataContract(Name = "ExternalChartBorderType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    40.     [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    41.     public enum ExternalChartBorderType
    42.     {
    43.         [EnumMember(Value = "None"), Description("Скрыть")]
    44.         None,
    45.         [EnumMember(Value = "Box"), Description("Коробка")]
    46.         Box,
    47.         [EnumMember(Value = "ColoredBox"), Description("Коробка с раскраской")]
    48.         ColoredBox,
    49.         [EnumMember(Value = "Candle"), Description("Свеча")]
    50.         Candle,
    51.         [EnumMember(Value = "ColoredCandle"), Description("Свеча с раскраской")]
    52.         ColoredCandle
    53.     }
    54.  
    55.     [DataContract(Name = "ExternalChartIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    56.     [Indicator("Z_ExternalChart", "*ExternalChart", true, Type = typeof(ExternalChartIndicator))]
    57.     internal sealed class ExternalChartIndicator : IndicatorBase
    58.     {
    59.         private ExternalChartPeriodType _periodType;
    60.  
    61.         [DataMember(Name = "PeriodType")]
    62.         [Category("Период"), DisplayName("Интервал")]
    63.         public ExternalChartPeriodType PeriodType
    64.         {
    65.             get => _periodType;
    66.             set
    67.             {
    68.                 if (value == _periodType)
    69.                 {
    70.                     return;
    71.                 }
    72.  
    73.                 _periodType = value;
    74.  
    75.                 _periodValue = _periodType == ExternalChartPeriodType.Minute ? 15 : 1;
    76.  
    77.                 Clear();
    78.  
    79.                 OnPropertyChanged();
    80.                 OnPropertyChanged(nameof(PeriodValue));
    81.             }
    82.         }
    83.  
    84.         private int _periodValue;
    85.  
    86.         [DataMember(Name = "PeriodValue")]
    87.         [Category("Период"), DisplayName("Значение")]
    88.         public int PeriodValue
    89.         {
    90.             get => _periodValue;
    91.             set
    92.             {
    93.                 value = Math.Max(1, value);
    94.  
    95.                 if (value == _periodValue)
    96.                 {
    97.                     return;
    98.                 }
    99.  
    100.                 _periodValue = value;
    101.  
    102.                 Clear();
    103.  
    104.                 OnPropertyChanged();
    105.             }
    106.         }
    107.  
    108.         private bool _showBack;
    109.  
    110.         [DataMember(Name = "ShowBack")]
    111.         [Category("Фон"), DisplayName("Отображать фон")]
    112.         public bool ShowBack
    113.         {
    114.             get => _showBack;
    115.             set
    116.             {
    117.                 if (value == _showBack)
    118.                 {
    119.                     return;
    120.                 }
    121.  
    122.                 _showBack = value;
    123.  
    124.                 OnPropertyChanged();
    125.             }
    126.         }
    127.  
    128.         private XBrush _backBrush;
    129.  
    130.         private XColor _backColor;
    131.  
    132.         [DataMember(Name = "BackColor")]
    133.         [Category("Фон"), DisplayName("Цвет фона")]
    134.         public XColor BackColor
    135.         {
    136.             get => _backColor;
    137.             set
    138.             {
    139.                 if (value == _backColor)
    140.                 {
    141.                     return;
    142.                 }
    143.  
    144.                 _backColor = value;
    145.  
    146.                 _backBrush = new XBrush(_backColor);
    147.  
    148.                 OnPropertyChanged();
    149.             }
    150.         }
    151.  
    152.         private bool _showGrid;
    153.  
    154.         [DataMember(Name = "ShowGrid")]
    155.         [Category("Сетка"), DisplayName("Отображать сетку")]
    156.         public bool ShowGrid
    157.         {
    158.             get => _showGrid;
    159.             set
    160.             {
    161.                 if (value == _showGrid)
    162.                 {
    163.                     return;
    164.                 }
    165.  
    166.                 _showGrid = value;
    167.  
    168.                 OnPropertyChanged();
    169.             }
    170.         }
    171.  
    172.         private XBrush _gridBrush;
    173.  
    174.         private XPen _gridPen;
    175.  
    176.         private XColor _gridColor;
    177.  
    178.         [DataMember(Name = "GridColor")]
    179.         [Category("Сетка"), DisplayName("Цвет Сетки")]
    180.         public XColor GridColor
    181.         {
    182.             get => _gridColor;
    183.             set
    184.             {
    185.                 if (value == _gridColor)
    186.                 {
    187.                     return;
    188.                 }
    189.  
    190.                 _gridColor = value;
    191.  
    192.                 _gridBrush = new XBrush(_gridColor);
    193.  
    194.                 _gridPen = new XPen(_gridBrush, 1);
    195.  
    196.                 OnPropertyChanged();
    197.             }
    198.         }
    199.  
    200.         private ExternalChartBorderType _borderType;
    201.  
    202.         [DataMember(Name = "BorderType")]
    203.         [Category("Граница"), DisplayName("Тип границы")]
    204.         public ExternalChartBorderType BorderType
    205.         {
    206.             get => _borderType;
    207.             set
    208.             {
    209.                 if (value == _borderType)
    210.                 {
    211.                     return;
    212.                 }
    213.  
    214.                 _borderType = value;
    215.  
    216.                 OnPropertyChanged();
    217.             }
    218.         }
    219.  
    220.         private int _borderWidth;
    221.  
    222.         [DataMember(Name = "BorderWidth")]
    223.         [Category("Граница"), DisplayName("Ширина границы")]
    224.         public int BorderWidth
    225.         {
    226.             get => _borderWidth;
    227.             set
    228.             {
    229.                 value = Math.Max(1, value);
    230.  
    231.                 if (value == _borderWidth)
    232.                 {
    233.                     return;
    234.                 }
    235.  
    236.                 _borderWidth = value;
    237.  
    238.                 OnPropertyChanged();
    239.             }
    240.         }
    241.  
    242.         private XBrush _borderBrush;
    243.  
    244.         private XColor _borderColor;
    245.  
    246.         [DataMember(Name = "BorderColor")]
    247.         [Category("Граница"), DisplayName("Цвет границы")]
    248.         public XColor BorderColor
    249.         {
    250.             get => _borderColor;
    251.             set
    252.             {
    253.                 if (value == _borderColor)
    254.                 {
    255.                     return;
    256.                 }
    257.  
    258.                 _borderColor = value;
    259.  
    260.                 _borderBrush = new XBrush(_borderColor);
    261.  
    262.                 OnPropertyChanged();
    263.             }
    264.         }
    265.  
    266.         [Browsable(false)]
    267.         public override bool ShowIndicatorValues => false;
    268.  
    269.         [Browsable(false)]
    270.         public override bool ShowIndicatorLabels => false;
    271.  
    272.         [Browsable(false)]
    273.         public override IndicatorCalculation Calculation => IndicatorCalculation.OnPriceChange;
    274.  
    275.         private List<ExternalBar> _bars;
    276.  
    277.         private List<ExternalBar> Bars => _bars ?? (_bars = new List<ExternalBar>());
    278.  
    279.         public ExternalChartIndicator()
    280.         {
    281.             ShowIndicatorTitle = false;
    282.  
    283.             PeriodType = ExternalChartPeriodType.Hour;
    284.             PeriodValue = 1;
    285.  
    286.             ShowBack = true;
    287.             BackColor = Color.FromArgb(30, 70, 130, 180);
    288.  
    289.             ShowGrid = false;
    290.             GridColor = Color.FromArgb(255, 70, 130, 180);
    291.  
    292.             BorderType = ExternalChartBorderType.ColoredBox;
    293.             BorderWidth = 1;
    294.             BorderColor = Color.FromArgb(255, 120, 120, 120);
    295.         }
    296.  
    297.         private int _lastFullID;
    298.  
    299.         private void Clear()
    300.         {
    301.             _lastFullID = 0;
    302.  
    303.             Bars.Clear();
    304.         }
    305.  
    306.         private int GetSequence(DateTime date, double offset)
    307.         {
    308.             var periodType = ChartPeriodType.Hour;
    309.  
    310.             switch (PeriodType)
    311.             {
    312.                 case ExternalChartPeriodType.Minute:
    313.  
    314.                     periodType = ChartPeriodType.Minute;
    315.  
    316.                     break;
    317.  
    318.                 case ExternalChartPeriodType.Hour:
    319.  
    320.                     periodType = ChartPeriodType.Hour;
    321.  
    322.                     break;
    323.  
    324.                 case ExternalChartPeriodType.Day:
    325.  
    326.                     periodType = ChartPeriodType.Day;
    327.  
    328.                     break;
    329.  
    330.                 case ExternalChartPeriodType.Week:
    331.  
    332.                     periodType = ChartPeriodType.Week;
    333.  
    334.                     break;
    335.  
    336.                 case ExternalChartPeriodType.Month:
    337.  
    338.                     periodType = ChartPeriodType.Month;
    339.  
    340.                     break;
    341.             }
    342.  
    343.             return DataProvider.Period.GetSequence(periodType, PeriodValue, date, offset);
    344.         }
    345.  
    346.         protected override void Execute()
    347.         {
    348.             if (ClearData)
    349.             {
    350.                 Clear();
    351.             }
    352.  
    353.             if (Bars.Count > 0 && !Bars[Bars.Count - 1].Completed)
    354.             {
    355.                 Bars.RemoveAt(Bars.Count - 1);
    356.             }
    357.  
    358.             var timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
    359.  
    360.             var lastSequence = -1;
    361.  
    362.             for (var i = _lastFullID; i < DataProvider.Count; i++)
    363.             {
    364.                 var cluster = DataProvider.GetCluster(i);
    365.  
    366.                 var currSequence = GetSequence(cluster.Time, timeOffset);
    367.  
    368.                 if (Bars.Count == 0 || currSequence != lastSequence)
    369.                 {
    370.                     lastSequence = currSequence;
    371.  
    372.                     if (Bars.Count > 0 && i > _lastFullID)
    373.                     {
    374.                         _lastFullID = i;
    375.  
    376.                         Bars[Bars.Count - 1].Completed = true;
    377.                     }
    378.  
    379.                     Bars.Add(new ExternalBar(i));
    380.                 }
    381.  
    382.                 Bars[Bars.Count - 1].Update(cluster, i);
    383.             }
    384.         }
    385.  
    386.         public override void Render(DxVisualQueue visual)
    387.         {
    388.             if (Bars.Count == 0)
    389.             {
    390.                 return;
    391.             }
    392.  
    393.             var startIndex = Canvas.Stop;
    394.             var endIndex = Canvas.Stop + Canvas.Count;
    395.  
    396.             var step = (decimal)DataProvider.Step;
    397.  
    398.             var columnWidth2 = Canvas.ColumnWidth / 2.0;
    399.  
    400.             var prevRight = int.MinValue;
    401.  
    402.             foreach (var bar in Bars)
    403.             {
    404.                 if (bar.EndBar < startIndex || bar.StartBar > endIndex)
    405.                 {
    406.                     continue;
    407.                 }
    408.  
    409.                 var x1 = Canvas.GetX(bar.StartBar);
    410.                 var x2 = Canvas.GetX(bar.EndBar);
    411.  
    412.                 var left = (int)(x1 - columnWidth2);
    413.                 var right = (int)(x2 + columnWidth2 - 1);
    414.  
    415.                 if (prevRight != int.MinValue)
    416.                 {
    417.                     left = prevRight;
    418.                 }
    419.  
    420.                 prevRight = right;
    421.  
    422.                 var centerX = (int)((x1 + x2) / 2.0);
    423.  
    424.                 var isUp = bar.Open < bar.Close;
    425.  
    426.                 var highY = (int)GetY(bar.High + step / 2m);
    427.                 var lowY = (int)GetY(bar.Low - step / 2m);
    428.  
    429.                 var bodyHighY = isUp
    430.                     ? (int)GetY(bar.Close + step / 2m)
    431.                     : (int)GetY(bar.Open + step / 2m);
    432.  
    433.                 var bodyLowY = !isUp
    434.                     ? (int)GetY(bar.Close - step / 2m)
    435.                     : (int)GetY(bar.Open - step / 2m);
    436.  
    437.                 if (ShowBack)
    438.                 {
    439.                     visual.FillRectangle(_backBrush,
    440.                         new Rect(new Point(left, highY - 1), new Point(right, lowY)));
    441.                 }
    442.  
    443.                 if (ShowGrid)
    444.                 {
    445.                     for (var j = bar.High + step; j >= bar.Low; j -= step)
    446.                     {
    447.                         var currY = (int)GetY(j - step / 2m) - 1;
    448.  
    449.                         visual.DrawLine(_gridPen, new Point(left, currY), new Point(right, currY));
    450.                     }
    451.  
    452.                     for (var j = bar.StartBar; j <= bar.EndBar; j++)
    453.                     {
    454.                         var barLeft = j == bar.StartBar ? left : Canvas.GetX(j) - columnWidth2 - 1;
    455.  
    456.                         visual.DrawLine(_gridPen, new Point(barLeft, highY - 1), new Point(barLeft, lowY));
    457.  
    458.                         if (j == bar.EndBar)
    459.                         {
    460.                             visual.DrawLine(_gridPen, new Point(right, highY - 1), new Point(right, lowY));
    461.                         }
    462.                     }
    463.                 }
    464.  
    465.                 if (BorderType != ExternalChartBorderType.None)
    466.                 {
    467.                     var borderBrush = _borderBrush;
    468.  
    469.                     if (BorderType == ExternalChartBorderType.ColoredCandle ||
    470.                         BorderType == ExternalChartBorderType.ColoredBox)
    471.                     {
    472.                         borderBrush = new XBrush(isUp ? Canvas.Theme.ClusterUpBarColor : Canvas.Theme.ClusterDownBarColor);
    473.                     }
    474.  
    475.                     var borderPen = new XPen(borderBrush, BorderWidth);
    476.  
    477.                     if (BorderType == ExternalChartBorderType.Candle ||
    478.                         BorderType == ExternalChartBorderType.ColoredCandle)
    479.                     {
    480.                         var correct = (int)Math.Ceiling(_borderWidth / 2.0);
    481.  
    482.                         visual.DrawRectangle(borderPen, new Rect(new Point(left + correct, bodyHighY), new Point(right - correct, bodyLowY)));
    483.  
    484.                         visual.DrawLine(borderPen, new Point(centerX, highY), new Point(centerX, bodyHighY));
    485.  
    486.                         visual.DrawLine(borderPen, new Point(centerX, bodyLowY), new Point(centerX, lowY));
    487.                     }
    488.                     else if (BorderType == ExternalChartBorderType.Box ||
    489.                              BorderType == ExternalChartBorderType.ColoredBox)
    490.                     {
    491.                         var correct = (int)Math.Ceiling(_borderWidth / 2.0);
    492.  
    493.                         visual.DrawRectangle(borderPen, new Rect(new Point(left + correct, highY), new Point(right - correct, lowY)));
    494.                     }
    495.                 }
    496.             }
    497.         }
    498.  
    499.         public override void CopyTemplate(IndicatorBase indicator, bool style)
    500.         {
    501.             var i = (ExternalChartIndicator)indicator;
    502.  
    503.             PeriodType = i.PeriodType;
    504.             PeriodValue = i.PeriodValue;
    505.  
    506.             ShowBack = i.ShowBack;
    507.             BackColor = i.BackColor;
    508.  
    509.             ShowGrid = i.ShowGrid;
    510.             GridColor = i.GridColor;
    511.  
    512.             BorderType = i.BorderType;
    513.             BorderWidth = i.BorderWidth;
    514.             BackColor = i.BorderColor;
    515.  
    516.             base.CopyTemplate(indicator, style);
    517.         }
    518.  
    519.         private class ExternalBar
    520.         {
    521.             public readonly int StartBar;
    522.             public int EndBar;
    523.             public bool Completed;
    524.  
    525.             public decimal Open;
    526.             public decimal High;
    527.             public decimal Low;
    528.             public decimal Close;
    529.  
    530.             private bool _new;
    531.  
    532.             public ExternalBar(int startBar)
    533.             {
    534.                 StartBar = startBar;
    535.  
    536.                 _new = true;
    537.             }
    538.  
    539.             public void Update(IChartCluster cluster, int bar)
    540.             {
    541.                 if (_new)
    542.                 {
    543.                     Open = cluster.Open;
    544.                     High = cluster.High;
    545.                     Low = cluster.Low;
    546.  
    547.                     _new = false;
    548.                 }
    549.                 else
    550.                 {
    551.                     High = Math.Max(High, cluster.High);
    552.                     Low = Math.Min(Low, cluster.Low);
    553.                 }
    554.  
    555.                 Close = cluster.Close;
    556.  
    557.                 EndBar = bar;
    558.             }
    559.         }
    560.     }
    561. }
     
    #1 Support, 3 июл 2019
    Последнее редактирование: 6 июл 2019