DynamicLevels

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

  1. Support

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

    Регистрация:
    5 сен 2015
    Сообщения:
    1 023
    Симпатии:
    195
    Код индикатора DynamicLevels
    1. //--------------------------------------------------------------------------------
    2. //
    3. // Индикатор DynamicLevels. 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.Media;
    12. using TigerTrade.Chart.Base;
    13. using TigerTrade.Chart.Base.Enums;
    14. using TigerTrade.Chart.Data;
    15. using TigerTrade.Chart.Indicators.Common;
    16. using TigerTrade.Chart.Indicators.Drawings;
    17. using TigerTrade.Chart.Indicators.Drawings.Enums;
    18. using TigerTrade.Chart.Indicators.Enums;
    19. using TigerTrade.Core.UI.Converters;
    20. using TigerTrade.Core.Utils.Time;
    21. using TigerTrade.Dx;
    22.  
    23. namespace TigerTrade.Chart.Indicators.Custom
    24. {
    25.     [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    26.     [DataContract(Name = "DynamicLevelsPeriodType", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    27.     public enum DynamicLevelsPeriodType
    28.     {
    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.         [EnumMember(Value = "AllBars"), Description("Все бары")]
    38.         AllBars,
    39.     }
    40.  
    41.     [DataContract(Name = "DynamicLevelsIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    42.     [Indicator("X_DynamicLevels", "*DynamicLevels", true, Type = typeof(DynamicLevelsIndicator))]
    43.     internal sealed class DynamicLevelsIndicator : IndicatorBase
    44.     {
    45.         private DynamicLevelsPeriodType _period;
    46.  
    47.         [DataMember(Name = "Period")]
    48.         [Category("Параметры"), DisplayName("Период")]
    49.         public DynamicLevelsPeriodType Period
    50.         {
    51.             get => _period;
    52.             set
    53.             {
    54.                 if (value == _period)
    55.                 {
    56.                     return;
    57.                 }
    58.  
    59.                 _period = value;
    60.  
    61.                 _lastDataWrapper?.Clear();
    62.  
    63.                 OnPropertyChanged();
    64.             }
    65.         }
    66.  
    67.         private bool _showValueArea;
    68.  
    69.         [DataMember(Name = "ShowValueArea")]
    70.         [Category("ChartIndicatorsValueArea"), DisplayName("Отображать Value Area")]
    71.         public bool ShowValueArea
    72.         {
    73.             get => _showValueArea;
    74.             set
    75.             {
    76.                 if (value == _showValueArea)
    77.                 {
    78.                     return;
    79.                 }
    80.  
    81.                 _showValueArea = value;
    82.  
    83.                 _lastDataWrapper?.Clear();
    84.  
    85.                 OnPropertyChanged();
    86.             }
    87.         }
    88.  
    89.         private int _valueAreaPercent;
    90.  
    91.         [DataMember(Name = "ValueAreaPercent")]
    92.         [Category("ChartIndicatorsValueArea"), DisplayName("ValueArea %")]
    93.         public int ValueAreaPercent
    94.         {
    95.             get => _valueAreaPercent;
    96.             set
    97.             {
    98.                 value = Math.Max(0, Math.Min(100, value));
    99.  
    100.                 if (value == 0)
    101.                 {
    102.                     value = 70;
    103.                 }
    104.  
    105.                 if (value == _valueAreaPercent)
    106.                 {
    107.                     return;
    108.                 }
    109.  
    110.                 _valueAreaPercent = value;
    111.  
    112.                 _lastDataWrapper?.Clear();
    113.  
    114.                 OnPropertyChanged();
    115.             }
    116.         }
    117.  
    118.         private XColor _valueAreaBackColor;
    119.  
    120.         [DataMember(Name = "ValueAreaBackColor")]
    121.         [Category("ChartIndicatorsValueArea"), DisplayName("Цвет фона")]
    122.         public XColor ValueAreaBackColor
    123.         {
    124.             get => _valueAreaBackColor;
    125.             set
    126.             {
    127.                 if (value == _valueAreaBackColor)
    128.                 {
    129.                     return;
    130.                 }
    131.  
    132.                 _valueAreaBackColor = value;
    133.  
    134.                 OnPropertyChanged();
    135.             }
    136.         }
    137.  
    138.         private XColor _valueAreaBorderColor;
    139.  
    140.         [DataMember(Name = "ValueAreaBorderColor")]
    141.         [Category("ChartIndicatorsValueArea"), DisplayName("Цвет границы")]
    142.         public XColor ValueAreaBorderColor
    143.         {
    144.             get => _valueAreaBorderColor;
    145.             set
    146.             {
    147.                 if (value == _valueAreaBorderColor)
    148.                 {
    149.                     return;
    150.                 }
    151.  
    152.                 _valueAreaBorderColor = value;
    153.  
    154.                 OnPropertyChanged();
    155.             }
    156.         }
    157.  
    158.         private int _valueAreaBorderWidth;
    159.  
    160.         [DataMember(Name = "ValueAreaBorderWidth")]
    161.         [Category("ChartIndicatorsValueArea"), DisplayName("Ширина границы")]
    162.         public int ValueAreaBorderWidth
    163.         {
    164.             get => _valueAreaBorderWidth;
    165.             set
    166.             {
    167.                 value = Math.Max(0, Math.Min(10, value));
    168.  
    169.                 if (value == _valueAreaBorderWidth)
    170.                 {
    171.                     return;
    172.                 }
    173.  
    174.                 _valueAreaBorderWidth = value;
    175.  
    176.                 OnPropertyChanged();
    177.             }
    178.         }
    179.  
    180.         private bool _showPoc;
    181.  
    182.         [DataMember(Name = "ShowPoc")]
    183.         [Category("ChartIndicatorsPoc"), DisplayName("Отображать POC")]
    184.         public bool ShowPoc
    185.         {
    186.             get => _showPoc;
    187.             set
    188.             {
    189.                 if (value == _showPoc)
    190.                 {
    191.                     return;
    192.                 }
    193.  
    194.                 _showPoc = value;
    195.  
    196.                 OnPropertyChanged();
    197.             }
    198.         }
    199.  
    200.         private XColor _pocLineColor;
    201.  
    202.         [DataMember(Name = "PocLineColor")]
    203.         [Category("ChartIndicatorsPoc"), DisplayName("Цвет линии")]
    204.         public XColor PocLineColor
    205.         {
    206.             get => _pocLineColor;
    207.             set
    208.             {
    209.                 if (value == _pocLineColor)
    210.                 {
    211.                     return;
    212.                 }
    213.  
    214.                 _pocLineColor = value;
    215.  
    216.                 OnPropertyChanged();
    217.             }
    218.         }
    219.  
    220.         private int _pocLineWidth;
    221.  
    222.         [DataMember(Name = "PocLineWidth")]
    223.         [Category("ChartIndicatorsPoc"), DisplayName("Толщина линии")]
    224.         public int PocLineWidth
    225.         {
    226.             get => _pocLineWidth;
    227.             set
    228.             {
    229.                 value = Math.Max(1, Math.Min(10, value));
    230.  
    231.                 if (value == _pocLineWidth)
    232.                 {
    233.                     return;
    234.                 }
    235.  
    236.                 _pocLineWidth = value;
    237.  
    238.                 OnPropertyChanged();
    239.             }
    240.         }
    241.  
    242.         [Browsable(false)]
    243.         public override IndicatorCalculation Calculation => IndicatorCalculation.OnBarClose;
    244.  
    245.         public DynamicLevelsIndicator()
    246.         {
    247.             Period = DynamicLevelsPeriodType.Day;
    248.  
    249.             ShowValueArea = true;
    250.             ValueAreaPercent = 70;
    251.  
    252.             ValueAreaBackColor = Color.FromArgb(50, 255, 255, 255);
    253.             ValueAreaBorderColor = Colors.Black;
    254.             ValueAreaBorderWidth = 1;
    255.  
    256.             ShowPoc = true;
    257.  
    258.             PocLineColor = Colors.Black;
    259.             PocLineWidth = 1;
    260.         }
    261.  
    262.         private class LastDataWrapper
    263.         {
    264.             public double[] Vah;
    265.             public double[] Val;
    266.             public double[] Poc;
    267.  
    268.             public bool[] Splits;
    269.  
    270.             public int LastSequence;
    271.             public int LastIndex;
    272.             public int LastCount;
    273.  
    274.             public readonly List<DynamicCluster> Clusters = new List<DynamicCluster>();
    275.  
    276.             public LastDataWrapper()
    277.             {
    278.                 Clear();
    279.             }
    280.  
    281.             public void Clear()
    282.             {
    283.                 LastSequence = -1;
    284.                 LastIndex = 0;
    285.                 LastCount = 0;
    286.  
    287.                 Vah = new double[0];
    288.                 Val = new double[0];
    289.                 Poc = new double[0];
    290.  
    291.                 Splits = new bool[0];
    292.  
    293.                 Clusters.Clear();
    294.             }
    295.  
    296.             public void Prepare(int count, double step)
    297.             {
    298.                 LastIndex = Math.Max(0, count - 1);
    299.                 LastCount = count;
    300.  
    301.                 Vah = new double[count];
    302.                 Val = new double[count];
    303.                 Poc = new double[count];
    304.  
    305.                 Splits = new bool[count];
    306.  
    307.                 for (var i = 0; i < count - 1; i++)
    308.                 {
    309.                     var cluster = Clusters[i];
    310.  
    311.                     Vah[i] = cluster.Vah * step;
    312.                     Val[i] = cluster.Val * step;
    313.                     Poc[i] = cluster.Poc * step;
    314.  
    315.                     Splits[i] = cluster.Split;
    316.                 }
    317.  
    318.                 if (count > 1)
    319.                 {
    320.                     Vah[count - 1] = Vah[count - 2];
    321.                     Val[count - 1] = Val[count - 2];
    322.                     Poc[count - 1] = Poc[count - 2];
    323.                 }
    324.             }
    325.         }
    326.  
    327.         private LastDataWrapper _lastDataWrapper;
    328.  
    329.         protected override void Execute()
    330.         {
    331.             if (ClearData)
    332.             {
    333.                 _lastDataWrapper = null;
    334.             }
    335.  
    336.             if (_lastDataWrapper == null)
    337.             {
    338.                 _lastDataWrapper = new LastDataWrapper();
    339.             }
    340.  
    341.             var date = Helper.Date;
    342.  
    343.             var timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
    344.  
    345.             if (date.Length > _lastDataWrapper.LastCount)
    346.             {
    347.                 for (var i = _lastDataWrapper.LastIndex; i < date.Length - 1; i++)
    348.                 {
    349.                     var sequence = -1;
    350.  
    351.                     switch (Period)
    352.                     {
    353.                         case DynamicLevelsPeriodType.Hour:
    354.  
    355.                             sequence = DataProvider.Period.GetSequence(ChartPeriodType.Hour, 1, date[i], timeOffset);
    356.  
    357.                             break;
    358.  
    359.                         case DynamicLevelsPeriodType.Day:
    360.  
    361.                             sequence = DataProvider.Period.GetSequence(ChartPeriodType.Day, 1, date[i], timeOffset);
    362.  
    363.                             break;
    364.  
    365.                         case DynamicLevelsPeriodType.Week:
    366.  
    367.                             sequence = DataProvider.Period.GetSequence(ChartPeriodType.Week, 1, date[i], timeOffset);
    368.  
    369.                             break;
    370.  
    371.                         case DynamicLevelsPeriodType.Month:
    372.  
    373.                             sequence = DataProvider.Period.GetSequence(ChartPeriodType.Month, 1, date[i], timeOffset);
    374.  
    375.                             break;
    376.                     }
    377.  
    378.                     var currCluster = DataProvider.GetRawCluster(i);
    379.  
    380.                     var prevCluster = i > 0 ? _lastDataWrapper.Clusters[i - 1] : null;
    381.  
    382.                     var split = false;
    383.  
    384.                     if (sequence != _lastDataWrapper.LastSequence)
    385.                     {
    386.                         prevCluster = null;
    387.  
    388.                         _lastDataWrapper.LastSequence = sequence;
    389.  
    390.                         split = true;
    391.                     }
    392.  
    393.                     var newCluster = new DynamicCluster(prevCluster)
    394.                     {
    395.                         Split = split
    396.                     };
    397.  
    398.                     newCluster.AddCluster(currCluster);
    399.  
    400.                     newCluster.UpdateData();
    401.  
    402.                     if (ShowValueArea)
    403.                     {
    404.                         newCluster.UpdateValueArea(ValueAreaPercent / 100.0);
    405.                     }
    406.  
    407.                     if (_lastDataWrapper.Clusters.Count == date.Length)
    408.                     {
    409.                         _lastDataWrapper.Clusters[i] = newCluster;
    410.                     }
    411.                     else
    412.                     {
    413.                         _lastDataWrapper.Clusters.Add(newCluster);
    414.  
    415.                         if (_lastDataWrapper.Clusters.Count > 1)
    416.                         {
    417.                             _lastDataWrapper.Clusters[_lastDataWrapper.Clusters.Count - 2].ClearItems();
    418.                         }
    419.                     }
    420.                 }
    421.  
    422.                 _lastDataWrapper.Prepare(date.Length, DataProvider.Step);
    423.             }
    424.  
    425.             if (ShowValueArea)
    426.             {
    427.                 var vaData = new IndicatorSeriesData(_lastDataWrapper.Vah, new ChartRegion(ValueAreaBackColor))
    428.                 {
    429.                     Style = { DisableMinMax = true },
    430.                     ["L"] = _lastDataWrapper.Val
    431.                 };
    432.  
    433.                 Series.Add(vaData);
    434.  
    435.                 if (ValueAreaBorderWidth > 0)
    436.                 {
    437.                     var vahData = new IndicatorSeriesData(_lastDataWrapper.Vah,
    438.                         new ChartSeries(ChartSeriesType.Line, ValueAreaBorderColor)
    439.                         {
    440.                             Width = ValueAreaBorderWidth
    441.                         })
    442.                     {
    443.                         Style =
    444.                         {
    445.                             DisableMinMax = true
    446.                         }
    447.                     };
    448.  
    449.                     var valData = new IndicatorSeriesData(_lastDataWrapper.Val,
    450.                         new ChartSeries(ChartSeriesType.Line, ValueAreaBorderColor)
    451.                         {
    452.                             Width = ValueAreaBorderWidth
    453.                         })
    454.                     {
    455.                         Style =
    456.                         {
    457.                             DisableMinMax = true
    458.                         }
    459.                     };
    460.  
    461.                     Series.Add(vahData, valData);
    462.                 }
    463.             }
    464.  
    465.             if (ShowPoc)
    466.             {
    467.                 var pocData = new IndicatorSeriesData(_lastDataWrapper.Poc,
    468.                     new ChartSeries(ChartSeriesType.Line, PocLineColor))
    469.                 {
    470.                     Style =
    471.                     {
    472.                         DisableMinMax = true,
    473.                         StraightLine = true,
    474.                         LineWidth = PocLineWidth
    475.                     }
    476.                 };
    477.  
    478.                 Series.Add(pocData);
    479.             }
    480.  
    481.             foreach (var series in Series)
    482.             {
    483.                 series.UserData["S"] = _lastDataWrapper.Splits;
    484.                 series.UserData["SE"] = true;
    485.             }
    486.         }
    487.  
    488.         public override void ApplyColors(IChartTheme theme)
    489.         {
    490.             ValueAreaBorderColor = theme.GetNextColor();
    491.  
    492.             ValueAreaBackColor = new XColor(50, ValueAreaBorderColor);
    493.  
    494.             PocLineColor = theme.GetNextColor();
    495.  
    496.             base.ApplyColors(theme);
    497.         }
    498.  
    499.         public override void CopyTemplate(IndicatorBase indicator, bool style)
    500.         {
    501.             var i = (DynamicLevelsIndicator)indicator;
    502.  
    503.             Period = i.Period;
    504.  
    505.             ShowValueArea = i.ShowValueArea;
    506.             ValueAreaPercent = i.ValueAreaPercent;
    507.  
    508.             ValueAreaBackColor = i.ValueAreaBackColor;
    509.             ValueAreaBorderColor = i.ValueAreaBorderColor;
    510.             ValueAreaBorderWidth = i.ValueAreaBorderWidth;
    511.  
    512.             ShowPoc = i.ShowPoc;
    513.  
    514.             PocLineColor = i.PocLineColor;
    515.             PocLineWidth = i.PocLineWidth;
    516.  
    517.             base.CopyTemplate(indicator, style);
    518.         }
    519.  
    520.         internal sealed class DynamicCluster
    521.         {
    522.             public DateTime Time;
    523.  
    524.             public long High;
    525.             public long Low;
    526.  
    527.             public long Volume;
    528.             public long MaxVolume;
    529.  
    530.             public long Poc;
    531.             public long Vah;
    532.             public long Val;
    533.  
    534.             public bool Split;
    535.  
    536.             private readonly Dictionary<long, long> _items = new Dictionary<long, long>();
    537.  
    538.             public DynamicCluster(DynamicCluster cluster)
    539.             {
    540.                 if (cluster == null)
    541.                 {
    542.                     return;
    543.                 }
    544.  
    545.                 Time = cluster.Time;
    546.  
    547.                 _items = new Dictionary<long, long>(cluster._items.Count);
    548.  
    549.                 foreach (var item in cluster._items)
    550.                 {
    551.                     _items.Add(item.Key, item.Value);
    552.                 }
    553.  
    554.                 High = cluster.High;
    555.                 Low = cluster.Low;
    556.  
    557.                 Volume = cluster.Volume;
    558.             }
    559.  
    560.             public void AddCluster(IRawCluster cluster)
    561.             {
    562.                 Time = cluster.Time;
    563.  
    564.                 foreach (var item in cluster.Items)
    565.                 {
    566.                     if (!_items.ContainsKey(item.Price))
    567.                     {
    568.                         _items.Add(item.Price, 0);
    569.                     }
    570.  
    571.                     _items[item.Price] += item.Volume;
    572.                 }
    573.  
    574.                 High = High == 0 ? cluster.High : Math.Max(High, cluster.High);
    575.                 Low = Low == 0 ? cluster.Low : Math.Min(Low, cluster.Low);
    576.  
    577.                 Volume += cluster.Volume;
    578.             }
    579.  
    580.             public void UpdateData()
    581.             {
    582.                 MaxVolume = 0;
    583.                 Poc = 0;
    584.  
    585.                 foreach (var item in _items)
    586.                 {
    587.                     if (item.Value <= MaxVolume)
    588.                     {
    589.                         continue;
    590.                     }
    591.  
    592.                     MaxVolume = item.Value;
    593.  
    594.                     Poc = item.Key;
    595.                 }
    596.             }
    597.  
    598.             public void UpdateValueArea(double valueArea)
    599.             {
    600.                 if (_items.Count == 0)
    601.                 {
    602.                     return;
    603.                 }
    604.  
    605.                 if (High - Low > 100000)
    606.                 {
    607.                     return;
    608.                 }
    609.  
    610.                 if (valueArea < 0.01)
    611.                 {
    612.                     Vah = Poc;
    613.                     Val = Poc;
    614.  
    615.                     return;
    616.                 }
    617.  
    618.                 if (valueArea > 0.99)
    619.                 {
    620.                     Vah = High;
    621.                     Val = Low;
    622.  
    623.                     return;
    624.                 }
    625.  
    626.                 var vah = 0L;
    627.                 var val = 0L;
    628.  
    629.                 if (High != 0 && Low != 0)
    630.                 {
    631.                     vah = Poc;
    632.                     val = Poc;
    633.  
    634.                     var vol = MaxVolume;
    635.  
    636.                     var areaVol = Volume * valueArea;
    637.  
    638.                     while (vol < areaVol || (vah == High && val == Low))
    639.                     {
    640.                         var currentVahVol = 0L;
    641.                         var currentValVol = 0L;
    642.                         var currentVah = vah;
    643.                         var currentVal = val;
    644.  
    645.                         for (var i = 0; i <= 1; i++)
    646.                         {
    647.                             if (High >= currentVah + 1)
    648.                             {
    649.                                 currentVah++;
    650.  
    651.                                 if (_items.ContainsKey(currentVah))
    652.                                 {
    653.                                     currentVahVol += _items[currentVah];
    654.                                 }
    655.                             }
    656.                         }
    657.  
    658.                         for (var j = 0; j <= 1; j++)
    659.                         {
    660.                             if (Low <= currentVal - 1)
    661.                             {
    662.                                 currentVal--;
    663.  
    664.                                 if (_items.ContainsKey(currentVal))
    665.                                 {
    666.                                     currentValVol += _items[currentVal];
    667.                                 }
    668.                             }
    669.                         }
    670.  
    671.                         if (currentVahVol == currentValVol && currentVahVol == 0)
    672.                         {
    673.                             if (High == currentVah)
    674.                             {
    675.                                 val = currentVal;
    676.                             }
    677.  
    678.                             if (Low == currentVal)
    679.                             {
    680.                                 vah = currentVah;
    681.                             }
    682.                         }
    683.  
    684.                         if (currentVahVol >= currentValVol)
    685.                         {
    686.                             vah = currentVah;
    687.                             vol += currentVahVol;
    688.                         }
    689.                         else
    690.                         {
    691.                             val = currentVal;
    692.                             vol += currentValVol;
    693.                         }
    694.  
    695.                         if (vol > Volume * valueArea)
    696.                         {
    697.                             break;
    698.                         }
    699.                     }
    700.                 }
    701.  
    702.                 Vah = vah;
    703.                 Val = val;
    704.             }
    705.  
    706.             public void ClearItems()
    707.             {
    708.                 _items.Clear();
    709.             }
    710.         }
    711.     }
    712. }
     
    #1 Support, 6 июл 2019
    Последнее редактирование: 6 июл 2019