Add bundle backtest refact + fix whitelist
This commit is contained in:
@@ -419,21 +419,30 @@ public class BacktestController : BaseController
|
||||
/// Creates a bundle backtest request with the specified configurations.
|
||||
/// This endpoint creates a request that will be processed by a background worker.
|
||||
/// </summary>
|
||||
/// <param name="requests">The list of backtest requests to execute.</param>
|
||||
/// <param name="name">Display name for the bundle (required).</param>
|
||||
/// <param name="request">The bundle backtest request with variant lists.</param>
|
||||
/// <returns>The bundle backtest request with ID for tracking progress.</returns>
|
||||
[HttpPost]
|
||||
[Route("BacktestBundle")]
|
||||
public async Task<ActionResult<BundleBacktestRequest>> RunBundle([FromBody] RunBundleBacktestRequest request)
|
||||
{
|
||||
if (request?.Requests == null || !request.Requests.Any())
|
||||
if (request?.UniversalConfig == null)
|
||||
{
|
||||
return BadRequest("At least one backtest request is required");
|
||||
return BadRequest("Universal configuration is required");
|
||||
}
|
||||
|
||||
if (request.Requests.Count > 10)
|
||||
if (request.DateTimeRanges == null || !request.DateTimeRanges.Any())
|
||||
{
|
||||
return BadRequest("Maximum of 10 backtests allowed per bundle request");
|
||||
return BadRequest("At least one DateTime range is required");
|
||||
}
|
||||
|
||||
if (request.MoneyManagementVariants == null || !request.MoneyManagementVariants.Any())
|
||||
{
|
||||
return BadRequest("At least one money management variant is required");
|
||||
}
|
||||
|
||||
if (request.TickerVariants == null || !request.TickerVariants.Any())
|
||||
{
|
||||
return BadRequest("At least one ticker variant is required");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Name))
|
||||
@@ -441,32 +450,35 @@ public class BacktestController : BaseController
|
||||
return BadRequest("Bundle name is required");
|
||||
}
|
||||
|
||||
// Calculate total number of backtests
|
||||
var totalBacktests = request.DateTimeRanges.Count * request.MoneyManagementVariants.Count * request.TickerVariants.Count;
|
||||
|
||||
if (totalBacktests > 100)
|
||||
{
|
||||
return BadRequest("Maximum of 100 backtests allowed per bundle request");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var user = await GetUser();
|
||||
|
||||
// Validate all requests before creating the bundle
|
||||
foreach (var req in request.Requests)
|
||||
// Validate universal configuration
|
||||
if (string.IsNullOrEmpty(request.UniversalConfig.AccountName))
|
||||
{
|
||||
if (req?.Config == null)
|
||||
{
|
||||
return BadRequest("Invalid request: Configuration is required");
|
||||
}
|
||||
return BadRequest("Account name is required in universal configuration");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(req.Config.AccountName))
|
||||
{
|
||||
return BadRequest("Invalid request: Account name is required");
|
||||
}
|
||||
if (string.IsNullOrEmpty(request.UniversalConfig.ScenarioName) && request.UniversalConfig.Scenario == null)
|
||||
{
|
||||
return BadRequest("Either scenario name or scenario object is required in universal configuration");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(req.Config.ScenarioName) && req.Config.Scenario == null)
|
||||
// Validate all money management variants
|
||||
foreach (var mmVariant in request.MoneyManagementVariants)
|
||||
{
|
||||
if (mmVariant.MoneyManagement == null)
|
||||
{
|
||||
return BadRequest("Invalid request: Either scenario name or scenario object is required");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(req.Config.MoneyManagementName) && req.Config.MoneyManagement == null)
|
||||
{
|
||||
return BadRequest(
|
||||
"Invalid request: Either money management name or money management object is required");
|
||||
return BadRequest("Each money management variant must have a money management object");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,8 +486,11 @@ public class BacktestController : BaseController
|
||||
var bundleRequest = new BundleBacktestRequest
|
||||
{
|
||||
User = user,
|
||||
BacktestRequestsJson = JsonSerializer.Serialize(request.Requests),
|
||||
TotalBacktests = request.Requests.Count,
|
||||
UniversalConfigJson = JsonSerializer.Serialize(request.UniversalConfig),
|
||||
DateTimeRangesJson = JsonSerializer.Serialize(request.DateTimeRanges),
|
||||
MoneyManagementVariantsJson = JsonSerializer.Serialize(request.MoneyManagementVariants),
|
||||
TickerVariantsJson = JsonSerializer.Serialize(request.TickerVariants),
|
||||
TotalBacktests = totalBacktests,
|
||||
CompletedBacktests = 0,
|
||||
FailedBacktests = 0,
|
||||
Status = BundleBacktestRequestStatus.Pending,
|
||||
@@ -491,6 +506,72 @@ public class BacktestController : BaseController
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates individual backtest requests from variant configuration
|
||||
/// </summary>
|
||||
/// <param name="request">The bundle backtest request</param>
|
||||
/// <returns>List of individual backtest requests</returns>
|
||||
private List<RunBacktestRequest> GenerateBacktestRequests(RunBundleBacktestRequest request)
|
||||
{
|
||||
var backtestRequests = new List<RunBacktestRequest>();
|
||||
|
||||
foreach (var dateRange in request.DateTimeRanges)
|
||||
{
|
||||
foreach (var mmVariant in request.MoneyManagementVariants)
|
||||
{
|
||||
foreach (var ticker in request.TickerVariants)
|
||||
{
|
||||
var config = new TradingBotConfigRequest
|
||||
{
|
||||
AccountName = request.UniversalConfig.AccountName,
|
||||
Ticker = ticker,
|
||||
Timeframe = request.UniversalConfig.Timeframe,
|
||||
IsForWatchingOnly = request.UniversalConfig.IsForWatchingOnly,
|
||||
BotTradingBalance = request.UniversalConfig.BotTradingBalance,
|
||||
Name = $"{request.UniversalConfig.BotName}_{ticker}_{dateRange.StartDate:yyyyMMdd}_{dateRange.EndDate:yyyyMMdd}",
|
||||
FlipPosition = request.UniversalConfig.FlipPosition,
|
||||
CooldownPeriod = request.UniversalConfig.CooldownPeriod,
|
||||
MaxLossStreak = request.UniversalConfig.MaxLossStreak,
|
||||
Scenario = request.UniversalConfig.Scenario,
|
||||
ScenarioName = request.UniversalConfig.ScenarioName,
|
||||
MoneyManagement = mmVariant.MoneyManagement,
|
||||
MaxPositionTimeHours = request.UniversalConfig.MaxPositionTimeHours,
|
||||
CloseEarlyWhenProfitable = request.UniversalConfig.CloseEarlyWhenProfitable,
|
||||
FlipOnlyWhenInProfit = request.UniversalConfig.FlipOnlyWhenInProfit,
|
||||
UseSynthApi = request.UniversalConfig.UseSynthApi,
|
||||
UseForPositionSizing = request.UniversalConfig.UseForPositionSizing,
|
||||
UseForSignalFiltering = request.UniversalConfig.UseForSignalFiltering,
|
||||
UseForDynamicStopLoss = request.UniversalConfig.UseForDynamicStopLoss
|
||||
};
|
||||
|
||||
var backtestRequest = new RunBacktestRequest
|
||||
{
|
||||
Config = config,
|
||||
StartDate = dateRange.StartDate,
|
||||
EndDate = dateRange.EndDate,
|
||||
Balance = request.UniversalConfig.BotTradingBalance,
|
||||
WatchOnly = request.UniversalConfig.WatchOnly,
|
||||
Save = request.UniversalConfig.Save,
|
||||
WithCandles = request.UniversalConfig.WithCandles,
|
||||
MoneyManagement = mmVariant.MoneyManagement != null ?
|
||||
new MoneyManagement
|
||||
{
|
||||
Name = mmVariant.MoneyManagement.Name,
|
||||
Timeframe = mmVariant.MoneyManagement.Timeframe,
|
||||
StopLoss = mmVariant.MoneyManagement.StopLoss,
|
||||
TakeProfit = mmVariant.MoneyManagement.TakeProfit,
|
||||
Leverage = mmVariant.MoneyManagement.Leverage
|
||||
} : null
|
||||
};
|
||||
|
||||
backtestRequests.Add(backtestRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return backtestRequests;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all bundle backtest requests for the authenticated user.
|
||||
/// </summary>
|
||||
@@ -741,35 +822,3 @@ public class BacktestController : BaseController
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request model for running a backtest
|
||||
/// </summary>
|
||||
public class RunBacktestRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The trading bot configuration request to use for the backtest
|
||||
/// </summary>
|
||||
public TradingBotConfigRequest Config { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The start date for the backtest
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The end date for the backtest
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to save the backtest results
|
||||
/// </summary>
|
||||
public bool Save { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to include candles and indicators values in the response.
|
||||
/// Set to false to reduce response size dramatically.
|
||||
/// </summary>
|
||||
public bool WithCandles { get; set; } = false;
|
||||
}
|
||||
Reference in New Issue
Block a user