Esempio n. 1
0
        private async Task ProcessInstrumentAsync(Instrument instrument)
        {
            try
            {
                OrderBook directOrderBook = await CalculateDirectOrderBookAsync(instrument);

                if (directOrderBook == null)
                {
                    return;
                }

                var orderBooks = new List <OrderBook>
                {
                    directOrderBook
                };

                if (instrument.CrossInstruments != null)
                {
                    foreach (CrossInstrument crossInstrument in instrument.CrossInstruments)
                    {
                        OrderBook crossOrderBook = await CalculateCrossOrderBookAsync(directOrderBook, crossInstrument);

                        if (crossOrderBook == null)
                        {
                            continue;
                        }

                        orderBooks.Add(crossOrderBook);
                    }
                }

                await ValidatePnLThresholdAsync(orderBooks, instrument);

                await ValidateInventoryThresholdAsync(orderBooks, instrument);

                await ValidateMarketMakerStateAsync(orderBooks);

                ValidateInstrumentMode(orderBooks, instrument.Mode);

                foreach (OrderBook orderBook in orderBooks)
                {
                    await _orderBookService.UpdateAsync(orderBook);
                }

                foreach (OrderBook orderBook in orderBooks)
                {
                    LimitOrder[] allowedLimitOrders = orderBook.LimitOrders
                                                      .Where(o => o.Error == LimitOrderError.None)
                                                      .ToArray();

                    await _lykkeExchangeService.ApplyAsync(orderBook.AssetPairId, allowedLimitOrders);
                }
            }
            catch (Exception exception)
            {
                _log.WarningWithDetails("An error occured while processing instrument", exception, instrument);
            }
        }
Esempio n. 2
0
        private async Task ProcessInstrumentAsync(Instrument instrument)
        {
            Quote quote = _quoteService.Get(instrument.QuoteSource, instrument.AssetPairId);

            if (quote == null)
            {
                _log.WarningWithDetails("No quote for instrument", new { instrument.AssetPairId });
                return;
            }

            AssetPair assetPair = _assetPairsReadModelRepository.TryGetIfEnabled(instrument.AssetPairId);

            if (assetPair == null)
            {
                _log.WarningWithDetails("Asset pair not found", new { instrument.AssetPairId });
                return;
            }

            Balance balance = await _balanceService.GetByAssetIdAsync(assetPair.BaseAssetId);

            IReadOnlyCollection <LimitOrder> limitOrders = EvenlyDistributedVolumeTrader.Calculate(quote, instrument,
                                                                                                   balance.Amount, assetPair.Accuracy, assetPair.InvertedAccuracy);

            await ValidateQuoteAsync(limitOrders, quote);

            ValidateMinVolume(limitOrders, assetPair.MinVolume);

            await _orderBookService.UpdateAsync(new OrderBook
            {
                AssetPairId = instrument.AssetPairId,
                Time        = DateTime.UtcNow,
                LimitOrders = limitOrders
            });

            if (instrument.Mode != InstrumentMode.Active)
            {
                SetError(limitOrders, LimitOrderError.Idle);
            }

            limitOrders = limitOrders
                          .Where(o => o.Error == LimitOrderError.None)
                          .ToArray();

            try
            {
                await _lykkeExchangeService.ApplyAsync(instrument.AssetPairId, limitOrders);
            }
            catch (Exception exception)
            {
                _log.WarningWithDetails("An error occurred while processing limit orders", exception, limitOrders);

                SetError(limitOrders, LimitOrderError.Unknown, "ME error");
            }
        }
        public async Task ExecuteLimitOrderAsync(HedgeLimitOrder hedgeLimitOrder)
        {
            await _hedgeLimitOrderService.AddAsync(hedgeLimitOrder);

            AssetPairSettings assetPairSettings =
                await _instrumentService.GetAssetPairAsync(hedgeLimitOrder.AssetPairId, Name);

            if (assetPairSettings == null)
            {
                hedgeLimitOrder.Error        = LimitOrderError.Unknown;
                hedgeLimitOrder.ErrorMessage = "Instrument not configured";

                _log.WarningWithDetails("No settings for instrument", hedgeLimitOrder);

                return;
            }

            decimal price = hedgeLimitOrder.Price
                            .TruncateDecimalPlaces(assetPairSettings.PriceAccuracy, hedgeLimitOrder.Type == LimitOrderType.Sell);

            decimal volume = Math.Round(hedgeLimitOrder.Volume, assetPairSettings.VolumeAccuracy);

            if (volume < assetPairSettings.MinVolume)
            {
                hedgeLimitOrder.Error = LimitOrderError.TooSmallVolume;
                return;
            }

            var limitOrder = new LimitOrder
            {
                Id     = hedgeLimitOrder.Id,
                Price  = price,
                Volume = volume,
                Type   = hedgeLimitOrder.Type
            };

            try
            {
                await _lykkeExchangeService.ApplyAsync(hedgeLimitOrder.AssetPairId, limitOrder);

                if (limitOrder.Error == LimitOrderError.None)
                {
                    _hedgeLimitOrders[hedgeLimitOrder.AssetId] = hedgeLimitOrder;
                }

                hedgeLimitOrder.Error        = limitOrder.Error;
                hedgeLimitOrder.ErrorMessage = limitOrder.ErrorMessage;
            }
            catch (ExchangeException exception)
            {
                hedgeLimitOrder.Error        = LimitOrderError.Unknown;
                hedgeLimitOrder.ErrorMessage = exception.Message;
            }
            catch (Exception exception)
            {
                hedgeLimitOrder.Error        = LimitOrderError.Unknown;
                hedgeLimitOrder.ErrorMessage = "Cannot create limit orders an unexpected error occurred";

                _log.WarningWithDetails("An error occurred during creating limit orders", exception, hedgeLimitOrder);
            }
        }
Esempio n. 4
0
        private async Task ProcessInstrumentAsync(Instrument instrument, DateTime iterationDateTime)
        {
            try
            {
                var startedAt = DateTime.UtcNow;

                OrderBook directOrderBook = await CalculateDirectOrderBookAsync(instrument, iterationDateTime);

                var finishedObCalculationAt = DateTime.UtcNow;

                //_log.Info("MarketMakerService.CalculateDirectOrderBookAsync() completed.", new
                //{
                //    AssetPairId = instrument.AssetPairId,
                //    StartedAt = startedAt,
                //    FinishedAt = finishedObCalculationAt,
                //    Latency = (finishedObCalculationAt - startedAt).TotalMilliseconds
                //});

                if (directOrderBook == null)
                {
                    return;
                }

                var orderBooks = new List <OrderBook>
                {
                    directOrderBook
                };

                if (instrument.CrossInstruments != null)
                {
                    foreach (CrossInstrument crossInstrument in instrument.CrossInstruments)
                    {
                        OrderBook crossOrderBook = await CalculateCrossOrderBookAsync(directOrderBook, crossInstrument);

                        if (crossOrderBook == null)
                        {
                            continue;
                        }

                        orderBooks.Add(crossOrderBook);
                    }
                }

                await ValidatePnLThresholdAsync(orderBooks, instrument);

                await ValidateInventoryThresholdAsync(orderBooks, instrument);

                await ValidateMarketMakerStateAsync(orderBooks);

                ValidateInstrumentMode(orderBooks, instrument.Mode);

                foreach (OrderBook orderBook in orderBooks)
                {
                    await _orderBookService.UpdateAsync(orderBook);
                }

                foreach (OrderBook orderBook in orderBooks)
                {
                    LimitOrder[] allowedLimitOrders = orderBook.LimitOrders
                                                      .Where(o => o.Error == LimitOrderError.None)
                                                      .ToArray();

                    await _lykkeExchangeService.ApplyAsync(orderBook.AssetPairId, allowedLimitOrders);
                }

                var finishedAt = DateTime.UtcNow;

                //_log.Info("MarketMakerService.ProcessInstrumentAsync() completed.", new
                //{
                //    AssetPairId = instrument.AssetPairId,
                //    StartedAt = startedAt,
                //    FinishedAt = finishedAt,
                //    Latency = (finishedAt - startedAt).TotalMilliseconds
                //});

                PrometheusMetrics.MarketMakingAssetPairLatency.Inc((finishedAt - startedAt).TotalMilliseconds);
            }
            catch (Exception exception)
            {
                _log.WarningWithDetails("An error occured while processing instrument", exception, instrument);
            }
        }
Esempio n. 5
0
        public async Task UpdateLimitOrdersAsync(string indexName)
        {
            IndexPrice indexPrice = await _indexPriceService.GetByIndexAsync(indexName);

            if (indexPrice == null)
            {
                throw new InvalidOperationException("Index price not found");
            }

            IndexSettings indexSettings = await _indexSettingsService.GetByIndexAsync(indexName);

            if (indexSettings == null)
            {
                throw new InvalidOperationException("Index settings not found");
            }

            AssetPairSettings assetPairSettings =
                await _instrumentService.GetAssetPairAsync(indexSettings.AssetPairId, Exchange);

            if (assetPairSettings == null)
            {
                throw new InvalidOperationException("Asset pair settings not found");
            }

            AssetSettings baseAssetSettings =
                await _instrumentService.GetAssetAsync(assetPairSettings.BaseAsset, ExchangeNames.Lykke);

            if (baseAssetSettings == null)
            {
                throw new InvalidOperationException("Base asset settings not found");
            }

            AssetSettings quoteAssetSettings =
                await _instrumentService.GetAssetAsync(assetPairSettings.QuoteAsset, ExchangeNames.Lykke);

            if (quoteAssetSettings == null)
            {
                throw new InvalidOperationException("Quote asset settings not found");
            }

            decimal sellPrice = (indexPrice.Price + indexSettings.SellMarkup)
                                .TruncateDecimalPlaces(assetPairSettings.PriceAccuracy, true);

            decimal buyPrice = indexPrice.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy);

            IReadOnlyCollection <LimitOrder> limitOrders =
                CreateLimitOrders(indexSettings, assetPairSettings, sellPrice, buyPrice);

            ValidateBalance(limitOrders, baseAssetSettings, quoteAssetSettings);

            ValidateMinVolume(limitOrders, assetPairSettings.MinVolume);

            LimitOrder[] allowedLimitOrders = limitOrders
                                              .Where(o => o.Error == LimitOrderError.None)
                                              .ToArray();

            _log.InfoWithDetails("Limit orders created", limitOrders);

            _limitOrderService.Update(indexSettings.AssetPairId, limitOrders);

            await _lykkeExchangeService.ApplyAsync(indexSettings.AssetPairId, allowedLimitOrders);

            _traceWriter.LimitOrders(indexSettings.AssetPairId, limitOrders);
        }