diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedTrade.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedTrade.cs index aa7508ef..162e7360 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedTrade.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedTrade.cs @@ -12,7 +12,12 @@ namespace CryptoExchange.Net.SharedApis /// /// Quantity of the trade /// - public decimal Quantity { get; set; } + [Obsolete("Use `Quantities` instead")] + public decimal Quantity => Quantities.QuantityInBaseAsset ?? Quantities.QuantityInContracts ?? 0; + /// + /// The quantities of the trade + /// + public SharedOrderQuantity Quantities { get; set; } /// /// Price of the trade /// @@ -29,9 +34,9 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public SharedTrade(SharedSymbol? sharedSymbol, string symbol, decimal quantity, decimal price, DateTime timestamp) : base(sharedSymbol, symbol) + public SharedTrade(SharedSymbol? sharedSymbol, string symbol, SharedOrderQuantity quantities, decimal price, DateTime timestamp) : base(sharedSymbol, symbol) { - Quantity = quantity; + Quantities = quantities; Price = price; Timestamp = timestamp; } diff --git a/CryptoExchange.Net/SharedApis/SharedQuantity.cs b/CryptoExchange.Net/SharedApis/SharedQuantity.cs index 13a0dd7c..dcddd06a 100644 --- a/CryptoExchange.Net/SharedApis/SharedQuantity.cs +++ b/CryptoExchange.Net/SharedApis/SharedQuantity.cs @@ -160,6 +160,22 @@ namespace CryptoExchange.Net.SharedApis { } + /// + /// Get the quantity in quote asset. Will use the set `QuantityInQuoteAsset` property if it has a value, or `QuantityInBaseAsset` * `price` if not. Null otherwise. + /// + /// The price to use for the QuantityInBaseAsset to quote asset quantity calculation + /// Quantity in quote asset if it's available or can be calculated, null otherwise + public decimal? GetQuantityInQuoteAsset(decimal? price) + { + if (QuantityInQuoteAsset != null) + return QuantityInQuoteAsset; + + if (QuantityInBaseAsset != null && price != null) + return QuantityInBaseAsset * price; + + return null; + } + /// public override string ToString() => base.ToString(); } diff --git a/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs b/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs index a9ec83e6..5cb3ba7e 100644 --- a/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs +++ b/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs @@ -284,8 +284,10 @@ namespace CryptoExchange.Net.Trackers.Klines LastOpenTime = klines.Last().OpenTime, HighPrice = klines.Select(d => d.LowPrice).Max(), LowPrice = klines.Select(d => d.HighPrice).Min(), +#pragma warning disable CS0618 // Type or member is obsolete | Temporary to maintain previous behavior Volume = klines.Select(d => d.Volume).Sum(), AverageVolume = Math.Round(klines.OrderByDescending(d => d.OpenTime).Skip(1).Select(d => d.Volume).DefaultIfEmpty().Average(), 8) +#pragma warning restore }; } diff --git a/CryptoExchange.Net/Trackers/Trades/TradeTracker.cs b/CryptoExchange.Net/Trackers/Trades/TradeTracker.cs index 718ef7c9..88bd2565 100644 --- a/CryptoExchange.Net/Trackers/Trades/TradeTracker.cs +++ b/CryptoExchange.Net/Trackers/Trades/TradeTracker.cs @@ -138,6 +138,11 @@ namespace CryptoExchange.Net.Trackers.Trades } } + /// + /// The type of quantity the trades and stats are denoted in + /// + public TradeQuantityType QuantityType { get; } + /// public event Func? OnAdded; /// @@ -156,12 +161,14 @@ namespace CryptoExchange.Net.Trackers.Trades SharedSymbol symbol, int? limit = null, TimeSpan? period = null, + TradeQuantityType tradeQuantityType = TradeQuantityType.BaseAsset, ExchangeParameters? exchangeParameters = null) { _logger = logger ?? new NullLogger(); _recentRestClient = recentRestClient; _historyRestClient = historyRestClient; _socketClient = socketClient; + QuantityType = tradeQuantityType; _exchangeParameters = exchangeParameters; Exchange = socketClient.Exchange; Symbol = symbol; @@ -170,22 +177,41 @@ namespace CryptoExchange.Net.Trackers.Trades Period = period; } - private static TradesStats GetStats(IEnumerable trades) + private TradesStats GetStats(IEnumerable trades) { if (!trades.Any()) return new TradesStats(); - return new TradesStats + + var stats = new TradesStats { TradeCount = trades.Count(), FirstTradeTime = trades.First().Timestamp, LastTradeTime = trades.Last().Timestamp, - AveragePrice = Math.Round(trades.Select(d => d.Price).DefaultIfEmpty().Average(), 8), - VolumeWeightedAveragePrice = trades.Any() ? Math.Round(trades.Select(d => d.Price * d.Quantity).DefaultIfEmpty().Sum() / trades.Select(d => d.Quantity).DefaultIfEmpty().Sum(), 8) : null, - Volume = Math.Round(trades.Sum(d => d.Quantity), 8), - QuoteVolume = Math.Round(trades.Sum(d => d.Quantity * d.Price), 8), - BuySellRatio = Math.Round(trades.Where(x => x.Side == SharedOrderSide.Buy).Sum(x => x.Quantity) / trades.Sum(x => x.Quantity), 8) + AveragePrice = Math.Round(trades.Select(d => d.Price).DefaultIfEmpty().Average(), 8), + QuoteVolume = Math.Round(trades.Sum(d => d.Quantities.GetQuantityInQuoteAsset(d.Price) ?? 0), 8), }; + + if (QuantityType == TradeQuantityType.BaseAsset) + { + stats.VolumeWeightedAveragePrice = + trades.Any() + ? Math.Round(trades.Select(d => d.Quantities.GetQuantityInQuoteAsset(d.Price) ?? 0).DefaultIfEmpty().Sum() / trades.Select(d => d.Quantities.QuantityInBaseAsset!.Value).DefaultIfEmpty().Sum(), 8) + : null; + stats.Volume = Math.Round(trades.Sum(d => d.Quantities.QuantityInBaseAsset!.Value), 8); + stats.BuySellRatio = Math.Round(trades.Where(x => x.Side == SharedOrderSide.Buy).Sum(x => x.Quantities.QuantityInBaseAsset!.Value) / trades.Sum(x => x.Quantities.QuantityInBaseAsset!.Value), 8); + } + else + { + stats.VolumeWeightedAveragePrice = + trades.Any() + ? Math.Round(trades.Select(d => d.Quantities.GetQuantityInQuoteAsset(d.Price) ?? 0).DefaultIfEmpty().Sum() / trades.Select(d => d.Quantities.QuantityInContracts!.Value).DefaultIfEmpty().Sum(), 8) + : null; + stats.Volume = Math.Round(trades.Sum(d => d.Quantities.QuantityInContracts!.Value), 8); + stats.BuySellRatio = Math.Round(trades.Where(x => x.Side == SharedOrderSide.Buy).Sum(x => x.Quantities.QuantityInContracts!.Value) / trades.Sum(x => x.Quantities.QuantityInContracts!.Value), 8); + } + + return stats; } /// @@ -498,4 +524,19 @@ namespace CryptoExchange.Net.Trackers.Trades Status = SyncStatus.Synced; } } + + /// + /// The quantities to use for trade tracking + /// + public enum TradeQuantityType + { + /// + /// Base asset + /// + BaseAsset, + /// + /// Contracts + /// + Contracts + } }