Example #1
0
        public static double CalculateAveragePrice(
            OrderBookNoSql orderBook,
            ISpotInstrument instrument,
            IAsset fromAsset,
            IAsset toAsset,
            IAsset volumeAsset,
            double volume)
        {
            if (instrument.BaseAsset == fromAsset.Symbol && volumeAsset.Symbol == fromAsset.Symbol)
            {
                return((double)CalculateAveragePriceStraight(orderBook.BuyLevels.OrderByDescending(e => e.Price),
                                                             (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == fromAsset.Symbol && volumeAsset.Symbol == toAsset.Symbol)
            {
                return((double)CalculateAveragePriceNotStraight(orderBook.BuyLevels.OrderByDescending(e => e.Price),
                                                                (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == toAsset.Symbol && volumeAsset.Symbol == toAsset.Symbol)
            {
                return((double)CalculateAveragePriceStraight(orderBook.SellLevels.OrderBy(e => e.Price),
                                                             (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == toAsset.Symbol && volumeAsset.Symbol == fromAsset.Symbol)
            {
                return((double)CalculateAveragePriceNotStraight(orderBook.SellLevels.OrderBy(e => e.Price),
                                                                (decimal)volume, instrument.Accuracy));
            }

            throw new Exception("CalculateAveragePrice cant calculate price and volume");
        }
        private ProcessQuoteResult ProcessOneInstrument(GetQuoteRequest requestQuote,
                                                        ISpotInstrument instrument, double markUp)
        {
            _logger.LogInformation("Receive ProcessOneInstrument requestQuote: {JsonTextRequestQuote}; instrument: {JsonTextInstrument}; markUp : {JsonTextMarkUp}",
                                   JsonConvert.SerializeObject(requestQuote),
                                   JsonConvert.SerializeObject(instrument),
                                   JsonConvert.SerializeObject(markUp));

            var fromAsset = _assetsClient.GetAssetById(new AssetIdentity()
            {
                BrokerId = requestQuote.BrokerId, Symbol = requestQuote.FromAsset
            });

            if (fromAsset == null)
            {
                return(new ProcessQuoteResult("Unknown asset"));
            }

            var toAsset = _assetsClient.GetAssetById(new AssetIdentity()
            {
                BrokerId = requestQuote.BrokerId,
                Symbol   = instrument.BaseAsset == fromAsset.Symbol
                    ? instrument.QuoteAsset
                    : instrument.BaseAsset
            });

            if (toAsset == null)
            {
                return(new ProcessQuoteResult("Unknown opposite asset"));
            }

            double volume;
            IAsset fixedAsset;

            if (requestQuote.IsFromFixed)
            {
                volume     = requestQuote.FromAssetVolume;
                fixedAsset = fromAsset;
            }
            else
            {
                volume     = requestQuote.ToAssetVolume;
                fixedAsset = toAsset;
            }

            var fees = _spotInstrumentFeesClient.GetSpotInstrumentFees(requestQuote.BrokerId, instrument.Symbol);
            var fee  = fees?.TakerFeeSize ?? 0;

            var orderBook = _orderBookService.GetOrderBook(requestQuote.BrokerId, instrument.Symbol);

            if (orderBook == null)
            {
                return(new ProcessQuoteResult("No liquidity"));
            }

            var price = AveragePriceCalculator.CalculateAveragePrice(orderBook, instrument, fromAsset, toAsset,
                                                                     fixedAsset, volume);

            if (price <= 0)
            {
                return(new ProcessQuoteResult("No liquidity"));
            }

            price = (1 + markUp + fee) * price;
            price = Math.Round(price, Mathematics.AccuracyToNormalizeDouble);
            price = Math.Round(price, instrument.Accuracy, MidpointRounding.ToZero);

            var toAssetVolume       = 0.0;
            var fromAssetVolume     = 0.0;
            var oppositeVolume      = 0.0;
            var oppositeAssetSymbol = string.Empty;

            if (requestQuote.IsFromFixed)
            {
                fromAssetVolume = volume;
                if (instrument.BaseAsset == fromAsset.Symbol)
                {
                    toAssetVolume       = oppositeVolume = volume * price;
                    oppositeAssetSymbol = toAsset.Symbol;
                }
                else
                {
                    toAssetVolume       = oppositeVolume = volume / price;
                    oppositeAssetSymbol = toAsset.Symbol;
                }
            }
            else
            {
                toAssetVolume = volume;
                if (instrument.BaseAsset == toAsset.Symbol)
                {
                    fromAssetVolume     = oppositeVolume = volume * price;
                    oppositeAssetSymbol = fromAsset.Symbol;
                }
                else
                {
                    fromAssetVolume     = oppositeVolume = volume / price;
                    oppositeAssetSymbol = fromAsset.Symbol;
                }
            }

            fromAssetVolume = Math.Round(fromAssetVolume, Mathematics.AccuracyToNormalizeDouble);
            fromAssetVolume = Math.Round(fromAssetVolume, fromAsset.Accuracy, MidpointRounding.ToPositiveInfinity);

            toAssetVolume = Math.Round(toAssetVolume, Mathematics.AccuracyToNormalizeDouble);
            toAssetVolume = Math.Round(toAssetVolume, toAsset.Accuracy, MidpointRounding.ToZero);

            return(new ProcessQuoteResult(
                       fromAssetVolume,
                       toAssetVolume,
                       price,
                       oppositeVolume,
                       oppositeAssetSymbol,
                       new List <InstrumentInTrade>()
            {
                new InstrumentInTrade()
                {
                    Symbol = instrument.Symbol,
                    Price = price
                }
            }));
        }