Refactoring TradingBotBase.cs + clean architecture (#38)

* Refactoring TradingBotBase.cs + clean architecture

* Fix basic tests

* Fix tests

* Fix workers

* Fix open positions

* Fix closing position stucking the grain

* Fix comments

* Refactor candle handling to use IReadOnlyList for chronological order preservation across various components
This commit is contained in:
Oda
2025-12-01 19:32:06 +07:00
committed by GitHub
parent ab26260f6d
commit 9d536ea49e
74 changed files with 4525 additions and 2350 deletions

View File

@@ -568,7 +568,7 @@ public class BacktestController : BaseController
Timeframe = request.Config.Timeframe,
IsForWatchingOnly = request.Config.IsForWatchingOnly,
BotTradingBalance = request.Config.BotTradingBalance,
IsForBacktest = true,
TradingType = TradingType.BacktestFutures,
CooldownPeriod = request.Config.CooldownPeriod ?? 1,
MaxLossStreak = request.Config.MaxLossStreak,
MaxPositionTimeHours = request.Config.MaxPositionTimeHours,

View File

@@ -814,7 +814,7 @@ public class BotController : BaseController
UseForSignalFiltering = request.Config.UseForSignalFiltering,
UseForDynamicStopLoss = request.Config.UseForDynamicStopLoss,
// Set computed/default properties
IsForBacktest = false,
TradingType = TradingType.Futures,
FlipPosition = request.Config.FlipPosition,
Name = request.Config.Name
};
@@ -976,7 +976,7 @@ public class BotController : BaseController
UseForSignalFiltering = request.Config.UseForSignalFiltering,
UseForDynamicStopLoss = request.Config.UseForDynamicStopLoss,
// Set computed/default properties
IsForBacktest = false,
TradingType = TradingType.Futures,
FlipPosition = request.Config.FlipPosition,
Name = request.Config.Name
};

View File

@@ -350,7 +350,9 @@ public class DataController : ControllerBase
{
// Map ScenarioRequest to domain Scenario object
var domainScenario = MapScenarioRequestToScenario(request.Scenario);
indicatorsValues = TradingBox.CalculateIndicatorsValues(domainScenario, candles);
// Convert to ordered List to preserve chronological order for indicators
var candlesList = candles.OrderBy(c => c.Date).ToList();
indicatorsValues = TradingBox.CalculateIndicatorsValues(domainScenario, candlesList);
}
return Ok(new CandlesWithIndicatorsResponse

View File

@@ -25,7 +25,8 @@ namespace Managing.Api.Controllers;
public class TradingController : BaseController
{
private readonly ICommandHandler<OpenPositionRequest, Position> _openTradeCommandHandler;
private readonly ICommandHandler<ClosePositionCommand, Position> _closeTradeCommandHandler;
private readonly ICommandHandler<CloseBacktestFuturesPositionCommand, Position> _closeBacktestFuturesCommandHandler;
private readonly ICommandHandler<CloseFuturesPositionCommand, Position> _closeFuturesCommandHandler;
private readonly ITradingService _tradingService;
private readonly IMoneyManagementService _moneyManagementService;
private readonly IMediator _mediator;
@@ -50,7 +51,8 @@ public class TradingController : BaseController
public TradingController(
ILogger<TradingController> logger,
ICommandHandler<OpenPositionRequest, Position> openTradeCommandHandler,
ICommandHandler<ClosePositionCommand, Position> closeTradeCommandHandler,
ICommandHandler<CloseBacktestFuturesPositionCommand, Position> closeBacktestFuturesCommandHandler,
ICommandHandler<CloseFuturesPositionCommand, Position> closeFuturesCommandHandler,
ITradingService tradingService,
IMediator mediator, IMoneyManagementService moneyManagementService,
IUserService userService, IAdminConfigurationService adminService,
@@ -60,7 +62,8 @@ public class TradingController : BaseController
{
_logger = logger;
_openTradeCommandHandler = openTradeCommandHandler;
_closeTradeCommandHandler = closeTradeCommandHandler;
_closeBacktestFuturesCommandHandler = closeBacktestFuturesCommandHandler;
_closeFuturesCommandHandler = closeFuturesCommandHandler;
_tradingService = tradingService;
_mediator = mediator;
_moneyManagementService = moneyManagementService;
@@ -98,20 +101,6 @@ public class TradingController : BaseController
return Ok(result);
}
/// <summary>
/// Closes a position identified by its unique identifier.
/// </summary>
/// <param name="identifier">The unique identifier of the position to close.</param>
/// <returns>The closed position.</returns>
[HttpPost("ClosePosition")]
public async Task<ActionResult<Position>> ClosePosition(Guid identifier)
{
var position = await _tradingService.GetPositionByIdentifierAsync(identifier);
var result = await _closeTradeCommandHandler.Handle(new ClosePositionCommand(position, position.AccountId));
return Ok(result);
}
/// <summary>
/// Opens a new position based on the provided parameters.
/// </summary>