Merge workers into API
This commit is contained in:
@@ -97,11 +97,11 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
if (botStatus == BotStatus.Running && _tradingBot == null)
|
||||
{
|
||||
// Now, we can proceed with resuming the bot.
|
||||
await ResumeBotInternalAsync();
|
||||
await ResumeBotInternalAsync(botStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ResumeBotInternalAsync()
|
||||
private async Task ResumeBotInternalAsync(BotStatus previousStatus)
|
||||
{
|
||||
// Idempotency check
|
||||
if (_tradingBot != null)
|
||||
@@ -113,7 +113,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
{
|
||||
// Create and initialize trading bot instance
|
||||
_tradingBot = CreateTradingBotInstance(_state.State.Config);
|
||||
await _tradingBot.Start();
|
||||
await _tradingBot.Start(previousStatus);
|
||||
|
||||
// Set startup time when bot actually starts running
|
||||
_state.State.StartupTime = DateTime.UtcNow;
|
||||
@@ -155,7 +155,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
try
|
||||
{
|
||||
// Resume the bot - this handles registry status update internally
|
||||
await ResumeBotInternalAsync();
|
||||
await ResumeBotInternalAsync(status);
|
||||
_logger.LogInformation("LiveTradingBotGrain {GrainId} started successfully", this.GetPrimaryKey());
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -54,7 +54,7 @@ public class TradingBotBase : ITradingBot
|
||||
PreloadSince = CandleExtensions.GetBotPreloadSinceFromTimeframe(config.Timeframe);
|
||||
}
|
||||
|
||||
public async Task Start()
|
||||
public async Task Start(BotStatus previousStatus)
|
||||
{
|
||||
if (!Config.IsForBacktest)
|
||||
{
|
||||
@@ -77,27 +77,37 @@ public class TradingBotBase : ITradingBot
|
||||
// await CancelAllOrders();
|
||||
|
||||
// Send startup message only for fresh starts (not reboots)
|
||||
if (!true)
|
||||
switch (previousStatus)
|
||||
{
|
||||
var indicatorNames = Config.Scenario.Indicators.Select(i => i.Type.ToString()).ToList();
|
||||
var startupMessage = $"🚀 **Bot Started Successfully!**\n\n" +
|
||||
$"📊 **Trading Setup:**\n" +
|
||||
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
||||
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
||||
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
||||
$"💰 Balance: `${Config.BotTradingBalance:F2}`\n" +
|
||||
$"👀 Mode: `{(Config.IsForWatchingOnly ? "Watch Only" : "Live Trading")}`\n\n" +
|
||||
$"📈 **Active Indicators:** `{string.Join(", ", indicatorNames)}`\n\n" +
|
||||
$"✅ Ready to monitor signals and execute trades!\n" +
|
||||
$"📢 I'll notify you when signals are triggered.";
|
||||
case BotStatus.Saved:
|
||||
var indicatorNames = Config.Scenario.Indicators.Select(i => i.Type.ToString()).ToList();
|
||||
var startupMessage = $"🚀 **Bot Started Successfully!**\n\n" +
|
||||
$"📊 **Trading Setup:**\n" +
|
||||
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
||||
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
||||
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
||||
$"💰 Balance: `${Config.BotTradingBalance:F2}`\n" +
|
||||
$"👀 Mode: `{(Config.IsForWatchingOnly ? "Watch Only" : "Live Trading")}`\n\n" +
|
||||
$"📈 **Active Indicators:** `{string.Join(", ", indicatorNames)}`\n\n" +
|
||||
$"✅ Ready to monitor signals and execute trades!\n" +
|
||||
$"📢 I'll notify you when signals are triggered.";
|
||||
|
||||
await LogInformation(startupMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogInformation($"🔄 **Bot Restarted**\n" +
|
||||
$"📊 Resuming operations with {Signals.Count} signals and {Positions.Count} positions\n" +
|
||||
$"✅ Ready to continue trading");
|
||||
await LogInformation(startupMessage);
|
||||
break;
|
||||
|
||||
case BotStatus.Running:
|
||||
return;
|
||||
|
||||
case BotStatus.Stopped:
|
||||
// If status was Stopped we log a message to inform the user that the bot is restarting
|
||||
await LogInformation($"🔄 **Bot Restarted**\n" +
|
||||
$"📊 Resuming operations with {Signals.Count} signals and {Positions.Count} positions\n" +
|
||||
$"✅ Ready to continue trading");
|
||||
break;
|
||||
|
||||
default:
|
||||
// Handle any other status if needed
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -160,6 +170,7 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
ExecutionCount++;
|
||||
|
||||
Logger.LogInformation($"Date server : {DateTime.UtcNow} - Last candle date bot : {LastCandle.Date}");
|
||||
Logger.LogInformation($"Signals : {Signals.Count}");
|
||||
Logger.LogInformation($"ExecutionCount : {ExecutionCount}");
|
||||
Logger.LogInformation($"Positions : {Positions.Count}");
|
||||
@@ -377,26 +388,30 @@ public class TradingBotBase : ITradingBot
|
||||
if (position.Status.Equals(PositionStatus.New))
|
||||
{
|
||||
await SetPositionStatus(position.SignalIdentifier, PositionStatus.Filled);
|
||||
|
||||
|
||||
// Notify platform summary about the executed trade
|
||||
try
|
||||
{
|
||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
||||
{
|
||||
var platformGrain = grainFactory.GetGrain<IPlatformSummaryGrain>("platform-summary");
|
||||
var tradeExecutedEvent = new TradeExecutedEvent
|
||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory,
|
||||
async grainFactory =>
|
||||
{
|
||||
TradeId = position.Identifier,
|
||||
Ticker = position.Ticker,
|
||||
Volume = position.Open.Price * position.Open.Quantity * position.Open.Leverage
|
||||
};
|
||||
|
||||
await platformGrain.OnTradeExecutedAsync(tradeExecutedEvent);
|
||||
});
|
||||
var platformGrain =
|
||||
grainFactory.GetGrain<IPlatformSummaryGrain>("platform-summary");
|
||||
var tradeExecutedEvent = new TradeExecutedEvent
|
||||
{
|
||||
TradeId = position.Identifier,
|
||||
Ticker = position.Ticker,
|
||||
Volume = position.Open.Price * position.Open.Quantity * position.Open.Leverage
|
||||
};
|
||||
|
||||
await platformGrain.OnTradeExecutedAsync(tradeExecutedEvent);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Failed to notify platform summary about trade execution for position {PositionId}", position.Identifier);
|
||||
Logger.LogWarning(ex,
|
||||
"Failed to notify platform summary about trade execution for position {PositionId}",
|
||||
position.Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -979,7 +994,8 @@ public class TradingBotBase : ITradingBot
|
||||
_scopeFactory, async (exchangeService, accountService, tradingService) =>
|
||||
{
|
||||
closedPosition =
|
||||
await new ClosePositionCommandHandler(exchangeService, accountService, tradingService, _scopeFactory)
|
||||
await new ClosePositionCommandHandler(exchangeService, accountService, tradingService,
|
||||
_scopeFactory)
|
||||
.Handle(command);
|
||||
});
|
||||
|
||||
@@ -1024,35 +1040,39 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
if (currentCandle != null)
|
||||
{
|
||||
List<Candle> recentCandles = null;
|
||||
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory, async exchangeService =>
|
||||
{
|
||||
recentCandles = Config.IsForBacktest
|
||||
? (LastCandle != null ? new List<Candle>() { LastCandle } : new List<Candle>())
|
||||
: (await exchangeService.GetCandlesInflux(TradingExchanges.Evm, Config.Ticker,
|
||||
DateTime.UtcNow.AddHours(-4), Config.Timeframe)).ToList();
|
||||
});
|
||||
|
||||
// Check if we have any candles before proceeding
|
||||
if (recentCandles == null || !recentCandles.Any())
|
||||
{
|
||||
await LogWarning($"No recent candles available for position {position.Identifier}. Using current candle data instead.");
|
||||
|
||||
// Fallback to current candle if available
|
||||
if (currentCandle != null)
|
||||
List<Candle> recentCandles = null;
|
||||
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory, async exchangeService =>
|
||||
{
|
||||
recentCandles = new List<Candle> { currentCandle };
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogWarning($"No candle data available for position {position.Identifier}. Cannot determine stop loss/take profit hit.");
|
||||
Logger.LogError("No candle data available for position {PositionId}. Cannot determine stop loss/take profit hit.", position.Identifier);
|
||||
return;
|
||||
}
|
||||
}
|
||||
recentCandles = Config.IsForBacktest
|
||||
? (LastCandle != null ? new List<Candle>() { LastCandle } : new List<Candle>())
|
||||
: (await exchangeService.GetCandlesInflux(TradingExchanges.Evm, Config.Ticker,
|
||||
DateTime.UtcNow.AddHours(-4), Config.Timeframe)).ToList();
|
||||
});
|
||||
|
||||
var minPriceRecent = recentCandles.Min(c => c.Low);
|
||||
var maxPriceRecent = recentCandles.Max(c => c.High);
|
||||
// Check if we have any candles before proceeding
|
||||
if (recentCandles == null || !recentCandles.Any())
|
||||
{
|
||||
await LogWarning(
|
||||
$"No recent candles available for position {position.Identifier}. Using current candle data instead.");
|
||||
|
||||
// Fallback to current candle if available
|
||||
if (currentCandle != null)
|
||||
{
|
||||
recentCandles = new List<Candle> { currentCandle };
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogWarning(
|
||||
$"No candle data available for position {position.Identifier}. Cannot determine stop loss/take profit hit.");
|
||||
Logger.LogError(
|
||||
"No candle data available for position {PositionId}. Cannot determine stop loss/take profit hit.",
|
||||
position.Identifier);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var minPriceRecent = recentCandles.Min(c => c.Low);
|
||||
var maxPriceRecent = recentCandles.Max(c => c.High);
|
||||
|
||||
bool wasStopLossHit = false;
|
||||
bool wasTakeProfitHit = false;
|
||||
|
||||
@@ -39,7 +39,7 @@ public class PricesService : IPricesService
|
||||
throw new Exception($"Enable to found account for exchange {exchange}");
|
||||
|
||||
var lastCandles =
|
||||
await _candleRepository.GetCandles(exchange, ticker, timeframe, DateTime.UtcNow.AddDays(-2));
|
||||
await _candleRepository.GetCandles(exchange, ticker, timeframe, DateTime.UtcNow.AddDays(-30), limit: 5);
|
||||
var lastCandle = lastCandles.LastOrDefault();
|
||||
var startDate = lastCandle != null ? lastCandle.Date : new DateTime(2017, 1, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user