Fix fetch and restart bot

This commit is contained in:
2025-10-04 18:31:50 +07:00
parent 15eba0fc3c
commit 343b85dada
3 changed files with 30 additions and 27 deletions

View File

@@ -248,13 +248,21 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
public async Task StopAsync() public async Task StopAsync()
{ {
// Check if bot has open positions in database before allowing stop await StopAsyncInternal(false);
var hasOpenPositions = await HasOpenPositionsInDatabaseAsync(); }
if (hasOpenPositions)
private async Task StopAsyncInternal(bool isRestarting)
{
// Only check for open positions if this is not part of a restart operation
if (!isRestarting)
{ {
_logger.LogWarning("Cannot stop LiveTradingBotGrain {GrainId} - bot has open positions in database", var hasOpenPositions = await HasOpenPositionsInDatabaseAsync();
this.GetPrimaryKey()); if (hasOpenPositions)
throw new InvalidOperationException("Cannot stop bot while it has open positions. Please close all positions first."); {
_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 // The check is now against the registry status
@@ -578,18 +586,10 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
{ {
_logger.LogInformation("Restarting LiveTradingBotGrain {GrainId}", this.GetPrimaryKey()); _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 try
{ {
await StopAsync(); // Use internal stop method that bypasses open position check for restart
await StopAsyncInternal(true);
// Add a small delay to ensure stop operations complete // Add a small delay to ensure stop operations complete
await Task.Delay(100); await Task.Delay(100);

View File

@@ -402,7 +402,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
entity.ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0; entity.ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0;
entity.NetPnL = position.ProfitAndLoss?.Net ?? 0; entity.NetPnL = position.ProfitAndLoss?.Net ?? 0;
entity.UiFees = position.UiFees; entity.UiFees = position.UiFees;
entity.OriginDirection = position.OriginDirection; // entity.OriginDirection = position.OriginDirection;
entity.GasFees = position.GasFees; entity.GasFees = position.GasFees;
entity.Status = position.Status; entity.Status = position.Status;
entity.MoneyManagementJson = position.MoneyManagement != null entity.MoneyManagementJson = position.MoneyManagement != null

View File

@@ -184,7 +184,7 @@ public class EvmManager : IEvmManager
public async Task<List<EvmBalance>> GetAllBalances(Chain chain, string publicAddress) public async Task<List<EvmBalance>> GetAllBalances(Chain chain, string publicAddress)
{ {
var cacheKey = $"balances_{chain.Name}_{publicAddress.ToLowerInvariant()}"; var cacheKey = $"balances_{chain.Name}_{publicAddress.ToLowerInvariant()}";
// Try to get from cache first // Try to get from cache first
var cachedBalances = _cacheService.GetValue<List<EvmBalance>>(cacheKey); var cachedBalances = _cacheService.GetValue<List<EvmBalance>>(cacheKey);
if (cachedBalances != null) if (cachedBalances != null)
@@ -194,7 +194,7 @@ public class EvmManager : IEvmManager
// If not in cache, fetch from blockchain // If not in cache, fetch from blockchain
var balances = new List<EvmBalance>(); var balances = new List<EvmBalance>();
foreach (var ticker in TokenService.GetEligibleTickersForBalance()) foreach (var ticker in TokenService.GetEligibleTickersForBalance())
{ {
try try
@@ -349,14 +349,14 @@ public class EvmManager : IEvmManager
{ {
// Define the assets and chains we want to query // Define the assets and chains we want to query
var assets = new[] { Ticker.USDC, Ticker.ETH }; var assets = new[] { Ticker.USDC, Ticker.ETH };
var chains = new[] { "arbitrum", "ethereum" }; var chains = new[] { "arbitrum" };
// Get balances from Web3Proxy service // Get balances from Web3Proxy service
var balances = await _web3ProxyService.GetWalletBalanceAsync(publicAddress, assets, chains); var balances = await _web3ProxyService.GetWalletBalanceAsync(publicAddress, assets, chains);
// Convert Balance objects to EvmBalance objects // Convert Balance objects to EvmBalance objects
var evmBalances = new List<EvmBalance>(); var evmBalances = new List<EvmBalance>();
foreach (var balance in balances) foreach (var balance in balances)
{ {
if (balance.Amount > 0) if (balance.Amount > 0)
@@ -395,7 +395,7 @@ public class EvmManager : IEvmManager
{ {
// Log the exception and fallback to original implementation if Web3Proxy fails // Log the exception and fallback to original implementation if Web3Proxy fails
Console.WriteLine($"Web3Proxy balance retrieval failed: {ex.Message}"); Console.WriteLine($"Web3Proxy balance retrieval failed: {ex.Message}");
var chainBalances = new List<EvmBalance>(); var chainBalances = new List<EvmBalance>();
var chains = ChainService.GetChains(); var chains = ChainService.GetChains();
@@ -442,24 +442,27 @@ public class EvmManager : IEvmManager
if (gmxPrices == null) if (gmxPrices == null)
{ {
Console.WriteLine($"Warning: GMX API returned null for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}"); Console.WriteLine(
$"Warning: GMX API returned null for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}");
return new List<Candle>(); return new List<Candle>();
} }
if (gmxPrices.Candles == null || !gmxPrices.Candles.Any()) if (gmxPrices.Candles == null || !gmxPrices.Candles.Any())
{ {
Console.WriteLine($"Warning: GMX API returned empty candles array for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}"); Console.WriteLine(
$"Warning: GMX API returned empty candles array for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}");
return new List<Candle>(); return new List<Candle>();
} }
var filteredCandles = gmxPrices.Candles.Where(p => p[0] >= startDate.AddMinutes(-1).ToUnixTimestamp()).ToList(); var filteredCandles = gmxPrices.Candles.Where(p => p[0] >= startDate.AddMinutes(-1).ToUnixTimestamp()).ToList();
if (!filteredCandles.Any()) if (!filteredCandles.Any())
{ {
Console.WriteLine($"Warning: No candles found after filtering for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}. Total candles before filtering: {gmxPrices.Candles.Count}"); Console.WriteLine(
$"Warning: No candles found after filtering for ticker {ticker}, timeframe {timeframe}, startDate {startDate:yyyy-MM-dd HH:mm:ss}. Total candles before filtering: {gmxPrices.Candles.Count}");
return new List<Candle>(); return new List<Candle>();
} }
var candles = new List<Candle>(); var candles = new List<Candle>();
var timeBetweenCandles = CandleHelpers.GetBaseIntervalInSeconds(timeframe); var timeBetweenCandles = CandleHelpers.GetBaseIntervalInSeconds(timeframe);