Fix worker and signal
This commit is contained in:
@@ -8,8 +8,13 @@ public interface IBacktestRepository
|
|||||||
void InsertBacktestForUser(User user, Backtest result);
|
void InsertBacktestForUser(User user, Backtest result);
|
||||||
IEnumerable<Backtest> GetBacktestsByUser(User user);
|
IEnumerable<Backtest> GetBacktestsByUser(User user);
|
||||||
IEnumerable<Backtest> GetBacktestsByRequestId(string requestId);
|
IEnumerable<Backtest> GetBacktestsByRequestId(string requestId);
|
||||||
(IEnumerable<LightBacktest> Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc");
|
|
||||||
(IEnumerable<LightBacktest> Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc");
|
(IEnumerable<LightBacktest> Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page,
|
||||||
|
int pageSize, string sortBy = "score", string sortOrder = "desc");
|
||||||
|
|
||||||
|
(IEnumerable<LightBacktest> Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page,
|
||||||
|
int pageSize, string sortBy = "score", string sortOrder = "desc");
|
||||||
|
|
||||||
Backtest GetBacktestByIdForUser(User user, string id);
|
Backtest GetBacktestByIdForUser(User user, string id);
|
||||||
void DeleteBacktestByIdForUser(User user, string id);
|
void DeleteBacktestByIdForUser(User user, string id);
|
||||||
void DeleteBacktestsByIdsForUser(User user, IEnumerable<string> ids);
|
void DeleteBacktestsByIdsForUser(User user, IEnumerable<string> ids);
|
||||||
@@ -22,5 +27,5 @@ public interface IBacktestRepository
|
|||||||
BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id);
|
BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id);
|
||||||
void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest);
|
void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest);
|
||||||
void DeleteBundleBacktestRequestByIdForUser(User user, string id);
|
void DeleteBundleBacktestRequestByIdForUser(User user, string id);
|
||||||
IEnumerable<BundleBacktestRequest> GetPendingBundleBacktestRequests();
|
IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus status);
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id);
|
BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id);
|
||||||
void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest);
|
void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest);
|
||||||
void DeleteBundleBacktestRequestByIdForUser(User user, string id);
|
void DeleteBundleBacktestRequestByIdForUser(User user, string id);
|
||||||
IEnumerable<BundleBacktestRequest> GetPendingBundleBacktestRequests();
|
IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus status);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Get pending bundle backtest requests
|
// Get pending bundle backtest requests
|
||||||
var pendingRequests = _backtester.GetPendingBundleBacktestRequests();
|
var pendingRequests = _backtester.GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus.Pending);
|
||||||
|
|
||||||
foreach (var bundleRequest in pendingRequests)
|
foreach (var bundleRequest in pendingRequests)
|
||||||
{
|
{
|
||||||
@@ -46,6 +46,8 @@ public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
|
|||||||
|
|
||||||
await ProcessBundleRequest(bundleRequest, cancellationToken);
|
await ProcessBundleRequest(bundleRequest, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await RetryUnfinishedBacktestsInFailedBundles(cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -87,7 +89,11 @@ public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
|
|||||||
_backtester.UpdateBundleBacktestRequest(bundleRequest);
|
_backtester.UpdateBundleBacktestRequest(bundleRequest);
|
||||||
|
|
||||||
// Run the backtest directly with the strongly-typed request
|
// Run the backtest directly with the strongly-typed request
|
||||||
await RunSingleBacktest(runBacktestRequest, bundleRequest, i, cancellationToken);
|
var backtestId = await RunSingleBacktest(runBacktestRequest, bundleRequest, i, cancellationToken);
|
||||||
|
if (!string.IsNullOrEmpty(backtestId))
|
||||||
|
{
|
||||||
|
bundleRequest.Results.Add(backtestId);
|
||||||
|
}
|
||||||
|
|
||||||
// Update progress
|
// Update progress
|
||||||
bundleRequest.CompletedBacktests++;
|
bundleRequest.CompletedBacktests++;
|
||||||
@@ -140,13 +146,14 @@ public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Change RunSingleBacktest to accept RunBacktestRequest directly
|
// Change RunSingleBacktest to accept RunBacktestRequest directly
|
||||||
private async Task RunSingleBacktest(RunBacktestRequest runBacktestRequest, BundleBacktestRequest bundleRequest,
|
private async Task<string> RunSingleBacktest(RunBacktestRequest runBacktestRequest,
|
||||||
|
BundleBacktestRequest bundleRequest,
|
||||||
int index, CancellationToken cancellationToken)
|
int index, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (runBacktestRequest == null || runBacktestRequest.Config == null)
|
if (runBacktestRequest == null || runBacktestRequest.Config == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Invalid RunBacktestRequest in bundle (null config)");
|
_logger.LogError("Invalid RunBacktestRequest in bundle (null config)");
|
||||||
return;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map MoneyManagement
|
// Map MoneyManagement
|
||||||
@@ -232,11 +239,48 @@ public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
|
|||||||
runBacktestRequest.StartDate,
|
runBacktestRequest.StartDate,
|
||||||
runBacktestRequest.EndDate,
|
runBacktestRequest.EndDate,
|
||||||
bundleRequest.User, // No user context in worker
|
bundleRequest.User, // No user context in worker
|
||||||
runBacktestRequest.Save,
|
true,
|
||||||
runBacktestRequest.WithCandles,
|
runBacktestRequest.WithCandles,
|
||||||
bundleRequest.RequestId // Use bundleRequestId as requestId for traceability
|
bundleRequest.RequestId // Use bundleRequestId as requestId for traceability
|
||||||
);
|
);
|
||||||
|
|
||||||
_logger.LogInformation("Processed backtest for bundle request {RequestId}", bundleRequest.RequestId);
|
_logger.LogInformation("Processed backtest for bundle request {RequestId}", bundleRequest.RequestId);
|
||||||
|
// Assume the backtest is created and you have its ID (e.g., backtest.Id)
|
||||||
|
// Return the backtest ID
|
||||||
|
return result.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RetryUnfinishedBacktestsInFailedBundles(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var failedBundles = _backtester.GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus.Failed);
|
||||||
|
foreach (var failedBundle in failedBundles)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Use Results property to determine which backtests need to be retried
|
||||||
|
var succeededIds = new HashSet<string>(failedBundle.Results ?? new List<string>());
|
||||||
|
|
||||||
|
// Deserialize the original requests
|
||||||
|
var originalRequests =
|
||||||
|
JsonSerializer
|
||||||
|
.Deserialize<List<RunBacktestRequest>>(failedBundle.BacktestRequestsJson);
|
||||||
|
if (originalRequests == null) continue;
|
||||||
|
|
||||||
|
for (int i = 0; i < originalRequests.Count; i++)
|
||||||
|
{
|
||||||
|
var expectedId = /* logic to compute expected backtest id for this request */ string.Empty;
|
||||||
|
// If this backtest was not run or did not succeed, re-run it
|
||||||
|
if (!succeededIds.Contains(expectedId))
|
||||||
|
{
|
||||||
|
var backtestId = await RunSingleBacktest(originalRequests[i], failedBundle, i, cancellationToken);
|
||||||
|
if (!string.IsNullOrEmpty(backtestId))
|
||||||
|
{
|
||||||
|
failedBundle.Results?.Add(backtestId);
|
||||||
|
_backtester.UpdateBundleBacktestRequest(failedBundle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +200,7 @@ namespace Managing.Application.Backtesting
|
|||||||
}
|
}
|
||||||
|
|
||||||
tradingBot.User = user;
|
tradingBot.User = user;
|
||||||
await tradingBot.LoadAccount();
|
tradingBot.Account = await GetAccountFromConfig(config);
|
||||||
|
|
||||||
var result =
|
var result =
|
||||||
await GetBacktestingResult(config, tradingBot, candles, user, withCandles, requestId, metadata);
|
await GetBacktestingResult(config, tradingBot, candles, user, withCandles, requestId, metadata);
|
||||||
@@ -215,7 +215,16 @@ namespace Managing.Application.Backtesting
|
|||||||
|
|
||||||
private async Task<Account> GetAccountFromConfig(TradingBotConfig config)
|
private async Task<Account> GetAccountFromConfig(TradingBotConfig config)
|
||||||
{
|
{
|
||||||
var account = await _accountService.GetAccount(config.AccountName, false, false);
|
var accounts = _accountService.GetAccounts(false, false).ToArray();
|
||||||
|
var account = accounts.FirstOrDefault(a =>
|
||||||
|
a.Name.Equals(config.AccountName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
a.Exchange == TradingExchanges.GmxV2);
|
||||||
|
|
||||||
|
if (account == null && accounts.Any())
|
||||||
|
{
|
||||||
|
account = accounts.First();
|
||||||
|
}
|
||||||
|
|
||||||
if (account != null)
|
if (account != null)
|
||||||
{
|
{
|
||||||
return account;
|
return account;
|
||||||
@@ -606,9 +615,10 @@ namespace Managing.Application.Backtesting
|
|||||||
_backtestRepository.DeleteBundleBacktestRequestByIdForUser(user, id);
|
_backtestRepository.DeleteBundleBacktestRequestByIdForUser(user, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<BundleBacktestRequest> GetPendingBundleBacktestRequests()
|
public IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus status)
|
||||||
{
|
{
|
||||||
return _backtestRepository.GetPendingBundleBacktestRequests();
|
// Use the repository method to get all bundles, then filter by status
|
||||||
|
return _backtestRepository.GetBundleBacktestRequestsByStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
|
|
||||||
public async Task LoadAccount()
|
public async Task LoadAccount()
|
||||||
{
|
{
|
||||||
|
if (Config.IsForBacktest) return;
|
||||||
var account = await AccountService.GetAccount(Config.AccountName, false, false);
|
var account = await AccountService.GetAccount(Config.AccountName, false, false);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ public class NotifyBundleBacktestWorker : BaseWorker<NotifyBundleBacktestWorker>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Fetch all running bundle requests
|
// Fetch all running bundle requests
|
||||||
var runningBundles = _backtester.GetPendingBundleBacktestRequests()
|
var runningBundles = _backtester.GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus.Running);
|
||||||
.Where(b => b.Status == BundleBacktestRequestStatus.Running)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var bundle in runningBundles)
|
foreach (var bundle in runningBundles)
|
||||||
{
|
{
|
||||||
@@ -53,7 +51,8 @@ public class NotifyBundleBacktestWorker : BaseWorker<NotifyBundleBacktestWorker>
|
|||||||
var lightResponse = backtest as LightBacktest;
|
var lightResponse = backtest as LightBacktest;
|
||||||
if (lightResponse != null)
|
if (lightResponse != null)
|
||||||
{
|
{
|
||||||
await _hubContext.Clients.Group($"bundle-{requestId}").SendAsync("BundleBacktestUpdate", lightResponse, stoppingToken);
|
await _hubContext.Clients.Group($"bundle-{requestId}")
|
||||||
|
.SendAsync("BundleBacktestUpdate", lightResponse, stoppingToken);
|
||||||
_sentBacktestIds[requestId].Add(backtest.Id);
|
_sentBacktestIds[requestId].Add(backtest.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class BundleBacktestRequest
|
|||||||
RequestId = Guid.NewGuid().ToString();
|
RequestId = Guid.NewGuid().ToString();
|
||||||
CreatedAt = DateTime.UtcNow;
|
CreatedAt = DateTime.UtcNow;
|
||||||
Status = BundleBacktestRequestStatus.Pending;
|
Status = BundleBacktestRequestStatus.Pending;
|
||||||
Results = new List<Backtest>();
|
Results = new List<string>();
|
||||||
BacktestRequestsJson = string.Empty;
|
BacktestRequestsJson = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ public class BundleBacktestRequest
|
|||||||
RequestId = requestId;
|
RequestId = requestId;
|
||||||
CreatedAt = DateTime.UtcNow;
|
CreatedAt = DateTime.UtcNow;
|
||||||
Status = BundleBacktestRequestStatus.Pending;
|
Status = BundleBacktestRequestStatus.Pending;
|
||||||
Results = new List<Backtest>();
|
Results = new List<string>();
|
||||||
BacktestRequestsJson = string.Empty;
|
BacktestRequestsJson = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class BundleBacktestRequest
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The results of the bundle backtest execution
|
/// The results of the bundle backtest execution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Backtest> Results { get; set; } = new();
|
public List<string> Results { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total number of backtests in the bundle
|
/// Total number of backtests in the bundle
|
||||||
|
|||||||
@@ -320,8 +320,24 @@ public class BacktestRepository : IBacktestRepository
|
|||||||
|
|
||||||
public IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByUser(User user)
|
public IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByUser(User user)
|
||||||
{
|
{
|
||||||
var bundleRequests = _bundleBacktestRepository.AsQueryable()
|
var projection = Builders<BundleBacktestRequestDto>.Projection
|
||||||
.Where(b => b.User.Name == user.Name)
|
.Include(b => b.RequestId)
|
||||||
|
.Include(b => b.Status)
|
||||||
|
.Include(b => b.CreatedAt)
|
||||||
|
.Include(b => b.CurrentBacktest)
|
||||||
|
.Include(b => b.EstimatedTimeRemainingSeconds)
|
||||||
|
.Include(b => b.TotalBacktests)
|
||||||
|
.Include(b => b.CurrentBacktest)
|
||||||
|
.Include(b => b.CompletedAt)
|
||||||
|
.Include(b => b.ErrorMessage)
|
||||||
|
.Include(b => b.ProgressInfo)
|
||||||
|
.Include(b => b.Name)
|
||||||
|
.Include(b => b.User);
|
||||||
|
|
||||||
|
var filter = Builders<BundleBacktestRequestDto>.Filter.Eq(b => b.User.Name, user.Name);
|
||||||
|
var bundleRequests = _bundleBacktestRepository.GetCollection()
|
||||||
|
.Find(filter)
|
||||||
|
.Project<BundleBacktestRequestDto>(projection)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return bundleRequests.Select(MongoMappers.Map);
|
return bundleRequests.Select(MongoMappers.Map);
|
||||||
@@ -329,7 +345,7 @@ public class BacktestRepository : IBacktestRepository
|
|||||||
|
|
||||||
public BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id)
|
public BundleBacktestRequest? GetBundleBacktestRequestByIdForUser(User user, string id)
|
||||||
{
|
{
|
||||||
var bundleRequest = _bundleBacktestRepository.FindOne(b => b.RequestId == id);
|
var bundleRequest = _bundleBacktestRepository.FindOne(b => b.RequestId == id && b.User.Name == user.Name);
|
||||||
|
|
||||||
if (bundleRequest != null && bundleRequest.User.Name == user.Name)
|
if (bundleRequest != null && bundleRequest.User.Name == user.Name)
|
||||||
{
|
{
|
||||||
@@ -340,10 +356,15 @@ public class BacktestRepository : IBacktestRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest)
|
public void UpdateBundleBacktestRequest(BundleBacktestRequest bundleRequest)
|
||||||
|
{
|
||||||
|
var existingRequest = _bundleBacktestRepository.FindOne(b => b.RequestId == bundleRequest.RequestId);
|
||||||
|
if (existingRequest != null)
|
||||||
{
|
{
|
||||||
var dto = MongoMappers.Map(bundleRequest);
|
var dto = MongoMappers.Map(bundleRequest);
|
||||||
|
dto.Id = existingRequest.Id; // Preserve the MongoDB ObjectId
|
||||||
_bundleBacktestRepository.ReplaceOne(dto);
|
_bundleBacktestRepository.ReplaceOne(dto);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void DeleteBundleBacktestRequestByIdForUser(User user, string id)
|
public void DeleteBundleBacktestRequestByIdForUser(User user, string id)
|
||||||
{
|
{
|
||||||
@@ -355,12 +376,12 @@ public class BacktestRepository : IBacktestRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<BundleBacktestRequest> GetPendingBundleBacktestRequests()
|
public IEnumerable<BundleBacktestRequest> GetBundleBacktestRequestsByStatus(BundleBacktestRequestStatus status)
|
||||||
{
|
{
|
||||||
var pendingRequests = _bundleBacktestRepository.AsQueryable()
|
var requests = _bundleBacktestRepository.AsQueryable()
|
||||||
.Where(b => b.Status == BundleBacktestRequestStatus.Pending)
|
.Where(b => b.Status == status)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return pendingRequests.Select(MongoMappers.Map);
|
return requests.Select(MongoMappers.Map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,4 +20,5 @@ public class BundleBacktestRequestDto : Document
|
|||||||
public string? CurrentBacktest { get; set; }
|
public string? CurrentBacktest { get; set; }
|
||||||
public int? EstimatedTimeRemainingSeconds { get; set; }
|
public int? EstimatedTimeRemainingSeconds { get; set; }
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public List<string> Results { get; set; } = new();
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,8 @@ public class IndexService
|
|||||||
// Create indexes for BacktestDto
|
// Create indexes for BacktestDto
|
||||||
await CreateBacktestIndexesAsync();
|
await CreateBacktestIndexesAsync();
|
||||||
|
|
||||||
|
await CreateBundleBacktestIndexesAsync();
|
||||||
|
|
||||||
// Create indexes for GeneticRequestDto
|
// Create indexes for GeneticRequestDto
|
||||||
await CreateGeneticRequestIndexesAsync();
|
await CreateGeneticRequestIndexesAsync();
|
||||||
|
|
||||||
@@ -74,6 +76,17 @@ public class IndexService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CreateBundleBacktestIndexesAsync()
|
||||||
|
{
|
||||||
|
var bundleCollection = _database.GetCollection<BundleBacktestRequestDto>("BundleBacktestRequests");
|
||||||
|
// Index on RequestId (unique)
|
||||||
|
var requestIdIndex = Builders<BundleBacktestRequestDto>.IndexKeys.Ascending(b => b.RequestId);
|
||||||
|
await bundleCollection.Indexes.CreateOneAsync(new CreateIndexModel<BundleBacktestRequestDto>(requestIdIndex, new CreateIndexOptions { Unique = true }));
|
||||||
|
// Index on User.Name (non-unique)
|
||||||
|
var userNameIndex = Builders<BundleBacktestRequestDto>.IndexKeys.Ascending("User.Name");
|
||||||
|
await bundleCollection.Indexes.CreateOneAsync(new CreateIndexModel<BundleBacktestRequestDto>(userNameIndex));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates indexes for the GeneticRequestDto collection
|
/// Creates indexes for the GeneticRequestDto collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1128,7 +1128,8 @@ public static class MongoMappers
|
|||||||
ProgressInfo = domain.ProgressInfo,
|
ProgressInfo = domain.ProgressInfo,
|
||||||
CurrentBacktest = domain.CurrentBacktest,
|
CurrentBacktest = domain.CurrentBacktest,
|
||||||
EstimatedTimeRemainingSeconds = domain.EstimatedTimeRemainingSeconds,
|
EstimatedTimeRemainingSeconds = domain.EstimatedTimeRemainingSeconds,
|
||||||
Name = domain.Name
|
Name = domain.Name,
|
||||||
|
Results = domain.Results
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1150,7 +1151,8 @@ public static class MongoMappers
|
|||||||
ProgressInfo = dto.ProgressInfo,
|
ProgressInfo = dto.ProgressInfo,
|
||||||
CurrentBacktest = dto.CurrentBacktest,
|
CurrentBacktest = dto.CurrentBacktest,
|
||||||
EstimatedTimeRemainingSeconds = dto.EstimatedTimeRemainingSeconds,
|
EstimatedTimeRemainingSeconds = dto.EstimatedTimeRemainingSeconds,
|
||||||
Name = dto.Name
|
Name = dto.Name,
|
||||||
|
Results = dto.Results
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const getBadgeColor = (signalType: SignalType) => {
|
|||||||
|
|
||||||
// Helper function to format indicator type for display
|
// Helper function to format indicator type for display
|
||||||
const formatIndicatorType = (type: IndicatorType) => {
|
const formatIndicatorType = (type: IndicatorType) => {
|
||||||
return type.replace(/([A-Z])/g, ' $1').trim();
|
return type.length > 0 ? type.replace(/([A-Z])/g, ' $1').trim() : 'Unknown';
|
||||||
};
|
};
|
||||||
|
|
||||||
const IndicatorsDisplay: React.FC<IndicatorsDisplayProps> = ({ indicators, className = "" }) => {
|
const IndicatorsDisplay: React.FC<IndicatorsDisplayProps> = ({ indicators, className = "" }) => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Toast from '../../components/mollecules/Toast/Toast';
|
|||||||
import {useQuery} from '@tanstack/react-query';
|
import {useQuery} from '@tanstack/react-query';
|
||||||
import * as signalR from '@microsoft/signalr';
|
import * as signalR from '@microsoft/signalr';
|
||||||
import AuthorizedApiBase from '../../generated/AuthorizedApiBase';
|
import AuthorizedApiBase from '../../generated/AuthorizedApiBase';
|
||||||
|
import BacktestTable from '../../components/organism/Backtest/backtestTable';
|
||||||
|
|
||||||
interface BundleRequestModalProps {
|
interface BundleRequestModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -125,32 +126,7 @@ const BundleRequestModal: React.FC<BundleRequestModalProps> = ({ open, onClose,
|
|||||||
) : queryError ? (
|
) : queryError ? (
|
||||||
<div className="text-error">{(queryError as any)?.message || 'Failed to fetch backtests'}</div>
|
<div className="text-error">{(queryError as any)?.message || 'Failed to fetch backtests'}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="overflow-x-auto max-h-96">
|
<BacktestTable list={backtests} />
|
||||||
<table className="table table-zebra w-full text-xs">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Final PnL</th>
|
|
||||||
<th>Win Rate</th>
|
|
||||||
<th>Growth %</th>
|
|
||||||
<th>Start</th>
|
|
||||||
<th>End</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{backtests.map((b) => (
|
|
||||||
<tr key={b.id}>
|
|
||||||
<td className="font-mono">{b.id}</td>
|
|
||||||
<td>{b.finalPnl}</td>
|
|
||||||
<td>{b.winRate}</td>
|
|
||||||
<td>{b.growthPercentage}</td>
|
|
||||||
<td>{b.startDate ? new Date(b.startDate).toLocaleString() : '-'}</td>
|
|
||||||
<td>{b.endDate ? new Date(b.endDate).toLocaleString() : '-'}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
<div className="modal-action">
|
<div className="modal-action">
|
||||||
<button className="btn" onClick={onClose}>Close</button>
|
<button className="btn" onClick={onClose}>Close</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user