public async Task UpdateAsync(AssetPairLink assetPairLink)
 {
     await _storage.MergeAsync(GetPartitionKey(), GetRowKey(assetPairLink.AssetPairId), entity =>
     {
         Mapper.Map(assetPairLink, entity);
         return(entity);
     });
 }
        private async Task <string> GetInstrumentAsync(string assetPairId)
        {
            IReadOnlyCollection <AssetPairLink> assetPairLinks = await _assetPairLinkService.GetAllAsync();

            AssetPairLink assetPairLink = assetPairLinks.SingleOrDefault(o => o.AssetPairId == assetPairId);

            return(assetPairLink != null ? assetPairLink.ExternalAssetPairId : assetPairId);
        }
        public async Task InsertAsync(AssetPairLink assetPairLink)
        {
            var entity = new AssetPairLinkEntity(GetPartitionKey(), GetRowKey(assetPairLink.AssetPairId));

            Mapper.Map(assetPairLink, entity);

            await _storage.InsertThrowConflictAsync(entity);
        }
        public async Task UpdateAsync([FromBody] AssetPairLinkModel model)
        {
            try
            {
                AssetPairLink assetPairLink = Mapper.Map <AssetPairLink>(model);

                await _assetPairLinkService.UpdateAsync(assetPairLink);
            }
            catch (EntityNotFoundException)
            {
                throw new ValidationApiException(HttpStatusCode.Conflict, "Asset pair link already exists.");
            }
        }
예제 #5
0
        public async Task AddAsync(AssetPairLink assetPairLink)
        {
            AssetPairLink currentAssetPairLink = await GetByInternalAssetPairIdAsync(assetPairLink.AssetPairId);

            if (currentAssetPairLink != null)
            {
                throw new EntityAlreadyExistsException();
            }

            await _assetPairLinkRepository.InsertAsync(assetPairLink);

            _cache.Set(assetPairLink);

            _log.InfoWithDetails("Asset pair link was added", assetPairLink);
        }
예제 #6
0
        public async Task DeleteAsync(string assetPairId)
        {
            IReadOnlyCollection <AssetPairLink> assetPairLinks = await GetAllAsync();

            AssetPairLink assetPairLink = assetPairLinks.FirstOrDefault(o => o.AssetPairId == assetPairId);

            if (assetPairLink == null)
            {
                throw new EntityNotFoundException();
            }

            await _assetPairLinkRepository.DeleteAsync(assetPairId);

            _cache.Remove(assetPairId);

            _log.InfoWithDetails("Asset pair link was removed", assetPairLink);
        }
예제 #7
0
        public async Task UpdateAsync(AssetPairLink assetPairLink)
        {
            AssetPairLink currentAssetPairLink = await GetByInternalAssetPairIdAsync(assetPairLink.AssetPairId);

            if (currentAssetPairLink == null)
            {
                throw new EntityNotFoundException();
            }

            currentAssetPairLink.Update(assetPairLink);

            await _assetPairLinkRepository.UpdateAsync(currentAssetPairLink);

            _cache.Set(currentAssetPairLink);

            _log.InfoWithDetails("Asset pair link was added", currentAssetPairLink);
        }
예제 #8
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
            });
        }
예제 #9
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
            });
        }
예제 #10
0
 public void Update(AssetPairLink assetPairLink)
 {
     ExternalAssetPairId  = assetPairLink.ExternalAssetPairId;
     ExternalBaseAssetId  = assetPairLink.ExternalBaseAssetId;
     ExternalQuoteAssetId = assetPairLink.ExternalQuoteAssetId;
 }