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)));
 }
Example #3
0
        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)
     });
 }
Example #9
0
 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);
        }
    }
Example #13
0
        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);
        }
Example #14
0
        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);
        }
    }
}
Example #15
0
 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);
 }
Example #19
0
 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;
 }
Example #25
0
        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);
        }
    }
}
Example #26
0
 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);
        }
    }