Beispiel #1
0
        public void RejectPriceRequest(string operationId, string reason)
        {
            _cqrsSender.PublishEvent(new PriceForSpecialLiquidationCalculationFailedEvent
            {
                OperationId  = operationId,
                CreationTime = _dateService.Now(),
                Reason       = reason
            }, _cqrsContextNamesSettings.Gavel);

            _requests.TryRemove(operationId, out _);
        }
Beispiel #2
0
        private void RecompileScheduleTimelineCacheUnsafe(string assetPairId, DateTime currentDateTime,
                                                          TimeSpan scheduleCutOff)
        {
            var scheduleSettings = _rawScheduleSettingsCache.TryGetValue(assetPairId, out var settings)
                ? settings
                : new List <ScheduleSettings>();

            if (!scheduleSettings.Any())
            {
                return;
            }

            var resultingTimeIntervals = CompileSchedule(scheduleSettings, currentDateTime, scheduleCutOff);

            _readerWriterLockSlim.EnterWriteLock();
            try
            {
                _compiledScheduleTimelineCache[assetPairId] = resultingTimeIntervals;

                _cqrsSender.PublishEvent(new CompiledScheduleChangedEvent
                {
                    AssetPairId    = assetPairId,
                    EventTimestamp = _dateService.Now(),
                    TimeIntervals  = resultingTimeIntervals.Select(x => x.ToRabbitMqContract()).ToList(),
                });
            }
            finally
            {
                _readerWriterLockSlim.ExitWriteLock();
            }
        }
Beispiel #3
0
        private void HandleMarketStateChangesUnsafe(DateTime currentTime, string[] marketIds = null)
        {
            foreach (var(marketId, scheduleSettings) in _compiledMarketScheduleCache
                     // ReSharper disable once AssignNullToNotNullAttribute
                     .Where(x => marketIds.IsNullOrEmpty() || marketIds.Contains(x.Key)))
            {
                var newState = scheduleSettings.GetMarketState(marketId, currentTime);
                _cqrsSender.PublishEvent(new MarketStateChangedEvent
                {
                    Id             = marketId,
                    IsEnabled      = newState.IsEnabled,
                    EventTimestamp = _dateService.Now(),
                });

                _marketStates[marketId] = newState;
            }
        }
Beispiel #4
0
        public void FakeGetPriceForSpecialLiquidation(string operationId, string instrument, decimal volume)
        {
            _threadSwitcher.SwitchThread(async() =>
            {
                await Task.Delay(1000);//waiting for the state to be saved into the repo

                _cqrsSender.PublishEvent(new PriceForSpecialLiquidationCalculatedEvent
                {
                    OperationId  = operationId,
                    CreationTime = _dateService.Now(),
                    Instrument   = instrument,
                    Volume       = volume,
                    Price        = _specialLiquidationSettings.FakePrice,
                }, _cqrsContextNamesSettings.Gavel);
            });
        }
Beispiel #5
0
        public async Task <string> PlaceAsync([FromBody] OrderPlaceRequest request)
        {
            var(baseOrder, relatedOrders) = (default(Order), default(List <Order>));
            try
            {
                (baseOrder, relatedOrders) = await _validateOrderService.ValidateRequestAndCreateOrders(request);
            }
            catch (ValidateOrderException exception)
            {
                _cqrsSender.PublishEvent(new OrderPlacementRejectedEvent
                {
                    EventTimestamp    = _dateService.Now(),
                    OrderPlaceRequest = request,
                    RejectReason      = exception.RejectReason.ToType <OrderRejectReasonContract>(),
                    RejectReasonText  = exception.Message,
                });
                throw;
            }

            var placedOrder = await _tradingEngine.PlaceOrderAsync(baseOrder);

            _operationsLogService.AddLog("action order.place", request.AccountId, request.ToJson(),
                                         placedOrder.ToJson());

            if (placedOrder.Status == OrderStatus.Rejected)
            {
                var message = $"Order {placedOrder.Id} from account {placedOrder.AccountId} for instrument {placedOrder.AssetPairId} is rejected: {placedOrder.RejectReason} ({placedOrder.RejectReasonText}). Comment: {placedOrder.Comment}.";
                throw new ValidateOrderException(placedOrder.RejectReason, placedOrder.RejectReasonText, message);
            }

            foreach (var order in relatedOrders)
            {
                var placedRelatedOrder = await _tradingEngine.PlaceOrderAsync(order);

                _operationsLogService.AddLog("action related.order.place", request.AccountId, request.ToJson(),
                                             placedRelatedOrder.ToJson());
            }

            return(placedOrder.Id);
        }
        public Task <ExecutionReport> ExecuteOrder(OrderModel orderModel, CancellationToken cancellationToken)
        {
            if (orderModel == null || orderModel.Volume == 0)
            {
                return(Task.FromResult(new ExecutionReport
                {
                    Success = false,
                    ExecutionStatus = OrderExecutionStatus.Rejected,
                    FailureType = OrderStatusUpdateFailureType.ConnectorError,
                }));
            }

            ExecutionReport result;

            try
            {
                _chaosKitty.Meow(nameof(FakeExchangeConnectorClient));

                ExternalOrderBook orderbook;
                decimal?          currentPrice;

                if (orderModel.Modality == TradeRequestModality.Liquidation_CorporateAction
                    ||
                    orderModel.Modality == TradeRequestModality.Liquidation_MarginCall)
                {
                    if (orderModel.Price == null)
                    {
                        throw new InvalidOperationException("Order should have price specified in case of special liquidation");
                    }

                    currentPrice = (decimal?)orderModel.Price;

                    orderbook = new ExternalOrderBook(MatchingEngineConstants.DefaultSpecialLiquidation,
                                                      orderModel.Instrument, _dateService.Now(), new
                                                      []
                    {
                        new VolumePrice
                        {
                            Price = currentPrice.Value, Volume = (decimal)orderModel.Volume
                        }
                    },
                                                      new
                                                      []
                    {
                        new VolumePrice
                        {
                            Price = currentPrice.Value, Volume = (decimal)orderModel.Volume
                        }
                    });
                }
                else
                {
                    orderbook = _orderbookService.GetOrderBook(orderModel.Instrument);

                    if (orderbook == null)
                    {
                        throw new InvalidOperationException("Orderbook was not found");
                    }

                    currentPrice = orderbook.GetMatchedPrice((decimal)orderModel.Volume,
                                                             orderModel.TradeType == TradeType.Buy ? OrderDirection.Buy : OrderDirection.Sell);
                }

                result = new ExecutionReport(
                    type: orderModel.TradeType,
                    time: DateTime.UtcNow,
                    price: (double)(currentPrice ?? throw new Exception("No price")),
                    volume: orderModel.Volume,
                    fee: 0,
                    success: true,
                    executionStatus: OrderExecutionStatus.Fill,
                    failureType: OrderStatusUpdateFailureType.None,
                    orderType: orderModel.OrderType,
                    execType: ExecType.Trade,
                    clientOrderId: Guid.NewGuid().ToString(),
                    exchangeOrderId: Guid.NewGuid().ToString(),
                    instrument: new Instrument(orderModel.Instrument, orderModel.ExchangeName));

                _cqrsSender.PublishEvent(new OrderExecutionOrderBookContract
                {
                    OrderId         = orderModel.OrderId,
                    Volume          = (decimal)orderModel.Volume,
                    ExternalOrderId = result.ExchangeOrderId,
                    OrderBook       = new ExternalOrderBookContract
                    {
                        AssetPairId      = orderbook.AssetPairId,
                        ExchangeName     = orderbook.ExchangeName,
                        Timestamp        = orderbook.Timestamp,
                        ReceiveTimestamp = _dateService.Now(),
                        Asks             = orderbook.Asks.Select(a => new VolumePriceContract
                        {
                            Price = a.Price, Volume = a.Volume
                        }).ToList(),
                        Bids = orderbook.Bids.Select(a => new VolumePriceContract
                        {
                            Price = a.Price, Volume = a.Volume
                        }).ToList()
                    }
                }, _settings.Cqrs.ContextNames.Gavel);
            }
            catch (Exception ex)
            {
                _log.WriteErrorAsync(nameof(FakeExchangeConnectorClient), nameof(ExecuteOrder),
                                     orderModel.ToJson(), ex);

                result = new ExecutionReport(
                    type: orderModel.TradeType,
                    time: DateTime.UtcNow,
                    price: 0,
                    volume: 0,
                    fee: 0,
                    success: false,
                    executionStatus: OrderExecutionStatus.Rejected,
                    failureType: OrderStatusUpdateFailureType.ExchangeError,
                    orderType: orderModel.OrderType,
                    execType: ExecType.Trade,
                    clientOrderId: null,
                    exchangeOrderId: null,
                    instrument: new Instrument(orderModel.Instrument, orderModel.ExchangeName));
            }

            return(Task.FromResult(result));
        }
Beispiel #7
0
        private void SendPositionHistoryEvent(Position position, PositionHistoryTypeContract historyType,
                                              decimal chargedPnl, string orderAdditionalInfo, Order dealOrder = null, decimal?dealVolume = null,
                                              PositionOpenMetadata metadata = null)
        {
            DealContract deal = null;

            if (dealOrder != null && dealVolume != null)
            {
                var sign = position.Volume > 0 ? 1 : -1;

                var accountBaseAssetAccuracy = AssetsConstants.DefaultAssetAccuracy;

                var fpl = Math.Round((dealOrder.ExecutionPrice.Value - position.OpenPrice) *
                                     dealOrder.FxRate * dealVolume.Value * sign, accountBaseAssetAccuracy);
                var balanceDelta = fpl - Math.Round(chargedPnl, accountBaseAssetAccuracy);

                var dealId = historyType == PositionHistoryTypeContract.Close
                    ? position.Id
                    : _identityGenerator.GenerateAlphanumericId();

                deal = new DealContract
                {
                    DealId                  = dealId,
                    PositionId              = position.Id,
                    Volume                  = dealVolume.Value,
                    Created                 = dealOrder.Executed.Value,
                    OpenTradeId             = position.OpenTradeId,
                    OpenOrderType           = position.OpenOrderType.ToType <OrderTypeContract>(),
                    OpenOrderVolume         = position.OpenOrderVolume,
                    OpenOrderExpectedPrice  = position.ExpectedOpenPrice,
                    CloseTradeId            = dealOrder.Id,
                    CloseOrderType          = dealOrder.OrderType.ToType <OrderTypeContract>(),
                    CloseOrderVolume        = dealOrder.Volume,
                    CloseOrderExpectedPrice = dealOrder.Price,
                    OpenPrice               = position.OpenPrice,
                    OpenFxPrice             = position.OpenFxPrice,
                    ClosePrice              = dealOrder.ExecutionPrice.Value,
                    CloseFxPrice            = dealOrder.FxRate,
                    Fpl             = fpl,
                    PnlOfTheLastDay = balanceDelta,
                    AdditionalInfo  = dealOrder.AdditionalInfo,
                    Originator      = dealOrder.Originator.ToType <OriginatorTypeContract>()
                };

                var account = _accountsCacheService.Get(position.AccountId);

                _cqrsSender.PublishEvent(new PositionClosedEvent(account.Id, account.ClientId,
                                                                 deal.DealId, position.AssetPairId, balanceDelta));

                _accountUpdateService.FreezeUnconfirmedMargin(position.AccountId, deal.DealId, balanceDelta)
                .GetAwaiter().GetResult();    //todo consider making this async or pass to broker
            }

            var positionContract = _convertService.Convert <Position, PositionContract>(position,
                                                                                        o => o.ConfigureMap(MemberList.Destination).ForMember(x => x.TotalPnL, c => c.Ignore()));

            positionContract.TotalPnL = position.GetFpl();

            var historyEvent = new PositionHistoryEvent
            {
                PositionSnapshot    = positionContract,
                Deal                = deal,
                EventType           = historyType,
                Timestamp           = _dateService.Now(),
                ActivitiesMetadata  = metadata?.ToJson(),
                OrderAdditionalInfo = orderAdditionalInfo,
            };

            _rabbitMqNotifyService.PositionHistory(historyEvent);
        }