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); }
public async Task UpdateAsync(Domain.AssetSettings assetSettings) { await _storage.MergeAsync(GetPartitionKey(), GetRowKey(assetSettings.AssetId), entity => { Mapper.Map(assetSettings, entity); return(entity); }); }
public async Task InsertAsync(Domain.AssetSettings assetSettings) { var entity = new AssetSettingsEntity(GetPartitionKey(), GetRowKey(assetSettings.AssetId)); Mapper.Map(assetSettings, entity); await _storage.InsertThrowConflictAsync(entity); }
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); }
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); }
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); }