Files
managing-apps/src/Managing.Application/ManageBot/BotService.cs

239 lines
8.6 KiB
C#

using System.Collections.Concurrent;
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
{
public class BotService : IBotService
{
private readonly IBotRepository _botRepository;
private readonly IExchangeService _exchangeService;
private readonly IMessengerService _messengerService;
private readonly IAccountService _accountService;
private readonly ILogger<TradingBot> _tradingBotLogger;
private readonly ITradingService _tradingService;
private ConcurrentDictionary<string, BotTaskWrapper> _botTasks =
new ConcurrentDictionary<string, BotTaskWrapper>();
public BotService(IBotRepository botRepository, IExchangeService exchangeService,
IMessengerService messengerService, IAccountService accountService, ILogger<TradingBot> tradingBotLogger,
ITradingService tradingService)
{
_botRepository = botRepository;
_exchangeService = exchangeService;
_messengerService = messengerService;
_accountService = accountService;
_tradingBotLogger = tradingBotLogger;
_tradingService = tradingService;
}
public async void SaveBotBackup(BotBackup botBackup)
{
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,
BotType = botType,
Data = data
};
_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)
{
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)
{
var botTask = new BotTaskWrapper(Task.Run(() => bot.Start()), bot.GetType(), bot);
_botTasks.AddOrUpdate(bot.GetName(), botTask, (key, existingVal) => botTask);
}
public List<ITradingBot> GetActiveBots()
{
return _botTasks.Values
.Where(wrapper => typeof(ITradingBot).IsAssignableFrom(wrapper.BotType))
.Select(wrapper => wrapper.BotInstance as ITradingBot)
.Where(bot => bot != null)
.ToList();
}
public IEnumerable<BotBackup> GetSavedBots()
{
return _botRepository.GetBots();
}
public void StartBotFromBackup(BotBackup backupBot)
{
object bot = null;
Task botTask = null;
switch (backupBot.BotType)
{
case Enums.BotType.SimpleBot:
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 scalpingBotData = JsonConvert.DeserializeObject<TradingBotBackup>(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 flippingBotData = JsonConvert.DeserializeObject<TradingBotBackup>(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)
{
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);
}
}
}