From abd5eb675c674d67fc02752ee17f043a23b13cba Mon Sep 17 00:00:00 2001 From: cryptooda Date: Mon, 27 Oct 2025 10:25:45 +0700 Subject: [PATCH] Re-update internal balance before opening position --- .../BacktestTests.cs | 10 ++-- .../Bots/TradingBotBase.cs | 57 +++++++++++++++++++ 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/Managing.Application.Tests/BacktestTests.cs b/src/Managing.Application.Tests/BacktestTests.cs index de603162..4a8c559e 100644 --- a/src/Managing.Application.Tests/BacktestTests.cs +++ b/src/Managing.Application.Tests/BacktestTests.cs @@ -212,18 +212,18 @@ public class BacktestTests : BaseTests Assert.NotNull(backtestResult); // Financial metrics - using decimal precision - Assert.Equal(-105.45m, Math.Round(backtestResult.FinalPnl, 2)); - Assert.Equal(-210.40m, Math.Round(backtestResult.NetPnl, 2)); - Assert.Equal(104.94m, Math.Round(backtestResult.Fees, 2)); + Assert.Equal(-106.56m, Math.Round(backtestResult.FinalPnl, 2)); + Assert.Equal(-187.36m, Math.Round(backtestResult.NetPnl, 2)); + Assert.Equal(80.80m, Math.Round(backtestResult.Fees, 2)); Assert.Equal(1000.0m, backtestResult.InitialBalance); // Performance metrics Assert.Equal(31, backtestResult.WinRate); - Assert.Equal(-10.55m, Math.Round(backtestResult.GrowthPercentage, 2)); + Assert.Equal(-10.66m, Math.Round(backtestResult.GrowthPercentage, 2)); Assert.Equal(-0.67m, Math.Round(backtestResult.HodlPercentage, 2)); // Risk metrics - Assert.Equal(243.84m, Math.Round(backtestResult.MaxDrawdown.Value, 2)); + Assert.Equal(247.62m, Math.Round(backtestResult.MaxDrawdown.Value, 2)); Assert.Equal(-0.021, Math.Round(backtestResult.SharpeRatio.Value, 3)); Assert.Equal(0.0, backtestResult.Score); diff --git a/src/Managing.Application/Bots/TradingBotBase.cs b/src/Managing.Application/Bots/TradingBotBase.cs index 6593e14c..0755fba3 100644 --- a/src/Managing.Application/Bots/TradingBotBase.cs +++ b/src/Managing.Application/Bots/TradingBotBase.cs @@ -169,6 +169,57 @@ public class TradingBotBase : ITradingBot }); } + /// + /// Verifies the actual USDC balance and updates the config if the actual balance is less than the configured balance. + /// This prevents bots from trying to trade with more funds than are actually available. + /// + public async Task VerifyAndUpdateBalance() + { + if (Config.IsForBacktest) return; + if (Account == null) + { + Logger.LogWarning("Cannot verify balance: Account is null"); + return; + } + + try + { + // Fetch actual USDC balance + var actualBalance = await ServiceScopeHelpers.WithScopedService(_scopeFactory, + async exchangeService => + { + var balances = await exchangeService.GetBalances(Account); + var usdcBalance = balances.FirstOrDefault(b => b.TokenName?.ToUpper() == "USDC"); + return usdcBalance?.Amount ?? 0; + }); + + // Check if actual balance is less than configured balance + if (actualBalance < Config.BotTradingBalance) + { + Logger.LogWarning( + "Actual USDC balance ({ActualBalance:F2}) is less than configured balance ({ConfiguredBalance:F2}). Updating configuration.", + actualBalance, Config.BotTradingBalance); + + // Create new config with updated balance + var newConfig = Config; + newConfig.BotTradingBalance = actualBalance; + + // Use UpdateConfiguration to notify and log the change + await UpdateConfiguration(newConfig); + } + else + { + Logger.LogDebug( + "Balance verification passed. Actual: {ActualBalance:F2}, Configured: {ConfiguredBalance:F2}", + actualBalance, Config.BotTradingBalance); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error verifying and updating balance"); + } + } + public async Task Run() { // Update signals for live trading only @@ -970,6 +1021,12 @@ public class TradingBotBase : ITradingBot try { + // Verify actual balance before opening position + if (!Config.IsForBacktest) + { + await VerifyAndUpdateBalance(); + } + var command = new OpenPositionRequest( Config.AccountName, Config.MoneyManagement,