Postgres (#30)
* Add postgres * Migrate users * Migrate geneticRequest * Try to fix Concurrent call * Fix asyncawait * Fix async and concurrent * Migrate backtests * Add cache for user by address * Fix backtest migration * Fix not open connection * Fix backtest command error * Fix concurrent * Fix all concurrency * Migrate TradingRepo * Fix scenarios * Migrate statistic repo * Save botbackup * Add settings et moneymanagement * Add bot postgres * fix a bit more backups * Fix bot model * Fix loading backup * Remove cache market for read positions * Add workers to postgre * Fix workers api * Reduce get Accounts for workers * Migrate synth to postgre * Fix backtest saved * Remove mongodb * botservice decorrelation * Fix tradingbot scope call * fix tradingbot * fix concurrent * Fix scope for genetics * Fix account over requesting * Fix bundle backtest worker * fix a lot of things * fix tab backtest * Remove optimized moneymanagement * Add light signal to not use User and too much property * Make money management lighter * insert indicators to awaitable * Migrate add strategies to await * Refactor scenario and indicator retrieval to use asynchronous methods throughout the application * add more async await * Add services * Fix and clean * Fix bot a bit * Fix bot and add message for cooldown * Remove fees * Add script to deploy db * Update dfeeploy script * fix script * Add idempotent script and backup * finish script migration * Fix did user and agent name on start bot
This commit is contained in:
@@ -6,8 +6,8 @@ using Managing.Application.Bots;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Users;
|
||||
using Managing.Domain.Workflows;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.ManageBot
|
||||
@@ -22,13 +22,16 @@ namespace Managing.Application.ManageBot
|
||||
private readonly ITradingService _tradingService;
|
||||
private readonly IMoneyManagementService _moneyManagementService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IBackupBotService _backupBotService;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
|
||||
private ConcurrentDictionary<string, BotTaskWrapper> _botTasks =
|
||||
new ConcurrentDictionary<string, BotTaskWrapper>();
|
||||
|
||||
public BotService(IBotRepository botRepository, IExchangeService exchangeService,
|
||||
IMessengerService messengerService, IAccountService accountService, ILogger<TradingBot> tradingBotLogger,
|
||||
ITradingService tradingService, IMoneyManagementService moneyManagementService, IUserService userService)
|
||||
ITradingService tradingService, IMoneyManagementService moneyManagementService, IUserService userService,
|
||||
IBackupBotService backupBotService, IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_botRepository = botRepository;
|
||||
_exchangeService = exchangeService;
|
||||
@@ -38,35 +41,8 @@ namespace Managing.Application.ManageBot
|
||||
_tradingService = tradingService;
|
||||
_moneyManagementService = moneyManagementService;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public BotBackup GetBotBackup(string identifier)
|
||||
{
|
||||
return _botRepository.GetBots().FirstOrDefault(b => b.Identifier == identifier);
|
||||
}
|
||||
|
||||
public void SaveOrUpdateBotBackup(User user, string identifier, BotStatus status, string data)
|
||||
{
|
||||
var backup = GetBotBackup(identifier);
|
||||
|
||||
if (backup != null)
|
||||
{
|
||||
backup.LastStatus = status;
|
||||
backup.Data = data;
|
||||
_botRepository.UpdateBackupBot(backup);
|
||||
}
|
||||
else
|
||||
{
|
||||
var botBackup = new BotBackup
|
||||
{
|
||||
LastStatus = status,
|
||||
User = user,
|
||||
Identifier = identifier,
|
||||
Data = data
|
||||
};
|
||||
|
||||
_botRepository.InsertBotAsync(botBackup);
|
||||
}
|
||||
_backupBotService = backupBotService;
|
||||
_scopeFactory = scopeFactory;
|
||||
}
|
||||
|
||||
public class BotTaskWrapper
|
||||
@@ -96,6 +72,27 @@ namespace Managing.Application.ManageBot
|
||||
_botTasks.AddOrUpdate(bot.Identifier, botTask, (key, existingVal) => botTask);
|
||||
}
|
||||
|
||||
|
||||
private async Task InitBot(ITradingBot bot, BotBackup backupBot)
|
||||
{
|
||||
var user = await _userService.GetUser(backupBot.User.Name);
|
||||
bot.User = user;
|
||||
// Config is already set correctly from backup data, so we only need to restore signals, positions, etc.
|
||||
bot.LoadBackup(backupBot);
|
||||
|
||||
// Only start the bot if the backup status is Up
|
||||
if (backupBot.LastStatus == BotStatus.Up)
|
||||
{
|
||||
// Start the bot asynchronously without waiting for completion
|
||||
_ = Task.Run(() => bot.Start());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep the bot in Down status if it was originally Down
|
||||
bot.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public List<ITradingBot> GetActiveBots()
|
||||
{
|
||||
var bots = _botTasks.Values
|
||||
@@ -107,17 +104,17 @@ namespace Managing.Application.ManageBot
|
||||
return bots;
|
||||
}
|
||||
|
||||
public IEnumerable<BotBackup> GetSavedBots()
|
||||
public async Task<IEnumerable<BotBackup>> GetSavedBotsAsync()
|
||||
{
|
||||
return _botRepository.GetBots();
|
||||
return await _botRepository.GetBotsAsync();
|
||||
}
|
||||
|
||||
public void StartBotFromBackup(BotBackup backupBot)
|
||||
public async Task StartBotFromBackup(BotBackup backupBot)
|
||||
{
|
||||
object bot = null;
|
||||
Task botTask = null;
|
||||
|
||||
var scalpingBotData = JsonConvert.DeserializeObject<TradingBotBackup>(backupBot.Data);
|
||||
var scalpingBotData = backupBot.Data;
|
||||
|
||||
// Get the config directly from the backup
|
||||
var scalpingConfig = scalpingBotData.Config;
|
||||
@@ -137,7 +134,7 @@ namespace Managing.Application.ManageBot
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (scalpingConfig.Scenario == null && !string.IsNullOrEmpty(scalpingConfig.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(scalpingConfig.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(scalpingConfig.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
scalpingConfig.Scenario = scenario;
|
||||
@@ -158,7 +155,7 @@ namespace Managing.Application.ManageBot
|
||||
// Ensure critical properties are set correctly for restored bots
|
||||
scalpingConfig.IsForBacktest = false;
|
||||
|
||||
bot = CreateTradingBot(scalpingConfig);
|
||||
bot = await CreateTradingBot(scalpingConfig);
|
||||
botTask = Task.Run(() => InitBot((ITradingBot)bot, backupBot));
|
||||
|
||||
if (bot != null && botTask != null)
|
||||
@@ -168,29 +165,38 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
}
|
||||
|
||||
private void InitBot(ITradingBot bot, BotBackup backupBot)
|
||||
public async Task<BotBackup> GetBotBackup(string identifier)
|
||||
{
|
||||
var user = _userService.GetUser(backupBot.User.Name);
|
||||
bot.User = user;
|
||||
// Config is already set correctly from backup data, so we only need to restore signals, positions, etc.
|
||||
bot.LoadBackup(backupBot);
|
||||
return await _botRepository.GetBotByIdentifierAsync(identifier);
|
||||
}
|
||||
|
||||
// Only start the bot if the backup status is Up
|
||||
if (backupBot.LastStatus == BotStatus.Up)
|
||||
public async Task SaveOrUpdateBotBackup(User user, string identifier, BotStatus status, TradingBotBackup data)
|
||||
{
|
||||
var backup = await GetBotBackup(identifier);
|
||||
|
||||
if (backup != null)
|
||||
{
|
||||
// Start the bot asynchronously without waiting for completion
|
||||
_ = Task.Run(() => bot.Start());
|
||||
backup.LastStatus = status;
|
||||
backup.Data = data;
|
||||
await _botRepository.UpdateBackupBot(backup);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep the bot in Down status if it was originally Down
|
||||
bot.Stop();
|
||||
var botBackup = new BotBackup
|
||||
{
|
||||
LastStatus = status,
|
||||
User = user,
|
||||
Identifier = identifier,
|
||||
Data = data
|
||||
};
|
||||
|
||||
await _botRepository.InsertBotAsync(botBackup);
|
||||
}
|
||||
}
|
||||
|
||||
public IBot CreateSimpleBot(string botName, Workflow workflow)
|
||||
{
|
||||
return new SimpleBot(botName, _tradingBotLogger, workflow, this);
|
||||
return new SimpleBot(botName, _tradingBotLogger, workflow, this, _backupBotService);
|
||||
}
|
||||
|
||||
public async Task<string> StopBot(string identifier)
|
||||
@@ -263,7 +269,7 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
// Restart the bot (this will update StartupTime)
|
||||
bot.Restart();
|
||||
|
||||
|
||||
// Start the bot asynchronously without waiting for completion
|
||||
_ = Task.Run(() => bot.Start());
|
||||
|
||||
@@ -282,12 +288,12 @@ namespace Managing.Application.ManageBot
|
||||
return BotStatus.Down.ToString();
|
||||
}
|
||||
|
||||
public void ToggleIsForWatchingOnly(string identifier)
|
||||
public async Task ToggleIsForWatchingOnly(string identifier)
|
||||
{
|
||||
if (_botTasks.TryGetValue(identifier, out var botTaskWrapper) &&
|
||||
botTaskWrapper.BotInstance is ITradingBot tradingBot)
|
||||
{
|
||||
tradingBot.ToggleIsForWatchOnly().Wait();
|
||||
await tradingBot.ToggleIsForWatchOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +311,7 @@ namespace Managing.Application.ManageBot
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (newConfig.Scenario == null && !string.IsNullOrEmpty(newConfig.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(newConfig.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(newConfig.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
newConfig.Scenario = scenario;
|
||||
@@ -365,12 +371,12 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
|
||||
|
||||
public ITradingBot CreateTradingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateTradingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -386,22 +392,15 @@ namespace Managing.Application.ManageBot
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
|
||||
public ITradingBot CreateBacktestTradingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateBacktestTradingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -418,22 +417,15 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
|
||||
config.IsForBacktest = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
|
||||
public ITradingBot CreateScalpingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateScalpingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -450,22 +442,15 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
|
||||
config.FlipPosition = false;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
|
||||
public ITradingBot CreateBacktestScalpingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateBacktestScalpingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -483,22 +468,15 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
config.IsForBacktest = true;
|
||||
config.FlipPosition = false;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
|
||||
public ITradingBot CreateFlippingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateFlippingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -515,22 +493,15 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
|
||||
config.FlipPosition = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
|
||||
public ITradingBot CreateBacktestFlippingBot(TradingBotConfig config)
|
||||
public async Task<ITradingBot> CreateBacktestFlippingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
var scenario = await _tradingService.GetScenarioByNameAsync(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
@@ -548,14 +519,7 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
config.IsForBacktest = true;
|
||||
config.FlipPosition = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
this,
|
||||
config);
|
||||
return new TradingBot(_tradingBotLogger, _scopeFactory, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user