diff --git a/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserFuturesDataTracker.cs b/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserFuturesDataTracker.cs index b762a05..fcc669e 100644 --- a/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserFuturesDataTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserFuturesDataTracker.cs @@ -65,5 +65,18 @@ namespace CryptoExchange.Net.Trackers.UserData.Interfaces /// /// Task StopAsync(); + + /// + /// Add symbols to the list of symbols for which data is being tracked + /// + /// Symbols to add + void AddTrackedSymbolsAsync(IEnumerable symbols); + + /// + /// Remove a symbol from the list of symbols for which data is being tracked. + /// Note that the symbol will be added again if new data for that symbol is received, unless the OnlyTrackProvidedSymbols option has been set to true. + /// + /// Symbol to remove + void RemoveTrackedSymbolAsync(SharedSymbol symbol); } } \ No newline at end of file diff --git a/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserSpotDataTracker.cs b/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserSpotDataTracker.cs index 6bc0242..de498bd 100644 --- a/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserSpotDataTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/Interfaces/IUserSpotDataTracker.cs @@ -61,5 +61,18 @@ namespace CryptoExchange.Net.Trackers.UserData.Interfaces /// /// Task StopAsync(); + + /// + /// Add symbols to the list of symbols for which data is being tracked + /// + /// Symbols to add + void AddTrackedSymbolsAsync(IEnumerable symbols); + + /// + /// Remove a symbol from the list of symbols for which data is being tracked. + /// Note that the symbol will be added again if new data for that symbol is received, unless the OnlyTrackProvidedSymbols option has been set to true. + /// + /// Symbol to remove + void RemoveTrackedSymbolAsync(SharedSymbol symbol); } } \ No newline at end of file diff --git a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesOrderTracker.cs b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesOrderTracker.cs index 9cfdb97..72b443d 100644 --- a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesOrderTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesOrderTracker.cs @@ -47,6 +47,20 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers _requiresSymbolParameterOpenOrders = restClient.GetOpenFuturesOrdersOptions.RequiredOptionalParameters.Any(x => x.Name == "Symbol"); } + internal void ClearDataForSymbol(SharedSymbol symbol) + { + foreach (var order in _store) + { + if (order.Value.SharedSymbol!.TradingMode == symbol.TradingMode + && order.Value.SharedSymbol.BaseAsset == symbol.BaseAsset + && order.Value.SharedSymbol.QuoteAsset == symbol.QuoteAsset + && order.Value.SharedSymbol.DeliverTime == symbol.DeliverTime) + { + _store.TryRemove(order.Key, out _); + } + } + } + /// protected override bool Update(SharedFuturesOrder existingItem, SharedFuturesOrder updateItem) { @@ -376,8 +390,8 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers if (DateTime.UtcNow - fromTime < TimeSpan.FromSeconds(1)) { - // Set it to at least a seconds in the past to prevent issues - fromTime = DateTime.UtcNow.AddSeconds(-1); + // Set it to at least 5 seconds in the past to prevent issues when local time isn't in sync + fromTime = DateTime.UtcNow.AddSeconds(-5); } _logger.LogTrace("{DataType}.{Symbol} UserDataTracker poll startTime filter based on {Source}: {Time:yyyy-MM-dd HH:mm:ss.fff}", diff --git a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesUserTradeTracker.cs b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesUserTradeTracker.cs index b5028ae..208928b 100644 --- a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesUserTradeTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/FuturesUserTradeTracker.cs @@ -43,6 +43,20 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers _exchangeParameters = exchangeParameters; } + internal void ClearDataForSymbol(SharedSymbol symbol) + { + foreach (var order in _store) + { + if (order.Value.SharedSymbol!.TradingMode == symbol.TradingMode + && order.Value.SharedSymbol.BaseAsset == symbol.BaseAsset + && order.Value.SharedSymbol.QuoteAsset == symbol.QuoteAsset + && order.Value.SharedSymbol.DeliverTime == symbol.DeliverTime) + { + _store.TryRemove(order.Key, out _); + } + } + } + /// protected override string GetKey(SharedUserTrade item) => item.Id; /// @@ -120,8 +134,8 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers var now = DateTime.UtcNow; if (now - fromTime < TimeSpan.FromSeconds(1)) { - // Set it to at least a seconds in the past to prevent issues - fromTime = now.AddSeconds(-1); + // Set it to at least 5 seconds in the past to prevent issues when local time isn't in sync + fromTime = DateTime.UtcNow.AddSeconds(-5); } _logger.LogTrace("{DataType} UserDataTracker poll startTime filter based on {Source}: {Time:yyyy-MM-dd HH:mm:ss.fff}", DataType, source, fromTime); diff --git a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/PositionTracker.cs b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/PositionTracker.cs index eda6185..092c01f 100644 --- a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/PositionTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/PositionTracker.cs @@ -119,7 +119,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers { toRemove ??= new List(); toRemove.Add(item); - _logger.LogWarning("Ignoring {DataType} update for {Key}, no SharedSymbol set", DataType, GetKey(item)); + _logger.LogTrace("Ignoring {DataType} update for {Key}, no SharedSymbol set", DataType, item.Symbol); } else if (!_symbolTracker.ShouldProcess(symbolModel.SharedSymbol)) { diff --git a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotOrderTracker.cs b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotOrderTracker.cs index c49090b..4264942 100644 --- a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotOrderTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotOrderTracker.cs @@ -47,6 +47,19 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers _requiresSymbolParameterOpenOrders = restClient.GetOpenSpotOrdersOptions.RequiredOptionalParameters.Any(x => x.Name == "Symbol"); } + internal void ClearDataForSymbol(SharedSymbol symbol) + { + foreach(var order in _store) + { + if (order.Value.SharedSymbol!.TradingMode == symbol.TradingMode + && order.Value.SharedSymbol.BaseAsset == symbol.BaseAsset + && order.Value.SharedSymbol.QuoteAsset == symbol.QuoteAsset) + { + _store.TryRemove(order.Key, out _); + } + } + } + /// protected override bool Update(SharedSpotOrder existingItem, SharedSpotOrder updateItem) { @@ -388,8 +401,8 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers if (DateTime.UtcNow - fromTime < TimeSpan.FromSeconds(1)) { - // Set it to at least a seconds in the past to prevent issues - fromTime = DateTime.UtcNow.AddSeconds(-1); + // Set it to at least 5 seconds in the past to prevent issues when local time isn't in sync + fromTime = DateTime.UtcNow.AddSeconds(-5); } _logger.LogTrace("{DataType}.{Symbol} UserDataTracker poll startTime filter based on {Source}: {Time:yyyy-MM-dd HH:mm:ss.fff}", diff --git a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotUserTradeTracker.cs b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotUserTradeTracker.cs index 2824574..21eeae2 100644 --- a/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotUserTradeTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/ItemTrackers/SpotUserTradeTracker.cs @@ -43,6 +43,19 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers _exchangeParameters = exchangeParameters; } + internal void ClearDataForSymbol(SharedSymbol symbol) + { + foreach (var trade in _store) + { + if (trade.Value.SharedSymbol!.TradingMode == symbol.TradingMode + && trade.Value.SharedSymbol.BaseAsset == symbol.BaseAsset + && trade.Value.SharedSymbol.QuoteAsset == symbol.QuoteAsset) + { + _store.TryRemove(trade.Key, out _); + } + } + } + /// protected override string GetKey(SharedUserTrade item) => item.Id; /// @@ -117,8 +130,8 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers if (DateTime.UtcNow - fromTime < TimeSpan.FromSeconds(1)) { - // Set it to at least a seconds in the past to prevent issues - fromTime = DateTime.UtcNow.AddSeconds(-1); + // Set it to at least 5 seconds in the past to prevent issues when local time isn't in sync + fromTime = DateTime.UtcNow.AddSeconds(-5); } _logger.LogTrace("{DataType} UserDataTracker poll startTime filter based on {Source}: {Time:yyyy-MM-dd HH:mm:ss.fff}", DataType, source, fromTime); diff --git a/CryptoExchange.Net/Trackers/UserData/Objects/UserDataSymbolTracker.cs b/CryptoExchange.Net/Trackers/UserData/Objects/UserDataSymbolTracker.cs index adfdf59..36e3470 100644 --- a/CryptoExchange.Net/Trackers/UserData/Objects/UserDataSymbolTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/Objects/UserDataSymbolTracker.cs @@ -38,10 +38,9 @@ namespace CryptoExchange.Net.Trackers.UserData.Objects /// /// Update the tracked symbol list with potential new symbols /// - /// - public void UpdateTrackedSymbols(IEnumerable symbols) + public void UpdateTrackedSymbols(IEnumerable symbols, bool addByUser = false) { - if (_onlyTrackProvidedSymbols) + if (!addByUser && _onlyTrackProvidedSymbols) return; lock (_symbolLock) @@ -56,5 +55,18 @@ namespace CryptoExchange.Net.Trackers.UserData.Objects } } } + + /// + /// Remove a symbol from the list + /// + public void RemoveTrackedSymbol(SharedSymbol symbol) + { + lock (_symbolLock) + { + var symbolToRemove = _trackedSymbols.SingleOrDefault(x => x.TradingMode == symbol.TradingMode && x.BaseAsset == symbol.BaseAsset && x.QuoteAsset == symbol.QuoteAsset); + if (symbolToRemove != null) + _trackedSymbols.Remove(symbolToRemove); + } + } } } diff --git a/CryptoExchange.Net/Trackers/UserData/UserFuturesDataTracker.cs b/CryptoExchange.Net/Trackers/UserData/UserFuturesDataTracker.cs index 3721447..e081f78 100644 --- a/CryptoExchange.Net/Trackers/UserData/UserFuturesDataTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/UserFuturesDataTracker.cs @@ -154,5 +154,30 @@ namespace CryptoExchange.Net.Trackers.UserData interval = result ? TimeSpan.FromMinutes(30) : TimeSpan.FromMinutes(5); } } + + /// + /// Add symbols to the list of symbols for which data is being tracked + /// + /// Symbols to add + public void AddTrackedSymbolsAsync(IEnumerable symbols) + { + if (symbols.Any(x => x.TradingMode == TradingMode.Spot)) + throw new ArgumentException("Spot symbol not allowed in futures tracker", nameof(symbols)); + + SymbolTracker.UpdateTrackedSymbols(symbols, true); + } + + /// + /// Remove a symbol from the list of symbols for which data is being tracked. + /// Note that the symbol will be added again if new data for that symbol is received, unless the OnlyTrackProvidedSymbols option has been set to true. + /// + /// Symbol to remove + public void RemoveTrackedSymbolAsync(SharedSymbol symbol) + { + SymbolTracker.RemoveTrackedSymbol(symbol); + + ((FuturesOrderTracker)Orders).ClearDataForSymbol(symbol); + ((FuturesUserTradeTracker)Trades).ClearDataForSymbol(symbol); + } } } diff --git a/CryptoExchange.Net/Trackers/UserData/UserSpotDataTracker.cs b/CryptoExchange.Net/Trackers/UserData/UserSpotDataTracker.cs index 43796ca..212ac46 100644 --- a/CryptoExchange.Net/Trackers/UserData/UserSpotDataTracker.cs +++ b/CryptoExchange.Net/Trackers/UserData/UserSpotDataTracker.cs @@ -127,5 +127,30 @@ namespace CryptoExchange.Net.Trackers.UserData interval = result ? TimeSpan.FromMinutes(30) : TimeSpan.FromMinutes(5); } } + + /// + /// Add symbols to the list of symbols for which data is being tracked + /// + /// Symbols to add + public void AddTrackedSymbolsAsync(IEnumerable symbols) + { + if (symbols.Any(x => x.TradingMode != TradingMode.Spot)) + throw new ArgumentException("Futures symbol not allowed in spot tracker", nameof(symbols)); + + SymbolTracker.UpdateTrackedSymbols(symbols, true); + } + + /// + /// Remove a symbol from the list of symbols for which data is being tracked. Also removes stored data for that symbol. + /// Note that the symbol will be added again if new data for that symbol is received, unless the OnlyTrackProvidedSymbols option has been set to true. + /// + /// Symbol to remove + public void RemoveTrackedSymbolAsync(SharedSymbol symbol) + { + SymbolTracker.RemoveTrackedSymbol(symbol); + + ((SpotOrderTracker)Orders).ClearDataForSymbol(symbol); + ((SpotUserTradeTracker)Trades).ClearDataForSymbol(symbol); + } } }