Example #1
1
        /// <summary> Основная функция, выполняющая поиск всех боковиков в глобальном списке свечей </summary>
        public void FindAllFlats()
        {
            // Как правило, globalIterator хранит в себе индекс начала окна во всём датасете

            for (int globalIterator = 0; globalIterator < globalCandles.Count - _Constants.NAperture * 2;)
            {
                FlatIdentifier flat = new FlatIdentifier();
                flat.AssignAperture(aperture);
                flat.Identify(); // Определяем начальное окно

                // Если не определили боковик сходу
                if (!flat.isFlat)
                {
                    Printer printer = new Printer(flat);
                    printer.PrintReasonsApertureIsNotFlat();
                    globalIterator++;
                    MoveAperture(ref globalIterator);
                    continue;
                }

                while (flat.isFlat)
                {
                    // ExpansionRate раз...
                    for (int j = 0; j < _Constants.ExpansionRate; j++)
                    {
                        // ЕСЛИ не конец данных
                        if (globalIterator + aperture.Count + 1 != globalCandles[globalCandles.Count - 1].index)
                        {
                            // ... расширяем окно на 1 свечу
                            ExtendAperture(globalIterator, ref aperture);
                        }
                        else
                        {
                            flatList.Add(flat);
                            flatsFound++;
                            return;
                        }
                    }
                    flat.AssignAperture(aperture);
                    flat.Identify(); // Identify() вызывает SetBounds(), если isFlat == true

                    if (flat.isFlat)
                    {
                        continue;
                    }

                    Printer printer = new Printer(flat);
                    printer.PrintReasonsApertureIsNotFlat();
                    flatList.Add(flat);
                    flatsFound++;

                    globalIterator += aperture.Count; // Переместить итератор на следующую после найденного окна свечу
                    MoveAperture(ref globalIterator);
                }
            }
        }
        /// <summary>
        /// Функция склеивает находящиеся близко друг к другу боковики
        /// </summary>
        public void UniteFlats()
        {
            for (int i = 1; i < flatsFound; i++)
            {
                FlatIdentifier currentFlat = flatList[i];
                FlatIdentifier prevFlat    = flatList[i - 1];

                bool areFlatsInTheSameDay      = currentFlat.bounds.left.date == prevFlat.bounds.left.date;
                bool areFlatsTooClose          = currentFlat.bounds.left.index - prevFlat.bounds.right.index <= _Constants.MinFlatGap;
                bool areFlatsMeansRoughlyEqual = Math.Abs(currentFlat.mean - prevFlat.mean) <= _Constants.FlatsMeanOffset * (currentFlat.mean + prevFlat.mean) * 0.5;
                bool isPrevFlatHasClosing      = prevFlat.bounds.left.time != currentFlat.leavingCandle.time;

                logger.Trace($"{prevFlat.candles[0].date}: [{prevFlat.bounds.left.time} {prevFlat.bounds.right.time}] " +
                             $"and [{currentFlat.bounds.left.time} {currentFlat.bounds.right.time}] " +
                             $"Day = {areFlatsInTheSameDay} Distance = {areFlatsTooClose} Means = {areFlatsMeansRoughlyEqual} PrevFlatCloseAtCurr = {isPrevFlatHasClosing}");

                // ЕСЛИ левая граница предыдущего и левая граница текущего находятся в пределах одного дня
                // И ЕСЛИ разница в свечах между левой границей текущего и правой границей предыдущего меьше ГАПА
                // И ЕСЛИ разница в цене между мат. ожиданиями текущего и предыдущего <= (ОФФСЕТ * среднее между мат. ожиданиями обоих боковиков)
                if (!areFlatsInTheSameDay || !areFlatsTooClose || !areFlatsMeansRoughlyEqual || !isPrevFlatHasClosing)
                {
                    continue;
                }

                logger.Trace("Uniting");

                List <_CandleStruct> newAperture = new List <_CandleStruct>(currentFlat.bounds.right.index - prevFlat.bounds.left.index);
                for (int j = prevFlat.bounds.left.index; j <= currentFlat.bounds.right.index; j++)
                {
                    newAperture.Add(globalCandles[j]);
                }
                FlatIdentifier newFlat = new FlatIdentifier();
                newFlat.AssignAperture(newAperture);
                newFlat.CalculateFlatProperties();
                newFlat.bounds = newFlat.SetBounds(newFlat.candles[0], newFlat.candles[newFlat.candles.Count - 1]);
                newFlat.SetBounds(newFlat.candles[0], newFlat.candles[newFlat.candles.Count - 1]);

                flatList.RemoveRange(i - 1, 2);
                flatList.Insert(i - 1, newFlat);
                flatsFound--;
                i++;
                flatUnions++;
            }
        }