Balance for bot (#20)

* Add bot balance

* Update amount to trade

* fix initial trading balance

* Update MM modal

* fix backtest

* stop bot if no more balance

* Add constant for minimum trading

* Add constant
This commit is contained in:
Oda
2025-04-28 16:52:42 +02:00
committed by GitHub
parent 967e8410dc
commit 204bd87e6a
39 changed files with 600 additions and 546 deletions

View File

@@ -55,7 +55,7 @@ namespace Managing.Application.ManageBot
if (backup != null)
{
backup.Data = data;
_botRepository.UpdateBackupBot(backup);
_botRepository.UpdateBackupBot(backup);
}
else
{
@@ -136,7 +136,8 @@ namespace Managing.Application.ManageBot
scalpingBotData.Ticker,
scalpingBotData.ScenarioName,
scalpingBotData.Timeframe,
scalpingBotData.IsForWatchingOnly);
scalpingBotData.IsForWatchingOnly,
scalpingBotData.BotTradingBalance);
botTask = Task.Run(() => InitBot((ITradingBot)bot, backupBot));
break;
case Enums.BotType.FlippingBot:
@@ -150,7 +151,8 @@ namespace Managing.Application.ManageBot
flippingBotData.Ticker,
flippingBotData.ScenarioName,
flippingBotData.Timeframe,
flippingBotData.IsForWatchingOnly);
flippingBotData.IsForWatchingOnly,
flippingBotData.BotTradingBalance);
botTask = Task.Run(InitBot((ITradingBot)bot, backupBot));
break;
}
@@ -243,7 +245,8 @@ namespace Managing.Application.ManageBot
}
public ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name,
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly)
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly,
decimal initialTradingBalance)
{
return new ScalpingBot(
accountName,
@@ -258,11 +261,13 @@ namespace Managing.Application.ManageBot
_accountService,
_messengerService,
this,
initialTradingBalance,
isForWatchingOnly: isForWatchingOnly);
}
public ITradingBot CreateBacktestScalpingBot(string accountName, MoneyManagement moneyManagement,
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly)
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly,
decimal initialTradingBalance)
{
return new ScalpingBot(
accountName,
@@ -277,12 +282,14 @@ namespace Managing.Application.ManageBot
_accountService,
_messengerService,
this,
true,
isForWatchingOnly);
initialTradingBalance,
isForBacktest: true,
isForWatchingOnly: isForWatchingOnly);
}
public ITradingBot CreateFlippingBot(string accountName, MoneyManagement moneyManagement, string name,
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly)
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly,
decimal initialTradingBalance)
{
return new FlippingBot(
accountName,
@@ -297,11 +304,13 @@ namespace Managing.Application.ManageBot
_accountService,
_messengerService,
this,
initialTradingBalance,
isForWatchingOnly: isForWatchingOnly);
}
public ITradingBot CreateBacktestFlippingBot(string accountName, MoneyManagement moneyManagement,
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly)
Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly,
decimal initialTradingBalance)
{
return new FlippingBot(
accountName,
@@ -316,8 +325,9 @@ namespace Managing.Application.ManageBot
_accountService,
_messengerService,
this,
true,
isForWatchingOnly);
initialTradingBalance,
isForBacktest: true,
isForWatchingOnly: isForWatchingOnly);
}
}
}

View File

@@ -1,5 +1,5 @@
using MediatR;
using Managing.Domain.Users;
using Managing.Domain.Users;
using MediatR;
using static Managing.Common.Enums;
namespace Managing.Application.ManageBot.Commands
@@ -15,6 +15,7 @@ namespace Managing.Application.ManageBot.Commands
public string AccountName { get; internal set; }
public string MoneyManagementName { get; internal set; }
public User User { get; internal set; }
public decimal InitialTradingBalance { get; internal set; }
public StartBotCommand(BotType botType,
string name,
@@ -24,7 +25,8 @@ namespace Managing.Application.ManageBot.Commands
string accountName,
string moneyManagementName,
User user,
bool isForWatchingOnly = false)
bool isForWatchingOnly = false,
decimal initialTradingBalance = 0)
{
BotType = botType;
Name = name;
@@ -35,6 +37,8 @@ namespace Managing.Application.ManageBot.Commands
AccountName = accountName;
MoneyManagementName = moneyManagementName;
User = user;
InitialTradingBalance = initialTradingBalance > 0 ? initialTradingBalance :
throw new ArgumentException("Initial trading balance must be greater than zero", nameof(initialTradingBalance));
}
}
}

View File

@@ -1,7 +1,8 @@
using MediatR;
using static Managing.Common.Enums;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot.Commands;
using MediatR;
using static Managing.Common.Enums;
namespace Managing.Application.ManageBot
{
@@ -10,38 +11,61 @@ namespace Managing.Application.ManageBot
private readonly IBotFactory _botFactory;
private readonly IBotService _botService;
private readonly IMoneyManagementService _moneyManagementService;
private readonly IExchangeService _exchangeService;
private readonly IAccountService _accountService;
public StartBotCommandHandler(IBotFactory botFactory, IBotService botService,
IMoneyManagementService moneyManagementService)
IMoneyManagementService moneyManagementService, IExchangeService exchangeService,
IAccountService accountService)
{
_botFactory = botFactory;
_botService = botService;
_moneyManagementService = moneyManagementService;
_exchangeService = exchangeService;
_accountService = accountService;
}
public Task<string> Handle(StartBotCommand request, CancellationToken cancellationToken)
public async Task<string> Handle(StartBotCommand request, CancellationToken cancellationToken)
{
BotStatus botStatus = BotStatus.Down;
var moneyManagement = _moneyManagementService.GetMoneyMangement(request.User, request.MoneyManagementName).Result;
var account = await _accountService.GetAccount(request.AccountName, true, true);
if (account == null)
{
throw new Exception($"Account {request.AccountName} not found");
}
var usdcBalance = account.Balances.FirstOrDefault(b => b.TokenName == Ticker.USDC.ToString());
if (usdcBalance == null || usdcBalance.Value < request.InitialTradingBalance)
{
throw new Exception($"Account {request.AccountName} has no USDC balance or not enough balance");
}
var moneyManagement =
await _moneyManagementService.GetMoneyMangement(request.User, request.MoneyManagementName);
switch (request.BotType)
{
case BotType.SimpleBot:
var bot = _botFactory.CreateSimpleBot(request.Name, null);
_botService.AddSimpleBotToCache(bot);
return Task.FromResult(bot.GetStatus());
return bot.GetStatus();
case BotType.ScalpingBot:
var sBot = _botFactory.CreateScalpingBot(request.AccountName, moneyManagement, request.Name,
request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly);
request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly,
request.InitialTradingBalance);
_botService.AddTradingBotToCache(sBot);
return Task.FromResult(sBot.GetStatus());
return sBot.GetStatus();
case BotType.FlippingBot:
var fBot = _botFactory.CreateFlippingBot(request.AccountName, moneyManagement, request.Name,
request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly);
request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly,
request.InitialTradingBalance);
_botService.AddTradingBotToCache(fBot);
return Task.FromResult(fBot.GetStatus());
return fBot.GetStatus();
}
return Task.FromResult(botStatus.ToString());
return botStatus.ToString();
}
}
}