public async Task <TradingPositionWorker> CreateWorkerWithExistingPosition(TradingPosition tradingPosition, Action <TradingPositionWorker, PositionChangedEventArgs> positionChangedCallback) { var positionWorker = CreateNewWorker(positionChangedCallback); await positionWorker.LoadExistingPosition(tradingPosition); return(positionWorker); }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return((currentState.OpenPositionOrder.OrderStateType == OrderStateType.Cancelled && currentState.ClosePositionOrder.OrderStateType == OrderStateType.Pending && currentState.StopLossOrder.OrderStateType == OrderStateType.Pending) || ((currentState.OpenPositionOrder.OrderStateType == OrderStateType.Filled || currentState.OpenPositionOrder.OrderStateType == OrderStateType.Expired) && (currentState.ClosePositionOrder.OrderStateType == OrderStateType.Filled || currentState.ClosePositionOrder.OrderStateType == OrderStateType.Cancelled) && (currentState.StopLossOrder.OrderStateType == OrderStateType.Filled || currentState.StopLossOrder.OrderStateType == OrderStateType.Cancelled))); }
public async Task CreateNewPosition(NewOrderPositionInfo positionInfo) { Position = await _tradingPositionService.OpenPosition(positionInfo); Position = await _tradingPositionService.UpdatePosition(null, Position, true, OnPositionChanged); await SubscribeOnTradingEvents(); }
public static void ChangePosition(this TradingPosition tradingPosition, UpdateOrderInfo marketInfo) { var now = DateTime.UtcNow; tradingPosition.OpenPositionOrder.Price = marketInfo.OpenPrice; if (tradingPosition.OpenPositionOrder.OrderStateType == OrderStateType.Suspended) { //tradingPosition.OpenPositionOrder.StopPrice = marketInfo.OpenStopPrice; tradingPosition.OpenPositionOrder.OrderType = OrderType.StopLimit; } else { tradingPosition.OpenPositionOrder.OrderStateType = OrderStateType.New; tradingPosition.OpenPositionOrder.StopPrice = null; tradingPosition.OpenPositionOrder.OrderType = OrderType.Limit; } tradingPosition.OpenPositionOrder.Updated = now; tradingPosition.ClosePositionOrder.Price = marketInfo.ClosePrice; tradingPosition.ClosePositionOrder.StopPrice = marketInfo.CloseStopPrice; tradingPosition.ClosePositionOrder.OrderType = OrderType.StopLimit; tradingPosition.ClosePositionOrder.OrderStateType = OrderStateType.Pending; tradingPosition.ClosePositionOrder.Updated = now; tradingPosition.StopLossOrder.Price = 0; tradingPosition.StopLossOrder.StopPrice = marketInfo.StopLossPrice; tradingPosition.StopLossOrder.OrderStateType = OrderStateType.Pending; tradingPosition.StopLossOrder.Updated = now; }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return((currentState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && currentState.StopLossOrder.OrderStateType == OrderStateType.Suspended) && (nextState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && nextState.StopLossOrder.OrderStateType == OrderStateType.Suspended)); }
public static void ChangePosition(this TradingPosition tradingPosition, FixStopLossInfo marketInfo) { var now = DateTime.UtcNow; tradingPosition.StopLossOrder.Price = 0; tradingPosition.StopLossOrder.StopPrice = marketInfo.StopLossPrice; tradingPosition.StopLossOrder.Updated = now; }
public static TradingPosition CreatePosition(NewOrderPositionInfo positionInfo, CurrencyPair currencyPair, TradingSettings tradingSettings) { var now = DateTime.UtcNow; var parentClientId = Guid.NewGuid(); var position = new TradingPosition { OpenPositionOrder = new Order { ClientId = parentClientId, CurrencyPair = currencyPair, Role = OrderRoleType.OpenPosition, OrderSide = tradingSettings.BaseOrderSide, OrderType = OrderType.StopLimit, OrderStateType = OrderStateType.Suspended, TimeInForce = OrderTimeInForceType.GoodTillCancelled, Price = positionInfo.OpenPrice, StopPrice = positionInfo.OpenStopPrice, Created = now, Updated = now }, ClosePositionOrder = new Order { ClientId = Guid.NewGuid(), ParentClientId = parentClientId, CurrencyPair = currencyPair, Role = OrderRoleType.ClosePosition, OrderSide = tradingSettings.OppositeOrderSide, OrderType = OrderType.StopLimit, OrderStateType = OrderStateType.Pending, TimeInForce = OrderTimeInForceType.GoodTillCancelled, Price = positionInfo.ClosePrice, StopPrice = positionInfo.CloseStopPrice, Created = now, Updated = now }, StopLossOrder = new Order { ClientId = Guid.NewGuid(), ParentClientId = parentClientId, CurrencyPair = currencyPair, Role = OrderRoleType.StopLoss, OrderSide = tradingSettings.OppositeOrderSide, OrderType = OrderType.StopMarket, OrderStateType = OrderStateType.Pending, TimeInForce = OrderTimeInForceType.GoodTillCancelled, Price = 0, StopPrice = positionInfo.StopLossPrice, Created = now, Updated = now } }; return(position); }
public static TradingPosition Clone(this TradingPosition source) { return(new TradingPosition { OpenPositionOrder = source.OpenPositionOrder.Clone(true), ClosePositionOrder = source.ClosePositionOrder.Clone(true), StopLossOrder = source.StopLossOrder.Clone(true) }); }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return((currentState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && (currentState.ClosePositionOrder.OrderStateType == OrderStateType.Pending || currentState.ClosePositionOrder.OrderStateType == OrderStateType.Suspended || currentState.ClosePositionOrder.OrderStateType == OrderStateType.New)) && (nextState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && nextState.ClosePositionOrder.OrderStateType == OrderStateType.Filled)); }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return(((currentState.OpenPositionOrder.OrderStateType == OrderStateType.New || currentState.OpenPositionOrder.OrderStateType == OrderStateType.Suspended) && currentState.ClosePositionOrder.OrderStateType == OrderStateType.Pending && currentState.StopLossOrder.OrderStateType == OrderStateType.Pending) && ((nextState.OpenPositionOrder.OrderStateType == OrderStateType.Filled || nextState.OpenPositionOrder.OrderStateType == OrderStateType.PartiallyFilled) && nextState.ClosePositionOrder.OrderStateType == OrderStateType.Pending && nextState.StopLossOrder.OrderStateType == OrderStateType.Pending)); }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return((currentState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && (currentState.ClosePositionOrder.OrderStateType == OrderStateType.Suspended || currentState.ClosePositionOrder.OrderStateType == OrderStateType.New || currentState.ClosePositionOrder.OrderStateType == OrderStateType.PartiallyFilled)) && (nextState.OpenPositionOrder.OrderStateType == OrderStateType.Filled && (nextState.ClosePositionOrder.OrderStateType == OrderStateType.Cancelled || nextState.ClosePositionOrder.OrderStateType == OrderStateType.Expired))); }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { nextState.OpenPositionOrder = await _ordersService.CreateBuyLimitOrder(nextState.OpenPositionOrder); nextState.ClosePositionOrder.ParentClientId = nextState.OpenPositionOrder.ClientId; nextState.StopLossOrder.ParentClientId = nextState.OpenPositionOrder.ClientId; _orderRepository.Insert(nextState.OpenPositionOrder.ToEntity()); _orderRepository.Insert(nextState.ClosePositionOrder.ToEntity()); _orderRepository.Insert(nextState.StopLossOrder.ToEntity()); var storedOrderPair = _orderRepository.GetAll() .ToList() .GroupOrders() .SingleOrDefault(orderPair => orderPair.Item1.ClientId == nextState.OpenPositionOrder.ClientId); if (storedOrderPair == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(nextState.OpenPositionOrder)}" } } ; nextState.OpenPositionOrder.Id = storedOrderPair.Item1.Id; nextState.ClosePositionOrder.Id = storedOrderPair.Item2.Id; nextState.StopLossOrder.Id = storedOrderPair.Item3.Id; _loggingService.LogAction(nextState.OpenPositionOrder.ToLogAction(OrderActionType.Create)); onPositionChangedCallback?.Invoke(new PositionChangedEventArgs(TradingEventType.NewPosition, nextState)); return(nextState); } }
public async Task <TradingPosition> UpdateTradingPositionState(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { ITradingPositionStateProcessor selectedProcessor; var completedProcessors = new List <ITradingPositionStateProcessor>(); var latestCurrentState = currentState; do { selectedProcessor = null; foreach (var stateProcessor in _workflowProcessors.Where(processor => !completedProcessors.Contains(processor))) { if (latestCurrentState == null || stateProcessor.IsAllowToProcess(latestCurrentState, nextState)) { selectedProcessor = stateProcessor; completedProcessors.Add(selectedProcessor); break; } } if (selectedProcessor != null) { latestCurrentState = await selectedProcessor.ProcessTradingPositionChanging(latestCurrentState, nextState, syncWithStock, onPositionChangedCallback); } if (currentState == null) { break; } } while (latestCurrentState != null && selectedProcessor != null); return(latestCurrentState); }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { if (syncWithStock) { try { nextState.StopLossOrder = await _ordersService.CancelOrder(currentState.StopLossOrder); } catch (ConnectorException e) { if (e.Message?.Contains("Order not found") ?? false) { var activeOrders = await _ordersService.GetActiveOrders(currentState.StopLossOrder.CurrencyPair); var serverSideStopLossOrder = activeOrders.FirstOrDefault(order => order.ClientId == currentState.StopLossOrder.ClientId) ?? await _ordersService.GetOrderFromHistory(currentState.StopLossOrder.ClientId, currentState.StopLossOrder.CurrencyPair); if (serverSideStopLossOrder != null) { if (serverSideStopLossOrder.OrderStateType == OrderStateType.Filled) { nextState.StopLossOrder.SyncWithAnotherOrder(serverSideStopLossOrder); var nextProcessor = new StopLossOrderFillingProcessor(_orderRepository, _ordersService, _loggingService); return(await nextProcessor.ProcessTradingPositionChanging(currentState, nextState, true, onPositionChangedCallback)); } if (serverSideStopLossOrder.OrderStateType == OrderStateType.Cancelled || serverSideStopLossOrder.OrderStateType == OrderStateType.Expired) { nextState.StopLossOrder.SyncWithAnotherOrder(serverSideStopLossOrder); } else { throw; } } else { throw; } } else { throw; } } } nextState.StopLossOrder.OrderStateType = OrderStateType.Cancelled; if (currentState.ClosePositionOrder.OrderStateType != OrderStateType.Filled) { if (!(currentState.ClosePositionOrder.OrderStateType == OrderStateType.Pending || currentState.ClosePositionOrder.OrderStateType == OrderStateType.Cancelled || currentState.ClosePositionOrder.OrderStateType == OrderStateType.Expired)) { try { await _ordersService.CancelOrder(currentState.ClosePositionOrder); } catch { // ignored } finally { nextState.ClosePositionOrder.OrderStateType = OrderStateType.Cancelled; } } var immediateCloseOrder = new Order { ClientId = Guid.NewGuid(), CurrencyPair = currentState.ClosePositionOrder.CurrencyPair, Role = OrderRoleType.ClosePosition, OrderSide = currentState.ClosePositionOrder.OrderSide, OrderType = OrderType.Market, OrderStateType = OrderStateType.New, TimeInForce = OrderTimeInForceType.GoodTillCancelled }; var serverSideOrder = await _ordersService.CreateSellMarketOrder(immediateCloseOrder); if (serverSideOrder.OrderStateType != OrderStateType.Filled) { throw new BusinessException("Unexpected order state found") { Details = $"Close position market order: {JsonConvert.SerializeObject(serverSideOrder)}" } } ; } var stopLossOrderEntity = _orderRepository.Get(nextState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(nextState.StopLossOrder)}" } } ; _orderRepository.Update(nextState.StopLossOrder.ToEntity(stopLossOrderEntity)); _loggingService.LogAction(nextState.ClosePositionOrder.ToLogAction(OrderActionType.Cancel)); return(nextState); } } }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return(currentState.ClosePositionOrder.OrderStateType != OrderStateType.Filled && (nextState.StopLossOrder.OrderStateType == OrderStateType.Cancelled || nextState.StopLossOrder.OrderStateType == OrderStateType.Expired)); }
internal bool TryGetPosition(Instrument instrument, out TradingPosition position) { return(positionPerInstrument.TryGetValue(instrument, out position)); }
public void AddPosition(TradingPosition position) { positionPerInstrument.Add(position.Instrument, position); }
public void RemovePosition(TradingPosition position) { positionPerInstrument.Remove(position.Instrument); }
public async Task LoadExistingPosition(TradingPosition existingPosition) { Position = existingPosition; await SubscribeOnTradingEvents(); }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { if (syncWithStock) { var newClientId = Guid.NewGuid(); await _ordersService.RequestReplaceOrder(currentState.OpenPositionOrder, newClientId, () => currentState.IsAwaitingOrderUpdating = false); currentState.IsAwaitingOrderUpdating = true; //currentState.OpenPositionOrder.ClientId = newClientId; //currentState.ClosePositionOrder.ParentClientId = newClientId; //currentState.StopLossOrder.ParentClientId = newClientId; var openOrderEntity = _orderRepository.Get(currentState.OpenPositionOrder.Id); if (openOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(currentState.OpenPositionOrder)}" } } ; _orderRepository.Update(currentState.OpenPositionOrder.ToEntity(openOrderEntity)); _loggingService.LogAction(currentState.OpenPositionOrder.ToLogAction(OrderActionType.Update)); var closeOrderEntity = _orderRepository.Get(currentState.ClosePositionOrder.Id); if (closeOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Close position order: {JsonConvert.SerializeObject(currentState.ClosePositionOrder)}" } } ; _orderRepository.Update(currentState.ClosePositionOrder.ToEntity(closeOrderEntity)); var stopLossOrderEntity = _orderRepository.Get(currentState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(currentState.StopLossOrder)}" } } ; _orderRepository.Update(currentState.StopLossOrder.ToEntity(stopLossOrderEntity)); return(currentState); } else { if (nextState.OpenPositionOrder.OrderStateType != OrderStateType.New && nextState.OpenPositionOrder.StopPrice == null) { throw new BusinessException("Unexpected order state found") { Details = $"Open position order: {JsonConvert.SerializeObject(nextState.OpenPositionOrder)}" } } ; var openOrderEntity = _orderRepository.Get(nextState.OpenPositionOrder.Id); if (openOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(nextState.OpenPositionOrder)}" } } ; _orderRepository.Update(nextState.OpenPositionOrder.ToEntity(openOrderEntity)); _loggingService.LogAction(nextState.OpenPositionOrder.ToLogAction(OrderActionType.Update)); var closeOrderEntity = _orderRepository.Get(nextState.ClosePositionOrder.Id); if (closeOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Close position order: {JsonConvert.SerializeObject(nextState.ClosePositionOrder)}" } } ; _orderRepository.Update(nextState.ClosePositionOrder.ToEntity(closeOrderEntity)); var stopLossOrderEntity = _orderRepository.Get(nextState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(nextState.StopLossOrder)}" } } ; _orderRepository.Update(nextState.StopLossOrder.ToEntity(stopLossOrderEntity)); return(nextState); } } } }
public static void SyncWithAnotherPosition(this TradingPosition targetPosition, TradingPosition sourcePosition, bool syncPrice = false) { targetPosition.OpenPositionOrder.SyncWithAnotherOrder(sourcePosition.OpenPositionOrder, syncPrice); targetPosition.ClosePositionOrder.SyncWithAnotherOrder(sourcePosition.ClosePositionOrder, syncPrice); targetPosition.StopLossOrder.SyncWithAnotherOrder(sourcePosition.StopLossOrder, syncPrice); }
public static void ChangePosition(this TradingPosition tradingPosition, CancelOrderInfo marketInfo) { tradingPosition.OpenPositionOrder.OrderStateType = OrderStateType.Cancelled; }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { var openOrderEntity = _orderRepository.Get(currentState.OpenPositionOrder.Id); if (openOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(currentState.OpenPositionOrder)}" } } ; _orderRepository.Delete(openOrderEntity); _loggingService.LogAction(currentState.OpenPositionOrder.ToLogAction(currentState.OpenPositionOrder.OrderStateType == OrderStateType.Filled ? OrderActionType.Fill : OrderActionType.Cancel)); var closeOrderEntity = _orderRepository.Get(currentState.ClosePositionOrder.Id); if (closeOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Close position order: {JsonConvert.SerializeObject(currentState.ClosePositionOrder)}" } } ; _orderRepository.Delete(closeOrderEntity); _loggingService.LogAction(currentState.ClosePositionOrder.ToLogAction(currentState.ClosePositionOrder.OrderStateType == OrderStateType.Filled ? OrderActionType.Fill : OrderActionType.Cancel)); var stopLossOrderEntity = _orderRepository.Get(currentState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(currentState.StopLossOrder)}" } } ; _orderRepository.Delete(stopLossOrderEntity); _loggingService.LogAction(currentState.StopLossOrder.ToLogAction(currentState.StopLossOrder.OrderStateType == OrderStateType.Filled ? OrderActionType.Fill : OrderActionType.Cancel)); _orderRepository.SaveChanges(); _orderHistoryRepository.Insert(currentState.OpenPositionOrder.ToHistory()); _orderHistoryRepository.Insert(currentState.ClosePositionOrder.ToHistory()); _orderHistoryRepository.Insert(currentState.StopLossOrder.ToHistory()); currentState.IsClosedPosition = true; TradingEventType eventType; if (currentState.OpenPositionOrder.OrderStateType == OrderStateType.Cancelled) { eventType = TradingEventType.PositionClosedDueCancel; } else if (currentState.ClosePositionOrder.OrderStateType == OrderStateType.Filled) { eventType = TradingEventType.PositionClosedSuccessfully; } else { eventType = TradingEventType.PositionClosedDueStopLoss; } onPositionChangedCallback?.Invoke(new PositionChangedEventArgs(eventType, currentState)); return(await Task.FromResult <TradingPosition>(null)); } } }
public static void ChangePosition(this TradingPosition tradingPosition, SuspendPositionInfo marketInfo) { tradingPosition.ClosePositionOrder.OrderStateType = OrderStateType.Pending; }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { if (syncWithStock && currentState.ClosePositionOrder.OrderStateType != OrderStateType.Pending) { try { await _ordersService.CancelOrder(currentState.ClosePositionOrder); } catch (ConnectorException e) { if (e.Message?.Contains("Order not found") ?? false) { var activeOrders = await _ordersService.GetActiveOrders(currentState.ClosePositionOrder.CurrencyPair); var serverSideClosePositionOrder = activeOrders.FirstOrDefault(order => order.ClientId == currentState.ClosePositionOrder.ClientId) ?? await _ordersService.GetOrderFromHistory(currentState.ClosePositionOrder.ClientId, currentState.ClosePositionOrder.CurrencyPair); if (serverSideClosePositionOrder?.OrderStateType != OrderStateType.Filled) { throw; } } else { throw; } } } if (!(nextState.StopLossOrder.OrderStateType == OrderStateType.Pending || nextState.StopLossOrder.OrderStateType == OrderStateType.Cancelled || nextState.StopLossOrder.OrderStateType == OrderStateType.Expired)) { try { await _ordersService.CancelOrder(currentState.StopLossOrder); } catch { // ignored } finally { nextState.StopLossOrder.OrderStateType = OrderStateType.Cancelled; } } var closeOrderEntity = _orderRepository.Get(nextState.ClosePositionOrder.Id); if (closeOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Close position order: {JsonConvert.SerializeObject(nextState.ClosePositionOrder)}" } } ; _orderRepository.Update(nextState.ClosePositionOrder.ToEntity(closeOrderEntity)); _loggingService.LogAction(nextState.ClosePositionOrder.ToLogAction(OrderActionType.Fill)); var stopLossOrderEntity = _orderRepository.Get(nextState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(nextState.StopLossOrder)}" } } ; _orderRepository.Update(nextState.StopLossOrder.ToEntity(stopLossOrderEntity)); _loggingService.LogAction(nextState.StopLossOrder.ToLogAction(OrderActionType.Cancel)); return(nextState); } } }
public async Task <TradingPosition> UpdatePosition(TradingPosition currentPosition, TradingPosition nextPosition, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { return(await _tradingWorkflowManager.UpdateTradingPositionState(currentPosition, nextPosition, syncWithStock, onPositionChangedCallback)); }
public bool IsAllowToProcess(TradingPosition currentState, TradingPosition nextState) { return(currentState == null); }
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); }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { if (nextState.OpenPositionOrder.OrderStateType == OrderStateType.PartiallyFilled) { try { await _ordersService.CancelOrder(currentState.OpenPositionOrder); } catch (ConnectorException e) { if (e.Message?.Contains("Order not found") ?? false) { var activeOrders = await _ordersService.GetActiveOrders(currentState.OpenPositionOrder.CurrencyPair); var serverSideOpenPositionOrder = activeOrders.FirstOrDefault(order => order.ClientId == currentState.OpenPositionOrder.ClientId) ?? await _ordersService.GetOrderFromHistory(currentState.OpenPositionOrder.ClientId, currentState.OpenPositionOrder.CurrencyPair); if (serverSideOpenPositionOrder?.OrderStateType != OrderStateType.Filled) { throw; } } else { throw; } } nextState.OpenPositionOrder.OrderStateType = OrderStateType.Filled; } nextState.StopLossOrder.OrderStateType = OrderStateType.Suspended; nextState.StopLossOrder = await _ordersService.CreateSellMarketOrder(nextState.StopLossOrder); var openOrderEntity = _orderRepository.Get(nextState.OpenPositionOrder.Id); if (openOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(nextState.OpenPositionOrder)}" } } ; _orderRepository.Update(nextState.OpenPositionOrder.ToEntity(openOrderEntity)); _loggingService.LogAction(nextState.OpenPositionOrder.ToLogAction(OrderActionType.Fill)); var stopLossOrderEntity = _orderRepository.Get(nextState.StopLossOrder.Id); if (stopLossOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Stop loss order: {JsonConvert.SerializeObject(nextState.StopLossOrder)}" } } ; _orderRepository.Update(nextState.StopLossOrder.ToEntity(stopLossOrderEntity)); _loggingService.LogAction(nextState.StopLossOrder.ToLogAction(OrderActionType.Create)); onPositionChangedCallback?.Invoke(new PositionChangedEventArgs(TradingEventType.PositionOpened, nextState)); return(nextState); } } }
public async Task <TradingPosition> ProcessTradingPositionChanging(TradingPosition currentState, TradingPosition nextState, bool syncWithStock, Action <PositionChangedEventArgs> onPositionChangedCallback) { if (syncWithStock) { try { nextState.OpenPositionOrder = await _ordersService.CancelOrder(currentState.OpenPositionOrder); } catch (ConnectorException e) { if (e.Message?.Contains("Order not found") ?? false) { var activeOrders = await _ordersService.GetActiveOrders(currentState.OpenPositionOrder.CurrencyPair); var serverSideOpenPositionOrder = activeOrders.FirstOrDefault(order => order.ClientId == currentState.OpenPositionOrder.ClientId) ?? await _ordersService.GetOrderFromHistory(currentState.OpenPositionOrder.ClientId, currentState.OpenPositionOrder.CurrencyPair); if (serverSideOpenPositionOrder != null) { if (serverSideOpenPositionOrder.OrderStateType == OrderStateType.Filled) { nextState.OpenPositionOrder.SyncWithAnotherOrder(serverSideOpenPositionOrder); var nextProcessor = new BuyOrderFillingProcessor(_orderRepository, _ordersService, _loggingService); return(await nextProcessor.ProcessTradingPositionChanging(currentState, nextState, true, onPositionChangedCallback)); } if (serverSideOpenPositionOrder.OrderStateType == OrderStateType.Cancelled || serverSideOpenPositionOrder.OrderStateType == OrderStateType.Expired) { nextState.OpenPositionOrder.SyncWithAnotherOrder(serverSideOpenPositionOrder); } else { throw; } } else { throw; } } else { throw; } } } var openOrderEntity = _orderRepository.Get(nextState.OpenPositionOrder.Id); if (openOrderEntity == null) { throw new BusinessException("Order was not found in storage") { Details = $"Open position order: {JsonConvert.SerializeObject(nextState.OpenPositionOrder)}" } } ; _orderRepository.Update(nextState.OpenPositionOrder.ToEntity(openOrderEntity)); _loggingService.LogAction(nextState.OpenPositionOrder.ToLogAction(nextState.OpenPositionOrder.OrderStateType == OrderStateType.Cancelled ? OrderActionType.Cancel : OrderActionType.Update)); if (nextState.OpenPositionOrder.OrderStateType == OrderStateType.Cancelled) { onPositionChangedCallback?.Invoke(new PositionChangedEventArgs(TradingEventType.PositionCancelled, nextState)); } return(nextState); } }