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);
        }
示例#2
0
        public async Task InsertOrReplaceAsync(MarketMakerSettings marketMakerSettings)
        {
            var entity = new MarketMakerSettingsEntity(GetPartitionKey(), GetRowKey());

            Mapper.Map(marketMakerSettings, entity);

            await _storage.InsertOrReplaceAsync(entity);
        }
示例#3
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 static SettingsMarketMakerNoSql Create(MarketMakerSettings settings)
 {
     return(new SettingsMarketMakerNoSql()
     {
         PartitionKey = GeneratePartitionKey(),
         RowKey = GenerateRowKey(),
         Settings = settings
     });
 }
示例#5
0
        private async Task ValidatePriceAsync(IReadOnlyCollection <LimitOrder> limitOrders)
        {
            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            if (marketMakerSettings.LimitOrderPriceMaxDeviation == 0)
            {
                return;
            }

            LimitOrder[] sellLimitOrders = limitOrders
                                           .Where(o => o.Type == LimitOrderType.Sell)
                                           .OrderBy(o => o.Price)
                                           .ToArray();

            LimitOrder[] buyLimitOrders = limitOrders
                                          .Where(o => o.Type == LimitOrderType.Buy)
                                          .OrderByDescending(o => o.Price)
                                          .ToArray();

            if (sellLimitOrders.Any())
            {
                decimal maxSellPrice = sellLimitOrders[0].Price * (1 + marketMakerSettings.LimitOrderPriceMaxDeviation);

                foreach (LimitOrder limitOrder in sellLimitOrders.Where(o => o.Error == LimitOrderError.None))
                {
                    if (limitOrder.Price > maxSellPrice)
                    {
                        limitOrder.Error = LimitOrderError.PriceIsOutOfTheRange;
                    }
                }
            }

            if (buyLimitOrders.Any())
            {
                decimal minBuyPrice = buyLimitOrders[0].Price * (1 - marketMakerSettings.LimitOrderPriceMaxDeviation);

                foreach (LimitOrder limitOrder in buyLimitOrders.Where(o => o.Error == LimitOrderError.None))
                {
                    if (limitOrder.Price < minBuyPrice)
                    {
                        limitOrder.Error = LimitOrderError.PriceIsOutOfTheRange;
                    }
                }
            }
        }
        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);
        }
示例#7
0
        public async Task <MarketMakerSettings> GetAsync()
        {
            MarketMakerSettings marketMakerSettings = _cache.Get(CacheKey);

            if (marketMakerSettings == null)
            {
                marketMakerSettings = await _marketMakerSettingsRepository.GetAsync();

                if (marketMakerSettings == null)
                {
                    marketMakerSettings = new MarketMakerSettings
                    {
                        LimitOrderPriceMaxDeviation = 0.2m
                    };
                }

                _cache.Set(marketMakerSettings);
            }

            return(marketMakerSettings);
        }
示例#8
0
        public async Task <MarketMakerSettingsModel> GetMarketMakerSettingsAsync()
        {
            MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync();

            return(Mapper.Map <MarketMakerSettingsModel>(marketMakerSettings));
        }
示例#9
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
            });
        }
示例#10
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
            });
        }
示例#11
0
        public async Task UpdateAsync(MarketMakerSettings marketMakerSettings)
        {
            await _marketMakerSettingsRepository.InsertOrReplaceAsync(marketMakerSettings);

            _cache.Set(marketMakerSettings);
        }
 public Task UpdateMarketMakerSettingsAsync(MarketMakerSettings request)
 {
     return(_manager.UpdateMarketMakerSettingsAsync(request));
 }