Implement force closing of remaining balance in SpotBot
- Added a new method to force close any remaining balance in a trading position if it was not fully closed. - Enhanced logging to provide detailed information during the force close process, including current price checks and retry attempts. - Implemented error handling to manage potential failures during the force close operation, ensuring manual intervention is flagged when necessary.
This commit is contained in:
@@ -1046,7 +1046,10 @@ public class SpotBot : TradingBotBase
|
||||
$"Ticker: {Config.Ticker}\n" +
|
||||
$"Remaining Token Balance: `{tokenBalance.Amount:F5}`\n" +
|
||||
$"Expected: `0` or less than `{maxDustAmount:F5}` (dust)\n" +
|
||||
$"Position may not have been fully closed on exchange");
|
||||
$"Attempting to force close remaining balance...");
|
||||
|
||||
// Attempt to force close the remaining balance
|
||||
await ForceCloseRemainingBalance(closedPosition, tokenBalance.Amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1064,4 +1067,81 @@ public class SpotBot : TradingBotBase
|
||||
// Don't throw - this is just a verification step
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ForceCloseRemainingBalance(Position position, decimal remainingBalance)
|
||||
{
|
||||
try
|
||||
{
|
||||
await LogInformationAsync(
|
||||
$"🔄 Force Closing Remaining Balance\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Ticker: {Config.Ticker}\n" +
|
||||
$"Remaining Balance: `{remainingBalance:F5}`");
|
||||
|
||||
// Get current price for closing
|
||||
var currentPrice = await ServiceScopeHelpers.WithScopedService<IExchangeService, decimal>(
|
||||
_scopeFactory,
|
||||
async exchangeService => await exchangeService.GetCurrentPrice(Account, Config.Ticker));
|
||||
|
||||
if (currentPrice <= 0)
|
||||
{
|
||||
await LogWarningAsync(
|
||||
$"❌ Cannot Force Close\n" +
|
||||
$"Current price is invalid: `{currentPrice}`\n" +
|
||||
$"Will retry on next cycle");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new command to close the remaining balance
|
||||
var retryCommand = new CloseSpotPositionCommand(position, position.AccountId, currentPrice);
|
||||
|
||||
Position retryClosedPosition = await ServiceScopeHelpers
|
||||
.WithScopedServices<IExchangeService, IAccountService, ITradingService, Position>(
|
||||
_scopeFactory, async (exchangeService, accountService, tradingService) =>
|
||||
await new CloseSpotPositionCommandHandler(exchangeService, accountService, tradingService)
|
||||
.Handle(retryCommand));
|
||||
|
||||
if (retryClosedPosition != null &&
|
||||
(retryClosedPosition.Status == PositionStatus.Finished || retryClosedPosition.Status == PositionStatus.Flipped))
|
||||
{
|
||||
await LogInformationAsync(
|
||||
$"✅ Remaining Balance Force Closed Successfully\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Cleared Balance: `{remainingBalance:F5}`\n" +
|
||||
$"Close Price: `${currentPrice:F2}`");
|
||||
|
||||
// Verify one more time that balance is now cleared
|
||||
await Task.Delay(2000); // Wait for swap to complete
|
||||
|
||||
var finalBalance = await ServiceScopeHelpers.WithScopedService<IExchangeService, Balance?>(
|
||||
_scopeFactory,
|
||||
async exchangeService => await exchangeService.GetBalance(Account, Config.Ticker));
|
||||
|
||||
if (finalBalance is { Amount: > 0.0001m })
|
||||
{
|
||||
await LogWarningAsync(
|
||||
$"⚠️ Balance Still Remaining After Retry\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Remaining: `{finalBalance.Amount:F5}`\n" +
|
||||
$"Manual intervention may be required");
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogInformationAsync(
|
||||
$"✅ Balance Fully Cleared After Retry\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Final Balance: `{finalBalance?.Amount ?? 0:F5}`");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error force closing remaining balance for position {PositionId}", position.Identifier);
|
||||
await LogWarningAsync(
|
||||
$"❌ Force Close Failed\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Error: {ex.Message}\n" +
|
||||
$"Manual intervention may be required");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user