コード例 #1
16
        /// <summary> Функция находит ближайший экстремум слева, начиная поиск с левого края окна </summary>
        /// <param name="flatNumber">Номер объекта в списке боковиков</param>
        /// <returns>Свеча</returns>
        private _CandleStruct FindClosestExtremum(int flatNumber)
        {
            int            candlesPassed = 1;
            FlatIdentifier currentFlat   = flatList[flatNumber];

            // Цикл выполняется, пока на найдётся подходящий экстремум либо не пройдёт константное число итераций
            while (candlesPassed < _Constants.MaxFlatLeftExtremumDistance)
            {
                candlesPassed++;
                int           currentIndex    = currentFlat.bounds.left.index - candlesPassed;
                _CandleStruct closestExtremum = globalCandles[currentIndex];

                if (globalCandles[currentIndex].index < 5)
                {
                    return(globalCandles[0]);
                }

                if (closestExtremum.low < currentFlat.gMin - _Constants.FlatClassifyOffset * currentFlat.gMin && IsCandleLowerThanNearests(closestExtremum))
                {
                    return(closestExtremum);
                }

                if (closestExtremum.high > currentFlat.gMax + _Constants.FlatClassifyOffset * currentFlat.gMax && IsCandleHigherThanNearests(closestExtremum))
                {
                    return(closestExtremum);
                }
            }

            logger.Trace("Extremum not found");
            return(globalCandles[0]);
        }
コード例 #2
1
        /// <summary> Находит свечу, определяющую сторону выхода боковика </summary>
        /// <param name="flatNumber">Номер боковика</param>
        /// <returns>Свеча снизу или сверху после движения</returns>
        private _CandleStruct FindLeavingCandle(int flatNumber)
        {
            FlatIdentifier currentFlat    = flatList[flatNumber];
            int            currentIndex   = currentFlat.bounds.right.index + 1;
            _CandleStruct  result         = globalCandles[currentIndex];
            double         priceOffset    = currentFlat.mean * _Constants.LeavingCoeff;
            double         flatUpperBound = currentFlat.SDH + priceOffset;
            double         flatLowerBound = currentFlat.SDL - priceOffset;

            if (flatNumber == flatsOverall - 1)
            {
                return(globalCandles[globalCandles.Count - 1]);
            }

            while (result.time != flatList[flatNumber + 1].bounds.right.time)
            {
                result = globalCandles[currentIndex];
                if (result.high > flatUpperBound || result.low < flatLowerBound)
                {
                    result = globalCandles[currentIndex];
                    return(result);
                }
                currentIndex++;
            }
            return(result);
        }
コード例 #3
1
        /// <summary> Находит и устанавливает тейк-профит для флета, закрывающегося вниз на шорт </summary>
        /// <param name="i">Индекс флета</param>
        private void SetTakeProfitsForDownLeavingFlats(ref int i)
        {
            FlatIdentifier currentFlat     = flatList[i];
            FlatIdentifier nextFlat        = flatList[i + 1];
            int            flatsToOpposite = 0;

            currentFlat.takeProfitCandle.deltaPrice = double.PositiveInfinity;
            while (currentFlat.leavingDirection == flatList[i + flatsToOpposite].leavingDirection && i + flatsToOpposite < flatsOverall - 1)
            {
                flatsToOpposite++;
            }

            for (int j = currentFlat.leavingCandle.index; j <= nextFlat.leavingCandle.index; j++)
            {
                if (globalCandles[j].low - currentFlat.leavingCandle.close < currentFlat.takeProfitCandle.deltaPrice)
                {
                    _TakeProfitCandle takeProfit;
                    takeProfit.candle        = globalCandles[j];
                    takeProfit.deltaDistance = globalCandles[j].index - currentFlat.leavingCandle.index;
                    takeProfit.deltaPrice    = Math.Abs(currentFlat.leavingCandle.close - globalCandles[j].low);

                    currentFlat.takeProfitCandle = takeProfit;
                }
            }
            flatList[i].takeProfitCandle = currentFlat.takeProfitCandle;
            i += flatsToOpposite;
        }
コード例 #4
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);
                }
            }
        }
コード例 #5
1
        /// <summary> Определяет, что предшествовало боковому движению </summary>
        /// <param name="flat">Боковик</param>
        /// <param name="flatNumber">Номер боковика</param>
        /// <returns>Восходящий или нисходящий тренд</returns>
        private Direction ClassifyFormedFrom(FlatIdentifier flat, int flatNumber)
        {
            _CandleStruct closestExtremum = FindClosestExtremum(flatNumber);

            flat.formedFromCandle = closestExtremum;
            logger.Trace($"[{flat.bounds.left.time} {flat.bounds.right.time}] Closest extremum in {flat.formedFromCandle.time}");
            Direction result = closestExtremum.avg > flat.mean ? Direction.Up : Direction.Down;

            flat.formedFrom = result;
            return(result);
        }
コード例 #6
1
 private void ClassifySlops(FlatIdentifier flat, double atan)
 {
     if (atan < _Constants.ArcTanThreshold && flat.formedFrom == flat.leavingDirection ||
         atan >= _Constants.ArcTanThreshold && flat.formedFrom != flat.leavingDirection)
     {
         slopPositiveCounter++;
     }
     else
     {
         slopNegativeCounter++;
     }
 }
コード例 #7
1
        /// <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++;
            }
        }
コード例 #8
1
        /// <summary> Определяет направление выхода боковика </summary>
        /// <param name="flat">Объект боковика</param>
        /// <param name="flatNumber">Номер объекта</param>
        /// <returns>Вниз или вверх</returns>
        private Direction ClassifyLeavingDirection(FlatIdentifier flat, int flatNumber)
        {
            _CandleStruct leavingCandle = FindLeavingCandle(flatNumber);

            flat.leavingCandle = leavingCandle;
            logger.Trace($"[{flat.bounds.left.time} {flat.bounds.right.time}]: Leaving to candle in {leavingCandle.time}");
            if (leavingCandle.close > flat.mean)
            {
                const Direction result = Direction.Up;
                flat.leavingDirection = Direction.Up;
                return(result);
            }
            if (leavingCandle.close < flat.mean)
            {
                const Direction result = Direction.Down;
                flat.leavingDirection = result;
                return(result);
            }

            return(Direction.Neutral);
        }
コード例 #9
1
 private double GetTangentForAscending(FlatIdentifier flat)
 {
     return((flat.candles[0].index - flat.formedFromCandle.index) / (flat.formedFromCandle.low - flat.mean));
 }
コード例 #10
1
 private double CalculateTangentFromClosestExtremum(FlatIdentifier flat)
 {
     return(flat.formedFrom == Direction.Down ? GetTangentForDescending(flat) : GetTangentForAscending(flat));
 }
コード例 #11
1
 private double CalculateArcTanFromClosestExtremum(FlatIdentifier flat)
 {
     return(Math.Atan(CalculateTangentFromClosestExtremum(flat)));
 }
コード例 #12
1
 public Printer(FlatIdentifier flat) : this()
 {
     this.flat = flat;
 }