private List<DiverSpan> FindDivergencePointsQuasi(MultyTimeframeIndexSettings src)
        {
            var divers = new List<DiverSpan>();
            var srcCount = src.seriesDest.DataCount;

            float? lastPeak = null;
            var peakPrice = 0f;
            var extremumSign = 0;
            var startIndex = 0;

            for (var i = 0; i < srcCount; i++)
            {
                var index = src.GetSourcePrice(i) ?? 0;
                var indexNext = i < srcCount ? (src.GetSourcePrice(i + 1) ?? 0) : index;
                // если находимся в зоне перекупленности / перепроданности,
                // если след. точка ниже (выше для перепроданности),
                // если текущая точка выше последнего максимума (ниже минимума...)

                var margUp = index >= src.marginUpper;
                var margDn = index <= src.marginLower;

                if ((margUp && indexNext < index &&
                    index > (lastPeak.HasValue ? lastPeak.Value : float.MinValue)) ||
                    (margDn && indexNext > index && index < (lastPeak.HasValue ? lastPeak.Value : float.MaxValue)))
                {// + или - экстремум
                    peakPrice = src.GetDestPrice(i) ?? 0;
                    extremumSign = margUp ? 1 : -1;
                    startIndex = i;
                    lastPeak = index;
                    continue;
                }
                if (!margUp && margDn == false)
                {// конец отсчета экстремума
                    extremumSign = 0;
                    lastPeak = null;
                    continue;
                }
                // отсчет экстремума - сравнить дельту цены и дельту индекса
                var deltaPrice = (src.GetDestPrice(i) ?? 0) - peakPrice;
                var deltaIndex = index - lastPeak;

                if (extremumSign > 0)
                    if (deltaPrice > 0 && deltaIndex < 0)
                    // медвежий дивер
                    {
                        divers.Add(new DiverSpan(startIndex, i, -1));
                        peakPrice = src.GetDestPrice(i) ?? 0;
                    }
                if (extremumSign < 0)
                    if (deltaPrice < 0 && deltaIndex > 0)
                    // бычий дивер
                    {
                        divers.Add(new DiverSpan(startIndex, i, 1));
                        peakPrice = src.GetDestPrice(i) ?? 0;
                    }
            }
            return divers;
        }
        private List <DiverSpan> FindDivergencePointsQuasi(MultyTimeframeIndexSettings src)
        {
            var divers   = new List <DiverSpan>();
            var srcCount = src.seriesDest.DataCount;

            float?lastPeak     = null;
            var   peakPrice    = 0f;
            var   extremumSign = 0;
            var   startIndex   = 0;

            for (var i = 0; i < srcCount; i++)
            {
                var index     = src.GetSourcePrice(i) ?? 0;
                var indexNext = i < srcCount ? (src.GetSourcePrice(i + 1) ?? 0) : index;
                // если находимся в зоне перекупленности / перепроданности,
                // если след. точка ниже (выше для перепроданности),
                // если текущая точка выше последнего максимума (ниже минимума...)

                var margUp = index >= src.marginUpper;
                var margDn = index <= src.marginLower;

                if ((margUp && indexNext < index &&
                     index > (lastPeak.HasValue ? lastPeak.Value : float.MinValue)) ||
                    (margDn && indexNext > index && index < (lastPeak.HasValue ? lastPeak.Value : float.MaxValue)))
                {// + или - экстремум
                    peakPrice    = src.GetDestPrice(i) ?? 0;
                    extremumSign = margUp ? 1 : -1;
                    startIndex   = i;
                    lastPeak     = index;
                    continue;
                }
                if (!margUp && margDn == false)
                {// конец отсчета экстремума
                    extremumSign = 0;
                    lastPeak     = null;
                    continue;
                }
                // отсчет экстремума - сравнить дельту цены и дельту индекса
                var deltaPrice = (src.GetDestPrice(i) ?? 0) - peakPrice;
                var deltaIndex = index - lastPeak;

                if (extremumSign > 0)
                {
                    if (deltaPrice > 0 && deltaIndex < 0)
                    // медвежий дивер
                    {
                        divers.Add(new DiverSpan(startIndex, i, -1));
                        peakPrice = src.GetDestPrice(i) ?? 0;
                    }
                }
                if (extremumSign < 0)
                {
                    if (deltaPrice < 0 && deltaIndex > 0)
                    // бычий дивер
                    {
                        divers.Add(new DiverSpan(startIndex, i, 1));
                        peakPrice = src.GetDestPrice(i) ?? 0;
                    }
                }
            }
            return(divers);
        }
        private static IEnumerable<DiverSpan> FindDivergencePointsClassic(MultyTimeframeIndexSettings src)
        {
            var diverPairs = new List<DiverSpan>();
            var srcCount = src.seriesDest.DataCount;

            // найти экстремумы
            var extremums = new List<Point>(); // index - sign
            for (var i = src.periodExtremum; i < srcCount - src.periodExtremum - 1; i++)
            {
                bool isPeak = true, isLow = true;
                var price = src.GetDestPrice(i) ?? 0;
                for (var j = i - src.periodExtremum; j <= i + src.periodExtremum; j++)
                {
                    if (j == i) continue;
                    var priceNear = src.GetDestPrice(j);
                    if (priceNear > price) isPeak = false;
                    if (priceNear < price) isLow = false;
                    if (!isPeak && isLow == false) break;
                }
                if (isPeak) extremums.Add(new Point(i, 1));
                if (isLow) extremums.Add(new Point(i, -1));
            }

            // от каждого экстремумы поиск вперед до M баров - поиск экстремума на интервале [i-N...i+1]
            foreach (var extr in extremums)
            {
                var signExtr = extr.Y;
                var indexExtr = extr.X;
                var priceExtr = src.GetDestPrice(indexExtr);

                for (var i = extr.X + 1; i <= (extr.X + src.maxPastExtremum); i++)
                {
                    if (i >= (srcCount - 1)) break;
                    // новый "экстремум" должен быть выше старого
                    var price = src.GetDestPrice(i) ?? 0;
                    if ((signExtr > 0 && price <= priceExtr) ||
                        (signExtr < 0 && price >= priceExtr)) continue;
                    // за новым "экстремумом" должна следовать точка ниже (выше для минимума)
                    var nextPrice = src.GetDestPrice(i + 1) ?? 0;
                    if ((signExtr > 0 && price <= nextPrice) ||
                        (signExtr < 0 && price >= nextPrice)) continue;
                    // сравнение с дельтой индекса
                    // !! смещение индекса
                    var srcPriceI = src.GetSourcePrice(i) ?? 0;
                    var srcPriceEx = src.GetSourcePrice(indexExtr) ?? 0;
                    var deltaIndex = Math.Sign(srcPriceI - srcPriceEx);
                    if (signExtr == deltaIndex) continue;
                    // экстремум найден
                    priceExtr = price;
                    diverPairs.Add(new DiverSpan(indexExtr, i, -signExtr));
                }
            }

            return diverPairs;
        }
        private static IEnumerable <DiverSpan> FindDivergencePointsClassic(MultyTimeframeIndexSettings src)
        {
            var diverPairs = new List <DiverSpan>();
            var srcCount   = src.seriesDest.DataCount;

            // найти экстремумы
            var extremums = new List <Point>(); // index - sign

            for (var i = src.periodExtremum; i < srcCount - src.periodExtremum - 1; i++)
            {
                bool isPeak = true, isLow = true;
                var  price = src.GetDestPrice(i) ?? 0;
                for (var j = i - src.periodExtremum; j <= i + src.periodExtremum; j++)
                {
                    if (j == i)
                    {
                        continue;
                    }
                    var priceNear = src.GetDestPrice(j);
                    if (priceNear > price)
                    {
                        isPeak = false;
                    }
                    if (priceNear < price)
                    {
                        isLow = false;
                    }
                    if (!isPeak && isLow == false)
                    {
                        break;
                    }
                }
                if (isPeak)
                {
                    extremums.Add(new Point(i, 1));
                }
                if (isLow)
                {
                    extremums.Add(new Point(i, -1));
                }
            }

            // от каждого экстремумы поиск вперед до M баров - поиск экстремума на интервале [i-N...i+1]
            foreach (var extr in extremums)
            {
                var signExtr  = extr.Y;
                var indexExtr = extr.X;
                var priceExtr = src.GetDestPrice(indexExtr);

                for (var i = extr.X + 1; i <= (extr.X + src.maxPastExtremum); i++)
                {
                    if (i >= (srcCount - 1))
                    {
                        break;
                    }
                    // новый "экстремум" должен быть выше старого
                    var price = src.GetDestPrice(i) ?? 0;
                    if ((signExtr > 0 && price <= priceExtr) ||
                        (signExtr < 0 && price >= priceExtr))
                    {
                        continue;
                    }
                    // за новым "экстремумом" должна следовать точка ниже (выше для минимума)
                    var nextPrice = src.GetDestPrice(i + 1) ?? 0;
                    if ((signExtr > 0 && price <= nextPrice) ||
                        (signExtr < 0 && price >= nextPrice))
                    {
                        continue;
                    }
                    // сравнение с дельтой индекса
                    // !! смещение индекса
                    var srcPriceI  = src.GetSourcePrice(i) ?? 0;
                    var srcPriceEx = src.GetSourcePrice(indexExtr) ?? 0;
                    var deltaIndex = Math.Sign(srcPriceI - srcPriceEx);
                    if (signExtr == deltaIndex)
                    {
                        continue;
                    }
                    // экстремум найден
                    priceExtr = price;
                    diverPairs.Add(new DiverSpan(indexExtr, i, -signExtr));
                }
            }

            return(diverPairs);
        }