public OpenPositionInfo ProcessMarketPosition(TradingPosition activeTradingPosition)
        {
            var settings = _configurationService.GetTradingSettings();
            var moment   = settings.Moment ?? DateTime.UtcNow;

            var initialPositionInfo = new UpdateClosePositionInfo
            {
                ClosePrice     = activeTradingPosition.ClosePositionOrder.Price,
                CloseStopPrice = activeTradingPosition.ClosePositionOrder.StopPrice ?? 0,
                StopLossPrice  = activeTradingPosition.StopLossOrder.StopPrice ?? 0
            };

            OpenPositionInfo newPositionInfo = null;

            var rsiSettings = new CommonIndicatorSettings
            {
                Period = 10
            };

            var higherPeriodMACDSettings = new MACDSettings
            {
                EMAPeriod1   = 12,
                EMAPeriod2   = 26,
                SignalPeriod = 9
            };

            var candleRangeSize = new[]
            {
                rsiSettings.Period + 2,
                2
            }.Max();

            var targetPeriodLastCandles = _candleLoadingService.LoadCandles(
                activeTradingPosition.OpenPositionOrder.CurrencyPair.Id,
                settings.Period,
                candleRangeSize,
                moment)
                                          .ToList();

            if (!targetPeriodLastCandles.Any())
            {
                throw new NoNullAllowedException("No candles loaded");
            }
            var currentTargetPeriodCandle = targetPeriodLastCandles.Last();

            var higherPeriodLastCandles = _candleLoadingService.LoadCandles(
                activeTradingPosition.OpenPositionOrder.CurrencyPair.Id,
                settings.Period.GetHigherFramePeriod(),
                rsiSettings.Period,
                moment)
                                          .ToList();

            if (!higherPeriodLastCandles.Any())
            {
                throw new NoNullAllowedException("No candles loaded");
            }

            var lowerPeriodCandles = _candleLoadingService.LoadCandles(
                activeTradingPosition.OpenPositionOrder.CurrencyPair.Id,
                settings.Period.GetLowerFramePeriod(),
                rsiSettings.Period + 1,
                moment)
                                     .ToList();

            if (!lowerPeriodCandles.Any())
            {
                throw new NoNullAllowedException("No candles loaded");
            }
            var currentLowPeriodCandle = lowerPeriodCandles.Last();

            if (currentTargetPeriodCandle.Moment < currentLowPeriodCandle.Moment)
            {
                var lastLowPeriodCandles = lowerPeriodCandles
                                           .Where(item => item.Moment > currentTargetPeriodCandle.Moment)
                                           .OrderBy(item => item.Moment)
                                           .ToList();

                if (lastLowPeriodCandles.Any())
                {
                    targetPeriodLastCandles.Add(new Candle
                    {
                        Moment                = lastLowPeriodCandles.Last().Moment,
                        MaxPrice              = lastLowPeriodCandles.Max(item => item.MaxPrice),
                        MinPrice              = lastLowPeriodCandles.Min(item => item.MinPrice),
                        OpenPrice             = lastLowPeriodCandles.First().OpenPrice,
                        ClosePrice            = lastLowPeriodCandles.Last().ClosePrice,
                        VolumeInBaseCurrency  = lastLowPeriodCandles.Sum(item => item.VolumeInBaseCurrency),
                        VolumeInQuoteCurrency = lastLowPeriodCandles.Sum(item => item.VolumeInQuoteCurrency)
                    });
                }
            }

            var candlesCount = targetPeriodLastCandles.Count;
            var period       = (candlesCount - 2) > rsiSettings.Period ? rsiSettings.Period : candlesCount - 2;
            var rsiValues    = _indicatorComputingService.ComputeRelativeStrengthIndex(
                targetPeriodLastCandles,
                period)
                               .OfType <SimpleIndicatorValue>()
                               .ToList();

            var currentRSIValue  = rsiValues.ElementAtOrDefault(rsiValues.Count - 1);
            var previousRSIValue = rsiValues.ElementAtOrDefault(rsiValues.Count - 2);

            var higherPeriodMACDValues = _indicatorComputingService.ComputeMACD(
                higherPeriodLastCandles,
                higherPeriodMACDSettings.EMAPeriod1,
                higherPeriodMACDSettings.EMAPeriod2,
                higherPeriodMACDSettings.SignalPeriod)
                                         .OfType <MACDValue>()
                                         .ToList();

            var higherPeriodCurrentMACDValue = higherPeriodMACDValues.ElementAtOrDefault(higherPeriodMACDValues.Count - 1);

            var rsiBottomBorder = 70;

            if (higherPeriodCurrentMACDValue?.MACD < 0 && higherPeriodCurrentMACDValue.Histogram < 0)
            {
                rsiBottomBorder = 50;
            }
            if (higherPeriodCurrentMACDValue?.MACD < 0 || higherPeriodCurrentMACDValue?.Histogram < 0)
            {
                rsiBottomBorder = 60;
            }

            if ((currentRSIValue?.Value >= rsiBottomBorder &&
                 currentRSIValue.Value < 80 &&
                 currentRSIValue.Value < previousRSIValue?.Value) ||
                (activeTradingPosition.ClosePositionOrder.OrderStateType != OrderStateType.Pending &&
                 currentRSIValue?.Value < 40 &&
                 currentRSIValue.Value < previousRSIValue?.Value))
            {
                var updatePositionInfo = new UpdateClosePositionInfo
                {
                    StopLossPrice = initialPositionInfo.StopLossPrice
                };

                if (activeTradingPosition.ClosePositionOrder.OrderStateType == OrderStateType.Pending ||
                    activeTradingPosition.ClosePositionOrder.OrderStateType == OrderStateType.Suspended)
                {
                    var bottomMeaningfulAskPrice = _orderBookLoadingService.GetBottomMeaningfulAskPrice(activeTradingPosition.ClosePositionOrder.CurrencyPair);

                    updatePositionInfo.ClosePrice = bottomMeaningfulAskPrice - activeTradingPosition.ClosePositionOrder.CurrencyPair.TickSize;

                    var topBidPrice = _orderBookLoadingService.GetTopBidPrice(activeTradingPosition.ClosePositionOrder.CurrencyPair, 3);

                    updatePositionInfo.CloseStopPrice = !activeTradingPosition.ClosePositionOrder.StopPrice.HasValue || topBidPrice >= activeTradingPosition.ClosePositionOrder.StopPrice ?
                                                        topBidPrice :
                                                        activeTradingPosition.ClosePositionOrder.StopPrice.Value;
                }
                else
                {
                    var bottomAskPrice = _orderBookLoadingService.GetBottomAskPrice(activeTradingPosition.ClosePositionOrder.CurrencyPair, 3);

                    updatePositionInfo.ClosePrice = activeTradingPosition.ClosePositionOrder.Price <= bottomAskPrice ?
                                                    activeTradingPosition.ClosePositionOrder.Price :
                                                    bottomAskPrice;

                    updatePositionInfo.CloseStopPrice = 0;
                }

                if (updatePositionInfo.ClosePrice != initialPositionInfo.ClosePrice ||
                    updatePositionInfo.CloseStopPrice != initialPositionInfo.CloseStopPrice)
                {
                    newPositionInfo = updatePositionInfo;
                }
            }
            else if (activeTradingPosition.ClosePositionOrder.OrderStateType != OrderStateType.Pending &&
                     currentRSIValue?.Value < rsiBottomBorder &&
                     currentRSIValue.Value > previousRSIValue?.Value)
            {
                newPositionInfo = new SuspendPositionInfo();
            }
            else if (activeTradingPosition.ClosePositionOrder.OrderStateType != OrderStateType.Pending &&
                     currentRSIValue?.Value >= 80)
            {
                newPositionInfo = new SuspendPositionInfo();
            }

            if (newPositionInfo == null &&
                currentTargetPeriodCandle.Moment >= currentLowPeriodCandle.Moment &&
                currentRSIValue?.Value > previousRSIValue?.Value)
            {
                var fixStopLossInfo = new FixStopLossInfo {
                    StopLossPrice = initialPositionInfo.StopLossPrice
                };
                ComputeStopLossUsingParabolicSAR(
                    fixStopLossInfo,
                    activeTradingPosition.StopLossOrder,
                    currentTargetPeriodCandle);

                if (fixStopLossInfo.StopLossPrice != initialPositionInfo.StopLossPrice)
                {
                    newPositionInfo = fixStopLossInfo;
                }
            }

            if (newPositionInfo == null)
            {
                return(new HoldPositionInfo());
            }

            return(newPositionInfo);
        }
        protected override ConditionCheckingResult CheckConditions(CurrencyPair currencyPair)
        {
            var settings = ConfigurationService.GetTradingSettings();
            var moment   = settings.Moment ?? DateTime.UtcNow;

            var conditionCheckingResult = new ConditionCheckingResult()
            {
                ResultType = ConditionCheckingResultType.Failed
            };

            var firstFrameMACDSettings = new MACDSettings
            {
                EMAPeriod1   = 12,
                EMAPeriod2   = 26,
                SignalPeriod = 9
            };

            var firstFrameCandles = CandleLoadingService.LoadCandles(
                currencyPair.Id,
                settings.Period.GetHigherFramePeriod(),
                firstFrameMACDSettings.RequiredCandleRangeSize,
                moment)
                                    .OrderBy(candle => candle.Moment)
                                    .ToList();

            var firstFrameMACDValues = IndicatorComputingService.ComputeMACD(
                firstFrameCandles,
                firstFrameMACDSettings.EMAPeriod1,
                firstFrameMACDSettings.EMAPeriod2,
                firstFrameMACDSettings.SignalPeriod)
                                       .OfType <MACDValue>()
                                       .ToList();

            var firstFrameCurrentMACDValue     = firstFrameMACDValues.ElementAtOrDefault(firstFrameMACDValues.Count - 1);
            var firstFrameOnePreviousMACDValue = firstFrameMACDValues.ElementAtOrDefault(firstFrameMACDValues.Count - 2);

            //If all valuable parameters are not null
            if (firstFrameCurrentMACDValue?.Histogram == null ||
                firstFrameOnePreviousMACDValue?.Histogram == null)
            {
                return(conditionCheckingResult);
            }

            //if MACD higher then Signal then it is Bullish trend
            //if Histogram is rising
            if (!(firstFrameCurrentMACDValue.MACD > 0 ||
                  firstFrameCurrentMACDValue.Histogram.Value >= 0 ||
                  firstFrameCurrentMACDValue.Histogram.Value > firstFrameOnePreviousMACDValue.Histogram))
            {
                return(conditionCheckingResult);
            }

            var rsiSettings = new RSISettings
            {
                Period = 14
            };

            var secondFrameTargetPeriodCandles = CandleLoadingService.LoadCandles(
                currencyPair.Id,
                settings.Period,
                rsiSettings.Period + 2,
                moment)
                                                 .OrderBy(candle => candle.Moment)
                                                 .ToList();

            var candlesCount = secondFrameTargetPeriodCandles.Count;

            if (candlesCount < rsiSettings.Period)
            {
                return(conditionCheckingResult);
            }

            var secondFrameCurrentCandle = secondFrameTargetPeriodCandles.ElementAtOrDefault(secondFrameTargetPeriodCandles.Count - 1);

            if (secondFrameCurrentCandle?.VolumeInBaseCurrency == null)
            {
                return(conditionCheckingResult);
            }

            var lowerPeriodCandles = CandleLoadingService.LoadCandles(
                currencyPair.Id,
                settings.Period.GetLowerFramePeriod(),
                rsiSettings.Period,
                moment)
                                     .OrderBy(candle => candle.Moment)
                                     .ToList();

            if (!lowerPeriodCandles.Any())
            {
                throw new NoNullAllowedException("No candles loaded");
            }
            var currentLowPeriodCandle = lowerPeriodCandles.Last();

            if (secondFrameCurrentCandle.Moment != currentLowPeriodCandle.Moment)
            {
                var lastLowPeriodCandles = lowerPeriodCandles
                                           .Where(item => item.Moment > secondFrameCurrentCandle.Moment)
                                           .OrderBy(item => item.Moment)
                                           .ToList();

                if (lastLowPeriodCandles.Any())
                {
                    secondFrameTargetPeriodCandles.Add(new Candle
                    {
                        Moment                = lastLowPeriodCandles.Last().Moment,
                        MaxPrice              = lastLowPeriodCandles.Max(item => item.MaxPrice),
                        MinPrice              = lastLowPeriodCandles.Min(item => item.MinPrice),
                        OpenPrice             = lastLowPeriodCandles.First().OpenPrice,
                        ClosePrice            = lastLowPeriodCandles.Last().ClosePrice,
                        VolumeInBaseCurrency  = lastLowPeriodCandles.Sum(item => item.VolumeInBaseCurrency),
                        VolumeInQuoteCurrency = lastLowPeriodCandles.Sum(item => item.VolumeInQuoteCurrency)
                    });
                }
            }

            var period = (candlesCount - 2) > rsiSettings.Period ? rsiSettings.Period : candlesCount - 2;
            var secondFrameRSIValues = IndicatorComputingService.ComputeRelativeStrengthIndex(
                secondFrameTargetPeriodCandles,
                period)
                                       .OfType <SimpleIndicatorValue>()
                                       .ToList();

            var secondFrameCurrentRSIValue     = secondFrameRSIValues.ElementAtOrDefault(secondFrameRSIValues.Count - 1);
            var secondFrameOnePreviousRSIValue = secondFrameRSIValues.ElementAtOrDefault(secondFrameRSIValues.Count - 2);

            if (secondFrameCurrentRSIValue?.Value == null || secondFrameOnePreviousRSIValue?.Value == null)
            {
                return(conditionCheckingResult);
            }

            var rsiTopBorder = 45;

            if (firstFrameCurrentMACDValue.MACD > 0 && firstFrameCurrentMACDValue.Histogram.Value >= 0)
            {
                rsiTopBorder = 65;
            }
            if (firstFrameCurrentMACDValue.MACD > 0 || firstFrameCurrentMACDValue.Histogram.Value >= 0)
            {
                rsiTopBorder = 60;
            }
            if (secondFrameCurrentRSIValue.Value > rsiTopBorder || secondFrameCurrentRSIValue.Value < 25)
            {
                return(conditionCheckingResult);
            }

            if (secondFrameCurrentRSIValue.Value < secondFrameOnePreviousRSIValue.Value)
            {
                return(conditionCheckingResult);
            }

            conditionCheckingResult.ResultType = ConditionCheckingResultType.Passed;
            return(conditionCheckingResult);
        }