public void Set(AssetRealisedPnL assetRealisedPnL) { lock (_sync) { if (!_cache.ContainsKey(assetRealisedPnL.WalletId)) { _cache[assetRealisedPnL.WalletId] = new Dictionary <string, AssetRealisedPnL>(); } _cache[assetRealisedPnL.WalletId][assetRealisedPnL.AssetId] = assetRealisedPnL; } }
public async Task InitializeAsync(string walletId, string assetId, double amount) { if (Math.Abs(amount) <= Double.Epsilon) { return; } IReadOnlyCollection <AssetPair> assetPairs = await _assetsServiceWithCache.GetAllAssetPairsAsync(); AssetPair assetPair = assetPairs .SingleOrDefault(o => o.BaseAssetId == assetId && o.QuotingAssetId == QuoteAssetId); if (assetPair == null) { assetPair = assetPairs .SingleOrDefault(o => o.BaseAssetId == QuoteAssetId && o.QuotingAssetId == assetId); } if (assetPair == null) { throw new InvalidOperationException($"Asset pair found by asset '{assetId}' and '{QuoteAssetId}'"); } Quote quote = await _quoteService.GetAsync(assetId, QuoteAssetId); var tradeData = new TradeData { Id = Guid.Empty.ToString("D"), Exchange = ExchangeNames.Lykke, AssetPair = assetPair.Id, BaseAsset = assetId, QuoteAsset = QuoteAssetId, Price = quote.Mid, Volume = (decimal)Math.Abs(amount), Type = amount < 0 ? TradeType.Sell : TradeType.Buy, Time = DateTime.UtcNow, LimitOrderId = Guid.Empty.ToString("D"), OppositeClientId = null, OppositeLimitOrderId = null }; AssetRealisedPnL assetRealisedPnL = await CalculateAsync(tradeData, walletId, assetId); await _assetRealisedPnLRepository.InsertAsync(assetRealisedPnL); _log.InfoWithDetails("Realised PnL initialized", new { walletId, assetId, amount }); _cache.Set(assetRealisedPnL); }
public async Task CalculateAsync(LykkeTrade lykkeTrade) { WalletSettings walletSettings = await _walletSettingsService.GetWalletAsync(lykkeTrade.ClientId); if (walletSettings == null || !walletSettings.Enabled) { return; } AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(lykkeTrade.AssetPairId); string[] assets = walletSettings.Assets .Intersect(new[] { assetPair.BaseAssetId, assetPair.QuotingAssetId }) .ToArray(); if (!assets.Any()) { return; } var tradeData = new TradeData { Id = lykkeTrade.Id, Exchange = ExchangeNames.Lykke, AssetPair = assetPair.Id, BaseAsset = assetPair.BaseAssetId, QuoteAsset = assetPair.QuotingAssetId, Price = lykkeTrade.Price, Volume = lykkeTrade.Volume, Type = lykkeTrade.Type, Time = lykkeTrade.Time, LimitOrderId = lykkeTrade.LimitOrderId, OppositeClientId = lykkeTrade.OppositeClientId, OppositeLimitOrderId = lykkeTrade.OppositeLimitOrderId }; foreach (string assetId in assets) { AssetRealisedPnL assetRealisedPnL = await CalculateAsync(tradeData, walletSettings.Id, assetId); await _assetRealisedPnLRepository.InsertAsync(assetRealisedPnL); _cache.Set(assetRealisedPnL); } _log.InfoWithDetails("Lykke trade handled", tradeData); }
public async Task CalculateAsync(ExternalTrade externalTrade) { IReadOnlyCollection <WalletSettings> walletsSettings = await _walletSettingsService.GetWalletsAsync(); walletsSettings = walletsSettings.Where(o => o.Enabled && o.HandleExternalTrades).ToArray(); if (!walletsSettings.Any()) { return; } var tradeData = new TradeData { Id = externalTrade.OrderId, Exchange = externalTrade.Exchange, AssetPair = externalTrade.AssetPairId, BaseAsset = externalTrade.BaseAssetId, QuoteAsset = externalTrade.QuoteAssetId, Price = externalTrade.Price, Volume = externalTrade.Volume, Type = externalTrade.Type, Time = externalTrade.Time, LimitOrderId = externalTrade.OrderId, OppositeClientId = null, OppositeLimitOrderId = null }; foreach (WalletSettings walletSettings in walletsSettings) { string[] assets = walletSettings.Assets .Intersect(new[] { externalTrade.BaseAssetId, externalTrade.QuoteAssetId }) .ToArray(); foreach (string assetId in assets) { AssetRealisedPnL assetRealisedPnL = await CalculateAsync(tradeData, walletSettings.Id, assetId); await _assetRealisedPnLRepository.InsertAsync(assetRealisedPnL); _cache.Set(assetRealisedPnL); } } _log.InfoWithDetails("External trade handled", tradeData); }
private async Task <AssetRealisedPnL> CalculateAsync(TradeData tradeData, string walletId, string assetId) { AssetRealisedPnL prevAssetPnL = await _assetRealisedPnLRepository.GetLastAsync(walletId, assetId) ?? new AssetRealisedPnL(); bool inverted = tradeData.QuoteAsset == assetId; string crossAssetId = inverted ? tradeData.BaseAsset : tradeData.QuoteAsset; Quote quote = await _quoteService.GetAsync(assetId, QuoteAssetId); Quote crossQuote = await _quoteService.GetAsync(crossAssetId, QuoteAssetId); RealisedPnLResult realisedPnLResult = RealisedPnLCalculator.Calculate( tradeData.Price, tradeData.Volume, inverted, tradeData.Type == TradeType.Sell ? -1 : 1, prevAssetPnL.CumulativeVolume, prevAssetPnL.CumulativeOppositeVolume, quote.Mid, prevAssetPnL.AvgPrice, crossQuote.Mid); return(new AssetRealisedPnL { WalletId = walletId, AssetId = assetId, Time = tradeData.Time, Exchange = tradeData.Exchange, TradeId = tradeData.Id, TradeAssetPair = tradeData.AssetPair, TradePrice = tradeData.Price, TradeVolume = tradeData.Volume, TradeType = tradeData.Type, CrossAssetPair = crossQuote.AssetPair, CrossPrice = crossQuote.Mid, Price = realisedPnLResult.Price, Volume = realisedPnLResult.Volume, OppositeVolume = realisedPnLResult.OppositeVolume, Inverted = inverted, PrevAvgPrice = prevAssetPnL.AvgPrice, PrevCumulativeVolume = prevAssetPnL.CumulativeVolume, PrevCumulativeOppositeVolume = prevAssetPnL.CumulativeOppositeVolume, OpenPrice = prevAssetPnL.AvgPrice, ClosePrice = realisedPnLResult.Price, CloseVolume = realisedPnLResult.ClosedVolume, RealisedPnL = realisedPnLResult.RealisedPnL, AvgPrice = realisedPnLResult.AvgPrice, CumulativeVolume = realisedPnLResult.CumulativeVolume, CumulativeOppositeVolume = realisedPnLResult.CumulativeOppositeVolume, CumulativeRealisedPnL = prevAssetPnL.CumulativeRealisedPnL + realisedPnLResult.RealisedPnL, Rate = quote.Mid, UnrealisedPnL = realisedPnLResult.UnrealisedPnL, LimitOrderId = tradeData.LimitOrderId, OppositeClientId = tradeData.OppositeClientId, OppositeLimitOrderId = tradeData.OppositeLimitOrderId }); }