Prevent bot from stopping if position is open
This commit is contained in:
@@ -248,6 +248,15 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
// Check if bot has open positions in database before allowing stop
|
||||
var hasOpenPositions = await HasOpenPositionsInDatabaseAsync();
|
||||
if (hasOpenPositions)
|
||||
{
|
||||
_logger.LogWarning("Cannot stop LiveTradingBotGrain {GrainId} - bot has open positions in database",
|
||||
this.GetPrimaryKey());
|
||||
throw new InvalidOperationException("Cannot stop bot while it has open positions. Please close all positions first.");
|
||||
}
|
||||
|
||||
// The check is now against the registry status
|
||||
var botRegistry = GrainFactory.GetGrain<ILiveBotRegistryGrain>(0);
|
||||
var botStatus = await botRegistry.GetBotStatus(this.GetPrimaryKey());
|
||||
@@ -569,6 +578,15 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
{
|
||||
_logger.LogInformation("Restarting LiveTradingBotGrain {GrainId}", this.GetPrimaryKey());
|
||||
|
||||
// Check if bot has open positions in database before allowing restart
|
||||
var hasOpenPositions = await HasOpenPositionsInDatabaseAsync();
|
||||
if (hasOpenPositions)
|
||||
{
|
||||
_logger.LogWarning("Cannot restart LiveTradingBotGrain {GrainId} - bot has open positions in database",
|
||||
this.GetPrimaryKey());
|
||||
throw new InvalidOperationException("Cannot restart bot while it has open positions. Please close all positions first.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await StopAsync();
|
||||
@@ -594,6 +612,15 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
// Check if bot has open positions in database before allowing deletion
|
||||
var hasOpenPositions = await HasOpenPositionsInDatabaseAsync();
|
||||
if (hasOpenPositions)
|
||||
{
|
||||
_logger.LogWarning("Cannot delete LiveTradingBotGrain {GrainId} - bot has open positions in database",
|
||||
this.GetPrimaryKey());
|
||||
throw new InvalidOperationException("Cannot delete bot while it has open positions. Please close all positions first.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Stop the bot first if it's running
|
||||
@@ -616,6 +643,11 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
|
||||
_logger.LogInformation("LiveTradingBotGrain {GrainId} deleted successfully", this.GetPrimaryKey());
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Re-throw InvalidOperationException from StopAsync (open positions check)
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to delete LiveTradingBotGrain {GrainId}", this.GetPrimaryKey());
|
||||
@@ -865,4 +897,38 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
return Task.FromResult(false); // Default to false on error to avoid blocking autoswap
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for open positions in database by bot identifier (initiator identifier).
|
||||
/// This is the source of truth for preventing bot stop when there are unfinished positions.
|
||||
/// </summary>
|
||||
private async Task<bool> HasOpenPositionsInDatabaseAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var botId = this.GetPrimaryKey();
|
||||
var positions = await ServiceScopeHelpers.WithScopedService<ITradingService, IEnumerable<Position>>(
|
||||
_scopeFactory,
|
||||
async tradingService => await tradingService.GetPositionsByInitiatorIdentifierAsync(botId));
|
||||
|
||||
var hasOpenPositions = positions?.Any(p => !p.IsFinished()) ?? false;
|
||||
_logger.LogDebug("Bot {GrainId} has open positions in database: {HasOpenPositions}",
|
||||
botId, hasOpenPositions);
|
||||
|
||||
if (hasOpenPositions)
|
||||
{
|
||||
var openPositions = positions?.Where(p => !p.IsFinished()).ToList() ?? new List<Position>();
|
||||
_logger.LogWarning("Bot {GrainId} cannot be stopped - has {Count} open positions in database: {Positions}",
|
||||
botId, openPositions.Count, string.Join(", ", openPositions.Select(p => p.Identifier)));
|
||||
}
|
||||
|
||||
return hasOpenPositions;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error checking database positions for bot {GrainId}", this.GetPrimaryKey());
|
||||
// Default to true on error to err on the side of caution - don't stop bot if we can't verify
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user