mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2026-04-13 00:22:22 +00:00
wip
This commit is contained in:
parent
fdc8b452b1
commit
9d43d358cf
@ -21,6 +21,11 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// </summary>
|
||||
public decimal? QuantityInContracts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether all values are null or zero
|
||||
/// </summary>
|
||||
public bool IsZero => !(QuantityInBaseAsset > 0) && !(QuantityInQuoteAsset > 0) && !(QuantityInContracts > 0);
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
|
||||
@ -295,6 +295,9 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
await (OnReconnecting?.Invoke() ?? Task.CompletedTask).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#warning debug
|
||||
await Task.Delay(10000).ConfigureAwait(false);
|
||||
|
||||
// Delay here to prevent very rapid looping when a connection to the server is accepted and immediately disconnected
|
||||
var initialDelay = GetReconnectDelay();
|
||||
await Task.Delay(initialDelay).ConfigureAwait(false);
|
||||
|
||||
@ -46,7 +46,8 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
return;
|
||||
|
||||
_status = value;
|
||||
Task.Run(() => StatusChanged?.Invoke(value));
|
||||
StatusChanged?.Invoke(value);
|
||||
//Task.Run(() => StatusChanged?.Invoke(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
private readonly IBalanceRestClient _restClient;
|
||||
private readonly IBalanceSocketClient? _socketClient;
|
||||
private readonly ExchangeParameters? _exchangeParameters;
|
||||
private readonly SharedAccountType _accountType;
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
@ -23,6 +24,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
ILogger logger,
|
||||
IBalanceRestClient restClient,
|
||||
IBalanceSocketClient? socketClient,
|
||||
SharedAccountType accountType,
|
||||
TrackerItemConfig config,
|
||||
ExchangeParameters? exchangeParameters = null
|
||||
) : base(logger, UserDataType.Balances, config, false, null)
|
||||
@ -30,6 +32,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
_restClient = restClient;
|
||||
_socketClient = socketClient;
|
||||
_exchangeParameters = exchangeParameters;
|
||||
_accountType = accountType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -52,7 +55,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetKey(SharedBalance item) => item.Asset;
|
||||
protected override string GetKey(SharedBalance item) => item.Asset + item.IsolatedMarginSymbol;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool? CheckIfUpdateShouldBeApplied(SharedBalance existingItem, SharedBalance updateItem) => true;
|
||||
@ -63,15 +66,20 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
if (_socketClient == null)
|
||||
return Task.FromResult(new CallResult<UpdateSubscription?>(data: null));
|
||||
|
||||
var accountType = _accountType == SharedAccountType.Spot ? TradingMode.Spot :
|
||||
_accountType == SharedAccountType.PerpetualInverseFutures ? TradingMode.PerpetualInverse :
|
||||
_accountType == SharedAccountType.DeliveryLinearFutures ? TradingMode.DeliveryLinear :
|
||||
_accountType == SharedAccountType.DeliveryInverseFutures ? TradingMode.DeliveryInverse :
|
||||
TradingMode.PerpetualLinear;
|
||||
return ExchangeHelpers.ProcessQueuedAsync<SharedBalance[]>(
|
||||
async handler => await _socketClient.SubscribeToBalanceUpdatesAsync(new SubscribeBalancesRequest(listenKey, exchangeParameters: _exchangeParameters), handler, ct: _cts!.Token).ConfigureAwait(false),
|
||||
async handler => await _socketClient.SubscribeToBalanceUpdatesAsync(new SubscribeBalancesRequest(listenKey, accountType, exchangeParameters: _exchangeParameters), handler, ct: _cts!.Token).ConfigureAwait(false),
|
||||
x => HandleUpdateAsync(UpdateSource.Push, x.Data))!;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<bool> DoPollAsync()
|
||||
{
|
||||
var balances = await _restClient.GetBalancesAsync(new GetBalancesRequest(exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
var balances = await _restClient.GetBalancesAsync(new GetBalancesRequest(accountType: _accountType, exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
if (balances.Success)
|
||||
await HandleUpdateAsync(UpdateSource.Poll, balances.Data).ConfigureAwait(false);
|
||||
|
||||
|
||||
@ -232,6 +232,24 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
|| x.CreateTime == null && x.UpdateTime == null // Unknown time
|
||||
).ToArray();
|
||||
|
||||
// Check for orders which are no longer returned in either open/closed and assume they're canceled without fill
|
||||
var openOrdersNotReturned = Values.Where(x =>
|
||||
x.SharedSymbol!.BaseAsset == symbol.BaseAsset && x.SharedSymbol.QuoteAsset == symbol.QuoteAsset // Orders for the same symbol
|
||||
&& x.QuantityFilled?.IsZero == true // With no filled value
|
||||
&& !openOrdersResult.Data.Any(r => r.OrderId == x.OrderId) // Not returned in open orders
|
||||
&& !relevantOrders.Any(r => r.OrderId == x.OrderId) // Not return in closed orders
|
||||
).ToList();
|
||||
|
||||
var additionalUpdates = new List<SharedFuturesOrder>();
|
||||
foreach (var order in openOrdersNotReturned)
|
||||
{
|
||||
additionalUpdates.Add(order with
|
||||
{
|
||||
Status = SharedOrderStatus.Canceled
|
||||
});
|
||||
}
|
||||
|
||||
relevantOrders = relevantOrders.Concat(additionalUpdates).ToArray();
|
||||
if (relevantOrders.Length > 0)
|
||||
await HandleUpdateAsync(UpdateSource.Poll, relevantOrders).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetKey(SharedPosition item) =>
|
||||
item.Id ?? item.Symbol + item.PositionMode + (item.PositionMode != SharedPositionMode.OneWay ? item.PositionSide.ToString() : "");
|
||||
item.SharedSymbol!.TradingMode + item.SharedSymbol.BaseAsset + item.SharedSymbol.QuoteAsset + item.PositionMode + (item.PositionMode != SharedPositionMode.OneWay ? item.PositionSide.ToString() : "");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool? CheckIfUpdateShouldBeApplied(SharedPosition existingItem, SharedPosition updateItem) => true;
|
||||
|
||||
@ -69,14 +69,42 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
|
||||
if (updateItem.OrderQuantity != null && updateItem.OrderQuantity != existingItem.OrderQuantity)
|
||||
{
|
||||
existingItem.OrderQuantity = updateItem.OrderQuantity;
|
||||
changed = true;
|
||||
existingItem.OrderQuantity ??= new SharedOrderQuantity();
|
||||
if (updateItem.OrderQuantity.QuantityInBaseAsset != null)
|
||||
{
|
||||
existingItem.OrderQuantity.QuantityInBaseAsset = updateItem.OrderQuantity.QuantityInBaseAsset;
|
||||
changed = true;
|
||||
}
|
||||
if (updateItem.OrderQuantity.QuantityInQuoteAsset != null)
|
||||
{
|
||||
existingItem.OrderQuantity.QuantityInQuoteAsset = updateItem.OrderQuantity.QuantityInQuoteAsset;
|
||||
changed = true;
|
||||
}
|
||||
if (updateItem.OrderQuantity.QuantityInContracts != null)
|
||||
{
|
||||
existingItem.OrderQuantity.QuantityInContracts = updateItem.OrderQuantity.QuantityInContracts;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateItem.QuantityFilled != null && updateItem.QuantityFilled != existingItem.QuantityFilled)
|
||||
{
|
||||
existingItem.QuantityFilled = updateItem.QuantityFilled;
|
||||
changed = true;
|
||||
existingItem.QuantityFilled ??= new SharedOrderQuantity();
|
||||
if (updateItem.QuantityFilled.QuantityInBaseAsset != null)
|
||||
{
|
||||
existingItem.QuantityFilled.QuantityInBaseAsset = updateItem.QuantityFilled.QuantityInBaseAsset;
|
||||
changed = true;
|
||||
}
|
||||
if (updateItem.QuantityFilled.QuantityInQuoteAsset != null)
|
||||
{
|
||||
existingItem.QuantityFilled.QuantityInQuoteAsset = updateItem.QuantityFilled.QuantityInQuoteAsset;
|
||||
changed = true;
|
||||
}
|
||||
if (updateItem.QuantityFilled.QuantityInContracts != null)
|
||||
{
|
||||
existingItem.QuantityFilled.QuantityInContracts = updateItem.QuantityFilled.QuantityInContracts;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateItem.Status != existingItem.Status)
|
||||
@ -214,6 +242,24 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
|| x.CreateTime == null && x.UpdateTime == null // Unknown time
|
||||
).ToArray();
|
||||
|
||||
// Check for orders which are no longer returned in either open/closed and assume they're canceled without fill
|
||||
var openOrdersNotReturned = Values.Where(x =>
|
||||
x.SharedSymbol!.BaseAsset == symbol.BaseAsset && x.SharedSymbol.QuoteAsset == symbol.QuoteAsset // Orders for the same symbol
|
||||
&& x.QuantityFilled?.IsZero == true // With no filled value
|
||||
&& !openOrdersResult.Data.Any(r => r.OrderId == x.OrderId) // Not returned in open orders
|
||||
&& !relevantOrders.Any(r => r.OrderId == x.OrderId) // Not return in closed orders
|
||||
).ToList();
|
||||
|
||||
var additionalUpdates = new List<SharedSpotOrder>();
|
||||
foreach (var order in openOrdersNotReturned)
|
||||
{
|
||||
additionalUpdates.Add(order with
|
||||
{
|
||||
Status = SharedOrderStatus.Canceled
|
||||
});
|
||||
}
|
||||
|
||||
relevantOrders = relevantOrders.Concat(additionalUpdates).ToArray();
|
||||
if (relevantOrders.Length > 0)
|
||||
await HandleUpdateAsync(UpdateSource.Poll, relevantOrders).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
/// <summary>
|
||||
/// Data store
|
||||
/// </summary>
|
||||
protected ConcurrentDictionary<string, T> _store = new ConcurrentDictionary<string, T>();
|
||||
protected ConcurrentDictionary<string, T> _store = new ConcurrentDictionary<string, T>(StringComparer.InvariantCultureIgnoreCase);
|
||||
/// <summary>
|
||||
/// Tracked symbols list
|
||||
/// </summary>
|
||||
@ -409,6 +409,7 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
catch { }
|
||||
}
|
||||
|
||||
var currentlyFirstPoll = !_firstPollDone;
|
||||
_firstPollDone = true;
|
||||
if (_cts.IsCancellationRequested)
|
||||
break;
|
||||
@ -433,6 +434,12 @@ namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
|
||||
|
||||
_lastPollAttempt = DateTime.UtcNow;
|
||||
_lastPollSuccess = !anyError;
|
||||
|
||||
if (anyError && currentlyFirstPoll && _pollAtStart)
|
||||
{
|
||||
// This is the initial polling at start and it failed, should this be a start error?
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@ namespace CryptoExchange.Net.Trackers.UserData.Objects
|
||||
/// <summary>
|
||||
/// User data tracker configuration
|
||||
/// </summary>
|
||||
public record UserDataTrackerConfig
|
||||
public abstract record UserDataTrackerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbols to initially track, used when polling data. Other symbols will get tracked when updates are received for orders or trades on a new symbol and when there are open orders or positions on a new symbol. To only track the symbols specified here set `OnlyTrackProvidedSymbols` to true.
|
||||
|
||||
@ -60,6 +60,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
IPositionSocketClient? positionSocketClient,
|
||||
string? userIdentifier,
|
||||
FuturesUserDataTrackerConfig config,
|
||||
SharedAccountType? accountType = null,
|
||||
ExchangeParameters? exchangeParameters = null) : base(logger, config, userIdentifier)
|
||||
{
|
||||
// create trackers
|
||||
@ -69,7 +70,8 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
|
||||
var trackers = new List<UserDataItemTracker>();
|
||||
|
||||
var balanceTracker = new BalanceTracker(logger, balanceRestClient, balanceSocketClient, config.BalancesConfig, exchangeParameters);
|
||||
var balanceAccountType = accountType ?? SharedAccountType.PerpetualLinearFutures;
|
||||
var balanceTracker = new BalanceTracker(logger, balanceRestClient, balanceSocketClient, balanceAccountType, config.BalancesConfig, exchangeParameters);
|
||||
Balances = balanceTracker;
|
||||
trackers.Add(balanceTracker);
|
||||
|
||||
@ -100,7 +102,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
var symbolResult = await _symbolClient.GetFuturesSymbolsAsync(new GetSymbolsRequest(exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
if (!symbolResult)
|
||||
{
|
||||
_logger.LogWarning("Failed to start UserFuturesDataTracker; symbols request failed: {Error}", symbolResult.Error!.Message);
|
||||
_logger.LogWarning("Failed to start UserFuturesDataTracker; symbols request failed: {Error}", symbolResult.Error);
|
||||
return symbolResult;
|
||||
}
|
||||
|
||||
@ -109,7 +111,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
var lkResult = await _listenKeyClient.StartListenKeyAsync(new StartListenKeyRequest(exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
if (!lkResult)
|
||||
{
|
||||
_logger.LogWarning("Failed to start UserFuturesDataTracker; listen key request failed: {Error}", lkResult.Error!.Message);
|
||||
_logger.LogWarning("Failed to start UserFuturesDataTracker; listen key request failed: {Error}", lkResult.Error);
|
||||
return lkResult;
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
|
||||
var trackers = new List<UserDataItemTracker>();
|
||||
|
||||
var balanceTracker = new BalanceTracker(logger, balanceRestClient, balanceSocketClient, config.BalancesConfig, exchangeParameters);
|
||||
var balanceTracker = new BalanceTracker(logger, balanceRestClient, balanceSocketClient, SharedAccountType.Spot, config.BalancesConfig, exchangeParameters);
|
||||
Balances = balanceTracker;
|
||||
trackers.Add(balanceTracker);
|
||||
|
||||
@ -78,7 +78,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
var symbolResult = await _symbolClient.GetSpotSymbolsAsync(new GetSymbolsRequest(exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
if (!symbolResult)
|
||||
{
|
||||
_logger.LogWarning("Failed to start UserSpotDataTracker; symbols request failed: {Error}", symbolResult.Error!.Message);
|
||||
_logger.LogWarning("Failed to start UserSpotDataTracker; symbols request failed: {Error}", symbolResult.Error);
|
||||
return symbolResult;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ namespace CryptoExchange.Net.Trackers.UserData
|
||||
var lkResult = await _listenKeyClient.StartListenKeyAsync(new StartListenKeyRequest(exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||
if (!lkResult)
|
||||
{
|
||||
_logger.LogWarning("Failed to start UserSpotDataTracker; listen key request failed: {Error}", lkResult.Error!.Message);
|
||||
_logger.LogWarning("Failed to start UserSpotDataTracker; listen key request failed: {Error}", lkResult.Error);
|
||||
return lkResult;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user