public async Task <decimal> GetNoFreshQuotesMarkup(string assetPairId)
        {
            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            TimeSpan noFreshQuotesInterval = marketMakerSettings.NoFreshQuotesInterval;
            decimal  noFreshQuotesMarkup   = marketMakerSettings.NoFreshQuotesMarkup;

            if (noFreshQuotesInterval == default(TimeSpan) || noFreshQuotesMarkup == default(decimal))
            {
                return(0);
            }

            Quote quote = await _quoteService.GetAsync(ExchangeNames.B2C2, assetPairId);

            if (quote == null)
            {
                return(noFreshQuotesMarkup);
            }

            if (DateTime.UtcNow - quote.Time > noFreshQuotesInterval)
            {
                return(noFreshQuotesMarkup);
            }

            return(0);
        }
Exemple #2
0
        public async Task <decimal> GetNoFreshQuotesMarkup(string assetPairId)
        {
            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            TimeSpan noFreshQuotesInterval = marketMakerSettings.NoFreshQuotesInterval;
            decimal  noFreshQuotesMarkup   = marketMakerSettings.NoFreshQuotesMarkup;

            if (noFreshQuotesInterval == default(TimeSpan) || noFreshQuotesMarkup == default(decimal))
            {
                _log.InfoWithDetails("No quotes check.", new
                {
                    assetPairId,
                    noFreshQuotesIntervalEqual = noFreshQuotesInterval == default(TimeSpan),
                    noFreshQuotesMarkupEqual   = noFreshQuotesMarkup == default(decimal),
                    noFreshQuotesInterval,
                    noFreshQuotesMarkup
                });

                return(0);
            }

            Quote quote = await _quoteService.GetAsync(ExchangeNames.B2C2, assetPairId);

            if (quote == null)
            {
                _log.InfoWithDetails("Quote is null.", assetPairId);

                return(noFreshQuotesMarkup);
            }

            _log.InfoWithDetails("Checking time.", new
            {
                assetPairId,
                quote.Time,
                noFreshQuotesInterval
            });

            if (DateTime.UtcNow - quote.Time > noFreshQuotesInterval)
            {
                _log.InfoWithDetails("No quotes.", new
                {
                    assetPairId,
                    quote.Time,
                    noFreshQuotesInterval
                });

                return(noFreshQuotesMarkup);
            }

            _log.InfoWithDetails("There is a quote so markup is 0.", new
            {
                assetPairId,
                quote.Time,
                noFreshQuotesInterval
            });

            return(0);
        }
        public async Task <decimal> GetFiatEquityMarkup(string assetPairId)
        {
            AssetPair lykkeAssetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(assetPairId);

            Domain.AssetSettings quoteAssetSettings = await _assetSettingsService.GetByLykkeIdAsync(lykkeAssetPair.QuotingAssetId);

            if (quoteAssetSettings == null)
            {
                _log.WarningWithDetails("Can't find asset settings while calculating fiat equity.", lykkeAssetPair.QuotingAssetId);

                return(0);
            }

            if (quoteAssetSettings.IsCrypto)
            {
                return(0);
            }

            decimal fiatEquity = GetFiatEquity();

            if (fiatEquity >= 0)
            {
                return(0);
            }

            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            decimal thresholdFrom = marketMakerSettings.FiatEquityThresholdFrom;
            decimal thresholdTo   = marketMakerSettings.FiatEquityThresholdTo;
            decimal markupFrom    = marketMakerSettings.FiatEquityMarkupFrom;
            decimal markupTo      = marketMakerSettings.FiatEquityMarkupTo;

            if (thresholdFrom >= thresholdTo)
            {
                return(0);
            }

            decimal markup = CalculateMarkup(fiatEquity, thresholdFrom, thresholdTo, markupFrom, markupTo);

            return(markup);
        }
Exemple #4
0
        public async Task <MarketMakerSettingsModel> GetMarketMakerSettingsAsync()
        {
            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            return(Mapper.Map <MarketMakerSettingsModel>(marketMakerSettings));
        }
Exemple #5
0
        private async Task <OrderBook> CalculateDirectOrderBookAsync(Instrument instrument, DateTime iterationDateTime)
        {
            Quote[] quotes = _b2C2OrderBookService.GetQuotes(instrument.AssetPairId);

            if (quotes == null || quotes.Length != 2)
            {
                _log.WarningWithDetails("No quotes for instrument", instrument.AssetPairId);
                return(null);
            }

            Balance  baseAssetBalance   = null;
            Balance  quoteAssetBalance  = null;
            TimeSpan timeSinceLastTrade = TimeSpan.Zero;

            if (instrument.AllowSmartMarkup)
            {
                AssetPairLink assetPairLink =
                    await _assetPairLinkService.GetByInternalAssetPairIdAsync(instrument.AssetPairId);

                if (assetPairLink != null && !assetPairLink.IsEmpty())
                {
                    baseAssetBalance =
                        await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalBaseAssetId);

                    quoteAssetBalance =
                        await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalQuoteAssetId);

                    timeSinceLastTrade =
                        DateTime.UtcNow - _tradeService.GetLastInternalTradeTime(instrument.AssetPairId);
                }
                else
                {
                    _log.WarningWithDetails("The asset pair link does not configured", new { instrument.AssetPairId });
                }
            }

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            Asset baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.BaseAssetId);

            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            decimal globalMarkup = marketMakerSettings.LimitOrderPriceMarkup;

            decimal noQuotesMarkup = await _noFreshQuotesStopLossService.GetNoFreshQuotesMarkup(assetPair.Id);

            decimal pnLStopLossMarkup = await _pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(assetPair.Id);

            decimal fiatEquityStopLossMarkup = await _fiatEquityStopLossService.GetFiatEquityMarkup(assetPair.Id);

            _log.InfoWithDetails("Arguments for Calculator.CalculateLimitOrders(...).", new
            {
                instrument.AssetPairId,
                quotes,
                levels                                   = instrument.Levels.ToArray(),
                baseAmountBalance                        = baseAssetBalance?.Amount ?? 0,
                quoteAmountBalance                       = quoteAssetBalance?.Amount ?? 0,
                timeSinceLastTradeTotalSeconds           = (int)timeSinceLastTrade.TotalSeconds,
                instrumentHalfLifePeriod                 = instrument.HalfLifePeriod,
                instrumentAllowSmartMarkup               = instrument.AllowSmartMarkup,
                marketMakerSettingsLimitOrderPriceMarkup = globalMarkup,
                pnLStopLossMarkup,
                fiatEquityStopLossMarkup,
                noQuotesMarkup,
                assetPairAccuracy = assetPair.Accuracy,
                baseAssetAccuracy = baseAsset.Accuracy,
                instrument
            });

            OrderBookUpdateReport orderBookUpdateReport = null;

            if (_isOrderBooksUpdateReportEnabled)
            {
                orderBookUpdateReport                    = new OrderBookUpdateReport(iterationDateTime);
                orderBookUpdateReport.AssetPair          = instrument.AssetPairId;
                orderBookUpdateReport.FirstQuoteAsk      = quotes[0].Ask;
                orderBookUpdateReport.FirstQuoteBid      = quotes[0].Bid;
                orderBookUpdateReport.SecondQuoteAsk     = quotes[1].Ask;
                orderBookUpdateReport.SecondQuoteBid     = quotes[1].Bid;
                orderBookUpdateReport.QuoteDateTime      = quotes[0].Time;
                orderBookUpdateReport.GlobalMarkup       = globalMarkup;
                orderBookUpdateReport.NoFreshQuoteMarkup = noQuotesMarkup;
                orderBookUpdateReport.PnLStopLossMarkup  = pnLStopLossMarkup;
                orderBookUpdateReport.FiatEquityMarkup   = fiatEquityStopLossMarkup;
            }

            IReadOnlyCollection <LimitOrder> limitOrders = Calculator.CalculateLimitOrders(
                quotes[0],
                quotes[1],
                instrument.Levels.ToArray(),
                baseAssetBalance?.Amount ?? 0,
                quoteAssetBalance?.Amount ?? 0,
                (int)timeSinceLastTrade.TotalSeconds,
                instrument.HalfLifePeriod,
                instrument.AllowSmartMarkup,
                globalMarkup,
                pnLStopLossMarkup,
                fiatEquityStopLossMarkup,
                noQuotesMarkup,
                assetPair.Accuracy,
                baseAsset.Accuracy,
                orderBookUpdateReport);

            await ValidateQuoteTimeoutAsync(limitOrders, quotes[0]);

            await ValidateQuoteTimeoutAsync(limitOrders, quotes[1]);

            ValidateMinVolume(limitOrders, (decimal)assetPair.MinVolume);

            await ValidatePriceAsync(limitOrders);

            await ValidateBalanceAsync(limitOrders, assetPair);

            WriteInfoLog(instrument.AssetPairId, quotes, timeSinceLastTrade, limitOrders,
                         "Direct limit orders calculated");

            if (orderBookUpdateReport != null)
            {
                await _orderBooksUpdatesReportPublisher.PublishAsync(orderBookUpdateReport);
            }

            return(new OrderBook
            {
                AssetPairId = instrument.AssetPairId,
                Time = DateTime.UtcNow,
                LimitOrders = limitOrders,
                IsDirect = true
            });
        }
Exemple #6
0
        public async Task <IReadOnlyCollection <AssetPairMarkup> > GetAllAsync()
        {
            List <AssetPairMarkup> result = new List <AssetPairMarkup>();

            decimal globalMarkup = (await _marketMakerSettingsService.GetAsync()).LimitOrderPriceMarkup;

            IReadOnlyCollection <AssetPairMarkup> pnLStopLossMarkups = await _pnLStopLossEngineService.GetTotalMarkups();

            IReadOnlyCollection <AssetPairMarkup> fiatEquityStopLossMarkups = await _fiatEquityStopLossService.GetMarkupsAsync();

            IReadOnlyCollection <AssetPairMarkup> noFreshQuotesStopLossMarkups = await _noFreshQuotesStopLossService.GetMarkupsAsync();

            var assetPairs = (await _instrumentService.GetAllAsync()).Select(x => x.AssetPairId).ToList();

            foreach (var assetPairId in assetPairs)
            {
                AssetPairMarkup assetPairMarkup = new AssetPairMarkup();

                assetPairMarkup.AssetPairId = assetPairId;

                // Global
                assetPairMarkup.TotalMarkup    += globalMarkup;
                assetPairMarkup.TotalAskMarkup += globalMarkup;
                assetPairMarkup.TotalBidMarkup += globalMarkup;

                // PnL Stop Loss Markups
                AssetPairMarkup pnLStopLossMarkup = pnLStopLossMarkups.SingleOrDefault(x => x.AssetPairId == assetPairId);
                if (pnLStopLossMarkup != null)
                {
                    assetPairMarkup.TotalMarkup    += pnLStopLossMarkup.TotalMarkup;
                    assetPairMarkup.TotalAskMarkup += pnLStopLossMarkup.TotalAskMarkup;
                    assetPairMarkup.TotalBidMarkup += pnLStopLossMarkup.TotalBidMarkup;
                }

                // Fiat Equity Stop Loss Markups
                AssetPairMarkup fiatEquityStopLossMarkup = fiatEquityStopLossMarkups.SingleOrDefault(x => x.AssetPairId == assetPairId);
                if (fiatEquityStopLossMarkup != null)
                {
                    // Can be applied to asks only
                    if (fiatEquityStopLossMarkup.TotalAskMarkup == decimal.MinusOne)
                    {
                        assetPairMarkup.TotalAskMarkup = decimal.MinusOne;
                    }
                    else
                    {
                        assetPairMarkup.TotalAskMarkup += fiatEquityStopLossMarkup.TotalAskMarkup;
                    }
                }

                // No Fresh Quotes Stop Loss Markups
                AssetPairMarkup noFreshQuotesStopLossMarkup = noFreshQuotesStopLossMarkups.SingleOrDefault(x => x.AssetPairId == assetPairId);
                if (noFreshQuotesStopLossMarkup != null)
                {
                    assetPairMarkup.TotalMarkup    += noFreshQuotesStopLossMarkup.TotalMarkup;
                    assetPairMarkup.TotalAskMarkup += noFreshQuotesStopLossMarkup.TotalAskMarkup;
                    assetPairMarkup.TotalBidMarkup += noFreshQuotesStopLossMarkup.TotalBidMarkup;
                }

                result.Add(assetPairMarkup);
            }

            return(result);
        }
Exemple #7
0
        private async Task <OrderBook> CalculateDirectOrderBookAsync(Instrument instrument)
        {
            Quote[] quotes = _b2C2OrderBookService.GetQuotes(instrument.AssetPairId);

            if (quotes == null || quotes.Length != 2)
            {
                _log.WarningWithDetails("No quotes for instrument", instrument.AssetPairId);
                return(null);
            }

            Balance  baseAssetBalance   = null;
            Balance  quoteAssetBalance  = null;
            TimeSpan timeSinceLastTrade = TimeSpan.Zero;

            if (instrument.AllowSmartMarkup)
            {
                AssetPairLink assetPairLink =
                    await _assetPairLinkService.GetByInternalAssetPairIdAsync(instrument.AssetPairId);

                if (assetPairLink != null && !assetPairLink.IsEmpty())
                {
                    baseAssetBalance =
                        await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalBaseAssetId);

                    quoteAssetBalance =
                        await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalQuoteAssetId);

                    timeSinceLastTrade =
                        DateTime.UtcNow - _tradeService.GetLastInternalTradeTime(instrument.AssetPairId);
                }
                else
                {
                    _log.WarningWithDetails("The asset pair link does not configured", new { instrument.AssetPairId });
                }
            }

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            Asset baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.BaseAssetId);

            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            decimal pnLStopLossMarkup = await _pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(assetPair.Id);

            decimal fiatEquityStopLossMarkup = await _fiatEquityStopLossService.GetFiatEquityMarkup(assetPair.Id);

            decimal stopLossMarkup = await _noFreshQuotesStopLossService.GetNoFreshQuotesMarkup(assetPair.Id);

            IReadOnlyCollection <LimitOrder> limitOrders = Calculator.CalculateLimitOrders(
                quotes[0],
                quotes[1],
                instrument.Levels.ToArray(),
                baseAssetBalance?.Amount ?? 0,
                quoteAssetBalance?.Amount ?? 0,
                (int)timeSinceLastTrade.TotalSeconds,
                instrument.HalfLifePeriod,
                instrument.AllowSmartMarkup,
                marketMakerSettings.LimitOrderPriceMarkup,
                pnLStopLossMarkup,
                fiatEquityStopLossMarkup,
                stopLossMarkup,
                assetPair.Accuracy,
                baseAsset.Accuracy);

            await ValidateQuoteTimeoutAsync(limitOrders, quotes[0]);

            await ValidateQuoteTimeoutAsync(limitOrders, quotes[1]);

            ValidateMinVolume(limitOrders, (decimal)assetPair.MinVolume);

            await ValidatePriceAsync(limitOrders);

            await ValidateBalanceAsync(limitOrders, assetPair);

            WriteInfoLog(instrument.AssetPairId, quotes, timeSinceLastTrade, limitOrders,
                         "Direct limit orders calculated");

            return(new OrderBook
            {
                AssetPairId = instrument.AssetPairId,
                Time = DateTime.UtcNow,
                LimitOrders = limitOrders,
                IsDirect = true
            });
        }