public void RejectPriceRequest(string operationId, string reason) { _cqrsSender.PublishEvent(new PriceForSpecialLiquidationCalculationFailedEvent { OperationId = operationId, CreationTime = _dateService.Now(), Reason = reason }, _cqrsContextNamesSettings.Gavel); _requests.TryRemove(operationId, out _); }
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(); } }
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; } }
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); }); }
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)); }
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); }