diff --git a/src/Managing.Api/Controllers/BacktestController.cs b/src/Managing.Api/Controllers/BacktestController.cs
index a26e8fc..28161d0 100644
--- a/src/Managing.Api/Controllers/BacktestController.cs
+++ b/src/Managing.Api/Controllers/BacktestController.cs
@@ -176,18 +176,11 @@ public class BacktestController : BaseController
switch (request.Config.BotType)
{
case BotType.SimpleBot:
+ // SimpleBot backtest not implemented yet
break;
case BotType.ScalpingBot:
- backtestResult = await _backtester.RunScalpingBotBacktest(
- backtestConfig,
- request.StartDate,
- request.EndDate,
- user,
- request.Save,
- null);
- break;
case BotType.FlippingBot:
- backtestResult = await _backtester.RunFlippingBotBacktest(
+ backtestResult = await _backtester.RunTradingBotBacktest(
backtestConfig,
request.StartDate,
request.EndDate,
diff --git a/src/Managing.Application.Abstractions/Services/IBacktester.cs b/src/Managing.Application.Abstractions/Services/IBacktester.cs
index 1fcdd83..2ef352d 100644
--- a/src/Managing.Application.Abstractions/Services/IBacktester.cs
+++ b/src/Managing.Application.Abstractions/Services/IBacktester.cs
@@ -7,6 +7,39 @@ namespace Managing.Application.Abstractions.Services
{
public interface IBacktester
{
+ ///
+ /// Runs a unified trading bot backtest with the specified configuration and date range.
+ /// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
+ ///
+ /// The trading bot configuration
+ /// The start date for the backtest
+ /// The end date for the backtest
+ /// The user running the backtest
+ /// Whether to save the backtest results
+ /// Optional pre-loaded candles
+ /// The backtest results
+ Task RunTradingBotBacktest(
+ TradingBotConfig config,
+ DateTime startDate,
+ DateTime endDate,
+ User user = null,
+ bool save = false,
+ List? initialCandles = null);
+
+ ///
+ /// Runs a unified trading bot backtest with pre-loaded candles.
+ /// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
+ ///
+ /// The trading bot configuration
+ /// The candles to use for backtesting
+ /// The user running the backtest
+ /// The backtest results
+ Task RunTradingBotBacktest(
+ TradingBotConfig config,
+ List candles,
+ User user = null);
+
+ // Legacy methods - maintained for backward compatibility
Task RunScalpingBotBacktest(
TradingBotConfig config,
DateTime startDate,
diff --git a/src/Managing.Application/Abstractions/IBotFactory.cs b/src/Managing.Application/Abstractions/IBotFactory.cs
index 25a7f97..4431d55 100644
--- a/src/Managing.Application/Abstractions/IBotFactory.cs
+++ b/src/Managing.Application/Abstractions/IBotFactory.cs
@@ -1,5 +1,4 @@
-using Managing.Application.Bots;
-using Managing.Domain.Bots;
+using Managing.Domain.Bots;
using Managing.Domain.Workflows;
namespace Managing.Application.Abstractions
@@ -7,6 +6,22 @@ namespace Managing.Application.Abstractions
public interface IBotFactory
{
IBot CreateSimpleBot(string botName, Workflow workflow);
+
+ ///
+ /// Creates a trading bot using the unified TradingBot class
+ ///
+ /// The trading bot configuration
+ /// ITradingBot instance
+ ITradingBot CreateTradingBot(TradingBotConfig config);
+
+ ///
+ /// Creates a trading bot for backtesting using the unified TradingBot class
+ ///
+ /// The trading bot configuration
+ /// ITradingBot instance configured for backtesting
+ ITradingBot CreateBacktestTradingBot(TradingBotConfig config);
+
+ // Legacy methods - these will use TradingBot internally but maintain backward compatibility
ITradingBot CreateScalpingBot(TradingBotConfig config);
ITradingBot CreateBacktestScalpingBot(TradingBotConfig config);
ITradingBot CreateFlippingBot(TradingBotConfig config);
diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs
index 6f2a4cf..4ce07c7 100644
--- a/src/Managing.Application/Abstractions/IBotService.cs
+++ b/src/Managing.Application/Abstractions/IBotService.cs
@@ -15,6 +15,21 @@ public interface IBotService
void StartBotFromBackup(BotBackup backupBot);
BotBackup GetBotBackup(string identifier);
+ ///
+ /// Creates a trading bot using the unified TradingBot class
+ ///
+ /// The trading bot configuration
+ /// ITradingBot instance
+ ITradingBot CreateTradingBot(TradingBotConfig config);
+
+ ///
+ /// Creates a trading bot for backtesting using the unified TradingBot class
+ ///
+ /// The trading bot configuration
+ /// ITradingBot instance configured for backtesting
+ ITradingBot CreateBacktestTradingBot(TradingBotConfig config);
+
+ // Legacy methods - these will use TradingBot internally but maintain backward compatibility
ITradingBot CreateScalpingBot(TradingBotConfig config);
ITradingBot CreateBacktestScalpingBot(TradingBotConfig config);
ITradingBot CreateFlippingBot(TradingBotConfig config);
diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs
index 4ad0d72..3b8ef7a 100644
--- a/src/Managing.Application/Backtesting/Backtester.cs
+++ b/src/Managing.Application/Backtesting/Backtester.cs
@@ -55,7 +55,18 @@ namespace Managing.Application.Backtesting
return result;
}
- public async Task RunScalpingBotBacktest(
+ ///
+ /// Runs a unified trading bot backtest with the specified configuration and date range.
+ /// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
+ ///
+ /// The trading bot configuration
+ /// The start date for the backtest
+ /// The end date for the backtest
+ /// The user running the backtest
+ /// Whether to save the backtest results
+ /// Optional pre-loaded candles
+ /// The backtest results
+ public async Task RunTradingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
@@ -64,12 +75,17 @@ namespace Managing.Application.Backtesting
List? initialCandles = null)
{
var account = await GetAccountFromConfig(config);
- var scalpingBot = _botFactory.CreateBacktestScalpingBot(config);
- scalpingBot.LoadScenario(config.ScenarioName);
- scalpingBot.User = user;
- await scalpingBot.LoadAccount();
+
+ // Set FlipPosition based on BotType
+ config.FlipPosition = config.BotType == BotType.FlippingBot;
+
+ var tradingBot = _botFactory.CreateBacktestTradingBot(config);
+ tradingBot.LoadScenario(config.ScenarioName);
+ tradingBot.User = user;
+ await tradingBot.LoadAccount();
+
var candles = initialCandles ?? GetCandles(account, config.Ticker, config.Timeframe, startDate, endDate);
- var result = GetBacktestingResult(config, scalpingBot, candles);
+ var result = GetBacktestingResult(config, tradingBot, candles);
if (user != null)
{
@@ -88,6 +104,52 @@ namespace Managing.Application.Backtesting
return result;
}
+ ///
+ /// Runs a unified trading bot backtest with pre-loaded candles.
+ /// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
+ ///
+ /// The trading bot configuration
+ /// The candles to use for backtesting
+ /// The user running the backtest
+ /// The backtest results
+ public async Task RunTradingBotBacktest(
+ TradingBotConfig config,
+ List candles,
+ User user = null)
+ {
+ var account = await GetAccountFromConfig(config);
+
+ // Set FlipPosition based on BotType
+ config.FlipPosition = config.BotType == BotType.FlippingBot;
+
+ var tradingBot = _botFactory.CreateBacktestTradingBot(config);
+ tradingBot.LoadScenario(config.ScenarioName);
+ tradingBot.User = user;
+ await tradingBot.LoadAccount();
+
+ var result = GetBacktestingResult(config, tradingBot, candles);
+
+ if (user != null)
+ {
+ result.User = user;
+ }
+
+ return result;
+ }
+
+ // Legacy methods - maintained for backward compatibility
+ public async Task RunScalpingBotBacktest(
+ TradingBotConfig config,
+ DateTime startDate,
+ DateTime endDate,
+ User user = null,
+ bool save = false,
+ List? initialCandles = null)
+ {
+ config.BotType = BotType.ScalpingBot; // Ensure correct type
+ return await RunTradingBotBacktest(config, startDate, endDate, user, save, initialCandles);
+ }
+
public async Task RunFlippingBotBacktest(
TradingBotConfig config,
DateTime startDate,
@@ -96,30 +158,8 @@ namespace Managing.Application.Backtesting
bool save = false,
List? initialCandles = null)
{
- var account = await GetAccountFromConfig(config);
- var flippingBot = _botFactory.CreateBacktestFlippingBot(config);
- flippingBot.LoadScenario(config.ScenarioName);
- flippingBot.User = user;
- await flippingBot.LoadAccount();
-
- var candles = initialCandles ?? GetCandles(account, config.Ticker, config.Timeframe, startDate, endDate);
- var result = GetBacktestingResult(config, flippingBot, candles);
-
- if (user != null)
- {
- result.User = user;
- }
-
- // Set start and end dates
- result.StartDate = startDate;
- result.EndDate = endDate;
-
- if (save)
- {
- _backtestRepository.InsertBacktestForUser(user, result);
- }
-
- return result;
+ config.BotType = BotType.FlippingBot; // Ensure correct type
+ return await RunTradingBotBacktest(config, startDate, endDate, user, save, initialCandles);
}
public async Task RunScalpingBotBacktest(
@@ -127,20 +167,8 @@ namespace Managing.Application.Backtesting
List candles,
User user = null)
{
- var account = await GetAccountFromConfig(config);
- var bot = _botFactory.CreateBacktestScalpingBot(config);
- bot.LoadScenario(config.ScenarioName);
- bot.User = user;
- await bot.LoadAccount();
-
- var result = GetBacktestingResult(config, bot, candles);
-
- if (user != null)
- {
- result.User = user;
- }
-
- return result;
+ config.BotType = BotType.ScalpingBot; // Ensure correct type
+ return await RunTradingBotBacktest(config, candles, user);
}
public async Task RunFlippingBotBacktest(
@@ -148,20 +176,8 @@ namespace Managing.Application.Backtesting
List candles,
User user = null)
{
- var account = await GetAccountFromConfig(config);
- var bot = _botFactory.CreateBacktestFlippingBot(config);
- bot.LoadScenario(config.ScenarioName);
- bot.User = user;
- await bot.LoadAccount();
-
- var result = GetBacktestingResult(config, bot, candles);
-
- if (user != null)
- {
- result.User = user;
- }
-
- return result;
+ config.BotType = BotType.FlippingBot; // Ensure correct type
+ return await RunTradingBotBacktest(config, candles, user);
}
private async Task GetAccountFromConfig(TradingBotConfig config)
diff --git a/src/Managing.Application/Bots/Base/BotFactory.cs b/src/Managing.Application/Bots/Base/BotFactory.cs
index fffa32d..f0ecb99 100644
--- a/src/Managing.Application/Bots/Base/BotFactory.cs
+++ b/src/Managing.Application/Bots/Base/BotFactory.cs
@@ -37,10 +37,37 @@ namespace Managing.Application.Bots.Base
return new SimpleBot(botName, _tradingBotLogger, workflow, _botService);
}
+ ITradingBot IBotFactory.CreateTradingBot(TradingBotConfig config)
+ {
+ return new TradingBot(
+ _exchangeService,
+ _tradingBotLogger,
+ _tradingService,
+ _accountService,
+ _messengerService,
+ _botService,
+ config);
+ }
+
+ ITradingBot IBotFactory.CreateBacktestTradingBot(TradingBotConfig config)
+ {
+ config.IsForBacktest = true;
+ return new TradingBot(
+ _exchangeService,
+ _tradingBotLogger,
+ _tradingService,
+ _accountService,
+ _messengerService,
+ _botService,
+ config);
+ }
+
+ // Legacy methods for backward compatibility - will be deprecated
ITradingBot IBotFactory.CreateScalpingBot(TradingBotConfig config)
{
config.BotType = BotType.ScalpingBot;
- return new ScalpingBot(
+ config.FlipPosition = false;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -54,7 +81,8 @@ namespace Managing.Application.Bots.Base
{
config.BotType = BotType.ScalpingBot;
config.IsForBacktest = true;
- return new ScalpingBot(
+ config.FlipPosition = false;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -67,7 +95,8 @@ namespace Managing.Application.Bots.Base
public ITradingBot CreateFlippingBot(TradingBotConfig config)
{
config.BotType = BotType.FlippingBot;
- return new FlippingBot(
+ config.FlipPosition = true;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -81,7 +110,8 @@ namespace Managing.Application.Bots.Base
{
config.BotType = BotType.FlippingBot;
config.IsForBacktest = true;
- return new FlippingBot(
+ config.FlipPosition = true;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
diff --git a/src/Managing.Application/Bots/FlippingBot.cs b/src/Managing.Application/Bots/FlippingBot.cs
deleted file mode 100644
index 45d283a..0000000
--- a/src/Managing.Application/Bots/FlippingBot.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Managing.Application.Abstractions;
-using Managing.Application.Abstractions.Services;
-using Managing.Domain.Bots;
-using Microsoft.Extensions.Logging;
-using static Managing.Common.Enums;
-
-namespace Managing.Application.Bots
-{
- public class FlippingBot : TradingBot
- {
- public FlippingBot(
- IExchangeService exchangeService,
- ILogger logger,
- ITradingService tradingService,
- IAccountService accountService,
- IMessengerService messengerService,
- IBotService botService,
- TradingBotConfig config)
- : base(exchangeService, logger, tradingService, accountService, messengerService, botService, config)
- {
- Config.BotType = BotType.FlippingBot;
- Config.FlipPosition = true;
- }
-
- public sealed override void Start()
- {
- Logger.LogInformation($"{Name} - Bot Started");
- base.Start();
- 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
deleted file mode 100644
index 1d92e5a..0000000
--- a/src/Managing.Application/Bots/ScalpingBot.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Managing.Application.Abstractions;
-using Managing.Application.Abstractions.Services;
-using Managing.Domain.Bots;
-using Microsoft.Extensions.Logging;
-using static Managing.Common.Enums;
-
-namespace Managing.Application.Bots
-{
- public class ScalpingBot : TradingBot
- {
- public ScalpingBot(
- IExchangeService exchangeService,
- ILogger logger,
- ITradingService tradingService,
- IAccountService accountService,
- IMessengerService messengerService,
- IBotService botService,
- TradingBotConfig config)
- : base(exchangeService, logger, tradingService, accountService, messengerService, botService, config)
- {
- Config.BotType = BotType.ScalpingBot;
- }
-
- public sealed override void Start()
- {
- Logger.LogInformation($"{Name} - Bot Started");
- base.Start();
- Logger.LogInformation($"Starting {Name} bot - Status : {Status}");
- }
- }
-}
\ No newline at end of file
diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs
index 34863ed..2023c7b 100644
--- a/src/Managing.Application/Bots/TradingBot.cs
+++ b/src/Managing.Application/Bots/TradingBot.cs
@@ -471,51 +471,74 @@ public class TradingBot : Bot, ITradingBot
// Check time-based position management (only if MaxPositionTimeHours is set)
if (Config.MaxPositionTimeHours.HasValue)
{
- var isPositionInProfit = await IsPositionInProfit(positionForSignal, lastCandle.Close);
- var isAtBreakeven = Math.Abs(lastCandle.Close - positionForSignal.Open.Price) < 0.01m; // Small tolerance for breakeven
var hasExceededTimeLimit = HasPositionExceededTimeLimit(positionForSignal, currentTime);
-
+
// Calculate current unrealized PNL for logging
var currentPnl = CalculateUnrealizedPnl(positionForSignal, lastCandle.Close);
- var pnlPercentage = Math.Round((currentPnl / (positionForSignal.Open.Price * positionForSignal.Open.Quantity)) * 100, 2);
+ var pnlPercentage =
+ Math.Round(
+ (currentPnl / (positionForSignal.Open.Price * positionForSignal.Open.Quantity)) * 100, 2);
// Early closure logic when CloseEarlyWhenProfitable is enabled
- if (Config.CloseEarlyWhenProfitable && (isPositionInProfit || isAtBreakeven))
+ if (Config.CloseEarlyWhenProfitable)
{
- await LogInformation(
- $"Closing position early due to profitability - Position opened at {positionForSignal.Open.Date}, " +
- $"current time {currentTime}. Position is {(isPositionInProfit ? "in profit" : "at breakeven")} " +
- $"(entry: {positionForSignal.Open.Price}, current: {lastCandle.Close}). " +
- $"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%). " +
- $"CloseEarlyWhenProfitable is enabled.");
- await CloseTrade(signal, positionForSignal, positionForSignal.Open, lastCandle.Close, true);
- return;
- }
-
- // Time limit exceeded logic
- if (hasExceededTimeLimit)
- {
- if (Config.CloseEarlyWhenProfitable || isPositionInProfit || isAtBreakeven)
+ var isPositionInProfit = await IsPositionInProfit(positionForSignal, lastCandle.Close);
+ var isAtBreakeven =
+ Math.Abs(lastCandle.Close - positionForSignal.Open.Price) <
+ 0.01m; // Small tolerance for breakeven
+
+ if (isPositionInProfit || isAtBreakeven)
{
- // Close when time limit is reached if:
- // 1. CloseEarlyWhenProfitable is enabled (safety net), OR
- // 2. Position is in profit/breakeven (when CloseEarlyWhenProfitable is disabled)
await LogInformation(
- $"Closing position due to time limit - Position opened at {positionForSignal.Open.Date}, " +
- $"current time {currentTime}, max time limit {Config.MaxPositionTimeHours} hours. " +
- $"Position is {(isPositionInProfit ? "in profit" : isAtBreakeven ? "at breakeven" : "at a loss")} " +
+ $"Closing position early due to profitability - Position opened at {positionForSignal.Open.Date}, " +
+ $"current time {currentTime}. Position is {(isPositionInProfit ? "in profit" : "at breakeven")} " +
$"(entry: {positionForSignal.Open.Price}, current: {lastCandle.Close}). " +
- $"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%)");
+ $"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%). " +
+ $"CloseEarlyWhenProfitable is enabled.");
await CloseTrade(signal, positionForSignal, positionForSignal.Open, lastCandle.Close, true);
return;
}
- else
+
+ // Time limit exceeded logic when CloseEarlyWhenProfitable is enabled
+ if (hasExceededTimeLimit && (isPositionInProfit || isAtBreakeven))
+ {
+ await LogInformation(
+ $"Closing position due to time limit - Position opened at {positionForSignal.Open.Date}, " +
+ $"current time {currentTime}, max time limit {Config.MaxPositionTimeHours} hours. " +
+ $"Position is {(isPositionInProfit ? "in profit" : "at breakeven")} " +
+ $"(entry: {positionForSignal.Open.Price}, current: {lastCandle.Close}). " +
+ $"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%). " +
+ $"CloseEarlyWhenProfitable is enabled.");
+ await CloseTrade(signal, positionForSignal, positionForSignal.Open, lastCandle.Close, true);
+ return;
+ }
+ else if (hasExceededTimeLimit)
{
await LogInformation(
$"Position has exceeded time limit ({Config.MaxPositionTimeHours} hours) but is at a loss " +
$"(entry: {positionForSignal.Open.Price}, current: {lastCandle.Close}). " +
$"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%). " +
- $"CloseEarlyWhenProfitable is disabled - waiting for profit or breakeven before closing.");
+ $"CloseEarlyWhenProfitable is enabled - waiting for profit or breakeven before closing.");
+ }
+ }
+ else
+ {
+ // Time limit exceeded logic when CloseEarlyWhenProfitable is disabled
+ if (hasExceededTimeLimit)
+ {
+ var isPositionInProfit = await IsPositionInProfit(positionForSignal, lastCandle.Close);
+ var profitStatus = isPositionInProfit ? "in profit" :
+ Math.Abs(lastCandle.Close - positionForSignal.Open.Price) < 0.01m ? "at breakeven" : "at a loss";
+
+ await LogInformation(
+ $"Closing position due to time limit - Position opened at {positionForSignal.Open.Date}, " +
+ $"current time {currentTime}, max time limit {Config.MaxPositionTimeHours} hours. " +
+ $"Position is {profitStatus} " +
+ $"(entry: {positionForSignal.Open.Price}, current: {lastCandle.Close}). " +
+ $"Current PNL: ${currentPnl:F2} ({pnlPercentage:F2}%). " +
+ $"CloseEarlyWhenProfitable is disabled - closing regardless of profit status.");
+ await CloseTrade(signal, positionForSignal, positionForSignal.Open, lastCandle.Close, true);
+ return;
}
}
}
@@ -665,7 +688,6 @@ public class TradingBot : Bot, ITradingBot
$"Position {previousSignal.Identifier} is not in profit (entry: {openedPosition.Open.Price}, current: {lastPrice}). " +
$"Signal {signal.Identifier} will wait for position to become profitable before flipping.");
- // Keep signal in waiting status to check again on next execution
SetSignalStatus(signal.Identifier, SignalStatus.Expired);
return;
}
@@ -1046,7 +1068,7 @@ public class TradingBot : Bot, ITradingBot
private void SetSignalStatus(string signalIdentifier, SignalStatus signalStatus)
{
- if (Signals.Any(s => s.Identifier == signalIdentifier))
+ if (Signals.Any(s => s.Identifier == signalIdentifier && s.Status != signalStatus))
{
Signals.First(s => s.Identifier == signalIdentifier).Status = signalStatus;
Logger.LogInformation($"Signal {signalIdentifier} is now {signalStatus}");
@@ -1294,7 +1316,7 @@ public class TradingBot : Bot, ITradingBot
var timeOpen = currentTime - position.Open.Date;
var maxTimeAllowed = TimeSpan.FromHours((double)Config.MaxPositionTimeHours.Value);
-
+
return timeOpen >= maxTimeAllowed;
}
@@ -1360,11 +1382,11 @@ public class TradingBot : Bot, ITradingBot
// Log the configuration update
await LogInformation($"Updating bot configuration. Previous config: " +
- $"Balance: {Config.BotTradingBalance}, " +
- $"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
- $"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
- $"Cooldown: {Config.CooldownPeriod}, " +
- $"MaxLoss: {Config.MaxLossStreak}");
+ $"Balance: {Config.BotTradingBalance}, " +
+ $"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
+ $"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
+ $"Cooldown: {Config.CooldownPeriod}, " +
+ $"MaxLoss: {Config.MaxLossStreak}");
// Update the configuration
Config = newConfig;
@@ -1388,11 +1410,11 @@ public class TradingBot : Bot, ITradingBot
}
await LogInformation($"Bot configuration updated successfully. New config: " +
- $"Balance: {Config.BotTradingBalance}, " +
- $"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
- $"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
- $"Cooldown: {Config.CooldownPeriod}, " +
- $"MaxLoss: {Config.MaxLossStreak}");
+ $"Balance: {Config.BotTradingBalance}, " +
+ $"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
+ $"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
+ $"Cooldown: {Config.CooldownPeriod}, " +
+ $"MaxLoss: {Config.MaxLossStreak}");
// Save the updated configuration as backup
if (!Config.IsForBacktest)
diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs
index 24739ca..6e570a0 100644
--- a/src/Managing.Application/ManageBot/BotService.cs
+++ b/src/Managing.Application/ManageBot/BotService.cs
@@ -146,7 +146,7 @@ namespace Managing.Application.ManageBot
CloseEarlyWhenProfitable = scalpingBotData.CloseEarlyWhenProfitable
};
- bot = CreateScalpingBot(scalpingConfig);
+ bot = CreateTradingBot(scalpingConfig);
botTask = Task.Run(() => InitBot((ITradingBot)bot, backupBot));
break;
@@ -176,7 +176,7 @@ namespace Managing.Application.ManageBot
CloseEarlyWhenProfitable = flippingBotData.CloseEarlyWhenProfitable
};
- bot = CreateFlippingBot(flippingConfig);
+ bot = CreateTradingBot(flippingConfig);
botTask = Task.Run(() => InitBot((ITradingBot)bot, backupBot));
break;
}
@@ -282,9 +282,35 @@ namespace Managing.Application.ManageBot
return false;
}
+ public ITradingBot CreateTradingBot(TradingBotConfig config)
+ {
+ return new TradingBot(
+ _exchangeService,
+ _tradingBotLogger,
+ _tradingService,
+ _accountService,
+ _messengerService,
+ this,
+ config);
+ }
+
+ public ITradingBot CreateBacktestTradingBot(TradingBotConfig config)
+ {
+ config.IsForBacktest = true;
+ return new TradingBot(
+ _exchangeService,
+ _tradingBotLogger,
+ _tradingService,
+ _accountService,
+ _messengerService,
+ this,
+ config);
+ }
+
public ITradingBot CreateScalpingBot(TradingBotConfig config)
{
- return new ScalpingBot(
+ config.FlipPosition = false;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -297,7 +323,8 @@ namespace Managing.Application.ManageBot
public ITradingBot CreateBacktestScalpingBot(TradingBotConfig config)
{
config.IsForBacktest = true;
- return new ScalpingBot(
+ config.FlipPosition = false;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -309,7 +336,8 @@ namespace Managing.Application.ManageBot
public ITradingBot CreateFlippingBot(TradingBotConfig config)
{
- return new FlippingBot(
+ config.FlipPosition = true;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
@@ -322,7 +350,8 @@ namespace Managing.Application.ManageBot
public ITradingBot CreateBacktestFlippingBot(TradingBotConfig config)
{
config.IsForBacktest = true;
- return new FlippingBot(
+ config.FlipPosition = true;
+ return new TradingBot(
_exchangeService,
_tradingBotLogger,
_tradingService,
diff --git a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs
index f8b656b..dfcdbe8 100644
--- a/src/Managing.Application/ManageBot/StartBotCommandHandler.cs
+++ b/src/Managing.Application/ManageBot/StartBotCommandHandler.cs
@@ -73,7 +73,7 @@ namespace Managing.Application.ManageBot
MaxLossStreak = request.Config.MaxLossStreak,
MaxPositionTimeHours = request.Config.MaxPositionTimeHours, // Properly handle nullable value
FlipOnlyWhenInProfit = request.Config.FlipOnlyWhenInProfit,
- FlipPosition = request.Config.FlipPosition,
+ FlipPosition = request.Config.BotType == BotType.FlippingBot, // Set FlipPosition based on BotType
Name = request.Config.Name ?? request.Name,
CloseEarlyWhenProfitable = request.Config.CloseEarlyWhenProfitable
};
@@ -87,24 +87,15 @@ namespace Managing.Application.ManageBot
return bot.GetStatus();
case BotType.ScalpingBot:
- var sBot = _botFactory.CreateScalpingBot(configToUse);
- sBot.User = request.User;
-
- // Log the configuration being used
- await LogBotConfigurationAsync(sBot, "ScalpingBot created");
-
- _botService.AddTradingBotToCache(sBot);
- return sBot.GetStatus();
-
case BotType.FlippingBot:
- var fBot = _botFactory.CreateFlippingBot(configToUse);
- fBot.User = request.User;
+ var tradingBot = _botFactory.CreateTradingBot(configToUse);
+ tradingBot.User = request.User;
// Log the configuration being used
- await LogBotConfigurationAsync(fBot, "FlippingBot created");
+ await LogBotConfigurationAsync(tradingBot, $"{configToUse.BotType} created");
- _botService.AddTradingBotToCache(fBot);
- return fBot.GetStatus();
+ _botService.AddTradingBotToCache(tradingBot);
+ return tradingBot.GetStatus();
}
return botStatus.ToString();
@@ -127,6 +118,7 @@ namespace Managing.Application.ManageBot
$"Balance: {config.BotTradingBalance}, " +
$"MaxTime: {config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
$"FlipOnlyProfit: {config.FlipOnlyWhenInProfit}, " +
+ $"FlipPosition: {config.FlipPosition}, " +
$"Cooldown: {config.CooldownPeriod}, " +
$"MaxLoss: {config.MaxLossStreak}";
diff --git a/src/Managing.Bootstrap/WorkersBootstrap.cs b/src/Managing.Bootstrap/WorkersBootstrap.cs
index cd9dea7..f99feaa 100644
--- a/src/Managing.Bootstrap/WorkersBootstrap.cs
+++ b/src/Managing.Bootstrap/WorkersBootstrap.cs
@@ -101,6 +101,7 @@ public static class WorkersBootstrap
// Repositories
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();