1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-08-11 08:22:53 +00:00

Updated SharedTrade to use SharedOrderQuantity for quantities

This commit is contained in:
Jkorf
2026-07-28 11:47:59 +02:00
parent 20bddd5c37
commit 4803ed91cd
4 changed files with 74 additions and 10 deletions
@@ -12,7 +12,12 @@ namespace CryptoExchange.Net.SharedApis
/// <summary>
/// Quantity of the trade
/// </summary>
public decimal Quantity { get; set; }
[Obsolete("Use `Quantities` instead")]
public decimal Quantity => Quantities.QuantityInBaseAsset ?? Quantities.QuantityInContracts ?? 0;
/// <summary>
/// The quantities of the trade
/// </summary>
public SharedOrderQuantity Quantities { get; set; }
/// <summary>
/// Price of the trade
/// </summary>
@@ -29,9 +34,9 @@ namespace CryptoExchange.Net.SharedApis
/// <summary>
/// ctor
/// </summary>
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;
}
@@ -160,6 +160,22 @@ namespace CryptoExchange.Net.SharedApis
{
}
/// <summary>
/// Get the quantity in quote asset. Will use the set `QuantityInQuoteAsset` property if it has a value, or `QuantityInBaseAsset` * `price` if not. Null otherwise.
/// </summary>
/// <param name="price">The price to use for the QuantityInBaseAsset to quote asset quantity calculation</param>
/// <returns>Quantity in quote asset if it's available or can be calculated, null otherwise</returns>
public decimal? GetQuantityInQuoteAsset(decimal? price)
{
if (QuantityInQuoteAsset != null)
return QuantityInQuoteAsset;
if (QuantityInBaseAsset != null && price != null)
return QuantityInBaseAsset * price;
return null;
}
/// <inheritdoc />
public override string ToString() => base.ToString();
}
@@ -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
};
}
@@ -138,6 +138,11 @@ namespace CryptoExchange.Net.Trackers.Trades
}
}
/// <summary>
/// The type of quantity the trades and stats are denoted in
/// </summary>
public TradeQuantityType QuantityType { get; }
/// <inheritdoc />
public event Func<SharedTrade, Task>? OnAdded;
/// <inheritdoc />
@@ -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<TradeTracker>();
_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<SharedTrade> trades)
private TradesStats GetStats(IEnumerable<SharedTrade> 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;
}
/// <inheritdoc />
@@ -498,4 +524,19 @@ namespace CryptoExchange.Net.Trackers.Trades
Status = SyncStatus.Synced;
}
}
/// <summary>
/// The quantities to use for trade tracking
/// </summary>
public enum TradeQuantityType
{
/// <summary>
/// Base asset
/// </summary>
BaseAsset,
/// <summary>
/// Contracts
/// </summary>
Contracts
}
}