public void LoadMarketData(string currencyPairId, int candleLimit) { foreach (var candlePeriod in Enum.GetValues(typeof(CandlePeriod)).Cast <CandlePeriod>()) { _candleLoadingService.LoadCandles(currencyPairId, candlePeriod, candleLimit, DateTime.UtcNow); } }
public ChartDataset GetChartData(ChartSettings settings) { var chartDataset = new ChartDataset(); chartDataset.Candles = _candleLoadingService.LoadCandles( settings.CurrencyPairId, settings.Period, settings.CandleRangeSize, settings.CurrentMoment).ToList(); foreach (var indicatorSettings in settings.Indicators) { var indicatorDataset = new IndicatorDataset(); indicatorDataset.Settings = indicatorSettings; var candles = indicatorSettings.CandlePeriod != settings.Period ? _candleLoadingService.LoadCandles( settings.CurrencyPairId, indicatorSettings.CandlePeriod, settings.CandleRangeSize, settings.CurrentMoment).ToList() : chartDataset.Candles; switch (indicatorSettings.Type) { case IndicatorType.HighestMaxPrice: indicatorDataset.Values = _indicatorComputingService.ComputeHighestMaxPrices( candles, ((CommonIndicatorSettings)indicatorSettings).Period); break; case IndicatorType.EMA: indicatorDataset.Values = _indicatorComputingService.ComputeEMA( candles, ((CommonIndicatorSettings)indicatorSettings).Period); break; case IndicatorType.MACD: indicatorDataset.Values = _indicatorComputingService.ComputeMACD( candles, ((MACDSettings)indicatorSettings).EMAPeriod1, ((MACDSettings)indicatorSettings).EMAPeriod2, ((MACDSettings)indicatorSettings).SignalPeriod); break; case IndicatorType.Stochastic: indicatorDataset.Values = _indicatorComputingService.ComputeStochastic( candles, ((StochasticSettings)indicatorSettings).Period, ((StochasticSettings)indicatorSettings).SMAPeriodK, ((StochasticSettings)indicatorSettings).SMAPeriodD); break; case IndicatorType.RelativeStrengthIndex: indicatorDataset.Values = _indicatorComputingService.ComputeRelativeStrengthIndex( candles, ((CommonIndicatorSettings)indicatorSettings).Period); break; case IndicatorType.AccumulationDistribution: indicatorDataset.Values = _indicatorComputingService.ComputeAccumulationDistribution( candles); break; case IndicatorType.WilliamsR: indicatorDataset.Values = _indicatorComputingService.ComputeWilliamsR( candles, ((CommonIndicatorSettings)indicatorSettings).Period); break; case IndicatorType.ParabolicSAR: indicatorDataset.Values = _indicatorComputingService.ComputeParabolicSAR(candles); break; default: throw new AnalysisException("Undefined indicator type"); } chartDataset.IndicatorData.Add(indicatorDataset); } var defaultTradingSettings = _configurationService.GetTradingSettings(); var tradingSettings = _configurationService.GetTradingSettings(); tradingSettings.Period = settings.Period; tradingSettings.Moment = settings.CurrentMoment; _configurationService.UpdateTradingSettings(tradingSettings); foreach (var candle in chartDataset.Candles) { tradingSettings.Moment = candle.Moment; _configurationService.UpdateTradingSettings(tradingSettings); //var newPositionInfo = await _marketNewPositionAnalysisService.ProcessMarketPosition(settings.CurrencyPairId); var tradingData = new TradingData { Moment = candle.Moment }; //switch (newPositionInfo.PositionType) //{ // case NewMarketPositionType.Buy: // tradingData.BuyPrice = candle.ClosePrice; // break; //} chartDataset.TradingData.Add(tradingData); } _configurationService.UpdateTradingSettings(defaultTradingSettings); return(chartDataset); }
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); }
public async Task <IList <Order> > GetActiveOrders(CurrencyPair currencyPair) { var storedOrders = _orderRepository.GetAll() .Where(orderEntity => String.Equals(orderEntity.CurrencyPair, currencyPair.Id, StringComparison.OrdinalIgnoreCase)) .ToList(); if (storedOrders.Any()) { var settings = _configurationService.GetTradingSettings(); var candle = (await _candleLoadingService.LoadCandles( currencyPair.Id, settings.Period.GetLowerFramePeriod(), 1, settings.Moment)) .Single(); var tradingBallanceQuoteCurrencyEntity = GetTradingBallnceInner(currencyPair.QuoteCurrencyId); if (tradingBallanceQuoteCurrencyEntity == null) { throw new ConnectorException(String.Format("Ballance for currency {0} not found", currencyPair.QuoteCurrencyId)); } var tradingBallanceBaseCurrencyEntity = GetTradingBallnceInner(currencyPair.BaseCurrencyId); if (tradingBallanceBaseCurrencyEntity == null) { throw new ConnectorException(String.Format("Ballance for currency {0} not found", currencyPair.BaseCurrencyId)); } var openPositionOrderEntity = storedOrders.Single(orderEntity => orderEntity.Role == OrderRoleType.OpenPosition); switch (openPositionOrderEntity.OrderStateType) { case OrderStateType.Suspended: if (openPositionOrderEntity.StopPrice <= candle.MaxPrice) { openPositionOrderEntity.OrderStateType = OrderStateType.New; openPositionOrderEntity.OrderType = OrderType.Limit; tradingBallanceQuoteCurrencyEntity.Reserved = openPositionOrderEntity.Price * openPositionOrderEntity.Quantity; tradingBallanceQuoteCurrencyEntity.Available -= openPositionOrderEntity.Price * openPositionOrderEntity.Quantity; if (tradingBallanceQuoteCurrencyEntity.Available < 0) { throw new ConnectorException("Ballance unavailable"); } _orderRepository.Update(openPositionOrderEntity); _tradingBallanceRepository.Update(tradingBallanceQuoteCurrencyEntity); } break; case OrderStateType.New: if (openPositionOrderEntity.Price >= candle.MinPrice) { openPositionOrderEntity.OrderStateType = OrderStateType.Filled; tradingBallanceQuoteCurrencyEntity.Available += openPositionOrderEntity.Price * openPositionOrderEntity.Quantity * 0.0001m; tradingBallanceBaseCurrencyEntity.Available += openPositionOrderEntity.Quantity; tradingBallanceQuoteCurrencyEntity.Reserved = 0m; _orderRepository.Update(openPositionOrderEntity); _tradingBallanceRepository.Update(tradingBallanceQuoteCurrencyEntity); _tradingBallanceRepository.Update(tradingBallanceBaseCurrencyEntity); } break; case OrderStateType.Filled: var closePositionOrderEntity = storedOrders.Single(orderEntity => orderEntity.Role == OrderRoleType.ClosePosition && orderEntity.ParentClientId == openPositionOrderEntity.ClientId); var processStopOrders = true; switch (closePositionOrderEntity.OrderStateType) { case OrderStateType.Suspended: if (closePositionOrderEntity.StopPrice >= candle.MinPrice) { closePositionOrderEntity.OrderStateType = OrderStateType.New; openPositionOrderEntity.OrderType = OrderType.Limit; tradingBallanceBaseCurrencyEntity.Reserved = closePositionOrderEntity.Quantity; tradingBallanceBaseCurrencyEntity.Available -= closePositionOrderEntity.Quantity; if (tradingBallanceBaseCurrencyEntity.Available < 0) { throw new ConnectorException("Ballance unavailable"); } _orderRepository.Update(closePositionOrderEntity); _tradingBallanceRepository.Update(tradingBallanceBaseCurrencyEntity); processStopOrders = false; } break; case OrderStateType.New: if (closePositionOrderEntity.Price <= candle.MaxPrice) { closePositionOrderEntity.OrderStateType = OrderStateType.Filled; tradingBallanceQuoteCurrencyEntity.Available += closePositionOrderEntity.Quantity * closePositionOrderEntity.Price * 1.0001m; tradingBallanceBaseCurrencyEntity.Reserved = 0m; _orderRepository.Update(closePositionOrderEntity); _tradingBallanceRepository.Update(tradingBallanceQuoteCurrencyEntity); _tradingBallanceRepository.Update(tradingBallanceBaseCurrencyEntity); processStopOrders = false; } break; } if (processStopOrders) { var stopLossOrderEntity = storedOrders.Single(orderEntity => orderEntity.Role == OrderRoleType.StopLoss && orderEntity.ParentClientId == openPositionOrderEntity.ClientId); switch (stopLossOrderEntity.OrderStateType) { case OrderStateType.Suspended: if (stopLossOrderEntity.StopPrice >= candle.MinPrice || stopLossOrderEntity.Price >= candle.MinPrice) { stopLossOrderEntity.OrderStateType = OrderStateType.Filled; tradingBallanceQuoteCurrencyEntity.Available += (stopLossOrderEntity.Quantity * stopLossOrderEntity.StopPrice ?? 0m) * 0.999m; if (tradingBallanceBaseCurrencyEntity.Reserved == 0) { tradingBallanceBaseCurrencyEntity.Available -= stopLossOrderEntity.Quantity; } tradingBallanceBaseCurrencyEntity.Reserved = 0m; _orderRepository.Update(stopLossOrderEntity); _tradingBallanceRepository.Update(tradingBallanceQuoteCurrencyEntity); _tradingBallanceRepository.Update(tradingBallanceBaseCurrencyEntity); } break; } } break; } } return(_orderRepository.GetAll() .Where(orderEntity => String.Equals(orderEntity.CurrencyPair, currencyPair.Id, StringComparison.OrdinalIgnoreCase)) .Select(orderEntity => orderEntity.ToModel(currencyPair)).ToList()); }
public PendingPositionInfo ProcessMarketPosition(TradingPosition activeTradingPosition) { var settings = _configurationService.GetTradingSettings(); var moment = settings.Moment ?? DateTime.UtcNow; var rsiSettings = new CommonIndicatorSettings { Period = 14 }; var targetPeriodLastCandles = _candleLoadingService.LoadCandles( activeTradingPosition.OpenPositionOrder.CurrencyPair.Id, settings.Period, rsiSettings.Period * 2, 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, 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) }); currentTargetPeriodCandle = targetPeriodLastCandles.Last(); } } 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 minWilliamsRValue = rsiValues.Where(item => item.Value.HasValue).Select(item => item.Value.Value).Min(); if (currentRSIValue?.Value == null) { throw new NoNullAllowedException("No WilliamR values calculated"); } //var higherPeriodMACDSettings = new MACDSettings //{ // EMAPeriod1 = 12, // EMAPeriod2 = 26, // SignalPeriod = 9 //}; //var higherPeriodMACDValues = _indicatorComputingService.ComputeMACD( // higherPeriodLastCandles, // higherPeriodMACDSettings.EMAPeriod1, // higherPeriodMACDSettings.EMAPeriod2, // higherPeriodMACDSettings.SignalPeriod) // .OfType<MACDValue>() // .ToList(); //var higherPeriodCurrentMACDValue = higherPeriodMACDValues.ElementAtOrDefault(higherPeriodMACDValues.Count - 1); var rsiTopBorder = 45; //if (higherPeriodCurrentMACDValue?.MACD > 0 && higherPeriodCurrentMACDValue.Histogram >= 0) // rsiTopBorder = 65; //if (higherPeriodCurrentMACDValue?.MACD > 0 || higherPeriodCurrentMACDValue?.Histogram >= 0) // rsiTopBorder = 60; if (currentRSIValue.Value <= rsiTopBorder && currentRSIValue.Value > 25 && ((activeTradingPosition.OpenPositionOrder.OrderStateType == OrderStateType.Suspended && currentRSIValue.Value > previousRSIValue?.Value) || (activeTradingPosition.OpenPositionOrder.OrderStateType != OrderStateType.Suspended)) && Math.Abs(minWilliamsRValue - currentRSIValue.Value ?? 0) < 20) { var topBidPrice = _orderBookLoadingService.GetTopBidPrice(activeTradingPosition.OpenPositionOrder.CurrencyPair, 3); var openPrice = activeTradingPosition.OpenPositionOrder.Price >= topBidPrice ? activeTradingPosition.OpenPositionOrder.Price : topBidPrice; if (activeTradingPosition.OpenPositionOrder.OrderStateType == OrderStateType.New && activeTradingPosition.OpenPositionOrder.Price != openPrice) { return new UpdateOrderInfo { OpenPrice = openPrice, ClosePrice = new[] { currentTargetPeriodCandle.MaxPrice, activeTradingPosition.ClosePositionOrder.Price }.Max(), CloseStopPrice = new[] { currentTargetPeriodCandle.MinPrice, activeTradingPosition.ClosePositionOrder.StopPrice ?? 0 }.Min(), StopLossPrice = new[] { currentTargetPeriodCandle.MinPrice - targetPeriodLastCandles.Select(candle => (candle.MaxPrice - candle.MinPrice) * 5).Average(), activeTradingPosition.StopLossOrder.StopPrice ?? 0 }.Min() } } ; return(new PendingOrderInfo()); } return(new CancelOrderInfo()); } }