From 897ff94a6666df2df60f4db6b7b1ed124e97a868 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Sun, 2 Jun 2024 15:56:52 +0700 Subject: [PATCH 01/12] Add test wallets --- src/Managing.Application/Users/UserService.cs | 4 ++-- .../src/components/mollecules/LogIn/LogIn.tsx | 14 ++++++++------ .../src/components/mollecules/Toast/Toast.tsx | 8 ++++++-- .../src/pages/backtestPage/backtestScanner.tsx | 15 +++++++++------ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Managing.Application/Users/UserService.cs b/src/Managing.Application/Users/UserService.cs index 84f2e4d..0b37d1a 100644 --- a/src/Managing.Application/Users/UserService.cs +++ b/src/Managing.Application/Users/UserService.cs @@ -11,7 +11,7 @@ public class UserService : IUserService private readonly IUserRepository _userRepository; private readonly IAccountService _accountService; - private string[] authorizedAddresses = new string[] { "0x6781920674dA695aa5120d95D80c4B1788046806" }; + private string[] authorizedAddresses = ["0x6781920674dA695aa5120d95D80c4B1788046806", "0xA2B43AFF0992a47838DF2e6099A8439981f0B717"]; public UserService( IEvmManager evmManager, @@ -29,7 +29,7 @@ public class UserService : IUserService if (!authorizedAddresses.Contains(recoveredAddress)) throw new Exception("Address not authorized"); - + if (recoveredAddress == null || !recoveredAddress.Equals(address)) throw new Exception("Address not corresponding"); diff --git a/src/Managing.WebApp/src/components/mollecules/LogIn/LogIn.tsx b/src/Managing.WebApp/src/components/mollecules/LogIn/LogIn.tsx index b80ff7a..92eca05 100644 --- a/src/Managing.WebApp/src/components/mollecules/LogIn/LogIn.tsx +++ b/src/Managing.WebApp/src/components/mollecules/LogIn/LogIn.tsx @@ -8,21 +8,24 @@ import { UserClient } from '../../../generated/ManagingApi' import type { ILoginFormInput } from '../../../global/type' import useCookie from '../../../hooks/useCookie' import { SecondaryNavbar } from '../NavBar/NavBar' +import Toast from '../Toast/Toast' const LogIn = () => { const { apiUrl } = useApiUrlStore() const { register, handleSubmit } = useForm() const { disconnect } = useDisconnect() const { address } = useAccount() - const { isLoading, signMessageAsync } = useSignMessage({}) + const { signMessageAsync } = useSignMessage({}) const { setCookie } = useCookie() const onSubmit: SubmitHandler = async (form) => { const message = 'wagmi' const signature = await signMessageAsync({ message }) + const t = new Toast('Creating token') if (signature && address) { const userClient = new UserClient({}, apiUrl) + await userClient .user_CreateToken({ address: address.toString(), @@ -34,11 +37,11 @@ const LogIn = () => { setCookie('token', data, 1) location.reload() }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error(err) + .catch((err: any) => { + t.update('error', 'Error :' + err.message) }) - } else { + }else{ + t.update('error', 'Error : No signature') } } @@ -77,7 +80,6 @@ const LogIn = () => { - + Date: Thu, 20 Jun 2024 22:38:26 +0700 Subject: [PATCH 02/12] Add backup management --- assets/Todo-v2.md | 1 + src/Managing.Api/Managing.Api.csproj | 3 + src/Managing.Api/Program.cs | 5 +- .../Repositories/IBotRepository.cs | 8 ++ .../Abstractions/IBotService.cs | 4 + src/Managing.Application/Bots/SimpleBot.cs | 13 +- src/Managing.Application/Bots/TradingBot.cs | 46 +++++++ .../ManageBot/BackupBotCommandHandler.cs | 68 ++++++++++ .../ManageBot/BotService.cs | 37 +++++ .../ManageBot/LoadBackupBotCommandHandler.cs | 127 ++++++++++++++++++ src/Managing.Bootstrap/ApiBootstrap.cs | 3 + src/Managing.Common/Enums.cs | 3 +- src/Managing.Domain/Bots/Bot.cs | 7 +- src/Managing.Domain/Bots/BotBackup.cs | 9 ++ src/Managing.Domain/Bots/IBot.cs | 2 + .../BotRepository.cs | 41 ++++++ .../MongoDb/Collections/BotDto.cs | 13 ++ .../MongoDb/MongoMappers.cs | 28 +++- 18 files changed, 413 insertions(+), 5 deletions(-) create mode 100644 src/Managing.Application.Abstractions/Repositories/IBotRepository.cs create mode 100644 src/Managing.Application/Abstractions/IBotService.cs create mode 100644 src/Managing.Application/ManageBot/BackupBotCommandHandler.cs create mode 100644 src/Managing.Application/ManageBot/BotService.cs create mode 100644 src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs create mode 100644 src/Managing.Domain/Bots/BotBackup.cs create mode 100644 src/Managing.Infrastructure.Database/BotRepository.cs create mode 100644 src/Managing.Infrastructure.Database/MongoDb/Collections/BotDto.cs diff --git a/assets/Todo-v2.md b/assets/Todo-v2.md index 8f4c220..f752975 100644 --- a/assets/Todo-v2.md +++ b/assets/Todo-v2.md @@ -151,6 +151,7 @@ ________________________________________________________________________________ - [ ] Create method to update the money management use by the bot - [ ] Implement from/to tickers array pattern - [ ] Extract all managing trade method into a TradingBox class => Create composable trading bot type easily +- [ ] Bot backup worker: Every x, get saved bots and check if still running. If not running call api to reboot bot. # Front-end ## Improve Account page diff --git a/src/Managing.Api/Managing.Api.csproj b/src/Managing.Api/Managing.Api.csproj index be05f0e..843053a 100644 --- a/src/Managing.Api/Managing.Api.csproj +++ b/src/Managing.Api/Managing.Api.csproj @@ -36,6 +36,9 @@ Always + + Always + Always diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index 7d8eba9..e01d702 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -17,12 +17,15 @@ using Serilog.Sinks.Elasticsearch; // Builder var builder = WebApplication.CreateBuilder(args); -builder.Configuration.AddJsonFile("appsettings.Lowpro.json", optional: true, reloadOnChange: true) +builder.Configuration.SetBasePath(System.AppContext.BaseDirectory); +builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json") .AddJsonFile($"config.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true); builder.Configuration.AddEnvironmentVariables(); builder.Configuration.AddUserSecrets(); + builder.Host.UseSerilog((hostBuilder, loggerConfiguration) => { var envName = builder.Environment.EnvironmentName.ToLower().Replace(".", "-"); diff --git a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs new file mode 100644 index 0000000..0473039 --- /dev/null +++ b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs @@ -0,0 +1,8 @@ +using Managing.Domain.Bots; + +public interface IBotRepository +{ + Task InsertBotAsync(BotBackup bot); + IEnumerable GetBots(); + Task UpdateBackupBot(BotBackup bot); +} diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs new file mode 100644 index 0000000..95feed0 --- /dev/null +++ b/src/Managing.Application/Abstractions/IBotService.cs @@ -0,0 +1,4 @@ + public interface IBotService + { + void SaveBotBackup(BotBackup botBackup); + } \ No newline at end of file diff --git a/src/Managing.Application/Bots/SimpleBot.cs b/src/Managing.Application/Bots/SimpleBot.cs index ee8feb8..8ed092a 100644 --- a/src/Managing.Application/Bots/SimpleBot.cs +++ b/src/Managing.Application/Bots/SimpleBot.cs @@ -1,13 +1,14 @@ using Managing.Domain.Bots; using Managing.Domain.Workflows; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; namespace Managing.Application.Bots { public class SimpleBot : Bot { public readonly ILogger Logger; - private readonly Workflow _workflow; + private Workflow _workflow; public SimpleBot(string name, ILogger logger, Workflow workflow) : base(name) { @@ -35,5 +36,15 @@ namespace Managing.Application.Bots Logger.LogInformation("__________________________________________________"); }); } + + public override string GetBackup() + { + return JsonConvert.SerializeObject(_workflow); + } + + public override void LoadBackup(BotBackup backup) + { + _workflow = JsonConvert.DeserializeObject(backup.Data); + } } } diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 1dde4ab..82fb14b 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -11,6 +11,7 @@ using Managing.Domain.Shared.Helpers; using Managing.Domain.Strategies; using Managing.Domain.Trades; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using static Managing.Common.Enums; namespace Managing.Application.Bots; @@ -64,6 +65,7 @@ public class TradingBot : Bot, ITradingBot MessengerService = messengerService; TradingService = tradingService; + IsForWatchingOnly = isForWatchingOnly; FlipPosition = flipPosition; AccountName = accountName; @@ -648,4 +650,48 @@ public class TradingBot : Bot, ITradingBot await MessengerService.SendTradeMessage(message, isBadBehavior); } } + + public override string GetBackup() + { + return JsonConvert.SerializeObject(new TradingBotBackup + { + Name = Name, + BotType = BotType, + Strategies = Strategies, + Signals = Signals, + Positions = Positions, + Timeframe = Timeframe, + Ticker = Ticker, + Scenario = Scenario, + AccountName = AccountName, + IsForWatchingOnly = IsForWatchingOnly, + WalletBalances = WalletBalances, + MoneyManagement = MoneyManagement + }); + } + + public override void LoadBackup(BotBackup backup) + { + var data = JsonConvert.DeserializeObject(backup.Data); + Strategies = data.Strategies; + Signals = data.Signals; + Positions = data.Positions; + WalletBalances = data.WalletBalances; + } } + +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; } + public Ticker Ticker { get; set; } + public string Scenario { get; set; } + public string AccountName { get; set; } + public bool IsForWatchingOnly { get; set; } + public Dictionary WalletBalances { get; set; } + public MoneyManagement MoneyManagement { get; internal set; } +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs new file mode 100644 index 0000000..4b5d127 --- /dev/null +++ b/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs @@ -0,0 +1,68 @@ +using Managing.Domain.Bots; +using MediatR; +using static Managing.Common.Enums; +using Managing.Application.Abstractions; +using Managing.Application.ManageBot.Commands; +using Managing.Domain.MoneyManagements; + +namespace Managing.Application.ManageBot +{ + public class BackupBotCommandHandler : IRequestHandler + { + private readonly IBotFactory _botFactory; + private readonly ITaskCache _taskCache; + private readonly IMoneyManagementService _moneyManagementService; + private readonly IBotService _botService; + + public BackupBotCommandHandler(IBotFactory botFactory, ITaskCache taskCache, IBotService botService) + { + _botFactory = botFactory; + _taskCache = taskCache; + _botService = botService; + } + + public Task Handle(BackupBotCommand request, CancellationToken cancellationToken) + { + var botBackup = new BotBackup + { + Name = request.Name, + BotType = request.BotType, + Data = "" + }; + + switch (request.BotType) + { + case BotType.SimpleBot: + var simpleBot = _taskCache.Get(request.Name); + botBackup.Data = simpleBot.GetBackup(); + break; + case BotType.ScalpingBot: + var scalpingBot = _taskCache.Get(request.Name); + botBackup.Data = scalpingBot.GetBackup(); + break; + case BotType.FlippingBot: + var flippingBot = _taskCache.Get(request.Name); + botBackup.Data = flippingBot.GetBackup(); + break; + default: + return Task.FromResult(false); + } + + _botService.SaveBotBackup(botBackup); + + return Task.FromResult(true); + } + } + + public class BackupBotCommand : IRequest + { + public string Name { get; } + public BotType BotType { get; } + + public BackupBotCommand(BotType botType, string name) + { + BotType = botType; + Name = name; + } + } +} diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs new file mode 100644 index 0000000..7319cc8 --- /dev/null +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -0,0 +1,37 @@ +using Managing.Application.Abstractions; +using Newtonsoft.Json; +using System.IO; + +namespace Managing.Application.ManageBot +{ + public class BotService : IBotService + { + private readonly IBotFactory _botFactory; + private readonly IBotRepository _botRepository; + + public BotService(IBotFactory botFactory, IBotRepository botRepository) + { + _botFactory = botFactory; + _botRepository = botRepository; + } + + // public void CreateBot() + // { + // // Use the factory to create a new bot + // return _botFactory.CreateBot(); + // } + + // public void LoadBotBackup(BotBackup botBackup) + // { + // // Deserialize the JSON into a Bot object + // var bot = JsonConvert.DeserializeObject(json); + + // return bot; + // } + + public async void SaveBotBackup(BotBackup botBackup) + { + await _botRepository.InsertBotAsync(botBackup); + } + } +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs new file mode 100644 index 0000000..b6c734c --- /dev/null +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -0,0 +1,127 @@ +using Managing.Domain.Bots; +using MediatR; +using static Managing.Common.Enums; +using Managing.Application.Abstractions; +using Managing.Core; +using Managing.Domain.MoneyManagements; +using Newtonsoft.Json; +using Managing.Application.Bots; + +namespace Managing.Application.ManageBot +{ + public class LoadBackupBotCommandHandler : IRequestHandler + { + private readonly IBotFactory _botFactory; + private readonly ITaskCache _taskCache; + private readonly IMoneyManagementService _moneyManagementService; + private readonly IBotRepository _botRepository; + private readonly IMediator _mediator; + + public LoadBackupBotCommandHandler( + IBotFactory botFactory, + ITaskCache taskCache, + IMoneyManagementService moneyManagementService, + IBotRepository botRepository, + IMediator mediator) + { + _botFactory = botFactory; + _taskCache = taskCache; + _moneyManagementService = moneyManagementService; + _botRepository = botRepository; + _mediator = mediator; + } + + public Task Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) + { + BotStatus botStatus = BotStatus.Down; + var backupBots = _botRepository.GetBots(); + var result = new Dictionary(); + + foreach (var backupBot in backupBots) + { + // Check if bot is existing in cache + switch (backupBot.BotType) + { + case BotType.SimpleBot: + var simpleBot = _taskCache.Get(backupBot.Name); + if (simpleBot == null) + { + StartBot(request, backupBot); + simpleBot.LoadBackup(backupBot); + result.Add(simpleBot.GetName(), BotStatus.Backup); + } + else + { + result.Add(simpleBot.GetName(), MiscExtensions.ParseEnum(simpleBot.GetStatus())); + } + + break; + case BotType.ScalpingBot: + case BotType.FlippingBot: + var scalpingBot = _taskCache.Get(backupBot.Name); + if (scalpingBot == null) + { + StartBot(request, backupBot); + scalpingBot.LoadBackup(backupBot); + result.Add(scalpingBot.GetName(), BotStatus.Backup); + } + else + { + result.Add(scalpingBot.GetName(), MiscExtensions.ParseEnum(scalpingBot.GetStatus())); + } + break; + default: + result.Add(backupBot.Name, BotStatus.Down); + break; + } + } + + + return Task.FromResult(botStatus.ToString()); + } + + private void StartBot(LoadBackupBotCommand request, BotBackup backupBot) + { + switch (backupBot.BotType) + { + case BotType.SimpleBot: + Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(request.Name, null)); + var bot1 = _taskCache.AddOrGetExisting(request.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(request.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(request.Name, flippingBot).Result; + bot3.LoadBackup(backupBot); + break; + }; + } + } + + public class LoadBackupBotCommand : IRequest + { + public string Name { get; internal set; } + public string AccountName { get; internal set; } + } +} diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs index f90c98a..0dfbc24 100644 --- a/src/Managing.Bootstrap/ApiBootstrap.cs +++ b/src/Managing.Bootstrap/ApiBootstrap.cs @@ -41,6 +41,7 @@ using Binance.Net.Interfaces.Clients; using Managing.Infrastructure.Evm.Services; using Managing.Application.Workflows; using Managing.Application.Bots.Base; +using Managing.Application.ManageBot; namespace Managing.Bootstrap; @@ -105,6 +106,7 @@ public static class ApiBootstrap services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // Cache services.AddDistributedMemoryCache(); @@ -123,6 +125,7 @@ public static class ApiBootstrap services.AddTransient(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // Stream services.AddSingleton(); diff --git a/src/Managing.Common/Enums.cs b/src/Managing.Common/Enums.cs index 6bf4d83..84c7988 100644 --- a/src/Managing.Common/Enums.cs +++ b/src/Managing.Common/Enums.cs @@ -73,7 +73,8 @@ public static class Enums { Down, Starting, - Up + Up, + Backup } public enum SignalStatus diff --git a/src/Managing.Domain/Bots/Bot.cs b/src/Managing.Domain/Bots/Bot.cs index ca4af2a..7e3959d 100644 --- a/src/Managing.Domain/Bots/Bot.cs +++ b/src/Managing.Domain/Bots/Bot.cs @@ -1,4 +1,5 @@ -using static Managing.Common.Enums; +using System.Text.Json; +using static Managing.Common.Enums; namespace Managing.Domain.Bots { @@ -14,6 +15,7 @@ namespace Managing.Domain.Bots public int Interval { get; set; } public BotStatus Status { get; set; } private CancellationTokenSource CancellationToken { get; set; } + public string Data { get; set; } public Bot(string name) { @@ -71,5 +73,8 @@ namespace Managing.Domain.Bots { return Name; } + + public abstract string GetBackup(); + public abstract void LoadBackup(BotBackup backup); } } \ No newline at end of file diff --git a/src/Managing.Domain/Bots/BotBackup.cs b/src/Managing.Domain/Bots/BotBackup.cs new file mode 100644 index 0000000..5ea153c --- /dev/null +++ b/src/Managing.Domain/Bots/BotBackup.cs @@ -0,0 +1,9 @@ +using Managing.Domain.MoneyManagements; +using static Managing.Common.Enums; + +public class BotBackup +{ + public string Name { get; set; } + public BotType BotType { get; set; } + public string Data { get; set; } +} \ No newline at end of file diff --git a/src/Managing.Domain/Bots/IBot.cs b/src/Managing.Domain/Bots/IBot.cs index 7572a3d..9c2c30f 100644 --- a/src/Managing.Domain/Bots/IBot.cs +++ b/src/Managing.Domain/Bots/IBot.cs @@ -8,5 +8,7 @@ void Restart(); string GetStatus(); string GetName(); + string GetBackup(); + void LoadBackup(BotBackup backup); } } diff --git a/src/Managing.Infrastructure.Database/BotRepository.cs b/src/Managing.Infrastructure.Database/BotRepository.cs new file mode 100644 index 0000000..4147431 --- /dev/null +++ b/src/Managing.Infrastructure.Database/BotRepository.cs @@ -0,0 +1,41 @@ +using Managing.Domain.Bots; +using Managing.Infrastructure.Databases.MongoDb; +using Managing.Infrastructure.Databases.MongoDb.Abstractions; +using Managing.Infrastructure.Databases.MongoDb.Collections; + +namespace Managing.Infrastructure.Databases; + +public class BotRepository : IBotRepository +{ + private readonly IMongoRepository _botRepository; + + public BotRepository(IMongoRepository botRepository) + { + _botRepository = botRepository; + } + + public async Task InsertBotAsync(BotBackup bot) + { + await _botRepository.InsertOneAsync(MongoMappers.Map(bot)); + } + + public IEnumerable GetBots() + { + var bots = _botRepository.FindAll(); + return bots.Select(b => MongoMappers.Map(b)); + } + + public async Task UpdateBackupBot(BotBackup bot) + { + var b = _botRepository.FindOne(b => b.Name == bot.Name); + var dto = MongoMappers.Map(bot); + dto.Id = b.Id; + _botRepository.Update(dto); + } + + public void DeleteBotByName(string name) + { + var bot = _botRepository.FindOne(b => b.Name == name); + _botRepository.DeleteById(bot.Id.ToString()); + } +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/MongoDb/Collections/BotDto.cs b/src/Managing.Infrastructure.Database/MongoDb/Collections/BotDto.cs new file mode 100644 index 0000000..ab7303a --- /dev/null +++ b/src/Managing.Infrastructure.Database/MongoDb/Collections/BotDto.cs @@ -0,0 +1,13 @@ +using Managing.Infrastructure.Databases.MongoDb.Attributes; +using Managing.Infrastructure.Databases.MongoDb.Configurations; +using static Managing.Common.Enums; + +namespace Managing.Infrastructure.Databases.MongoDb.Collections; + +[BsonCollection("Bots")] +public class BotDto : Document +{ + public string Name { get; set; } + public string Data { get; set; } + public BotType BotType { get; set; } +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index 8412872..9a2c864 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -1,5 +1,7 @@ -using Managing.Domain.Accounts; +using System.Reflection.Metadata.Ecma335; +using Managing.Domain.Accounts; using Managing.Domain.Backtests; +using Managing.Domain.Bots; using Managing.Domain.Candles; using Managing.Domain.MoneyManagements; using Managing.Domain.Scenarios; @@ -650,5 +652,29 @@ public static class MongoMappers }; } + internal static BotDto Map(BotBackup bot) + { + if (bot == null) return null; + + return new BotDto + { + Name = bot.Name, + BotType = bot.BotType, + Data = bot.Data, + }; + } + + internal static BotBackup Map(BotDto b) + { + if (b == null) return null; + + return new BotBackup + { + Name = b.Name, + BotType = b.BotType, + Data = b.Data + }; + } + #endregion } From fb976d231a4277b7c8a755db9c9ff1b931845d49 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Wed, 26 Jun 2024 19:14:32 +0700 Subject: [PATCH 03/12] Fix bot launch errors --- .../Managing.Api.Workers.csproj | 4 +- src/Managing.Api.Workers/Program.cs | 5 ++- .../appsettings.Oda-docker.json | 4 +- src/Managing.Api.Workers/appsettings.Oda.json | 2 +- src/Managing.Api/appsettings.Oda-docker.json | 2 +- src/Managing.Application/Bots/TradingBot.cs | 12 ++++- .../ManageBot/BackupBotCommandHandler.cs | 7 +-- .../ManageBot/BotService.cs | 2 - .../Trading/TradingService.cs | 2 +- ...e.sandbox.yml => docker-compose.local.yml} | 45 ++++++++++--------- src/Managing.Docker/docker-compose.yml | 12 ++--- .../BotRepository.cs | 5 +-- src/Managing.WebApp/.env | 2 +- 13 files changed, 54 insertions(+), 50 deletions(-) rename src/Managing.Docker/{docker-compose.sandbox.yml => docker-compose.local.yml} (52%) diff --git a/src/Managing.Api.Workers/Managing.Api.Workers.csproj b/src/Managing.Api.Workers/Managing.Api.Workers.csproj index c046e54..2e99aee 100644 --- a/src/Managing.Api.Workers/Managing.Api.Workers.csproj +++ b/src/Managing.Api.Workers/Managing.Api.Workers.csproj @@ -32,13 +32,13 @@ - + Always Always - + Always diff --git a/src/Managing.Api.Workers/Program.cs b/src/Managing.Api.Workers/Program.cs index a951a82..80d871e 100644 --- a/src/Managing.Api.Workers/Program.cs +++ b/src/Managing.Api.Workers/Program.cs @@ -14,8 +14,9 @@ using Serilog.Sinks.Elasticsearch; // Builder var builder = WebApplication.CreateBuilder(args); -builder.Configuration - .AddEnvironmentVariables(); +builder.Configuration.SetBasePath(System.AppContext.BaseDirectory); +builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json"); builder.Host.UseSerilog((hostBuilder, loggerConfiguration) => { diff --git a/src/Managing.Api.Workers/appsettings.Oda-docker.json b/src/Managing.Api.Workers/appsettings.Oda-docker.json index e81d760..efe660f 100644 --- a/src/Managing.Api.Workers/appsettings.Oda-docker.json +++ b/src/Managing.Api.Workers/appsettings.Oda-docker.json @@ -5,8 +5,8 @@ }, "InfluxDb": { "Url": "http://influxdb:8086/", - "Organization": "", - "Token": "" + "Organization": "managing-org", + "Token": "Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" }, "Serilog": { "MinimumLevel": { diff --git a/src/Managing.Api.Workers/appsettings.Oda.json b/src/Managing.Api.Workers/appsettings.Oda.json index d9754cb..643d440 100644 --- a/src/Managing.Api.Workers/appsettings.Oda.json +++ b/src/Managing.Api.Workers/appsettings.Oda.json @@ -1,7 +1,7 @@ { "ManagingDatabase": { "ConnectionString": "mongodb://localhost:27017", - "DatabaseName": "ManagingDb", + "DatabaseName": "ManagingDb" }, "InfluxDb": { "Url": "http://localhost:8086/", diff --git a/src/Managing.Api/appsettings.Oda-docker.json b/src/Managing.Api/appsettings.Oda-docker.json index e59c1c4..9a8a6a3 100644 --- a/src/Managing.Api/appsettings.Oda-docker.json +++ b/src/Managing.Api/appsettings.Oda-docker.json @@ -8,7 +8,7 @@ "InfluxDb": { "Url": "http://influxdb:8086/", "Organization": "managing-org", - "Token": "" + "Token": "Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" }, "Serilog": { "MinimumLevel": { diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 82fb14b..3923fc8 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -99,7 +99,15 @@ public class TradingBot : Bot, ITradingBot LoadScenario(); await PreloadCandles(); await CancelAllOrders(); - await MessengerService.SendMessage($"Hi everyone, I'm going to run {Name}. \nI will send a message here everytime a signal is triggered by the {string.Join(",", Strategies.Select(s => s.Name))} strategies."); + + try + { + await MessengerService.SendMessage($"Hi everyone, I'm going to run {Name}. \nI will send a message here everytime a signal is triggered by the {string.Join(",", Strategies.Select(s => s.Name))} strategies."); + } + catch (Exception ex) + { + Logger.LogError(ex, ex.Message); + } await InitWorker(Run); } @@ -553,7 +561,7 @@ public class TradingBot : Bot, ITradingBot private async Task CancelAllOrders() { - if (!IsForBacktest) + if (!IsForBacktest && !IsForWatchingOnly) { try { diff --git a/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs index 4b5d127..98c4690 100644 --- a/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs @@ -2,21 +2,16 @@ using MediatR; using static Managing.Common.Enums; using Managing.Application.Abstractions; -using Managing.Application.ManageBot.Commands; -using Managing.Domain.MoneyManagements; namespace Managing.Application.ManageBot { public class BackupBotCommandHandler : IRequestHandler { - private readonly IBotFactory _botFactory; private readonly ITaskCache _taskCache; - private readonly IMoneyManagementService _moneyManagementService; private readonly IBotService _botService; - public BackupBotCommandHandler(IBotFactory botFactory, ITaskCache taskCache, IBotService botService) + public BackupBotCommandHandler(ITaskCache taskCache, IBotService botService) { - _botFactory = botFactory; _taskCache = taskCache; _botService = botService; } diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 7319cc8..e5a0b6c 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -1,6 +1,4 @@ using Managing.Application.Abstractions; -using Newtonsoft.Json; -using System.IO; namespace Managing.Application.ManageBot { diff --git a/src/Managing.Application/Trading/TradingService.cs b/src/Managing.Application/Trading/TradingService.cs index 47871b5..d752d91 100644 --- a/src/Managing.Application/Trading/TradingService.cs +++ b/src/Managing.Application/Trading/TradingService.cs @@ -206,7 +206,7 @@ public class TradingService : ITradingService return _cacheService.GetOrSave($"Fee-{account.Exchange}", () => { - return _tradingRepository.GetFee(TradingExchanges.Evm).Cost; + return _tradingRepository.GetFee(TradingExchanges.Evm)?.Cost ?? 0m; }, TimeSpan.FromHours(2)); } diff --git a/src/Managing.Docker/docker-compose.sandbox.yml b/src/Managing.Docker/docker-compose.local.yml similarity index 52% rename from src/Managing.Docker/docker-compose.sandbox.yml rename to src/Managing.Docker/docker-compose.local.yml index d4c7d4e..5b4f8b7 100644 --- a/src/Managing.Docker/docker-compose.sandbox.yml +++ b/src/Managing.Docker/docker-compose.local.yml @@ -4,9 +4,9 @@ version: '3.4' services: managing.api: environment: - - ASPNETCORE_ENVIRONMENT=oda-docker + - ASPNETCORE_ENVIRONMENT=Oda-docker - ASPNETCORE_URLS=https://+:443;http://+:80 - - ASPNETCORE_Kestrel__Certificates__Default__Password=!MotdepasseFort11 + - ASPNETCORE_Kestrel__Certificates__Default__Password=!Managing94 - ASPNETCORE_Kestrel__Certificates__Default__Path=/app/managing_cert.pfx ports: - "80:80" @@ -14,20 +14,23 @@ services: volumes: - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + - /Users/oda/ASP.NET/Https:/root/.aspnet/https:ro + - /Users/oda/Microsoft/UserSecrets:/root/.microsoft/usersecrets/$USER_SECRETS_ID depends_on: - managingdb managing.api.workers: environment: - - ASPNETCORE_ENVIRONMENT=oda-docker + - ASPNETCORE_ENVIRONMENT=Oda-docker - ASPNETCORE_URLS=https://+:443;http://+:80 - - ASPNETCORE_Kestrel__Certificates__Default__Password=!MotdepasseFort11 + - ASPNETCORE_Kestrel__Certificates__Default__Password=!Managing94 - ASPNETCORE_Kestrel__Certificates__Default__Path=/app/managing_cert.pfx ports: - "81:80" - "444:443" volumes: - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + - /Users/oda/ASP.NET/Https:/root/.aspnet/https:ro depends_on: - managingdb @@ -38,24 +41,24 @@ services: ports: - "27017:27017" - elasticsearch: - ports: - - 9200:9200 - volumes: - - elasticsearch-data:/usr/share/elasticsearch/data - environment: - - discovery.type=single-node - - xpack.monitoring.templates.enabled=true - - ES_JAVA_OPTS=-Xms1g -Xmx1g - - xpack.security.enabled=false + # elasticsearch: + # ports: + # - 9200:9200 + # volumes: + # - elasticsearch-data:/usr/share/elasticsearch/data + # environment: + # - discovery.type=single-node + # - xpack.monitoring.templates.enabled=true + # - ES_JAVA_OPTS=-Xms1g -Xmx1g + # - xpack.security.enabled=false - kibana: - ports: - - 5601:5601 - depends_on: - - elasticsearch - environment: - - ELASTICSEARCH_URL=http://elasticsearch:9200 + # kibana: + # ports: + # - 5601:5601 + # depends_on: + # - elasticsearch + # environment: + # - ELASTICSEARCH_URL=http://elasticsearch:9200 influxdb: image: influxdb:latest diff --git a/src/Managing.Docker/docker-compose.yml b/src/Managing.Docker/docker-compose.yml index f86658c..e8e3f83 100644 --- a/src/Managing.Docker/docker-compose.yml +++ b/src/Managing.Docker/docker-compose.yml @@ -22,13 +22,13 @@ services: networks: - managing-network - elasticsearch: - image: elasticsearch:8.4.1 - networks: - - managing-network + # elasticsearch: + # image: elasticsearch:8.4.1 + # networks: + # - managing-network - kibana: - image: kibana:8.4.1 + # kibana: + # image: kibana:8.4.1 influxdb: image: influxdb:latest diff --git a/src/Managing.Infrastructure.Database/BotRepository.cs b/src/Managing.Infrastructure.Database/BotRepository.cs index 4147431..2fa3ec7 100644 --- a/src/Managing.Infrastructure.Database/BotRepository.cs +++ b/src/Managing.Infrastructure.Database/BotRepository.cs @@ -1,5 +1,4 @@ -using Managing.Domain.Bots; -using Managing.Infrastructure.Databases.MongoDb; +using Managing.Infrastructure.Databases.MongoDb; using Managing.Infrastructure.Databases.MongoDb.Abstractions; using Managing.Infrastructure.Databases.MongoDb.Collections; @@ -27,7 +26,7 @@ public class BotRepository : IBotRepository public async Task UpdateBackupBot(BotBackup bot) { - var b = _botRepository.FindOne(b => b.Name == bot.Name); + var b = await _botRepository.FindOneAsync(b => b.Name == bot.Name); var dto = MongoMappers.Map(bot); dto.Id = b.Id; _botRepository.Update(dto); diff --git a/src/Managing.WebApp/.env b/src/Managing.WebApp/.env index 0b33460..1f85358 100644 --- a/src/Managing.WebApp/.env +++ b/src/Managing.WebApp/.env @@ -1,4 +1,4 @@ -VITE_API_URL_LOCAL=https://localhost:5001 +VITE_API_URL_LOCAL=https://localhost:443 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 From 7a6d656335ba7606c34629bd88fbfefdc904f0f6 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Wed, 26 Jun 2024 19:15:03 +0700 Subject: [PATCH 04/12] Update script and doc --- assets/Todo-v2.md | 1 + ...docker-deploy-sandbox - Copy.cmd => docker-deploy-local.cmd} | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename scripts/{docker-deploy-sandbox - Copy.cmd => docker-deploy-local.cmd} (84%) diff --git a/assets/Todo-v2.md b/assets/Todo-v2.md index f752975..e6e2068 100644 --- a/assets/Todo-v2.md +++ b/assets/Todo-v2.md @@ -152,6 +152,7 @@ ________________________________________________________________________________ - [ ] Implement from/to tickers array pattern - [ ] Extract all managing trade method into a TradingBox class => Create composable trading bot type easily - [ ] Bot backup worker: Every x, get saved bots and check if still running. If not running call api to reboot bot. +- [ ] Create worker to fetch the biggest spread between long\short funding rate and send alert when most profitable delta neutral position is found # Front-end ## Improve Account page diff --git a/scripts/docker-deploy-sandbox - Copy.cmd b/scripts/docker-deploy-local.cmd similarity index 84% rename from scripts/docker-deploy-sandbox - Copy.cmd rename to scripts/docker-deploy-local.cmd index e554517..cc62723 100644 --- a/scripts/docker-deploy-sandbox - Copy.cmd +++ b/scripts/docker-deploy-local.cmd @@ -2,4 +2,4 @@ cd .. cd .\src\ docker build -t managing.api -f ./Managing.Api/Dockerfile . --no-cache docker build -t managing.api.workers -f ./Managing.Api.Workers/Dockerfile . --no-cache -docker-compose -f ./Managing.Docker/docker-compose.yml -f ./Managing.Docker/docker-compose.sandbox.yml up -d \ No newline at end of file +docker-compose -f ./Managing.Docker/docker-compose.yml -f ./Managing.Docker/docker-compose.local.yml up -d \ No newline at end of file From d96b2a4c3b314602b6574cf0f3e6ec9a888e5899 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 28 Jun 2024 17:26:28 +0700 Subject: [PATCH 05/12] Add bot worker --- src/Managing.Api.Workers/Workers/FeeWorker.cs | 1 + .../Workers/LeaderboardWorker.cs | 3 +- .../Workers/NoobiesboardWorker.cs | 3 +- .../Workers/PositionFetcher.cs | 1 + .../Workers/PositionManagerWorker.cs | 1 + .../Workers/PricesBaseWorker.cs | 3 +- .../Workers/SpotlightWorker.cs | 3 +- .../Workers/TraderWatcher.cs | 1 + src/Managing.Api/Program.cs | 2 + src/Managing.Api/Workers/BotManagerWorker.cs | 32 ++++++++++ .../BaseWorker.cs | 4 +- .../Managing.Application.Workers.csproj | 1 + .../Abstractions/IBotService.cs | 8 ++- .../Bots/Base/BotFactory.cs | 11 +++- src/Managing.Application/Bots/FlippingBot.cs | 2 + src/Managing.Application/Bots/ScalpingBot.cs | 2 + src/Managing.Application/Bots/SimpleBot.cs | 11 +++- src/Managing.Application/Bots/TradingBot.cs | 14 +++-- .../ManageBot/BackupBotCommandHandler.cs | 63 ------------------- .../ManageBot/BotService.cs | 32 +++++----- .../ManageBot/LoadBackupBotCommandHandler.cs | 28 ++++----- src/Managing.Bootstrap/ApiBootstrap.cs | 2 + src/Managing.Domain/Bots/Bot.cs | 3 +- src/Managing.Domain/Bots/IBot.cs | 2 +- 24 files changed, 120 insertions(+), 113 deletions(-) create mode 100644 src/Managing.Api/Workers/BotManagerWorker.cs rename src/{Managing.Api.Workers/Workers => Managing.Application.Workers}/BaseWorker.cs (95%) delete mode 100644 src/Managing.Application/ManageBot/BackupBotCommandHandler.cs diff --git a/src/Managing.Api.Workers/Workers/FeeWorker.cs b/src/Managing.Api.Workers/Workers/FeeWorker.cs index a0aa579..8ea937b 100644 --- a/src/Managing.Api.Workers/Workers/FeeWorker.cs +++ b/src/Managing.Api.Workers/Workers/FeeWorker.cs @@ -1,4 +1,5 @@ using Managing.Application.Abstractions.Services; +using Managing.Application.Workers; using Managing.Application.Workers.Abstractions; using static Managing.Common.Enums; diff --git a/src/Managing.Api.Workers/Workers/LeaderboardWorker.cs b/src/Managing.Api.Workers/Workers/LeaderboardWorker.cs index 96feb0e..f85bf6c 100644 --- a/src/Managing.Api.Workers/Workers/LeaderboardWorker.cs +++ b/src/Managing.Api.Workers/Workers/LeaderboardWorker.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/Workers/NoobiesboardWorker.cs b/src/Managing.Api.Workers/Workers/NoobiesboardWorker.cs index 13aa38a..0ca651a 100644 --- a/src/Managing.Api.Workers/Workers/NoobiesboardWorker.cs +++ b/src/Managing.Api.Workers/Workers/NoobiesboardWorker.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/Workers/PositionFetcher.cs b/src/Managing.Api.Workers/Workers/PositionFetcher.cs index 4e66188..59664d8 100644 --- a/src/Managing.Api.Workers/Workers/PositionFetcher.cs +++ b/src/Managing.Api.Workers/Workers/PositionFetcher.cs @@ -1,5 +1,6 @@ using Managing.Application.Abstractions.Services; using Managing.Application.Hubs; +using Managing.Application.Workers; using Managing.Application.Workers.Abstractions; using Microsoft.AspNetCore.SignalR; using static Managing.Common.Enums; diff --git a/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs b/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs index 61811e5..f9fa8f7 100644 --- a/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs +++ b/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs @@ -1,4 +1,5 @@ using Managing.Application.Abstractions.Services; +using Managing.Application.Workers; using Managing.Application.Workers.Abstractions; using Managing.Domain.Trades; using static Managing.Common.Enums; diff --git a/src/Managing.Api.Workers/Workers/PricesBaseWorker.cs b/src/Managing.Api.Workers/Workers/PricesBaseWorker.cs index d3816e2..c247fca 100644 --- a/src/Managing.Api.Workers/Workers/PricesBaseWorker.cs +++ b/src/Managing.Api.Workers/Workers/PricesBaseWorker.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/Workers/SpotlightWorker.cs b/src/Managing.Api.Workers/Workers/SpotlightWorker.cs index 91e550e..0a23db8 100644 --- a/src/Managing.Api.Workers/Workers/SpotlightWorker.cs +++ b/src/Managing.Api.Workers/Workers/SpotlightWorker.cs @@ -1,4 +1,5 @@ -using Managing.Application.Workers.Abstractions; +using Managing.Application.Workers; +using Managing.Application.Workers.Abstractions; using Managing.Common; namespace Managing.Api.Workers.Workers; diff --git a/src/Managing.Api.Workers/Workers/TraderWatcher.cs b/src/Managing.Api.Workers/Workers/TraderWatcher.cs index 90895a5..b9f2132 100644 --- a/src/Managing.Api.Workers/Workers/TraderWatcher.cs +++ b/src/Managing.Api.Workers/Workers/TraderWatcher.cs @@ -1,4 +1,5 @@ using Managing.Application.Abstractions.Services; +using Managing.Application.Workers; using Managing.Application.Workers.Abstractions; using static Managing.Common.Enums; diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index e01d702..0ad26cd 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -3,6 +3,7 @@ using System.Text.Json.Serialization; using Managing.Api.Authorization; using Managing.Api.Exceptions; using Managing.Api.Filters; +using Managing.Api.Workers; using Managing.Application.Hubs; using Managing.Bootstrap; using Managing.Common; @@ -126,6 +127,7 @@ builder.Services.AddSwaggerGen(options => }); builder.WebHost.SetupDiscordBot(); +builder.Services.AddHostedService(); // App var app = builder.Build(); diff --git a/src/Managing.Api/Workers/BotManagerWorker.cs b/src/Managing.Api/Workers/BotManagerWorker.cs new file mode 100644 index 0000000..8aff11c --- /dev/null +++ b/src/Managing.Api/Workers/BotManagerWorker.cs @@ -0,0 +1,32 @@ +using Managing.Application.ManageBot; +using Managing.Application.Workers; +using Managing.Application.Workers.Abstractions; +using MediatR; +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, + logger, + TimeSpan.FromMinutes(1), + workerService + ) + { + _mediator = tradingService; + } + + protected override async Task Run(CancellationToken cancellationToken) + { + var loadBackupBotCommand = new LoadBackupBotCommand(); + await _mediator.Send(loadBackupBotCommand, cancellationToken); + } +} diff --git a/src/Managing.Api.Workers/Workers/BaseWorker.cs b/src/Managing.Application.Workers/BaseWorker.cs similarity index 95% rename from src/Managing.Api.Workers/Workers/BaseWorker.cs rename to src/Managing.Application.Workers/BaseWorker.cs index cc11430..04856ff 100644 --- a/src/Managing.Api.Workers/Workers/BaseWorker.cs +++ b/src/Managing.Application.Workers/BaseWorker.cs @@ -1,8 +1,10 @@  using Managing.Application.Workers.Abstractions; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using static Managing.Common.Enums; -namespace Managing.Api.Workers; +namespace Managing.Application.Workers; public abstract class BaseWorker : BackgroundService where T : class { diff --git a/src/Managing.Application.Workers/Managing.Application.Workers.csproj b/src/Managing.Application.Workers/Managing.Application.Workers.csproj index 3a4c3ec..dfb4696 100644 --- a/src/Managing.Application.Workers/Managing.Application.Workers.csproj +++ b/src/Managing.Application.Workers/Managing.Application.Workers.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs index 95feed0..bbe668d 100644 --- a/src/Managing.Application/Abstractions/IBotService.cs +++ b/src/Managing.Application/Abstractions/IBotService.cs @@ -1,4 +1,8 @@ - public interface IBotService +using Managing.Application.Bots; +using Managing.Common; + +public interface IBotService { void SaveBotBackup(BotBackup botBackup); - } \ No newline at end of file + void SaveBotBackup(string name, Enums.BotType botType, string data); +} \ No newline at end of file diff --git a/src/Managing.Application/Bots/Base/BotFactory.cs b/src/Managing.Application/Bots/Base/BotFactory.cs index 539f3f5..b8d188d 100644 --- a/src/Managing.Application/Bots/Base/BotFactory.cs +++ b/src/Managing.Application/Bots/Base/BotFactory.cs @@ -16,6 +16,7 @@ namespace Managing.Application.Bots.Base private readonly IAccountService _accountService; private readonly ILogger _tradingBotLogger; private readonly ITradingService _tradingService; + private readonly IBotService _botService; public BotFactory( IExchangeService exchangeService, @@ -23,7 +24,8 @@ namespace Managing.Application.Bots.Base IMoneyManagementService moneyManagementService, IMessengerService messengerService, IAccountService accountService, - ITradingService tradingService) + ITradingService tradingService, + IBotService botService) { _tradingBotLogger = tradingBotLogger; _exchangeService = exchangeService; @@ -31,11 +33,12 @@ namespace Managing.Application.Bots.Base _messengerService = messengerService; _accountService = accountService; _tradingService = tradingService; + _botService = botService; } IBot IBotFactory.CreateSimpleBot(string botName, Workflow workflow) { - return new SimpleBot(botName, _tradingBotLogger, workflow); + return new SimpleBot(botName, _tradingBotLogger, workflow, _botService); } ITradingBot IBotFactory.CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, Ticker ticker, string scenario, Timeframe interval, bool isForWatchingOnly) @@ -52,6 +55,7 @@ namespace Managing.Application.Bots.Base interval, _accountService, _messengerService, + _botService, isForWatchingOnly: isForWatchingOnly); } @@ -69,6 +73,7 @@ namespace Managing.Application.Bots.Base interval, _accountService, _messengerService, + _botService, true, isForWatchingOnly); } @@ -87,6 +92,7 @@ namespace Managing.Application.Bots.Base interval, _accountService, _messengerService, + _botService, isForWatchingOnly: isForWatchingOnly); } @@ -104,6 +110,7 @@ namespace Managing.Application.Bots.Base interval, _accountService, _messengerService, + _botService, true, isForWatchingOnly); } diff --git a/src/Managing.Application/Bots/FlippingBot.cs b/src/Managing.Application/Bots/FlippingBot.cs index 058a910..dfac476 100644 --- a/src/Managing.Application/Bots/FlippingBot.cs +++ b/src/Managing.Application/Bots/FlippingBot.cs @@ -18,6 +18,7 @@ namespace Managing.Application.Bots Timeframe timeframe, IAccountService accountService, IMessengerService messengerService, + IBotService botService, bool isForBacktest = false, bool isForWatchingOnly = false) : base(accountName, @@ -31,6 +32,7 @@ namespace Managing.Application.Bots timeframe, accountService, messengerService, + botService, isForBacktest, isForWatchingOnly, flipPosition: true) diff --git a/src/Managing.Application/Bots/ScalpingBot.cs b/src/Managing.Application/Bots/ScalpingBot.cs index f770c15..1f656cd 100644 --- a/src/Managing.Application/Bots/ScalpingBot.cs +++ b/src/Managing.Application/Bots/ScalpingBot.cs @@ -18,6 +18,7 @@ namespace Managing.Application.Bots Timeframe timeframe, IAccountService accountService, IMessengerService messengerService, + IBotService botService, bool isForBacktest = false, bool isForWatchingOnly = false) : base(accountName, @@ -31,6 +32,7 @@ namespace Managing.Application.Bots timeframe, accountService, messengerService, + botService, isForBacktest, isForWatchingOnly) { diff --git a/src/Managing.Application/Bots/SimpleBot.cs b/src/Managing.Application/Bots/SimpleBot.cs index 8ed092a..041a5f0 100644 --- a/src/Managing.Application/Bots/SimpleBot.cs +++ b/src/Managing.Application/Bots/SimpleBot.cs @@ -2,17 +2,20 @@ using Managing.Domain.Workflows; using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using static Managing.Common.Enums; namespace Managing.Application.Bots { public class SimpleBot : Bot { public readonly ILogger Logger; + private readonly IBotService _botService; private Workflow _workflow; - public SimpleBot(string name, ILogger logger, Workflow workflow) : base(name) + public SimpleBot(string name, ILogger logger, Workflow workflow, IBotService botService) : base(name) { Logger = logger; + _botService = botService; _workflow = workflow; Interval = 100; Start(); @@ -33,13 +36,15 @@ namespace Managing.Application.Bots Logger.LogInformation(Identifier); Logger.LogInformation(DateTime.Now.ToString()); await _workflow.Execute(); + SaveBackup(); Logger.LogInformation("__________________________________________________"); }); } - public override string GetBackup() + public override void SaveBackup() { - return JsonConvert.SerializeObject(_workflow); + var data = JsonConvert.SerializeObject(_workflow); + _botService.SaveBotBackup(Name, BotType.SimpleBot, data); } public override void LoadBackup(BotBackup backup) diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 3923fc8..e774e0a 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -23,6 +23,7 @@ public class TradingBot : Bot, ITradingBot public readonly IMessengerService MessengerService; public readonly IAccountService AccountService; private readonly ITradingService TradingService; + private readonly IBotService BotService; public Account Account { get; set; } public HashSet Strategies { get; set; } @@ -55,6 +56,7 @@ public class TradingBot : Bot, ITradingBot Timeframe timeframe, IAccountService accountService, IMessengerService messengerService, + IBotService botService, bool isForBacktest = false, bool isForWatchingOnly = false, bool flipPosition = false) @@ -64,7 +66,7 @@ public class TradingBot : Bot, ITradingBot AccountService = accountService; MessengerService = messengerService; TradingService = tradingService; - + BotService = botService; IsForWatchingOnly = isForWatchingOnly; FlipPosition = flipPosition; @@ -168,6 +170,9 @@ public class TradingBot : Bot, ITradingBot if (!IsForWatchingOnly) await ManagePositions(); + if (!IsForBacktest) + SaveBackup(); + await UpdateWalletBalances(); Logger.LogInformation($"Candles : {Candles.Count}"); Logger.LogInformation($"Signals : {Signals.Count}"); @@ -659,9 +664,9 @@ public class TradingBot : Bot, ITradingBot } } - public override string GetBackup() + public override void SaveBackup() { - return JsonConvert.SerializeObject(new TradingBotBackup + var data = new TradingBotBackup { Name = Name, BotType = BotType, @@ -675,7 +680,8 @@ public class TradingBot : Bot, ITradingBot IsForWatchingOnly = IsForWatchingOnly, WalletBalances = WalletBalances, MoneyManagement = MoneyManagement - }); + }; + BotService.SaveBotBackup(Name, BotType, JsonConvert.SerializeObject(data)); } public override void LoadBackup(BotBackup backup) diff --git a/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs deleted file mode 100644 index 98c4690..0000000 --- a/src/Managing.Application/ManageBot/BackupBotCommandHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Managing.Domain.Bots; -using MediatR; -using static Managing.Common.Enums; -using Managing.Application.Abstractions; - -namespace Managing.Application.ManageBot -{ - public class BackupBotCommandHandler : IRequestHandler - { - private readonly ITaskCache _taskCache; - private readonly IBotService _botService; - - public BackupBotCommandHandler(ITaskCache taskCache, IBotService botService) - { - _taskCache = taskCache; - _botService = botService; - } - - public Task Handle(BackupBotCommand request, CancellationToken cancellationToken) - { - var botBackup = new BotBackup - { - Name = request.Name, - BotType = request.BotType, - Data = "" - }; - - switch (request.BotType) - { - case BotType.SimpleBot: - var simpleBot = _taskCache.Get(request.Name); - botBackup.Data = simpleBot.GetBackup(); - break; - case BotType.ScalpingBot: - var scalpingBot = _taskCache.Get(request.Name); - botBackup.Data = scalpingBot.GetBackup(); - break; - case BotType.FlippingBot: - var flippingBot = _taskCache.Get(request.Name); - botBackup.Data = flippingBot.GetBackup(); - break; - default: - return Task.FromResult(false); - } - - _botService.SaveBotBackup(botBackup); - - return Task.FromResult(true); - } - } - - public class BackupBotCommand : IRequest - { - public string Name { get; } - public BotType BotType { get; } - - public BackupBotCommand(BotType botType, string name) - { - BotType = botType; - Name = name; - } - } -} diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index e5a0b6c..aaca3d4 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -1,35 +1,33 @@ using Managing.Application.Abstractions; +using Managing.Application.Bots; +using Managing.Common; namespace Managing.Application.ManageBot { public class BotService : IBotService { - private readonly IBotFactory _botFactory; private readonly IBotRepository _botRepository; - public BotService(IBotFactory botFactory, IBotRepository botRepository) + public BotService(IBotRepository botRepository) { - _botFactory = botFactory; _botRepository = botRepository; } - // public void CreateBot() - // { - // // Use the factory to create a new bot - // return _botFactory.CreateBot(); - // } - - // public void LoadBotBackup(BotBackup botBackup) - // { - // // Deserialize the JSON into a Bot object - // var bot = JsonConvert.DeserializeObject(json); - - // return bot; - // } - public async void SaveBotBackup(BotBackup botBackup) { await _botRepository.InsertBotAsync(botBackup); } + + public void SaveBotBackup(string name, Enums.BotType botType, string data) + { + var botBackup = new BotBackup + { + Name = name, + BotType = botType, + Data = data + }; + + _botRepository.InsertBotAsync(botBackup); + } } } \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs index b6c734c..0d20f21 100644 --- a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -3,9 +3,9 @@ using MediatR; using static Managing.Common.Enums; using Managing.Application.Abstractions; using Managing.Core; -using Managing.Domain.MoneyManagements; using Newtonsoft.Json; using Managing.Application.Bots; +using Microsoft.Extensions.Logging; namespace Managing.Application.ManageBot { @@ -15,20 +15,18 @@ namespace Managing.Application.ManageBot private readonly ITaskCache _taskCache; private readonly IMoneyManagementService _moneyManagementService; private readonly IBotRepository _botRepository; - private readonly IMediator _mediator; + private readonly ILogger _logger; public LoadBackupBotCommandHandler( IBotFactory botFactory, ITaskCache taskCache, IMoneyManagementService moneyManagementService, - IBotRepository botRepository, - IMediator mediator) + IBotRepository botRepository) { _botFactory = botFactory; _taskCache = taskCache; _moneyManagementService = moneyManagementService; _botRepository = botRepository; - _mediator = mediator; } public Task Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) @@ -37,6 +35,8 @@ namespace Managing.Application.ManageBot 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 @@ -46,7 +46,8 @@ namespace Managing.Application.ManageBot var simpleBot = _taskCache.Get(backupBot.Name); if (simpleBot == null) { - StartBot(request, backupBot); + _logger.LogInformation($"Starting backup bot {backupBot.Name}"); + StartBot(backupBot); simpleBot.LoadBackup(backupBot); result.Add(simpleBot.GetName(), BotStatus.Backup); } @@ -61,7 +62,8 @@ namespace Managing.Application.ManageBot var scalpingBot = _taskCache.Get(backupBot.Name); if (scalpingBot == null) { - StartBot(request, backupBot); + _logger.LogInformation($"Starting backup bot {backupBot.Name}"); + StartBot(backupBot); scalpingBot.LoadBackup(backupBot); result.Add(scalpingBot.GetName(), BotStatus.Backup); } @@ -80,13 +82,13 @@ namespace Managing.Application.ManageBot return Task.FromResult(botStatus.ToString()); } - private void StartBot(LoadBackupBotCommand request, BotBackup backupBot) + private void StartBot(BotBackup backupBot) { switch (backupBot.BotType) { case BotType.SimpleBot: - Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(request.Name, null)); - var bot1 = _taskCache.AddOrGetExisting(request.Name, simpleBot).Result; + Func> simpleBot = () => Task.FromResult(_botFactory.CreateSimpleBot(backupBot.Name, null)); + var bot1 = _taskCache.AddOrGetExisting(backupBot.Name, simpleBot).Result; bot1.LoadBackup(backupBot); break; case BotType.ScalpingBot: @@ -99,7 +101,7 @@ namespace Managing.Application.ManageBot data.Scenario, data.Timeframe, data.IsForWatchingOnly)); - var bot2 = _taskCache.AddOrGetExisting(request.Name, scalpingBot).Result; + var bot2 = _taskCache.AddOrGetExisting(backupBot.Name, scalpingBot).Result; bot2.LoadBackup(backupBot); break; case BotType.FlippingBot: @@ -112,7 +114,7 @@ namespace Managing.Application.ManageBot dataFlippingBot.Scenario, dataFlippingBot.Timeframe, dataFlippingBot.IsForWatchingOnly)); - var bot3 = _taskCache.AddOrGetExisting(request.Name, flippingBot).Result; + var bot3 = _taskCache.AddOrGetExisting(backupBot.Name, flippingBot).Result; bot3.LoadBackup(backupBot); break; }; @@ -121,7 +123,5 @@ namespace Managing.Application.ManageBot public class LoadBackupBotCommand : IRequest { - public string Name { get; internal set; } - public string AccountName { get; internal set; } } } diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs index 0dfbc24..f48ae78 100644 --- a/src/Managing.Bootstrap/ApiBootstrap.cs +++ b/src/Managing.Bootstrap/ApiBootstrap.cs @@ -107,6 +107,7 @@ public static class ApiBootstrap services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // Cache services.AddDistributedMemoryCache(); @@ -126,6 +127,7 @@ public static class ApiBootstrap services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // Stream services.AddSingleton(); diff --git a/src/Managing.Domain/Bots/Bot.cs b/src/Managing.Domain/Bots/Bot.cs index 7e3959d..ff7b7bb 100644 --- a/src/Managing.Domain/Bots/Bot.cs +++ b/src/Managing.Domain/Bots/Bot.cs @@ -15,7 +15,6 @@ namespace Managing.Domain.Bots public int Interval { get; set; } public BotStatus Status { get; set; } private CancellationTokenSource CancellationToken { get; set; } - public string Data { get; set; } public Bot(string name) { @@ -74,7 +73,7 @@ namespace Managing.Domain.Bots return Name; } - public abstract string GetBackup(); + public abstract void SaveBackup(); public abstract void LoadBackup(BotBackup backup); } } \ No newline at end of file diff --git a/src/Managing.Domain/Bots/IBot.cs b/src/Managing.Domain/Bots/IBot.cs index 9c2c30f..95a240e 100644 --- a/src/Managing.Domain/Bots/IBot.cs +++ b/src/Managing.Domain/Bots/IBot.cs @@ -8,7 +8,7 @@ void Restart(); string GetStatus(); string GetName(); - string GetBackup(); + void SaveBackup(); void LoadBackup(BotBackup backup); } } From 13e70cbf6399ec91e22d52fb5578074dc2a2fc9f Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 06:51:29 +0700 Subject: [PATCH 06/12] Loading backup --- .../Workers/TopVolumeTickerWorker.cs | 3 +- src/Managing.Api/Workers/BotManagerWorker.cs | 25 +-- src/Managing.Api/appsettings.Oda.json | 4 +- src/Managing.Application.Tests/BotsTests.cs | 4 +- src/Managing.Application/Bots/FlippingBot.cs | 1 - src/Managing.Application/Bots/ScalpingBot.cs | 1 - src/Managing.Application/Bots/SimpleBot.cs | 1 - src/Managing.Application/Bots/TradingBot.cs | 3 - .../ManageBot/BotService.cs | 14 ++ .../ManageBot/LoadBackupBotCommandHandler.cs | 150 ++++++++++-------- .../ManageBot/StartBotCommandHandler.cs | 12 +- src/Managing.Bootstrap/ApiBootstrap.cs | 2 +- src/Managing.Bootstrap/WorkersBootstrap.cs | 3 + src/Managing.Common/Enums.cs | 3 +- .../TaskCache.cs | 3 +- src/Managing.WebApp/.env | 2 +- 16 files changed, 128 insertions(+), 103 deletions(-) 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 From 0544749a6975258204df24709aa6d0afff5db421 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 19:58:19 +0700 Subject: [PATCH 07/12] Commit before refact factory into service --- src/Managing.Application.Tests/BotsTests.cs | 1 - .../Abstractions/IBotService.cs | 31 ++++- .../Bots/Base/BotFactory.cs | 3 - src/Managing.Application/Bots/FlippingBot.cs | 33 ++--- src/Managing.Application/Bots/ScalpingBot.cs | 3 +- src/Managing.Application/Bots/SimpleBot.cs | 8 +- src/Managing.Application/Bots/TradingBot.cs | 120 ++++++++++++------ .../ManageBot/BotService.cs | 83 +++++++++++- .../ManageBot/GetActiveBotsCommandHandler.cs | 23 +--- .../ManageBot/LoadBackupBotCommandHandler.cs | 76 ++--------- .../ManageBot/StartBotCommandHandler.cs | 31 +++-- 11 files changed, 243 insertions(+), 169 deletions(-) diff --git a/src/Managing.Application.Tests/BotsTests.cs b/src/Managing.Application.Tests/BotsTests.cs index 31d1cef..e95c049 100644 --- a/src/Managing.Application.Tests/BotsTests.cs +++ b/src/Managing.Application.Tests/BotsTests.cs @@ -32,7 +32,6 @@ namespace Managing.Application.Tests _botFactory = new BotFactory( _exchangeService, tradingBotLogger, - _moneyManagementService.Object, discordService, _accountService.Object, _tradingService.Object, diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs index bbe668d..b0aef5c 100644 --- a/src/Managing.Application/Abstractions/IBotService.cs +++ b/src/Managing.Application/Abstractions/IBotService.cs @@ -1,8 +1,31 @@ -using Managing.Application.Bots; using Managing.Common; +using Managing.Domain.Bots; +using Managing.Domain.MoneyManagements; +using Managing.Domain.Workflows; + +namespace Managing.Application.Abstractions; public interface IBotService - { - void SaveBotBackup(BotBackup botBackup); - void SaveBotBackup(string name, Enums.BotType botType, string data); +{ + void SaveBotBackup(BotBackup botBackup); + void SaveBotBackup(string name, Enums.BotType botType, string data); + void AddSimpleBotToCache(IBot bot); + void AddTradingBotToCache(ITradingBot bot); + List GetActiveBots(); + IEnumerable GetSavedBots(); + void StartBot(BotBackup backupBot); + + ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, + string scenario, Enums.Timeframe interval, bool isForWatchingOnly); + + ITradingBot CreateBacktestScalpingBot(string accountName, MoneyManagement moneyManagement, Enums.Ticker ticker, + string scenario, Enums.Timeframe interval, bool isForWatchingOnly); + + ITradingBot CreateFlippingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, + string scenario, Enums.Timeframe interval, bool isForWatchingOnly); + + ITradingBot CreateBacktestFlippingBot(string accountName, MoneyManagement moneyManagement, Enums.Ticker ticker, + string scenario, Enums.Timeframe interval, bool isForWatchingOnly); + + IBot CreateSimpleBot(string botName, Workflow workflow); } \ No newline at end of file diff --git a/src/Managing.Application/Bots/Base/BotFactory.cs b/src/Managing.Application/Bots/Base/BotFactory.cs index b8d188d..ea49f14 100644 --- a/src/Managing.Application/Bots/Base/BotFactory.cs +++ b/src/Managing.Application/Bots/Base/BotFactory.cs @@ -10,7 +10,6 @@ namespace Managing.Application.Bots.Base { public class BotFactory : IBotFactory { - private readonly IMoneyManagementService _moneyManagementService; private readonly IExchangeService _exchangeService; private readonly IMessengerService _messengerService; private readonly IAccountService _accountService; @@ -21,7 +20,6 @@ namespace Managing.Application.Bots.Base public BotFactory( IExchangeService exchangeService, ILogger tradingBotLogger, - IMoneyManagementService moneyManagementService, IMessengerService messengerService, IAccountService accountService, ITradingService tradingService, @@ -29,7 +27,6 @@ namespace Managing.Application.Bots.Base { _tradingBotLogger = tradingBotLogger; _exchangeService = exchangeService; - _moneyManagementService = moneyManagementService; _messengerService = messengerService; _accountService = accountService; _tradingService = tradingService; diff --git a/src/Managing.Application/Bots/FlippingBot.cs b/src/Managing.Application/Bots/FlippingBot.cs index 86ea4d8..9bf2270 100644 --- a/src/Managing.Application/Bots/FlippingBot.cs +++ b/src/Managing.Application/Bots/FlippingBot.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Managing.Application.Abstractions; +using Microsoft.Extensions.Logging; using static Managing.Common.Enums; using Managing.Application.Abstractions.Services; using Managing.Domain.MoneyManagements; @@ -22,20 +23,20 @@ namespace Managing.Application.Bots bool isForBacktest = false, bool isForWatchingOnly = false) : base(accountName, - moneyManagement, - name, - ticker, - scenario, - exchangeService, - logger, - tradingService, - timeframe, - accountService, - messengerService, - botService, - isForBacktest, - isForWatchingOnly, - flipPosition: true) + moneyManagement, + name, + ticker, + scenario, + exchangeService, + logger, + tradingService, + timeframe, + accountService, + messengerService, + botService, + isForBacktest, + isForWatchingOnly, + flipPosition: true) { BotType = BotType.FlippingBot; } @@ -47,4 +48,4 @@ namespace Managing.Application.Bots Logger.LogInformation($"Starting {Name} bot - Status : {Status}"); } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Bots/ScalpingBot.cs b/src/Managing.Application/Bots/ScalpingBot.cs index d45bb3d..f69c336 100644 --- a/src/Managing.Application/Bots/ScalpingBot.cs +++ b/src/Managing.Application/Bots/ScalpingBot.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Managing.Application.Abstractions; +using Microsoft.Extensions.Logging; using static Managing.Common.Enums; using Managing.Application.Abstractions.Services; using Managing.Domain.MoneyManagements; diff --git a/src/Managing.Application/Bots/SimpleBot.cs b/src/Managing.Application/Bots/SimpleBot.cs index ce29c28..c22f3d4 100644 --- a/src/Managing.Application/Bots/SimpleBot.cs +++ b/src/Managing.Application/Bots/SimpleBot.cs @@ -1,4 +1,5 @@ -using Managing.Domain.Bots; +using Managing.Application.Abstractions; +using Managing.Domain.Bots; using Managing.Domain.Workflows; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -12,7 +13,8 @@ namespace Managing.Application.Bots private readonly IBotService _botService; private Workflow _workflow; - public SimpleBot(string name, ILogger logger, Workflow workflow, IBotService botService) : base(name) + public SimpleBot(string name, ILogger logger, Workflow workflow, IBotService botService) : + base(name) { Logger = logger; _botService = botService; @@ -51,4 +53,4 @@ namespace Managing.Application.Bots _workflow = JsonConvert.DeserializeObject(backup.Data); } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 490cca7..0a380e9 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -103,13 +103,15 @@ public class TradingBot : Bot, ITradingBot await CancelAllOrders(); try - { - await MessengerService.SendMessage($"Hi everyone, I'm going to run {Name}. \nI will send a message here everytime a signal is triggered by the {string.Join(",", Strategies.Select(s => s.Name))} strategies."); + { + await MessengerService.SendMessage( + $"Hi everyone, I'm going to run {Name}. \nI will send a message here everytime a signal is triggered by the {string.Join(",", Strategies.Select(s => s.Name))} strategies."); } catch (Exception ex) { Logger.LogError(ex, ex.Message); } + await InitWorker(Run); } @@ -155,7 +157,8 @@ public class TradingBot : Bot, ITradingBot public async Task Run() { Logger.LogInformation($"____________________{Name}____________________"); - Logger.LogInformation($"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}"); + Logger.LogInformation( + $"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}"); var previousCandleCount = Candles.Count; @@ -183,6 +186,9 @@ public class TradingBot : Bot, ITradingBot private async Task PreloadCandles() { + if (Candles.Any()) + return; + var candles = await ExchangeService.GetCandlesInflux(Account.Exchange, Ticker, PreloadSince, Timeframe); foreach (var candle in candles.Where(c => c.Date < DateTime.Now.ToUniversalTime())) @@ -218,7 +224,7 @@ public class TradingBot : Bot, ITradingBot signal.Status = SignalStatus.Expired; var signalText = $"{Scenario} trigger a signal. Signal told you " + - $"to {signal.Direction} {Ticker} on {Timeframe}. The confidence in this signal is {signal.Confidence}. Identifier : {signal.Identifier}"; + $"to {signal.Direction} {Ticker} on {Timeframe}. The confidence in this signal is {signal.Confidence}. Identifier : {signal.Identifier}"; Logger.LogInformation(signalText); @@ -280,7 +286,9 @@ public class TradingBot : Bot, ITradingBot { Logger.LogInformation($"Updating position {positionForSignal.SignalIdentifier}"); - var position = IsForBacktest ? positionForSignal : TradingService.GetPositionByIdentifier(positionForSignal.Identifier); + var position = IsForBacktest + ? positionForSignal + : TradingService.GetPositionByIdentifier(positionForSignal.Identifier); if (position.Status == (PositionStatus.Finished | PositionStatus.Flipped)) { @@ -292,32 +300,41 @@ public class TradingBot : Bot, ITradingBot // For backtesting or force close if not executed on exchange : // check if position is still open // Check status, if still open update the status of the position - var lastCandle = IsForBacktest ? Candles.Last() : ExchangeService.GetCandle(Account, Ticker, DateTime.UtcNow); + var lastCandle = IsForBacktest + ? Candles.Last() + : ExchangeService.GetCandle(Account, Ticker, DateTime.UtcNow); if (positionForSignal.OriginDirection == TradeDirection.Long) { if (positionForSignal.StopLoss.Price >= lastCandle.Low) { - await LogInformation($"Closing position - SL {positionForSignal.StopLoss.Price} >= Price {lastCandle.Low}"); - await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss, positionForSignal.StopLoss.Price, true); + await LogInformation( + $"Closing position - SL {positionForSignal.StopLoss.Price} >= Price {lastCandle.Low}"); + await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss, + positionForSignal.StopLoss.Price, true); positionForSignal.StopLoss.SetStatus(TradeStatus.Filled); } else if (positionForSignal.TakeProfit1.Price <= lastCandle.High - && positionForSignal.TakeProfit1.Status != TradeStatus.Filled) + && positionForSignal.TakeProfit1.Status != TradeStatus.Filled) { - await LogInformation($"Closing position - TP1 {positionForSignal.TakeProfit1.Price} <= Price {lastCandle.High}"); - await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1, positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null); + await LogInformation( + $"Closing position - TP1 {positionForSignal.TakeProfit1.Price} <= Price {lastCandle.High}"); + await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1, + positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null); positionForSignal.TakeProfit1.SetStatus(TradeStatus.Filled); } else if (positionForSignal.TakeProfit2?.Price <= lastCandle.High) { - await LogInformation($"Closing position - TP2 {positionForSignal.TakeProfit2.Price} <= Price {lastCandle.High}"); - await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2, positionForSignal.TakeProfit2.Price, true); + await LogInformation( + $"Closing position - TP2 {positionForSignal.TakeProfit2.Price} <= Price {lastCandle.High}"); + await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2, + positionForSignal.TakeProfit2.Price, true); positionForSignal.TakeProfit2.SetStatus(TradeStatus.Filled); } else { - Logger.LogInformation($"Position {signal.Identifier} don't need to be update. Position still opened"); + Logger.LogInformation( + $"Position {signal.Identifier} don't need to be update. Position still opened"); } } @@ -325,26 +342,33 @@ public class TradingBot : Bot, ITradingBot { if (positionForSignal.StopLoss.Price <= lastCandle.High) { - await LogInformation($"Closing position - SL {positionForSignal.StopLoss.Price} <= Price {lastCandle.High}"); - await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss, positionForSignal.StopLoss.Price, true); + await LogInformation( + $"Closing position - SL {positionForSignal.StopLoss.Price} <= Price {lastCandle.High}"); + await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss, + positionForSignal.StopLoss.Price, true); positionForSignal.StopLoss.SetStatus(TradeStatus.Filled); } else if (positionForSignal.TakeProfit1.Price >= lastCandle.Low - && positionForSignal.TakeProfit1.Status != TradeStatus.Filled) + && positionForSignal.TakeProfit1.Status != TradeStatus.Filled) { - await LogInformation($"Closing position - TP1 {positionForSignal.TakeProfit1.Price} >= Price {lastCandle.Low}"); - await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1, positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null); + await LogInformation( + $"Closing position - TP1 {positionForSignal.TakeProfit1.Price} >= Price {lastCandle.Low}"); + await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1, + positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null); positionForSignal.TakeProfit1.SetStatus(TradeStatus.Filled); } else if (positionForSignal.TakeProfit2?.Price >= lastCandle.Low) { - await LogInformation($"Closing position - TP2 {positionForSignal.TakeProfit2.Price} >= Price {lastCandle.Low}"); - await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2, positionForSignal.TakeProfit2.Price, true); + await LogInformation( + $"Closing position - TP2 {positionForSignal.TakeProfit2.Price} >= Price {lastCandle.Low}"); + await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2, + positionForSignal.TakeProfit2.Price, true); positionForSignal.TakeProfit2.SetStatus(TradeStatus.Filled); } else { - Logger.LogInformation($"Position {signal.Identifier} don't need to be update. Position still opened"); + Logger.LogInformation( + $"Position {signal.Identifier} don't need to be update. Position still opened"); } } } @@ -368,16 +392,17 @@ public class TradingBot : Bot, ITradingBot } - private async Task OpenPosition(Signal signal) { // Check if a position is already open Logger.LogInformation($"Opening position for {signal.Identifier}"); var openedPosition = Positions.FirstOrDefault(p => p.Status == PositionStatus.Filled - && p.SignalIdentifier != signal.Identifier); + && p.SignalIdentifier != signal.Identifier); - var lastPrice = IsForBacktest ? Candles.Last().Close : ExchangeService.GetPrice(Account, Ticker, DateTime.UtcNow); + var lastPrice = IsForBacktest + ? Candles.Last().Close + : ExchangeService.GetPrice(Account, Ticker, DateTime.UtcNow); // If position open if (openedPosition != null) @@ -388,7 +413,8 @@ public class TradingBot : Bot, ITradingBot if (openedPosition.OriginDirection == signal.Direction) { // An operation is already open for the same direction - await LogInformation($"Signal {signal.Identifier} try to open a position but {previousSignal.Identifier} is already open for the same direction"); + await LogInformation( + $"Signal {signal.Identifier} try to open a position but {previousSignal.Identifier} is already open for the same direction"); SetSignalStatus(signal.Identifier, SignalStatus.Expired); } else @@ -401,11 +427,13 @@ public class TradingBot : Bot, ITradingBot await CloseTrade(previousSignal, openedPosition, openedPosition.Open, lastPrice, true); await SetPositionStatus(previousSignal.Identifier, PositionStatus.Flipped); await OpenPosition(signal); - await LogInformation($"Position {previousSignal.Identifier} flipped by {signal.Identifier} at {lastPrice}$"); + await LogInformation( + $"Position {previousSignal.Identifier} flipped by {signal.Identifier} at {lastPrice}$"); } else { - await LogWarning($"A position is already open for signal {previousSignal.Identifier}. Position flipping is currently not enable, the position will not be flipped."); + await LogWarning( + $"A position is already open for signal {previousSignal.Identifier}. Position flipping is currently not enable, the position will not be flipped."); SetSignalStatus(signal.Identifier, SignalStatus.Expired); } } @@ -414,12 +442,14 @@ public class TradingBot : Bot, ITradingBot { if (!CanOpenPosition(signal)) { - await LogInformation("Tried to open position but last position was a loss. Wait for an opposition direction side or wait x candles to open a new position"); + await LogInformation( + "Tried to open position but last position was a loss. Wait for an opposition direction side or wait x candles to open a new position"); SetSignalStatus(signal.Identifier, SignalStatus.Expired); return; } - await LogInformation($"Open position - Date: {signal.Date:T} - SignalIdentifier : {signal.Identifier} - Strategie : {signal.StrategyType}"); + await LogInformation( + $"Open position - Date: {signal.Date:T} - SignalIdentifier : {signal.Identifier} - Strategie : {signal.StrategyType}"); try { @@ -474,9 +504,9 @@ public class TradingBot : Bot, ITradingBot return true; var lastPosition = Positions.LastOrDefault(p => p.IsFinished() - && p.SignalIdentifier != signal.Identifier - && p.ProfitAndLoss.Realized < 0 - && p.OriginDirection == signal.Direction); + && p.SignalIdentifier != signal.Identifier + && p.ProfitAndLoss.Realized < 0 + && p.OriginDirection == signal.Direction); if (lastPosition == null) return true; @@ -487,15 +517,18 @@ public class TradingBot : Bot, ITradingBot return positionSignal.Date < tenCandleAgo.Date; } - private async Task CloseTrade(Signal signal, Position position, Trade tradeToClose, decimal lastPrice, bool tradeClosingPosition = false) + private async Task CloseTrade(Signal signal, Position position, Trade tradeToClose, decimal lastPrice, + bool tradeClosingPosition = false) { - if (position.TakeProfit2 != null && position.TakeProfit1.Status == TradeStatus.Filled && tradeToClose.TradeType == TradeType.StopMarket) + if (position.TakeProfit2 != null && position.TakeProfit1.Status == TradeStatus.Filled && + tradeToClose.TradeType == TradeType.StopMarket) { // If trade is the 2nd Take profit tradeToClose.Quantity = position.TakeProfit2.Quantity; } - await LogInformation($"Trying to close trade {Ticker} at {lastPrice} - Type : {tradeToClose.TradeType} - Quantity : {tradeToClose.Quantity} " + + await LogInformation( + $"Trying to close trade {Ticker} at {lastPrice} - Type : {tradeToClose.TradeType} - Quantity : {tradeToClose.Quantity} " + $"- Closing Position : {tradeClosingPosition}"); // Get status of position before closing it. The position might be already close by the exchange @@ -509,8 +542,9 @@ public class TradingBot : Bot, ITradingBot var command = new ClosePositionCommand(position, lastPrice); try { - var closedPosition = await (new ClosePositionCommandHandler(ExchangeService, AccountService, TradingService)) - .Handle(command); + var closedPosition = + await (new ClosePositionCommandHandler(ExchangeService, AccountService, TradingService)) + .Handle(command); if (closedPosition.Status == (PositionStatus.Finished | PositionStatus.Flipped)) { @@ -536,7 +570,6 @@ public class TradingBot : Bot, ITradingBot await SetPositionStatus(signal.Identifier, PositionStatus.Finished); } } - } } @@ -549,7 +582,8 @@ public class TradingBot : Bot, ITradingBot position.SignalIdentifier = previousPosition.SignalIdentifier; Positions[positionIndex] = position; SetSignalStatus(position.SignalIdentifier, SignalStatus.Expired); - Logger.LogInformation($"Position {position.SignalIdentifier} type correctly close. Pnl on position : {position.ProfitAndLoss.Realized}"); + Logger.LogInformation( + $"Position {position.SignalIdentifier} type correctly close. Pnl on position : {position.ProfitAndLoss.Realized}"); } else { @@ -689,6 +723,12 @@ public class TradingBot : Bot, ITradingBot Signals = data.Signals; Positions = data.Positions; WalletBalances = data.WalletBalances; + MoneyManagement = data.MoneyManagement; + Timeframe = data.Timeframe; + Ticker = data.Ticker; + Scenario = data.Scenario; + AccountName = data.AccountName; + IsForWatchingOnly = data.IsForWatchingOnly; } } diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 2ab39a0..8f72196 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -1,23 +1,31 @@ using Managing.Application.Abstractions; using Managing.Application.Bots; using Managing.Common; +using Managing.Core; +using Managing.Domain.Bots; +using Newtonsoft.Json; namespace Managing.Application.ManageBot { public class BotService : IBotService { private readonly IBotRepository _botRepository; + private readonly ITaskCache _taskCache; + private readonly IBotFactory _botFactory; + - public BotService(IBotRepository botRepository) + public BotService(IBotRepository botRepository, ITaskCache taskCache, IBotFactory botFactory) { _botRepository = botRepository; + _taskCache = taskCache; + _botFactory = botFactory; } public async void SaveBotBackup(BotBackup botBackup) { - await _botRepository.InsertBotAsync(botBackup); + await _botRepository.InsertBotAsync(botBackup); } - + public BotBackup GetBotBackup(string name) { return _botRepository.GetBots().FirstOrDefault(b => b.Name == name); @@ -26,14 +34,14 @@ namespace Managing.Application.ManageBot 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, @@ -43,5 +51,70 @@ namespace Managing.Application.ManageBot _botRepository.InsertBotAsync(botBackup); } + + public void AddSimpleBotToCache(IBot bot) + { + _taskCache.AddOrGetExisting(bot.GetName(), () => Task.FromResult(bot)); + } + + public void AddTradingBotToCache(ITradingBot bot) + { + _taskCache.AddOrGetExisting(bot.GetName(), () => Task.FromResult(bot)); + } + + public List GetActiveBots() + { + var cachedTask = _taskCache.GetCache>(); + return cachedTask.Select(item => item.Value.Result).ToList(); + } + + public IEnumerable GetSavedBots() + { + return _botRepository.GetBots(); + } + + public void StartBot(BotBackup backupBot) + { + switch (backupBot.BotType) + { + case Enums.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 Enums.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 Enums.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; + } + + ; + } } } \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/GetActiveBotsCommandHandler.cs b/src/Managing.Application/ManageBot/GetActiveBotsCommandHandler.cs index 4ee8e46..930049e 100644 --- a/src/Managing.Application/ManageBot/GetActiveBotsCommandHandler.cs +++ b/src/Managing.Application/ManageBot/GetActiveBotsCommandHandler.cs @@ -1,30 +1,15 @@ using Managing.Application.Abstractions; using Managing.Application.ManageBot.Commands; -using Managing.Core; using MediatR; namespace Managing.Application.ManageBot { - public class GetActiveBotsCommandHandler : IRequestHandler> + public class GetActiveBotsCommandHandler(IBotService botService) + : IRequestHandler> { - private readonly ITaskCache taskCache; - - public GetActiveBotsCommandHandler(ITaskCache taskCache) - { - this.taskCache = taskCache; - } - public Task> Handle(GetActiveBotsCommand request, CancellationToken cancellationToken) { - var cachedTask = taskCache.GetCache>(); - var result = new List(); - - foreach (var item in cachedTask) - { - result.Add(item.Value.Result); - } - - return Task.FromResult(result); + return Task.FromResult(botService.GetActiveBots()); } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs index ae0e302..b738834 100644 --- a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -11,30 +11,21 @@ namespace Managing.Application.ManageBot; public class LoadBackupBotCommandHandler : IRequestHandler { - private readonly IBotFactory _botFactory; - private readonly ITaskCache _taskCache; - private readonly IMoneyManagementService _moneyManagementService; - private readonly IBotRepository _botRepository; + private readonly IBotService _botService; private readonly ILogger _logger; public LoadBackupBotCommandHandler( - IBotFactory botFactory, - ITaskCache taskCache, - IMoneyManagementService moneyManagementService, - IBotRepository botRepository, - ILogger logger) + ILogger logger, IBotService botService) { - _botFactory = botFactory; - _taskCache = taskCache; - _moneyManagementService = moneyManagementService; - _botRepository = botRepository; _logger = logger; + _botService = botService; } public Task Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) { BotStatus botStatus = BotStatus.Down; - var backupBots = _botRepository.GetBots(); + var backupBots = _botService.GetSavedBots(); + var activeBots = _botService.GetActiveBots(); var result = new Dictionary(); _logger.LogInformation($"Loading {backupBots.Count()} backup bots"); @@ -47,12 +38,11 @@ public class LoadBackupBotCommandHandler : IRequestHandler(backupBot.Name); + var simpleBot = activeBots.FirstOrDefault(b => b.GetName() == backupBot.Name); if (simpleBot == null) { _logger.LogInformation($"Starting backup bot {backupBot.Name}"); - StartBot(backupBot); - simpleBot.LoadBackup(backupBot); + _botService.StartBot(backupBot); result.Add(simpleBot.GetName(), BotStatus.Backup); } else @@ -63,19 +53,18 @@ public class LoadBackupBotCommandHandler : IRequestHandler(backupBot.Name); + var scalpingBot = activeBots.FirstOrDefault(b => b.GetName() == backupBot.Name); if (scalpingBot == null) { _logger.LogInformation($"Starting backup bot {backupBot.Name}"); - StartBot(backupBot); - scalpingBot = _taskCache.Get(backupBot.Name); - scalpingBot.LoadBackup(backupBot); - result.Add(scalpingBot.GetName(), BotStatus.Backup); + _botService.StartBot(backupBot); } else { - result.Add(scalpingBot.GetName(), MiscExtensions.ParseEnum(scalpingBot.GetStatus())); + result.Add(scalpingBot.GetName(), + MiscExtensions.ParseEnum(scalpingBot.GetStatus())); } + break; default: result.Add(backupBot.Name, BotStatus.Down); @@ -91,47 +80,6 @@ public class LoadBackupBotCommandHandler : IRequestHandler> 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 diff --git a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs index 4b74421..38fc4b5 100644 --- a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs @@ -9,13 +9,14 @@ namespace Managing.Application.ManageBot public class StartBotCommandHandler : IRequestHandler { private readonly IBotFactory _botFactory; - private readonly ITaskCache _taskCache; + private readonly IBotService _botService; private readonly IMoneyManagementService _moneyManagementService; - public StartBotCommandHandler(IBotFactory botFactory, ITaskCache taskCache, IMoneyManagementService moneyManagementService) + public StartBotCommandHandler(IBotFactory botFactory, IBotService botService, + IMoneyManagementService moneyManagementService) { _botFactory = botFactory; - _taskCache = taskCache; + _botService = botService; _moneyManagementService = moneyManagementService; } @@ -28,21 +29,25 @@ namespace Managing.Application.ManageBot case BotType.SimpleBot: var bot = _botFactory.CreateSimpleBot(request.Name, null); bot.Start(); - Func> simpleBot = () => Task.FromResult(bot); - return Task.FromResult(_taskCache.AddOrGetExisting(request.Name, simpleBot).Result.GetStatus()); + _botService.AddSimpleBotToCache(bot); + return Task.FromResult(bot.GetStatus()); case BotType.ScalpingBot: - var sBot = _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()); + _botService.AddTradingBotToCache(sBot); + return Task.FromResult(sBot.GetStatus()); case BotType.FlippingBot: - var fBot = _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()); - }; + _botService.AddTradingBotToCache(fBot); + return Task.FromResult(fBot.GetStatus()); + } + + ; return Task.FromResult(botStatus.ToString()); } } -} +} \ No newline at end of file From dfe92d787ee3d1a3be985bf7dd939bb34dedae68 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 21:33:35 +0700 Subject: [PATCH 08/12] Refact task --- .../Abstractions/IBotService.cs | 2 +- src/Managing.Application/Bots/TradingBot.cs | 2 +- .../ManageBot/BotService.cs | 113 ++++++++++++++++-- .../ManageBot/LoadBackupBotCommandHandler.cs | 7 +- .../TaskCache.cs | 12 +- 5 files changed, 120 insertions(+), 16 deletions(-) diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs index b0aef5c..cca593c 100644 --- a/src/Managing.Application/Abstractions/IBotService.cs +++ b/src/Managing.Application/Abstractions/IBotService.cs @@ -13,7 +13,7 @@ public interface IBotService void AddTradingBotToCache(ITradingBot bot); List GetActiveBots(); IEnumerable GetSavedBots(); - void StartBot(BotBackup backupBot); + void StartBotFromBackup(BotBackup backupBot); ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly); diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 0a380e9..21c1f80 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -744,5 +744,5 @@ public class TradingBotBackup public string AccountName { get; set; } public bool IsForWatchingOnly { get; set; } public Dictionary WalletBalances { get; set; } - public MoneyManagement MoneyManagement { get; internal set; } + public MoneyManagement MoneyManagement { get; set; } } \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 8f72196..d6591dc 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -1,8 +1,12 @@ using Managing.Application.Abstractions; +using Managing.Application.Abstractions.Services; using Managing.Application.Bots; using Managing.Common; using Managing.Core; using Managing.Domain.Bots; +using Managing.Domain.MoneyManagements; +using Managing.Domain.Workflows; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace Managing.Application.ManageBot @@ -11,14 +15,24 @@ namespace Managing.Application.ManageBot { private readonly IBotRepository _botRepository; private readonly ITaskCache _taskCache; - private readonly IBotFactory _botFactory; - + private readonly IExchangeService _exchangeService; + private readonly IMessengerService _messengerService; + private readonly IAccountService _accountService; + private readonly ILogger _tradingBotLogger; + private readonly ITradingService _tradingService; - public BotService(IBotRepository botRepository, ITaskCache taskCache, IBotFactory botFactory) + + public BotService(IBotRepository botRepository, ITaskCache taskCache, IExchangeService exchangeService, + IMessengerService messengerService, IAccountService accountService, ILogger tradingBotLogger, + ITradingService tradingService) { _botRepository = botRepository; _taskCache = taskCache; - _botFactory = botFactory; + _exchangeService = exchangeService; + _messengerService = messengerService; + _accountService = accountService; + _tradingBotLogger = tradingBotLogger; + _tradingService = tradingService; } public async void SaveBotBackup(BotBackup botBackup) @@ -73,20 +87,20 @@ namespace Managing.Application.ManageBot return _botRepository.GetBots(); } - public void StartBot(BotBackup backupBot) + public void StartBotFromBackup(BotBackup backupBot) { switch (backupBot.BotType) { case Enums.BotType.SimpleBot: Func> simpleBot = () => - Task.FromResult(_botFactory.CreateSimpleBot(backupBot.Name, null)); + Task.FromResult(CreateSimpleBot(backupBot.Name, null)); var bot1 = _taskCache.AddOrGetExisting(backupBot.Name, simpleBot).Result; bot1.LoadBackup(backupBot); bot1.Start(); break; case Enums.BotType.ScalpingBot: var data = JsonConvert.DeserializeObject(backupBot.Data); - Func> scalpingBot = () => Task.FromResult(_botFactory.CreateScalpingBot( + Func> scalpingBot = () => Task.FromResult(CreateScalpingBot( data.AccountName, data.MoneyManagement, data.Name, @@ -100,7 +114,7 @@ namespace Managing.Application.ManageBot break; case Enums.BotType.FlippingBot: var dataFlippingBot = JsonConvert.DeserializeObject(backupBot.Data); - Func> flippingBot = () => Task.FromResult(_botFactory.CreateFlippingBot( + Func> flippingBot = () => Task.FromResult(CreateFlippingBot( dataFlippingBot.AccountName, dataFlippingBot.MoneyManagement, dataFlippingBot.Name, @@ -116,5 +130,88 @@ namespace Managing.Application.ManageBot ; } + + public IBot CreateSimpleBot(string botName, Workflow workflow) + { + return new SimpleBot(botName, _tradingBotLogger, workflow, this); + } + + public ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, + Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) + { + return new ScalpingBot( + accountName, + moneyManagement, + name, + scenario, + _exchangeService, + ticker, + _tradingService, + _tradingBotLogger, + interval, + _accountService, + _messengerService, + this, + isForWatchingOnly: isForWatchingOnly); + } + + public ITradingBot CreateBacktestScalpingBot(string accountName, MoneyManagement moneyManagement, + Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) + { + return new ScalpingBot( + accountName, + moneyManagement, + "BacktestBot", + scenario, + _exchangeService, + ticker, + _tradingService, + _tradingBotLogger, + interval, + _accountService, + _messengerService, + this, + true, + isForWatchingOnly); + } + + public ITradingBot CreateFlippingBot(string accountName, MoneyManagement moneyManagement, string name, + Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) + { + return new FlippingBot( + accountName, + moneyManagement, + name, + scenario, + _exchangeService, + ticker, + _tradingService, + _tradingBotLogger, + interval, + _accountService, + _messengerService, + this, + isForWatchingOnly: isForWatchingOnly); + } + + public ITradingBot CreateBacktestFlippingBot(string accountName, MoneyManagement moneyManagement, + Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) + { + return new FlippingBot( + accountName, + moneyManagement, + "BacktestBot", + scenario, + _exchangeService, + ticker, + _tradingService, + _tradingBotLogger, + interval, + _accountService, + _messengerService, + this, + true, + isForWatchingOnly); + } } } \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs index b738834..84a8443 100644 --- a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -42,7 +42,7 @@ public class LoadBackupBotCommandHandler : IRequestHandler b.GetName() == backupBot.Name); + result.Add(scalpingBot.GetName(), BotStatus.Backup); } else { diff --git a/src/Managing.Infrastructure.Storage/TaskCache.cs b/src/Managing.Infrastructure.Storage/TaskCache.cs index 6a1c66d..ace37a9 100644 --- a/src/Managing.Infrastructure.Storage/TaskCache.cs +++ b/src/Managing.Infrastructure.Storage/TaskCache.cs @@ -8,11 +8,14 @@ namespace Managing.Infrastructure.Storage public class TaskCache : ITaskCache { private MemoryCache _cache { get; } = MemoryCache.Default; - private CacheItemPolicy _defaultPolicy { get; } = new CacheItemPolicy(); + + private CacheItemPolicy _defaultPolicy { get; } = new CacheItemPolicy() + { + SlidingExpiration = TimeSpan.FromMinutes(15), + }; public async Task AddOrGetExisting(string key, Func> valueFactory) { - var asyncLazyValue = new AsyncLazy(valueFactory); var existingValue = (AsyncLazy)_cache.AddOrGetExisting(key, asyncLazyValue, _defaultPolicy); @@ -33,6 +36,7 @@ namespace Managing.Infrastructure.Storage // Get the most recent value with a recursive call. return await AddOrGetExisting(key, valueFactory); } + return result; } catch (Exception) @@ -71,7 +75,7 @@ namespace Managing.Infrastructure.Storage public virtual List GetCache() { List list = new List(); - + foreach (var item in _cache) { list.Add((T)item.Value); @@ -80,4 +84,4 @@ namespace Managing.Infrastructure.Storage return list; } } -} +} \ No newline at end of file From 6718d08448a70863c6eb237bce2a6a6c527d7270 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 22:05:34 +0700 Subject: [PATCH 09/12] Replace cache by concurrentDictionary task --- .../ManageBot/BotService.cs | 96 ++++++++++++------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index d6591dc..1410eaf 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Bots; @@ -14,20 +15,20 @@ namespace Managing.Application.ManageBot public class BotService : IBotService { private readonly IBotRepository _botRepository; - private readonly ITaskCache _taskCache; private readonly IExchangeService _exchangeService; private readonly IMessengerService _messengerService; private readonly IAccountService _accountService; private readonly ILogger _tradingBotLogger; private readonly ITradingService _tradingService; + private ConcurrentDictionary _botTasks = + new ConcurrentDictionary(); - public BotService(IBotRepository botRepository, ITaskCache taskCache, IExchangeService exchangeService, + public BotService(IBotRepository botRepository, IExchangeService exchangeService, IMessengerService messengerService, IAccountService accountService, ILogger tradingBotLogger, ITradingService tradingService) { _botRepository = botRepository; - _taskCache = taskCache; _exchangeService = exchangeService; _messengerService = messengerService; _accountService = accountService; @@ -66,20 +67,40 @@ namespace Managing.Application.ManageBot _botRepository.InsertBotAsync(botBackup); } + public class BotTaskWrapper + { + public Task Task { get; private set; } + public Type BotType { get; private set; } + public object BotInstance { get; private set; } // Add this line + + public BotTaskWrapper(Task task, Type botType, object botInstance) // Update constructor + { + Task = task; + BotType = botType; + BotInstance = botInstance; // Set the bot instance + } + } + public void AddSimpleBotToCache(IBot bot) { - _taskCache.AddOrGetExisting(bot.GetName(), () => Task.FromResult(bot)); + var botTask = + new BotTaskWrapper(Task.Run(() => bot.Start()), bot.GetType(), bot); // Pass bot as the instance + _botTasks.AddOrUpdate(bot.GetName(), botTask, (key, existingVal) => botTask); } public void AddTradingBotToCache(ITradingBot bot) { - _taskCache.AddOrGetExisting(bot.GetName(), () => Task.FromResult(bot)); + var botTask = new BotTaskWrapper(Task.Run(() => bot.Start()), bot.GetType(), bot); + _botTasks.AddOrUpdate(bot.GetName(), botTask, (key, existingVal) => botTask); } public List GetActiveBots() { - var cachedTask = _taskCache.GetCache>(); - return cachedTask.Select(item => item.Value.Result).ToList(); + return _botTasks.Values + .Where(wrapper => typeof(ITradingBot).IsAssignableFrom(wrapper.BotType)) + .Select(wrapper => wrapper.BotInstance as ITradingBot) + .Where(bot => bot != null) + .ToList(); } public IEnumerable GetSavedBots() @@ -89,46 +110,47 @@ namespace Managing.Application.ManageBot public void StartBotFromBackup(BotBackup backupBot) { + object bot = null; + Task botTask = null; + switch (backupBot.BotType) { case Enums.BotType.SimpleBot: - Func> simpleBot = () => - Task.FromResult(CreateSimpleBot(backupBot.Name, null)); - var bot1 = _taskCache.AddOrGetExisting(backupBot.Name, simpleBot).Result; - bot1.LoadBackup(backupBot); - bot1.Start(); + bot = CreateSimpleBot(backupBot.Name, + null); // Assuming null is an acceptable parameter for workflow + botTask = Task.Run(() => ((IBot)bot).Start()); break; case Enums.BotType.ScalpingBot: - var data = JsonConvert.DeserializeObject(backupBot.Data); - Func> scalpingBot = () => Task.FromResult(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(); + var scalpingBotData = JsonConvert.DeserializeObject(backupBot.Data); + bot = CreateScalpingBot( + scalpingBotData.AccountName, + scalpingBotData.MoneyManagement, + backupBot.Name, + scalpingBotData.Ticker, + scalpingBotData.Scenario, + scalpingBotData.Timeframe, + scalpingBotData.IsForWatchingOnly); + botTask = Task.Run(() => ((ITradingBot)bot).Start()); break; case Enums.BotType.FlippingBot: - var dataFlippingBot = JsonConvert.DeserializeObject(backupBot.Data); - Func> flippingBot = () => Task.FromResult(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(); + var flippingBotData = JsonConvert.DeserializeObject(backupBot.Data); + bot = CreateFlippingBot( + flippingBotData.AccountName, + flippingBotData.MoneyManagement, + backupBot.Name, + flippingBotData.Ticker, + flippingBotData.Scenario, + flippingBotData.Timeframe, + flippingBotData.IsForWatchingOnly); + botTask = Task.Run(() => ((ITradingBot)bot).Start()); break; } - ; + if (bot != null && botTask != null) + { + var botWrapper = new BotTaskWrapper(botTask, bot.GetType(), bot); + _botTasks.AddOrUpdate(backupBot.Name, botWrapper, (key, existingVal) => botWrapper); + } } public IBot CreateSimpleBot(string botName, Workflow workflow) From 67630c2deb87f1d2978955775c63b2e8252ac491 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 22:20:43 +0700 Subject: [PATCH 10/12] fix --- .../Repositories/IBotRepository.cs | 3 +- .../Abstractions/IBotService.cs | 3 ++ .../ManageBot/BotService.cs | 40 +++++++++++++++++++ .../ManageBot/DeleteBotCommandHandler.cs | 19 +++------ .../ManageBot/RestartBotCommandHandler.cs | 26 +++--------- .../ManageBot/StopBotCommandHandler.cs | 26 +++--------- .../BotRepository.cs | 5 +-- 7 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs index 0473039..2d98040 100644 --- a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs @@ -5,4 +5,5 @@ public interface IBotRepository Task InsertBotAsync(BotBackup bot); IEnumerable GetBots(); Task UpdateBackupBot(BotBackup bot); -} + void DeleteBotBackup(string botName); +} \ No newline at end of file diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs index cca593c..55eee9d 100644 --- a/src/Managing.Application/Abstractions/IBotService.cs +++ b/src/Managing.Application/Abstractions/IBotService.cs @@ -28,4 +28,7 @@ public interface IBotService string scenario, Enums.Timeframe interval, bool isForWatchingOnly); IBot CreateSimpleBot(string botName, Workflow workflow); + Task StopBot(string requestName); + Task DeleteBot(string requestName); + Task RestartBot(string requestName); } \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 1410eaf..39f9784 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -158,6 +158,46 @@ namespace Managing.Application.ManageBot return new SimpleBot(botName, _tradingBotLogger, workflow, this); } + public async Task StopBot(string botName) + { + if (_botTasks.TryGetValue(botName, out var botWrapper)) + { + if (botWrapper.BotInstance is IBot bot) + { + await Task.Run(() => + bot.Stop()); // Assuming Stop is an asynchronous process wrapped in Task.Run for synchronous methods + return bot.GetStatus(); + } + } + + return Enums.BotStatus.Down.ToString(); + } + + public Task DeleteBot(string botName) + { + if (_botTasks.TryRemove(botName, out _)) + { + _botRepository.DeleteBotBackup(botName); + return Task.FromResult(true); + } + + return Task.FromResult(false); + } + + public Task RestartBot(string botName) + { + if (_botTasks.TryGetValue(botName, out var botWrapper)) + { + if (botWrapper.BotInstance is IBot bot) + { + bot.Restart(); + return Task.FromResult(bot.GetStatus()); + } + } + + return Task.FromResult(Enums.BotStatus.Down.ToString()); + } + public ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) { diff --git a/src/Managing.Application/ManageBot/DeleteBotCommandHandler.cs b/src/Managing.Application/ManageBot/DeleteBotCommandHandler.cs index 36c4757..7ae2734 100644 --- a/src/Managing.Application/ManageBot/DeleteBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/DeleteBotCommandHandler.cs @@ -8,25 +8,16 @@ namespace Managing.Application.ManageBot; public class DeleteBotCommandHandler : IRequestHandler { private readonly ILogger _log; - private readonly ITaskCache _taskCache; + private readonly IBotService _botService; - public DeleteBotCommandHandler(ITaskCache taskCache, ILogger log) + public DeleteBotCommandHandler(ILogger log, IBotService botService) { - _taskCache = taskCache; _log = log; + _botService = botService; } public Task Handle(DeleteBotCommand request, CancellationToken cancellationToken) { - try - { - _taskCache.Invalidate(request.Name); - return Task.FromResult(true); - } - catch (Exception e) - { - _log.LogError(e.Message); - return Task.FromResult(false); - } + return _botService.DeleteBot(request.Name); } -} +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs b/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs index b8a1079..c11ad69 100644 --- a/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs @@ -8,32 +8,16 @@ namespace Managing.Application.ManageBot { public class RestartBotCommandHandler : IRequestHandler { - private readonly ITaskCache _taskCache; + private readonly IBotService _botService; - public RestartBotCommandHandler(ITaskCache taskCache) + public RestartBotCommandHandler(IBotService botService) { - _taskCache = taskCache; + _botService = botService; } public Task Handle(RestartBotCommand request, CancellationToken cancellationToken) { - switch (request.BotType) - { - case BotType.SimpleBot: - var simpleBot = _taskCache.Get(request.Name); - simpleBot.Restart(); - return Task.FromResult(simpleBot.GetStatus()); - case BotType.ScalpingBot: - var scalpingBot = _taskCache.Get(request.Name); - scalpingBot.Restart(); - return Task.FromResult(scalpingBot.GetStatus()); - case BotType.FlippingBot: - var flippingBot = _taskCache.Get(request.Name); - flippingBot.Restart(); - return Task.FromResult(flippingBot.GetStatus()); - default: - return Task.FromResult(BotStatus.Down.ToString()); - } + return _botService.RestartBot(request.Name); } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/ManageBot/StopBotCommandHandler.cs b/src/Managing.Application/ManageBot/StopBotCommandHandler.cs index 5a0a701..def858c 100644 --- a/src/Managing.Application/ManageBot/StopBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/StopBotCommandHandler.cs @@ -8,32 +8,16 @@ namespace Managing.Application.ManageBot { public class StopBotCommandHandler : IRequestHandler { - private readonly ITaskCache _taskCache; + private readonly IBotService _botService; - public StopBotCommandHandler(ITaskCache taskCache) + public StopBotCommandHandler(IBotService botService) { - _taskCache = taskCache; + _botService = botService; } public Task Handle(StopBotCommand request, CancellationToken cancellationToken) { - switch (request.BotType) - { - case BotType.SimpleBot: - var simpleBot = _taskCache.Get(request.Name); - simpleBot.Stop(); - return Task.FromResult(simpleBot.GetStatus()); - case BotType.ScalpingBot: - var scalpingBot = _taskCache.Get(request.Name); - scalpingBot.Stop(); - return Task.FromResult(scalpingBot.GetStatus()); - case BotType.FlippingBot: - var flippingBot = _taskCache.Get(request.Name); - flippingBot.Stop(); - return Task.FromResult(flippingBot.GetStatus()); - default: - return Task.FromResult(BotStatus.Down.ToString()); - } + return _botService.StopBot(request.Name); } } -} +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/BotRepository.cs b/src/Managing.Infrastructure.Database/BotRepository.cs index 2fa3ec7..573e351 100644 --- a/src/Managing.Infrastructure.Database/BotRepository.cs +++ b/src/Managing.Infrastructure.Database/BotRepository.cs @@ -32,9 +32,8 @@ public class BotRepository : IBotRepository _botRepository.Update(dto); } - public void DeleteBotByName(string name) + public void DeleteBotBackup(string botName) { - var bot = _botRepository.FindOne(b => b.Name == name); - _botRepository.DeleteById(bot.Id.ToString()); + _botRepository.DeleteOne(b => b.Name == botName); } } \ No newline at end of file From b5b0292bf823a2b611ab1f3408207dccd26ff61c Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 22:21:49 +0700 Subject: [PATCH 11/12] Remove unused --- .../Repositories/IBotRepository.cs | 2 -- src/Managing.Application.Tests/WorkflowTests.cs | 3 +-- src/Managing.Application/ManageBot/BotService.cs | 1 - .../ManageBot/LoadBackupBotCommandHandler.cs | 5 +---- .../ManageBot/RestartBotCommandHandler.cs | 2 -- src/Managing.Application/ManageBot/StartBotCommandHandler.cs | 3 +-- src/Managing.Application/ManageBot/StopBotCommandHandler.cs | 2 -- src/Managing.Application/Trading/TradingService.cs | 4 +--- .../Workflows/Flows/Trading/OpenPosition.cs | 3 --- src/Managing.Domain/Bots/Bot.cs | 3 +-- src/Managing.Domain/Bots/BotBackup.cs | 1 - src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs | 4 +--- .../Exchanges/BinanceProcessor.cs | 1 - .../Exchanges/FtxProcessor.cs | 1 - src/Managing.Infrastructure.Tests/SubgraphTests.cs | 5 +---- 15 files changed, 7 insertions(+), 33 deletions(-) diff --git a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs index 2d98040..7af45de 100644 --- a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs @@ -1,5 +1,3 @@ -using Managing.Domain.Bots; - public interface IBotRepository { Task InsertBotAsync(BotBackup bot); diff --git a/src/Managing.Application.Tests/WorkflowTests.cs b/src/Managing.Application.Tests/WorkflowTests.cs index 8961bc2..893a221 100644 --- a/src/Managing.Application.Tests/WorkflowTests.cs +++ b/src/Managing.Application.Tests/WorkflowTests.cs @@ -1,5 +1,4 @@ -using Managing.Application.Workflows.Flows.Feeds; -using Managing.Domain.Workflows; +using Managing.Domain.Workflows; using Xunit; using static Managing.Common.Enums; diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 39f9784..5291d60 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -3,7 +3,6 @@ using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Bots; using Managing.Common; -using Managing.Core; using Managing.Domain.Bots; using Managing.Domain.MoneyManagements; using Managing.Domain.Workflows; diff --git a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs index 84a8443..9b0e37c 100644 --- a/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/LoadBackupBotCommandHandler.cs @@ -1,10 +1,7 @@ -using Managing.Domain.Bots; -using MediatR; +using MediatR; using static Managing.Common.Enums; using Managing.Application.Abstractions; using Managing.Core; -using Newtonsoft.Json; -using Managing.Application.Bots; using Microsoft.Extensions.Logging; namespace Managing.Application.ManageBot; diff --git a/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs b/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs index c11ad69..dd9a4a2 100644 --- a/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/RestartBotCommandHandler.cs @@ -1,8 +1,6 @@ using Managing.Application.Abstractions; using Managing.Application.ManageBot.Commands; -using Managing.Domain.Bots; using MediatR; -using static Managing.Common.Enums; namespace Managing.Application.ManageBot { diff --git a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs index 38fc4b5..b98b7c7 100644 --- a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs @@ -1,5 +1,4 @@ -using Managing.Domain.Bots; -using MediatR; +using MediatR; using static Managing.Common.Enums; using Managing.Application.Abstractions; using Managing.Application.ManageBot.Commands; diff --git a/src/Managing.Application/ManageBot/StopBotCommandHandler.cs b/src/Managing.Application/ManageBot/StopBotCommandHandler.cs index def858c..e92bbb4 100644 --- a/src/Managing.Application/ManageBot/StopBotCommandHandler.cs +++ b/src/Managing.Application/ManageBot/StopBotCommandHandler.cs @@ -1,8 +1,6 @@ using Managing.Application.Abstractions; using Managing.Application.ManageBot.Commands; -using Managing.Domain.Bots; using MediatR; -using static Managing.Common.Enums; namespace Managing.Application.ManageBot { diff --git a/src/Managing.Application/Trading/TradingService.cs b/src/Managing.Application/Trading/TradingService.cs index d752d91..12f7263 100644 --- a/src/Managing.Application/Trading/TradingService.cs +++ b/src/Managing.Application/Trading/TradingService.cs @@ -1,5 +1,4 @@ -using DnsClient.Internal; -using Managing.Application.Abstractions; +using Managing.Application.Abstractions; using Managing.Application.Abstractions.Repositories; using Managing.Application.Abstractions.Services; using Managing.Domain.Accounts; @@ -9,7 +8,6 @@ using Managing.Domain.Strategies; using Managing.Domain.Trades; using Managing.Domain.Shared.Helpers; using Microsoft.Extensions.Logging; -using MongoDB.Driver; using static Managing.Common.Enums; namespace Managing.Application.Trading; diff --git a/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs b/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs index 67eda2b..c309fd1 100644 --- a/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs +++ b/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs @@ -1,11 +1,8 @@ using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; -using Managing.Application.Accounts; -using Managing.Application.Shared; using Managing.Application.Trading.Commands; using Managing.Application.Trading; using Managing.Domain.Accounts; -using Managing.Domain.MoneyManagements; using Managing.Domain.Strategies; using Managing.Domain.Trades; using Managing.Domain.Workflows; diff --git a/src/Managing.Domain/Bots/Bot.cs b/src/Managing.Domain/Bots/Bot.cs index ff7b7bb..9911d32 100644 --- a/src/Managing.Domain/Bots/Bot.cs +++ b/src/Managing.Domain/Bots/Bot.cs @@ -1,5 +1,4 @@ -using System.Text.Json; -using static Managing.Common.Enums; +using static Managing.Common.Enums; namespace Managing.Domain.Bots { diff --git a/src/Managing.Domain/Bots/BotBackup.cs b/src/Managing.Domain/Bots/BotBackup.cs index 5ea153c..4028572 100644 --- a/src/Managing.Domain/Bots/BotBackup.cs +++ b/src/Managing.Domain/Bots/BotBackup.cs @@ -1,4 +1,3 @@ -using Managing.Domain.MoneyManagements; using static Managing.Common.Enums; public class BotBackup diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index 9a2c864..e1c0592 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -1,7 +1,5 @@ -using System.Reflection.Metadata.Ecma335; -using Managing.Domain.Accounts; +using Managing.Domain.Accounts; using Managing.Domain.Backtests; -using Managing.Domain.Bots; using Managing.Domain.Candles; using Managing.Domain.MoneyManagements; using Managing.Domain.Scenarios; diff --git a/src/Managing.Infrastructure.Exchanges/Exchanges/BinanceProcessor.cs b/src/Managing.Infrastructure.Exchanges/Exchanges/BinanceProcessor.cs index 71885ad..1516b8e 100644 --- a/src/Managing.Infrastructure.Exchanges/Exchanges/BinanceProcessor.cs +++ b/src/Managing.Infrastructure.Exchanges/Exchanges/BinanceProcessor.cs @@ -1,7 +1,6 @@ using Binance.Net.Clients; using Binance.Net.Enums; using Binance.Net.Interfaces.Clients; -using CryptoExchange.Net; using CryptoExchange.Net.Authentication; using Managing.Common; using Managing.Core; diff --git a/src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs b/src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs index de1b687..01fcd5c 100644 --- a/src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs +++ b/src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs @@ -1,5 +1,4 @@ using CryptoExchange.Net.Authentication; -using FTX.Net.Clients; using FTX.Net.Interfaces.Clients; using FTX.Net.Objects; using Managing.Common; diff --git a/src/Managing.Infrastructure.Tests/SubgraphTests.cs b/src/Managing.Infrastructure.Tests/SubgraphTests.cs index ff2040d..f2af853 100644 --- a/src/Managing.Infrastructure.Tests/SubgraphTests.cs +++ b/src/Managing.Infrastructure.Tests/SubgraphTests.cs @@ -1,7 +1,4 @@ -using Xunit; -using static Managing.Common.Enums; - -namespace Managing.Infrastructure.Tests; +namespace Managing.Infrastructure.Tests; public class SubgraphTests { From 34461840065ffd27d3d0b7092537d460f2cba3d0 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 12 Jul 2024 22:23:02 +0700 Subject: [PATCH 12/12] little clean --- src/Managing.Infrastructure.Storage/TaskCache.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Managing.Infrastructure.Storage/TaskCache.cs b/src/Managing.Infrastructure.Storage/TaskCache.cs index ace37a9..0461580 100644 --- a/src/Managing.Infrastructure.Storage/TaskCache.cs +++ b/src/Managing.Infrastructure.Storage/TaskCache.cs @@ -1,6 +1,5 @@ using Managing.Application.Abstractions; using Managing.Core; -//using Microsoft.Extensions.Caching.Memory; using System.Runtime.Caching; namespace Managing.Infrastructure.Storage @@ -9,10 +8,7 @@ namespace Managing.Infrastructure.Storage { private MemoryCache _cache { get; } = MemoryCache.Default; - private CacheItemPolicy _defaultPolicy { get; } = new CacheItemPolicy() - { - SlidingExpiration = TimeSpan.FromMinutes(15), - }; + private CacheItemPolicy _defaultPolicy { get; } = new CacheItemPolicy(); public async Task AddOrGetExisting(string key, Func> valueFactory) {