diff --git a/src/Managing.Application/Bots/SpotBot.cs b/src/Managing.Application/Bots/SpotBot.cs index d68b7ad5..d1704c2e 100644 --- a/src/Managing.Application/Bots/SpotBot.cs +++ b/src/Managing.Application/Bots/SpotBot.cs @@ -454,6 +454,43 @@ public class SpotBot : TradingBotBase if (positionQuantity > 0) { + // Check if token balance is very low (dust) compared to position quantity + // This likely means the position was closed but status wasn't updated + var dustThreshold = Config.Ticker == Ticker.ETH + ? 0.01m // ETH: 0.01 ETH is likely gas reserve or dust + : 0.0001m; // Other tokens: very small amount is dust + + var isDustAmount = tokenBalanceAmount <= dustThreshold; + var balanceIsVeryLow = tokenBalanceAmount < positionQuantity * 0.1m; // Less than 10% of expected + + // If balance is dust or very low, check if position was closed in history + if (isDustAmount || balanceIsVeryLow) + { + if (internalPosition.Status == PositionStatus.Filled) + { + var (positionFoundInHistory, hadWeb3ProxyError) = + await CheckSpotPositionInExchangeHistory(internalPosition); + + if (hadWeb3ProxyError) + { + await LogWarningAsync( + $"⏳ Web3Proxy Error During Spot Position Verification\n" + + $"Position: `{internalPosition.Identifier}`\n" + + $"Cannot verify if position is closed\n" + + $"Will retry on next execution cycle"); + return; + } + + if (positionFoundInHistory) + { + // Position was closed - mark as Finished + internalPosition.Status = PositionStatus.Finished; + await HandleClosedPosition(internalPosition); + return; + } + } + } + // Only check tolerance if token balance is LESS than position quantity // If balance is greater, it could be orphaned tokens from previous positions if (tokenBalanceAmount < positionQuantity) @@ -463,15 +500,19 @@ public class SpotBot : TradingBotBase if (difference > tolerance) { - await LogWarningAsync( - $"⚠️ Token Balance Below Position Quantity\n" + - $"Position: `{internalPosition.Identifier}`\n" + - $"Position Quantity: `{positionQuantity:F5}`\n" + - $"Token Balance: `{tokenBalanceAmount:F5}`\n" + - $"Difference: `{difference:F5}`\n" + - $"Tolerance (0.7%): `{tolerance:F5}`\n" + - $"Token balance is significantly lower than expected\n" + - $"Skipping position synchronization"); + // Only log warning if this is not a dust amount (already handled above) + if (!isDustAmount && !balanceIsVeryLow) + { + await LogWarningAsync( + $"⚠️ Token Balance Below Position Quantity\n" + + $"Position: `{internalPosition.Identifier}`\n" + + $"Position Quantity: `{positionQuantity:F5}`\n" + + $"Token Balance: `{tokenBalanceAmount:F5}`\n" + + $"Difference: `{difference:F5}`\n" + + $"Tolerance (0.7%): `{tolerance:F5}`\n" + + $"Token balance is significantly lower than expected\n" + + $"Skipping position synchronization"); + } return; // Skip processing if balance is too low } }