diff --git a/src/Managing.Api.Workers/Workers/TopVolumeTickerWorker.cs b/src/Managing.Api.Workers/Workers/TopVolumeTickerWorker.cs index e103728..602f584 100644 --- a/src/Managing.Api.Workers/Workers/TopVolumeTickerWorker.cs +++ b/src/Managing.Api.Workers/Workers/TopVolumeTickerWorker.cs @@ -1,4 +1,5 @@ -using Managing.Application.Workers.Abstractions; +using Managing.Application.Workers; +using Managing.Application.Workers.Abstractions; using static Managing.Common.Enums; namespace Managing.Api.Workers.Workers; diff --git a/src/Managing.Api/Workers/BotManagerWorker.cs b/src/Managing.Api/Workers/BotManagerWorker.cs index 8aff11c..b58aa6f 100644 --- a/src/Managing.Api/Workers/BotManagerWorker.cs +++ b/src/Managing.Api/Workers/BotManagerWorker.cs @@ -6,27 +6,18 @@ using static Managing.Common.Enums; namespace Managing.Api.Workers; -public class BotManagerWorker : BaseWorker -{ - private readonly IMediator _mediator; - private static readonly WorkerType _workerType = WorkerType.Fee; - - public BotManagerWorker( - ILogger logger, - IMediator tradingService, - IWorkerService workerService) : base( - _workerType, +public class BotManagerWorker( + ILogger logger, + IMediator mediadior, + IWorkerService workerService) + : BaseWorker(WorkerType.BotManager, logger, TimeSpan.FromMinutes(1), - workerService - ) - { - _mediator = tradingService; - } - + workerService) +{ protected override async Task Run(CancellationToken cancellationToken) { var loadBackupBotCommand = new LoadBackupBotCommand(); - await _mediator.Send(loadBackupBotCommand, cancellationToken); + await mediadior.Send(loadBackupBotCommand, cancellationToken); } } diff --git a/src/Managing.Api/appsettings.Oda.json b/src/Managing.Api/appsettings.Oda.json index e9b2a8d..bc7818a 100644 --- a/src/Managing.Api/appsettings.Oda.json +++ b/src/Managing.Api/appsettings.Oda.json @@ -5,8 +5,8 @@ }, "InfluxDb": { "Url": "http://localhost:8086/", - "Organization": "", - "Token": "" + "Organization": "managing-org", + "Token": "Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" }, "Serilog": { "MinimumLevel": { diff --git a/src/Managing.Application.Tests/BotsTests.cs b/src/Managing.Application.Tests/BotsTests.cs index 3f7400d..31d1cef 100644 --- a/src/Managing.Application.Tests/BotsTests.cs +++ b/src/Managing.Application.Tests/BotsTests.cs @@ -28,13 +28,15 @@ namespace Managing.Application.Tests var discordService = new Mock().Object; var tradingBotLogger = TradingBaseTests.CreateTradingBotLogger(); var backtestLogger = TradingBaseTests.CreateBacktesterLogger(); + var botService = new Mock().Object; _botFactory = new BotFactory( _exchangeService, tradingBotLogger, _moneyManagementService.Object, discordService, _accountService.Object, - _tradingService.Object); + _tradingService.Object, + botService); _backtester = new Backtester(_exchangeService, _botFactory, backtestRepository, backtestLogger); _elapsedTimes = new List(); } diff --git a/src/Managing.Application/Bots/FlippingBot.cs b/src/Managing.Application/Bots/FlippingBot.cs index dfac476..86ea4d8 100644 --- a/src/Managing.Application/Bots/FlippingBot.cs +++ b/src/Managing.Application/Bots/FlippingBot.cs @@ -38,7 +38,6 @@ namespace Managing.Application.Bots flipPosition: true) { BotType = BotType.FlippingBot; - Start(); } public sealed override void Start() diff --git a/src/Managing.Application/Bots/ScalpingBot.cs b/src/Managing.Application/Bots/ScalpingBot.cs index 1f656cd..d45bb3d 100644 --- a/src/Managing.Application/Bots/ScalpingBot.cs +++ b/src/Managing.Application/Bots/ScalpingBot.cs @@ -37,7 +37,6 @@ namespace Managing.Application.Bots isForWatchingOnly) { BotType = BotType.ScalpingBot; - Start(); } public sealed override void Start() diff --git a/src/Managing.Application/Bots/SimpleBot.cs b/src/Managing.Application/Bots/SimpleBot.cs index 041a5f0..ce29c28 100644 --- a/src/Managing.Application/Bots/SimpleBot.cs +++ b/src/Managing.Application/Bots/SimpleBot.cs @@ -18,7 +18,6 @@ namespace Managing.Application.Bots _botService = botService; _workflow = workflow; Interval = 100; - Start(); } public override void Start() diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index e774e0a..490cca7 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -670,7 +670,6 @@ public class TradingBot : Bot, ITradingBot { Name = Name, BotType = BotType, - Strategies = Strategies, Signals = Signals, Positions = Positions, Timeframe = Timeframe, @@ -687,7 +686,6 @@ public class TradingBot : Bot, ITradingBot public override void LoadBackup(BotBackup backup) { var data = JsonConvert.DeserializeObject(backup.Data); - Strategies = data.Strategies; Signals = data.Signals; Positions = data.Positions; WalletBalances = data.WalletBalances; @@ -698,7 +696,6 @@ public class TradingBotBackup { public string Name { get; set; } public BotType BotType { get; set; } - public HashSet Strategies { get; set; } public HashSet Signals { get; set; } public List Positions { get; set; } public Timeframe Timeframe { get; set; } diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index aaca3d4..2ab39a0 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -17,9 +17,23 @@ namespace Managing.Application.ManageBot { await _botRepository.InsertBotAsync(botBackup); } + + public BotBackup GetBotBackup(string name) + { + return _botRepository.GetBots().FirstOrDefault(b => b.Name == name); + } public void SaveBotBackup(string name, Enums.BotType botType, string data) { + var backup = GetBotBackup(name); + + if (backup != null) + { + backup.Data = data; + _botRepository.UpdateBackupBot(backup); + return; + } + var botBackup = new BotBackup { Name = name, diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs index 0d20f21..ae0e302 100644 --- a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -7,39 +7,43 @@ using Newtonsoft.Json; using Managing.Application.Bots; using Microsoft.Extensions.Logging; -namespace Managing.Application.ManageBot +namespace Managing.Application.ManageBot; + +public class LoadBackupBotCommandHandler : IRequestHandler { - public class LoadBackupBotCommandHandler : IRequestHandler + private readonly IBotFactory _botFactory; + private readonly ITaskCache _taskCache; + private readonly IMoneyManagementService _moneyManagementService; + private readonly IBotRepository _botRepository; + private readonly ILogger _logger; + + public LoadBackupBotCommandHandler( + IBotFactory botFactory, + ITaskCache taskCache, + IMoneyManagementService moneyManagementService, + IBotRepository botRepository, + ILogger logger) { - private readonly IBotFactory _botFactory; - private readonly ITaskCache _taskCache; - private readonly IMoneyManagementService _moneyManagementService; - private readonly IBotRepository _botRepository; - private readonly ILogger _logger; + _botFactory = botFactory; + _taskCache = taskCache; + _moneyManagementService = moneyManagementService; + _botRepository = botRepository; + _logger = logger; + } - public LoadBackupBotCommandHandler( - IBotFactory botFactory, - ITaskCache taskCache, - IMoneyManagementService moneyManagementService, - IBotRepository botRepository) + public Task Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) + { + BotStatus botStatus = BotStatus.Down; + var backupBots = _botRepository.GetBots(); + var result = new Dictionary(); + + _logger.LogInformation($"Loading {backupBots.Count()} backup bots"); + + foreach (var backupBot in backupBots) { - _botFactory = botFactory; - _taskCache = taskCache; - _moneyManagementService = moneyManagementService; - _botRepository = botRepository; - } - - public Task Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) - { - BotStatus botStatus = BotStatus.Down; - var backupBots = _botRepository.GetBots(); - var result = new Dictionary(); - - _logger.LogInformation($"Loading {backupBots.Count()} backup bots"); - - foreach (var backupBot in backupBots) + // Check if bot is existing in cache + try { - // Check if bot is existing in cache switch (backupBot.BotType) { case BotType.SimpleBot: @@ -64,6 +68,7 @@ namespace Managing.Application.ManageBot { _logger.LogInformation($"Starting backup bot {backupBot.Name}"); StartBot(backupBot); + scalpingBot = _taskCache.Get(backupBot.Name); scalpingBot.LoadBackup(backupBot); result.Add(scalpingBot.GetName(), BotStatus.Backup); } @@ -77,51 +82,58 @@ namespace Managing.Application.ManageBot break; } } - - - return Task.FromResult(botStatus.ToString()); - } - - private void StartBot(BotBackup backupBot) - { - switch (backupBot.BotType) + catch (Exception ex) { - case BotType.SimpleBot: - Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(backupBot.Name, null)); - var bot1 = _taskCache.AddOrGetExisting(backupBot.Name, simpleBot).Result; - bot1.LoadBackup(backupBot); - break; - case BotType.ScalpingBot: - var data = JsonConvert.DeserializeObject(backupBot.Data); - Func> scalpingBot = () => Task.FromResult(_botFactory.CreateScalpingBot( - data.AccountName, - data.MoneyManagement, - data.Name, - data.Ticker, - data.Scenario, - data.Timeframe, - data.IsForWatchingOnly)); - var bot2 = _taskCache.AddOrGetExisting(backupBot.Name, scalpingBot).Result; - bot2.LoadBackup(backupBot); - break; - case BotType.FlippingBot: - var dataFlippingBot = JsonConvert.DeserializeObject(backupBot.Data); - Func> flippingBot = () => Task.FromResult(_botFactory.CreateFlippingBot( - dataFlippingBot.AccountName, - dataFlippingBot.MoneyManagement, - dataFlippingBot.Name, - dataFlippingBot.Ticker, - dataFlippingBot.Scenario, - dataFlippingBot.Timeframe, - dataFlippingBot.IsForWatchingOnly)); - var bot3 = _taskCache.AddOrGetExisting(backupBot.Name, flippingBot).Result; - bot3.LoadBackup(backupBot); - break; - }; + _logger.LogError($"Error loading bot {backupBot.Name}", ex.Message); + result.Add(backupBot.Name, BotStatus.Down); + } } + + return Task.FromResult(botStatus.ToString()); } - public class LoadBackupBotCommand : IRequest + private void StartBot(BotBackup backupBot) { + switch (backupBot.BotType) + { + case BotType.SimpleBot: + Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(backupBot.Name, null)); + var bot1 = _taskCache.AddOrGetExisting(backupBot.Name, simpleBot).Result; + bot1.LoadBackup(backupBot); + bot1.Start(); + break; + case BotType.ScalpingBot: + var data = JsonConvert.DeserializeObject(backupBot.Data); + Func> scalpingBot = () => Task.FromResult(_botFactory.CreateScalpingBot( + data.AccountName, + data.MoneyManagement, + data.Name, + data.Ticker, + data.Scenario, + data.Timeframe, + data.IsForWatchingOnly)); + var bot2 = _taskCache.AddOrGetExisting(backupBot.Name, scalpingBot).Result; + bot2.LoadBackup(backupBot); + bot2.Start(); + break; + case BotType.FlippingBot: + var dataFlippingBot = JsonConvert.DeserializeObject(backupBot.Data); + Func> flippingBot = () => Task.FromResult(_botFactory.CreateFlippingBot( + dataFlippingBot.AccountName, + dataFlippingBot.MoneyManagement, + dataFlippingBot.Name, + dataFlippingBot.Ticker, + dataFlippingBot.Scenario, + dataFlippingBot.Timeframe, + dataFlippingBot.IsForWatchingOnly)); + var bot3 = _taskCache.AddOrGetExisting(backupBot.Name, flippingBot).Result; + bot3.LoadBackup(backupBot); + bot3.Start(); + break; + }; } } + +public class LoadBackupBotCommand : IRequest +{ +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs index 7828678..4b74421 100644 --- a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs @@ -26,13 +26,19 @@ namespace Managing.Application.ManageBot switch (request.BotType) { case BotType.SimpleBot: - Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(request.Name, null)); + var bot = _botFactory.CreateSimpleBot(request.Name, null); + bot.Start(); + Func> simpleBot = () => Task.FromResult(bot); return Task.FromResult(_taskCache.AddOrGetExisting(request.Name, simpleBot).Result.GetStatus()); case BotType.ScalpingBot: - Func> scalpingBot = () => Task.FromResult(_botFactory.CreateScalpingBot(request.AccountName, moneyManagement, request.Name, request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly)); + var sBot = _botFactory.CreateScalpingBot(request.AccountName, moneyManagement, request.Name, request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly); + sBot.Start(); + Func> scalpingBot = () => Task.FromResult(sBot); return Task.FromResult(_taskCache.AddOrGetExisting(request.Name, scalpingBot).Result.GetStatus()); case BotType.FlippingBot: - Func> flippingBot = () => Task.FromResult(_botFactory.CreateFlippingBot(request.AccountName, moneyManagement, request.Name, request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly)); + var fBot = _botFactory.CreateFlippingBot(request.AccountName, moneyManagement, request.Name, request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly); + fBot.Start(); + Func> flippingBot = () => Task.FromResult(fBot); return Task.FromResult(_taskCache.AddOrGetExisting(request.Name, flippingBot).Result.GetStatus()); }; diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs index f48ae78..509d180 100644 --- a/src/Managing.Bootstrap/ApiBootstrap.cs +++ b/src/Managing.Bootstrap/ApiBootstrap.cs @@ -112,7 +112,7 @@ public static class ApiBootstrap // Cache services.AddDistributedMemoryCache(); services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); // Processors services.AddTransient(); diff --git a/src/Managing.Bootstrap/WorkersBootstrap.cs b/src/Managing.Bootstrap/WorkersBootstrap.cs index b6676e1..ba0df40 100644 --- a/src/Managing.Bootstrap/WorkersBootstrap.cs +++ b/src/Managing.Bootstrap/WorkersBootstrap.cs @@ -33,6 +33,7 @@ using Managing.Application.Trading.Commands; using Managing.Domain.Trades; using Managing.Infrastructure.Evm.Services; using Managing.Application.Bots.Base; +using Managing.Application.ManageBot; namespace Managing.Bootstrap; @@ -58,6 +59,7 @@ public static class WorkersBootstrap services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddTransient, OpenPositionCommandHandler>(); services.AddTransient, ClosePositionCommandHandler>(); @@ -93,6 +95,7 @@ public static class WorkersBootstrap services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // Cache services.AddDistributedMemoryCache(); diff --git a/src/Managing.Common/Enums.cs b/src/Managing.Common/Enums.cs index 84c7988..b342b8a 100644 --- a/src/Managing.Common/Enums.cs +++ b/src/Managing.Common/Enums.cs @@ -317,7 +317,8 @@ public static class Enums PositionFetcher, TraderWatcher, LeaderboardWorker, - Noobiesboard + Noobiesboard, + BotManager } public enum WorkflowUsage diff --git a/src/Managing.Infrastructure.Storage/TaskCache.cs b/src/Managing.Infrastructure.Storage/TaskCache.cs index b89e52e..6a1c66d 100644 --- a/src/Managing.Infrastructure.Storage/TaskCache.cs +++ b/src/Managing.Infrastructure.Storage/TaskCache.cs @@ -64,7 +64,8 @@ namespace Managing.Infrastructure.Storage public T Get(string key) { var existingValue = (AsyncLazy)_cache.Get(key); - return existingValue.Value.Result; + if (existingValue != null) return existingValue.Value.Result; + return default(T); } public virtual List GetCache() diff --git a/src/Managing.WebApp/.env b/src/Managing.WebApp/.env index 1f85358..f8d9d0e 100644 --- a/src/Managing.WebApp/.env +++ b/src/Managing.WebApp/.env @@ -1,4 +1,4 @@ -VITE_API_URL_LOCAL=https://localhost:443 +VITE_API_URL_LOCAL=http://localhost:5000 VITE_API_URL_SERVER=https://dev-managing-api.apps.managing.live VITE_WORKER_URL_LOCAL=https://localhost:5002 VITE_WORKER_URL_SERVER=https://dev-managing-worker.apps.managing.live