Implement balance update callback in TradingBotBase for immediate sync
- Removed the private _currentBalance field and replaced it with direct access to Config.BotTradingBalance. - Added OnBalanceUpdatedCallback to TradingBotBase for immediate synchronization and database saving when the balance is updated. - Updated LiveTradingBotGrain to set the callback for balance updates, ensuring accurate state management. - Modified PostgreSqlBotRepository to save the updated bot trading balance during entity updates.
This commit is contained in:
@@ -593,6 +593,18 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
// Load state into the trading bot instance
|
||||
LoadStateIntoTradingBot(tradingBot);
|
||||
|
||||
// Set up callback for immediate balance sync and save when balance is updated
|
||||
tradingBot.OnBalanceUpdatedCallback = async () =>
|
||||
{
|
||||
SyncStateFromBase();
|
||||
await _state.WriteStateAsync();
|
||||
|
||||
// Save to database immediately so GetStrategiesPaginated shows correct balance
|
||||
var botRegistry = GrainFactory.GetGrain<ILiveBotRegistryGrain>(0);
|
||||
var status = await botRegistry.GetBotStatus(this.GetPrimaryKey());
|
||||
await SaveBotAsync(status);
|
||||
};
|
||||
|
||||
return tradingBot;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ public abstract class TradingBotBase : ITradingBot
|
||||
public Dictionary<string, LightSignal> Signals { get; set; }
|
||||
public Dictionary<Guid, Position> Positions { get; set; }
|
||||
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
||||
private decimal _currentBalance;
|
||||
public DateTime PreloadSince { get; set; }
|
||||
public int PreloadedCandlesCount { get; set; }
|
||||
public long ExecutionCount { get; set; } = 0;
|
||||
@@ -51,6 +50,12 @@ public abstract class TradingBotBase : ITradingBot
|
||||
// OPTIMIZATION 2: Cache open position state to avoid expensive Positions.Any() calls
|
||||
private bool _hasOpenPosition = false;
|
||||
|
||||
/// <summary>
|
||||
/// Callback to notify the grain when balance is updated (for immediate sync and save to database).
|
||||
/// Set by the grain after creating the bot instance.
|
||||
/// </summary>
|
||||
public Func<Task>? OnBalanceUpdatedCallback { get; set; }
|
||||
|
||||
public TradingBotBase(
|
||||
ILogger<TradingBotBase> logger,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
@@ -65,7 +70,6 @@ public abstract class TradingBotBase : ITradingBot
|
||||
Signals = new Dictionary<string, LightSignal>();
|
||||
Positions = new Dictionary<Guid, Position>();
|
||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||
_currentBalance = config.BotTradingBalance;
|
||||
PreloadSince = CandleHelpers.GetBotPreloadSinceFromTimeframe(config.Timeframe);
|
||||
}
|
||||
|
||||
@@ -433,13 +437,13 @@ public abstract class TradingBotBase : ITradingBot
|
||||
|
||||
if (WalletBalances.Count == 0)
|
||||
{
|
||||
WalletBalances[date] = _currentBalance;
|
||||
WalletBalances[date] = Config.BotTradingBalance;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WalletBalances.ContainsKey(date))
|
||||
{
|
||||
WalletBalances[date] = _currentBalance;
|
||||
WalletBalances[date] = Config.BotTradingBalance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1270,13 +1274,15 @@ public abstract class TradingBotBase : ITradingBot
|
||||
|
||||
if (position.ProfitAndLoss != null)
|
||||
{
|
||||
// Update the current balance when position closes
|
||||
_currentBalance += position.ProfitAndLoss.Net;
|
||||
// Update the balance when position closes
|
||||
Config.BotTradingBalance += position.ProfitAndLoss.Net;
|
||||
|
||||
await LogDebugAsync(
|
||||
string.Format("💰 Balance Updated\nNew bot trading balance: `${0:F2}`",
|
||||
Config.BotTradingBalance));
|
||||
|
||||
// For live trading, immediately sync and save to database
|
||||
await OnBalanceUpdatedAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2060,6 +2066,18 @@ public abstract class TradingBotBase : ITradingBot
|
||||
await CancelAllOrders();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the bot trading balance is updated (e.g., after a position closes).
|
||||
/// Calls the OnBalanceUpdatedCallback if set (by the grain for live trading).
|
||||
/// </summary>
|
||||
protected virtual async Task OnBalanceUpdatedAsync()
|
||||
{
|
||||
if (OnBalanceUpdatedCallback != null)
|
||||
{
|
||||
await OnBalanceUpdatedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
// Interface implementation
|
||||
public async Task LogInformation(string message)
|
||||
{
|
||||
|
||||
@@ -83,6 +83,7 @@ public class PostgreSqlBotRepository : IBotRepository
|
||||
existingEntity.AccumulatedRunTimeSeconds = bot.AccumulatedRunTimeSeconds;
|
||||
existingEntity.MasterBotUserId =
|
||||
bot.MasterBotUserId ?? existingEntity.MasterBotUserId;
|
||||
existingEntity.BotTradingBalance = bot.BotTradingBalance;
|
||||
|
||||
await _context.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user