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
|
// Load state into the trading bot instance
|
||||||
LoadStateIntoTradingBot(tradingBot);
|
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;
|
return tradingBot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
public Dictionary<string, LightSignal> Signals { get; set; }
|
public Dictionary<string, LightSignal> Signals { get; set; }
|
||||||
public Dictionary<Guid, Position> Positions { get; set; }
|
public Dictionary<Guid, Position> Positions { get; set; }
|
||||||
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
||||||
private decimal _currentBalance;
|
|
||||||
public DateTime PreloadSince { get; set; }
|
public DateTime PreloadSince { get; set; }
|
||||||
public int PreloadedCandlesCount { get; set; }
|
public int PreloadedCandlesCount { get; set; }
|
||||||
public long ExecutionCount { get; set; } = 0;
|
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
|
// OPTIMIZATION 2: Cache open position state to avoid expensive Positions.Any() calls
|
||||||
private bool _hasOpenPosition = false;
|
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(
|
public TradingBotBase(
|
||||||
ILogger<TradingBotBase> logger,
|
ILogger<TradingBotBase> logger,
|
||||||
IServiceScopeFactory scopeFactory,
|
IServiceScopeFactory scopeFactory,
|
||||||
@@ -65,7 +70,6 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
Signals = new Dictionary<string, LightSignal>();
|
Signals = new Dictionary<string, LightSignal>();
|
||||||
Positions = new Dictionary<Guid, Position>();
|
Positions = new Dictionary<Guid, Position>();
|
||||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||||
_currentBalance = config.BotTradingBalance;
|
|
||||||
PreloadSince = CandleHelpers.GetBotPreloadSinceFromTimeframe(config.Timeframe);
|
PreloadSince = CandleHelpers.GetBotPreloadSinceFromTimeframe(config.Timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,13 +437,13 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
|
|
||||||
if (WalletBalances.Count == 0)
|
if (WalletBalances.Count == 0)
|
||||||
{
|
{
|
||||||
WalletBalances[date] = _currentBalance;
|
WalletBalances[date] = Config.BotTradingBalance;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WalletBalances.ContainsKey(date))
|
if (!WalletBalances.ContainsKey(date))
|
||||||
{
|
{
|
||||||
WalletBalances[date] = _currentBalance;
|
WalletBalances[date] = Config.BotTradingBalance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,13 +1274,15 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
|
|
||||||
if (position.ProfitAndLoss != null)
|
if (position.ProfitAndLoss != null)
|
||||||
{
|
{
|
||||||
// Update the current balance when position closes
|
// Update the balance when position closes
|
||||||
_currentBalance += position.ProfitAndLoss.Net;
|
|
||||||
Config.BotTradingBalance += position.ProfitAndLoss.Net;
|
Config.BotTradingBalance += position.ProfitAndLoss.Net;
|
||||||
|
|
||||||
await LogDebugAsync(
|
await LogDebugAsync(
|
||||||
string.Format("💰 Balance Updated\nNew bot trading balance: `${0:F2}`",
|
string.Format("💰 Balance Updated\nNew bot trading balance: `${0:F2}`",
|
||||||
Config.BotTradingBalance));
|
Config.BotTradingBalance));
|
||||||
|
|
||||||
|
// For live trading, immediately sync and save to database
|
||||||
|
await OnBalanceUpdatedAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2060,6 +2066,18 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
await CancelAllOrders();
|
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
|
// Interface implementation
|
||||||
public async Task LogInformation(string message)
|
public async Task LogInformation(string message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public class PostgreSqlBotRepository : IBotRepository
|
|||||||
existingEntity.AccumulatedRunTimeSeconds = bot.AccumulatedRunTimeSeconds;
|
existingEntity.AccumulatedRunTimeSeconds = bot.AccumulatedRunTimeSeconds;
|
||||||
existingEntity.MasterBotUserId =
|
existingEntity.MasterBotUserId =
|
||||||
bot.MasterBotUserId ?? existingEntity.MasterBotUserId;
|
bot.MasterBotUserId ?? existingEntity.MasterBotUserId;
|
||||||
|
existingEntity.BotTradingBalance = bot.BotTradingBalance;
|
||||||
|
|
||||||
await _context.SaveChangesAsync().ConfigureAwait(false);
|
await _context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user