Индикатор ZigZag

Собственно сабж

  1. karuzzo

    Регистрация:
    16.08.19
    Сообщения:
    99
    Был на сайте:
    05.01.23

    Индикатор без визуализации так как не вызывает события перерисовки графика индикатора при изменении крайней точки, а так же в силу работы OsEngine с данными типа decimal которые не имеют не числовых значений. Индикатор в результируещем временном ряде содержит верные значения точек экстремумов, что позволяет использовать его значения в роботах так, как бы это был полноценный зигзаг с визуализацией.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Drawing;
    using OsEngine.Entity;
    using OsEngine.Indicators;
    
    namespace CustomIndicators.Scripts
    {
        public class ZigZag : Aindicator
        {
            private IndicatorParameterInt _period;
            private IndicatorDataSeries _series;
            public override void OnStateChange(IndicatorState state)
            {
                _period = CreateParameterInt("Length", 14);
                _series = CreateSeries("ZigZag", Color.DarkRed, IndicatorChartPaintType.Line, true);
            }
    
            private decimal currentZigZagHigh = 0;
            private decimal currentZigZagLow = 0;
            private int lastSwingIndex = -1;
            private decimal lastSwingPrice = 0;
            private int trendDir = 0;
            private int CurrentBar;
    
            private decimal GetExtremum(List<Candle> candles, int period, string points)
            {
                List<decimal> values = new List<decimal>();
                for (int i = candles.Count - 1; i >= candles.Count - period; i--)
                        values.Add(candles[i].GetPoint(points));
                if(points == "High")
                    return values.Max();
                if (points == "Low")
                    return values.Min();
    
                return 0;
            }
    
            public override void OnProcess(List<Candle> candles, int index)
            {
                CurrentBar = candles.Count;
    
                if (CurrentBar < _period.ValueInt * 2)
                    return;
    
                decimal High = candles[index].High;
                decimal Low = candles[index].Low;
    
                if (lastSwingPrice == 0)
                    lastSwingPrice = Low + (High - Low) / 2;
    
                bool isSwingHigh = High == GetExtremum(candles, _period.ValueInt, "High");
                bool isSwingLow = Low == GetExtremum(candles, _period.ValueInt, "Low");
                decimal saveValue = 0;
                bool addHigh = false;
                bool addLow = false;
                bool updateHigh = false;
                bool updateLow = false;
    
                if (!isSwingHigh && !isSwingLow)
                {
                    return;
                }
    
                if (trendDir == 1 && isSwingHigh && High >= lastSwingPrice)
                {
                    saveValue = High;
                    updateHigh = true;
                }
                else if (trendDir == -1 && isSwingLow && Low <= lastSwingPrice)
                {
                    saveValue = Low;
                    updateLow = true;
                }
                else if (trendDir <= 0 && isSwingHigh)
                {
                    saveValue = High;
                    addHigh = true;
                    trendDir = 1;
                }
                else if (trendDir >= 0 && isSwingLow)
                {
                    saveValue = Low;
                    addLow = true;
                    trendDir = -1;
                }
    
                if (addHigh || addLow || updateHigh || updateLow)
                {
                    if (updateHigh && lastSwingIndex >= 0)
                        _series.Values[lastSwingIndex] = 0; // тут в оригинале double.NaN
                    else if (updateLow && lastSwingIndex >= 0)
                        _series.Values[lastSwingIndex] = 0; // тут в оригинале double.NaN
    
                    if (addHigh || updateHigh)
                    {
                        currentZigZagHigh = saveValue;
                        _series.Values[index] = currentZigZagHigh;
                    }
                    else if (addLow || updateLow)
                    {
                        currentZigZagLow = saveValue;
                        _series.Values[index] = currentZigZagLow;
                    }
                    lastSwingIndex = CurrentBar - 1;
                    lastSwingPrice = saveValue;
                }
            }
        }
    }

    Данный индикатор хорошо показал себя в совокупности с ML для прогнозирования акций и фьючей.

    Работать со значениями индикатора из робота можно с помощью этого псевдокода получая значения в точках экстремумов и количество бар до исколого по счету экстремума, где indexFromEnd номер искомого экстремума с конца начиная с нуля.

            //---------------------------------------------------------------
            //---ПОЛУЧАЕМ НОМЕР СВЕЧИ ЭКСТРЕМУМА-----------------------------
            //---------------------------------------------------------------
            decimal GetZigZagCount(List<Candle> candles, int indexFromEnd)
            {
                for (var i = candles.Count - 1; i >= 0; i--)
                {
                    if (zigZag.Result[i] != 0)
                    {
                        if (indexFromEnd == 0)
                            return i;
                        indexFromEnd--;
                    }
                }
                return 0;
            }
    
            //---------------------------------------------------------------
            //---ПОЛУЧАЕМ ЗНАЧЕНИЯ ЦЕНЫ В ТОЧКАХ ЭКСТРЕМУМА------------------
            //---------------------------------------------------------------
            decimal GetZigZagValue(List<Candle> candles, int indexFromEnd)
            {
                for (var i = candles.Count - 1; i >= 0; i--)
                {
                    if (zigZag.Result[i] != 0)
                    {
                        if (indexFromEnd == 0)
                            return zigZag.Result[i];
                        indexFromEnd--;
                    }
                }
                return 0;
            }
    karuzzo
    01.04.2020 04:14
    #1
  2. Алексей Ван Команда форума

    Регистрация:
    02.02.13
    Сообщения:
    1172
    Был на сайте:
    23.04.24
    Цитата: karuzzo

    Индикатор без визуализации так как не вызывает события перерисовки графика индикатора при изменении крайней точки, а так же в силу работы OsEngine с данными типа decimal которые не имеют не числовых значений. Индикатор в результируещем временном ряде содержит верные значения точек экстремумов, что позволяет использовать его значения в роботах так, как бы это был полноценный зигзаг с визуализацией.

    Данный индикатор хорошо показал себя в совокупности с ML для прогнозирования акций и фьючей.

    Работать со значениями индикатора из робота можно с помощью этого псевдокода получая значения в точках экстремумов и количество бар до исколого по счету экстремума, где indexFromEnd номер искомого экстремума с конца начиная с нуля.

    Запушил на Гит. Спасибо.

    Добавил свойство CanReBuildHistoricalValues в серии данных. Чтобы чарт перерисовывал такие серии принудительно целиком по обновлению свечи. И серию для прорисовки тоже добавил

     

    Алексей Ван
    01.04.2020 14:19
    #2
  3. karuzzo

    Регистрация:
    16.08.19
    Сообщения:
    99
    Был на сайте:
    05.01.23
    Цитата: Алексей Ван
    Цитата: karuzzo

    Индикатор без визуализации так как не вызывает события перерисовки графика индикатора при изменении крайней точки, а так же в силу работы OsEngine с данными типа decimal которые не имеют не числовых значений. Индикатор в результируещем временном ряде содержит верные значения точек экстремумов, что позволяет использовать его значения в роботах так, как бы это был полноценный зигзаг с визуализацией.

    Данный индикатор хорошо показал себя в совокупности с ML для прогнозирования акций и фьючей.

    Работать со значениями индикатора из робота можно с помощью этого псевдокода получая значения в точках экстремумов и количество бар до исколого по счету экстремума, где indexFromEnd номер искомого экстремума с конца начиная с нуля.

    Запушил на Гит. Спасибо.

    Добавил свойство CanReBuildHistoricalValues в серии данных. Чтобы чарт перерисовывал такие серии принудительно целиком по обновлению свечи. И серию для прорисовки тоже добавил

     

    Круто!

    karuzzo
    01.04.2020 15:33
    #3