Example #1
0
        public async Task <(decimal?, decimal?)> ConvertAmountAsync(string assetId, decimal amount)
        {
            if (assetId == AssetConsts.UsdAssetId)
            {
                return(amount, 1);
            }

            IReadOnlyCollection <Domain.AssetSettings> assetSettings = await GetAllAsync();

            Domain.AssetSettings settings = assetSettings.SingleOrDefault(o => o.AssetId == assetId);

            if (settings == null)
            {
                _log.WarningWithDetails("Asset settings not found", assetId);
                return(null, null);
            }

            Quote quote = await _quoteService
                          .GetAsync(settings.QuoteSource, settings.ExternalAssetPairId);

            if (quote == null)
            {
                _log.WarningWithDetails("No quote for asset", settings);
                return(null, null);
            }

            (decimal amountInUsd, decimal rate) = Calculator.CalculateCrossMidPrice(amount, quote, settings.IsInverse);

            return(amountInUsd, rate);
        }
Example #2
0
 public async Task UpdateAsync(Domain.AssetSettings assetSettings)
 {
     await _storage.MergeAsync(GetPartitionKey(), GetRowKey(assetSettings.AssetId), entity =>
     {
         Mapper.Map(assetSettings, entity);
         return(entity);
     });
 }
Example #3
0
        public async Task InsertAsync(Domain.AssetSettings assetSettings)
        {
            var entity = new AssetSettingsEntity(GetPartitionKey(), GetRowKey(assetSettings.AssetId));

            Mapper.Map(assetSettings, entity);

            await _storage.InsertThrowConflictAsync(entity);
        }
Example #4
0
        public async Task AddAsync(Domain.AssetSettings assetSettings)
        {
            Domain.AssetSettings existingAssetSettings = (await GetAllAsync())
                                                         .SingleOrDefault(o => o.AssetId == assetSettings.AssetId);

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

            await _assetSettingsRepository.InsertAsync(assetSettings);

            _cache.Set(assetSettings);

            _log.InfoWithDetails("Asset settings were added", assetSettings);
        }
Example #5
0
        public async Task DeleteAsync(string assetId)
        {
            if (assetId == AssetConsts.UsdAssetId)
            {
                throw new InvalidOperationException("Can not delete non-editable asset.");
            }

            Domain.AssetSettings assetSettings = await GetByIdAsync(assetId);

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

            await _assetSettingsRepository.DeleteAsync(assetId);

            _cache.Remove(assetId);

            _log.InfoWithDetails("Asset settings were deleted", assetSettings);
        }
        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);
        }
Example #7
0
        public async Task UpdateAsync(Domain.AssetSettings assetSettings)
        {
            if (assetSettings.AssetId == AssetConsts.UsdAssetId)
            {
                throw new InvalidOperationException("Can not update non-editable asset.");
            }

            Domain.AssetSettings currentAssetSettings = await GetByIdAsync(assetSettings.AssetId);

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

            currentAssetSettings.Update(assetSettings);

            await _assetSettingsRepository.UpdateAsync(currentAssetSettings);

            _cache.Set(currentAssetSettings);

            _log.InfoWithDetails("Asset settings were updated", assetSettings);
        }
        public async Task <BalanceIndicatorsReport> GetAsync()
        {
            IReadOnlyCollection <Balance> externalBalances = await _balanceService.GetAsync(ExchangeNames.External);

            decimal riskExposure = 0;
            decimal equity       = 0;
            decimal fiatEquity   = 0;

            foreach (Balance balance in externalBalances)
            {
                decimal amountInUsd;
                bool    isFiat = false;

                if (balance.AssetId == AssetConsts.UsdAssetId)
                {
                    amountInUsd = balance.Amount;
                    isFiat      = true;
                }
                else
                {
                    Domain.AssetSettings assetSettings = await _assetSettingsService.GetByIdAsync(balance.AssetId);

                    if (assetSettings == null)
                    {
                        continue;
                    }

                    if (!assetSettings.IsCrypto)
                    {
                        isFiat = true;
                    }

                    Quote quote = await _quoteService
                                  .GetAsync(assetSettings.QuoteSource, assetSettings.ExternalAssetPairId);

                    if (quote == null)
                    {
                        continue;
                    }

                    amountInUsd = Calculator.CalculateCrossMidPrice(balance.Amount, quote, assetSettings.IsInverse)
                                  .Item1;
                }

                if (balance.Amount < 0)
                {
                    riskExposure += Math.Abs(amountInUsd);
                }

                equity += amountInUsd;

                if (isFiat)
                {
                    fiatEquity += amountInUsd;
                }
            }

            return(new BalanceIndicatorsReport
            {
                Equity = equity,
                FiatEquity = fiatEquity,
                RiskExposure = riskExposure
            });
        }
        public async Task ExecuteAsync(string settlementTradeId, string userId)
        {
            string walletId = await _settingsService.GetWalletIdAsync();

            SettlementTrade settlementTrade = (await _settlementTradeService.GetByIdAsync(settlementTradeId)).Copy();

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

            Domain.AssetSettings baseAssetSettings =
                await _assetSettingsService.GetByIdAsync(settlementTrade.BaseAsset);

            Domain.AssetSettings quoteAssetSettings =
                await _assetSettingsService.GetByIdAsync(settlementTrade.QuoteAsset);

            string baseAssetId = baseAssetSettings != null
                ? baseAssetSettings.LykkeAssetId
                : settlementTrade.BaseAsset;

            string quoteAssetId = quoteAssetSettings != null
                ? quoteAssetSettings.LykkeAssetId
                : settlementTrade.QuoteAsset;

            Asset baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(baseAssetId);

            Asset quoteAsset = await _assetsServiceWithCache.TryGetAssetAsync(quoteAssetId);

            if (baseAsset == null)
            {
                _log.WarningWithDetails("Can not map external asset id", new
                {
                    settlementTradeId,
                    userId,
                    baseAssetId
                });

                throw new InvalidOperationException("Unknown asset");
            }

            if (quoteAsset == null)
            {
                _log.WarningWithDetails("Can not map external asset id", new
                {
                    settlementTradeId,
                    userId,
                    quoteAssetId
                });

                throw new InvalidOperationException("Unknown asset");
            }

            settlementTrade.Complete();

            string comment =
                $"rebalance; {settlementTrade.Type} {settlementTrade.Volume} {settlementTrade.BaseAsset} for {settlementTrade.OppositeVolume} {settlementTrade.QuoteAsset} by price {settlementTrade.Price} ({settlementTrade.AssetPair})";

            int sign = settlementTrade.Type == TradeType.Sell ? 1 : -1;

            var balanceOperations = new[]
            {
                new BalanceOperation
                {
                    Time    = DateTime.UtcNow,
                    AssetId = baseAsset.Id,
                    Type    = "Settlement",
                    Amount  = Math.Abs(settlementTrade.Volume) * sign,
                    Comment = $"{comment}, for close position in {settlementTrade.BaseAsset}",
                    UserId  = userId
                },
                new BalanceOperation
                {
                    Time    = DateTime.UtcNow,
                    AssetId = quoteAsset.Id,
                    Type    = "Settlement",
                    Amount  = Math.Abs(settlementTrade.OppositeVolume) * -1 * sign,
                    Comment = $"{comment}, for close position in {settlementTrade.QuoteAsset}",
                    UserId  = userId
                }
            };

            foreach (BalanceOperation balanceOperation in balanceOperations.OrderBy(o => o.Amount))
            {
                if (balanceOperation.Amount > 0)
                {
                    await _lykkeExchangeService.CashInAsync(walletId, balanceOperation.AssetId,
                                                            Math.Abs(balanceOperation.Amount), userId, comment);
                }
                else
                {
                    await _lykkeExchangeService.CashOutAsync(walletId, balanceOperation.AssetId,
                                                             Math.Abs(balanceOperation.Amount), userId, comment);
                }

                await _balanceOperationService.AddAsync(balanceOperation);

                _log.InfoWithDetails("Settlement was executed", balanceOperation);
            }

            await _settlementTradeService.UpdateAsync(settlementTrade);
        }
        public async Task <IReadOnlyCollection <BalanceReport> > GetAsync()
        {
            IReadOnlyCollection <Balance> lykkeBalances = await _balanceService.GetAsync(ExchangeNames.Lykke);

            IReadOnlyCollection <Balance> externalBalances = await _balanceService.GetAsync(ExchangeNames.External);

            IReadOnlyCollection <Credit> credits = await _creditService.GetAllAsync();

            IReadOnlyCollection <Domain.AssetSettings> assetsSettings = await _assetSettingsService.GetAllAsync();

            string[] assets = externalBalances
                              .Select(o => o.AssetId)
                              .Union(lykkeBalances.Select(o => o.AssetId).Union(credits.Select(o => o.AssetId))
                                     .Select(o => assetsSettings.SingleOrDefault(p => p.LykkeAssetId == o)?.AssetId ?? o))
                              .ToArray();

            var reports = new List <BalanceReport>();

            foreach (string assetId in assets)
            {
                Domain.AssetSettings assetSettings = assetsSettings.SingleOrDefault(o => o.AssetId == assetId);

                string lykkeAssetId = assetSettings?.LykkeAssetId ?? assetId;

                Balance lykkeBalance = lykkeBalances.SingleOrDefault(o => o.AssetId == lykkeAssetId);

                Balance externalBalance = externalBalances.SingleOrDefault(o => o.AssetId == assetId);

                Credit credit = credits.SingleOrDefault(o => o.AssetId == lykkeAssetId);

                decimal lykkeDisbalance = (lykkeBalance?.Amount ?? 0) - (credit?.Amount ?? 0);

                decimal totalAmount = lykkeDisbalance + (externalBalance?.Amount ?? 0);

                if (totalAmount != 0)
                {
                    (decimal? TotalAmountInUsd, decimal? Rate)tuple = (null, null);

                    if (assetId == AssetConsts.UsdAssetId)
                    {
                        tuple = (totalAmount, 1);
                    }
                    else if (assetSettings != null)
                    {
                        Quote quote = await _quoteService
                                      .GetAsync(assetSettings.QuoteSource, assetSettings.ExternalAssetPairId);

                        if (quote != null)
                        {
                            tuple = Calculator.CalculateCrossMidPrice(totalAmount, quote, assetSettings.IsInverse);
                        }
                    }

                    reports.Add(new BalanceReport
                    {
                        Asset             = assetId,
                        LykkeAssetId      = lykkeAssetId,
                        ExternalAssetId   = assetId,
                        LykkeAmount       = lykkeBalance?.Amount,
                        LykkeCreditAmount = credit?.Amount,
                        LykkeDisbalance   = lykkeDisbalance,
                        ExternalAmount    = externalBalance?.Amount,
                        TotalAmount       = totalAmount,
                        TotalAmountInUsd  = tuple.TotalAmountInUsd,
                        CrossRate         = tuple.Rate
                    });
                }
            }

            return(reports);
        }