public NewPositionInfo ProcessMarketPosition(CurrencyPair currencyPair) { NewPositionInfo newPositionInfo; var conditionCheckingResult = CheckConditions(currencyPair); switch (conditionCheckingResult.ResultType) { case ConditionCheckingResultType.Passed: var buyPositionInfo = new NewOrderPositionInfo(NewMarketPositionType.Buy); buyPositionInfo.CurrencyPairId = currencyPair.Id; buyPositionInfo.OpenPrice = OrderBookLoadingService.GetTopMeaningfulBidPrice(currencyPair); buyPositionInfo.OpenStopPrice = OrderBookLoadingService.GetBottomAskPrice(currencyPair, 1); buyPositionInfo.ClosePrice = buyPositionInfo.CloseStopPrice = buyPositionInfo.OpenStopPrice; buyPositionInfo.StopLossPrice = buyPositionInfo.OpenPrice - currencyPair.TickSize * 2000; newPositionInfo = buyPositionInfo; break; default: newPositionInfo = new WaitPositionInfo(); break; } return(newPositionInfo); }
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); }
private async void OnOrderBookUpdated(object sender, OrderBookUpdatedEventArgs e) { if (Position.CurrencyPairId != e.CurrencyPairId) { return; } if (Position.IsAwaitingOrderUpdating) { return; } if (Interlocked.Read(ref _positionUpdatingTasksCount) > 0) { return; } Interlocked.Increment(ref _positionUpdatingTasksCount); await _positionUpdatingSemaphore.WaitAsync(); try { if (!Position.IsCompletedPosition) { if (Position.OpenPositionOrder.OrderStateType == OrderStateType.New) { var newPrice = _orderBookLoadingService.GetTopBidPrice(Position.OpenPositionOrder.CurrencyPair, 3); if (newPrice > Position.OpenPositionOrder.Price) { var nextPosition = Position.Clone(); nextPosition.OpenPositionOrder.Price = newPrice; nextPosition = await _tradingPositionService.UpdatePosition(Position, nextPosition, true, OnPositionChanged); if (nextPosition != null) { Position.SyncWithAnotherPosition(nextPosition, true); } } } else if (Position.ClosePositionOrder.OrderStateType == OrderStateType.New) { var newPrice = _orderBookLoadingService.GetBottomAskPrice(Position.OpenPositionOrder.CurrencyPair, 3); if (newPrice > 0 && newPrice < Position.ClosePositionOrder.Price) { var nextPosition = Position.Clone(); nextPosition.ClosePositionOrder.Price = newPrice; nextPosition = await _tradingPositionService.UpdatePosition(Position, nextPosition, true, OnPositionChanged); if (nextPosition != null) { Position.SyncWithAnotherPosition(nextPosition, true); } } } } } finally { _positionUpdatingSemaphore.Release(); } Interlocked.Decrement(ref _positionUpdatingTasksCount); }