diff --git a/src/Managing.Api/Controllers/BacktestController.cs b/src/Managing.Api/Controllers/BacktestController.cs index a8519eb..14356d4 100644 --- a/src/Managing.Api/Controllers/BacktestController.cs +++ b/src/Managing.Api/Controllers/BacktestController.cs @@ -179,7 +179,21 @@ public class BacktestController : BaseController var response = new PaginatedBacktestsResponse { - Backtests = backtests, + Backtests = backtests.Select(b => new LightBacktestResponse + { + Id = b.Id, + Config = b.Config, + FinalPnl = b.FinalPnl, + WinRate = b.WinRate, + GrowthPercentage = b.GrowthPercentage, + HodlPercentage = b.HodlPercentage, + StartDate = b.StartDate, + EndDate = b.EndDate, + MaxDrawdown = b.MaxDrawdown, + Fees = b.Fees, + SharpeRatio = b.SharpeRatio, + Score = b.Score + }), TotalCount = totalCount, CurrentPage = page, PageSize = pageSize, @@ -229,7 +243,21 @@ public class BacktestController : BaseController var response = new PaginatedBacktestsResponse { - Backtests = backtests, + Backtests = backtests.Select(b => new LightBacktestResponse + { + Id = b.Id, + Config = b.Config, + FinalPnl = b.FinalPnl, + WinRate = b.WinRate, + GrowthPercentage = b.GrowthPercentage, + HodlPercentage = b.HodlPercentage, + StartDate = b.StartDate, + EndDate = b.EndDate, + MaxDrawdown = b.MaxDrawdown, + Fees = b.Fees, + SharpeRatio = b.SharpeRatio, + Score = b.Score + }), TotalCount = totalCount, CurrentPage = page, PageSize = pageSize, diff --git a/src/Managing.Api/Models/Requests/LightBacktestResponse.cs b/src/Managing.Api/Models/Requests/LightBacktestResponse.cs new file mode 100644 index 0000000..6e0383a --- /dev/null +++ b/src/Managing.Api/Models/Requests/LightBacktestResponse.cs @@ -0,0 +1,19 @@ +using Managing.Domain.Bots; + +namespace Managing.Api.Models.Requests; + +public class LightBacktestResponse +{ + public string Id { get; set; } = string.Empty; + public TradingBotConfig Config { get; set; } = new(); + public decimal FinalPnl { get; set; } + public int WinRate { get; set; } + public decimal GrowthPercentage { get; set; } + public decimal HodlPercentage { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public decimal? MaxDrawdown { get; set; } + public decimal Fees { get; set; } + public double? SharpeRatio { get; set; } + public double Score { get; set; } +} \ No newline at end of file diff --git a/src/Managing.Api/Models/Requests/PaginatedBacktestsResponse.cs b/src/Managing.Api/Models/Requests/PaginatedBacktestsResponse.cs index 2f857a3..0812591 100644 --- a/src/Managing.Api/Models/Requests/PaginatedBacktestsResponse.cs +++ b/src/Managing.Api/Models/Requests/PaginatedBacktestsResponse.cs @@ -1,5 +1,3 @@ -using Managing.Domain.Backtests; - namespace Managing.Api.Models.Requests; /// @@ -10,7 +8,7 @@ public class PaginatedBacktestsResponse /// /// The list of backtests for the current page /// - public IEnumerable Backtests { get; set; } = new List(); + public IEnumerable Backtests { get; set; } = new List(); /// /// Total number of backtests across all pages diff --git a/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs index 5d044eb..5462900 100644 --- a/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs @@ -8,8 +8,8 @@ public interface IBacktestRepository void InsertBacktestForUser(User user, Backtest result); IEnumerable GetBacktestsByUser(User user); IEnumerable GetBacktestsByRequestId(string requestId); - (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); - (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); + (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); + (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); Backtest GetBacktestByIdForUser(User user, string id); void DeleteBacktestByIdForUser(User user, string id); void DeleteBacktestsByIdsForUser(User user, IEnumerable ids); diff --git a/src/Managing.Application.Abstractions/Services/IBacktester.cs b/src/Managing.Application.Abstractions/Services/IBacktester.cs index 8f8d19a..01b631a 100644 --- a/src/Managing.Application.Abstractions/Services/IBacktester.cs +++ b/src/Managing.Application.Abstractions/Services/IBacktester.cs @@ -54,12 +54,12 @@ namespace Managing.Application.Abstractions.Services bool DeleteBacktests(); IEnumerable GetBacktestsByUser(User user); IEnumerable GetBacktestsByRequestId(string requestId); - (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); + (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); Backtest GetBacktestByIdForUser(User user, string id); bool DeleteBacktestByUser(User user, string id); bool DeleteBacktestsByIdsForUser(User user, IEnumerable ids); bool DeleteBacktestsByUser(User user); - (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); + (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); } diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs index 9197bf4..c5dd163 100644 --- a/src/Managing.Application/Backtesting/Backtester.cs +++ b/src/Managing.Application/Backtesting/Backtester.cs @@ -448,7 +448,7 @@ namespace Managing.Application.Backtesting return backtests; } - public (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") + public (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") { var (backtests, totalCount) = _backtestRepository.GetBacktestsByRequestIdPaginated(requestId, page, pageSize, sortBy, sortOrder); return (backtests, totalCount); @@ -531,7 +531,7 @@ namespace Managing.Application.Backtesting } } - public (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") + public (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") { var (backtests, totalCount) = _backtestRepository.GetBacktestsByUserPaginated(user, page, pageSize, sortBy, sortOrder); return (backtests, totalCount); diff --git a/src/Managing.Domain/Backtests/LightBacktest.cs b/src/Managing.Domain/Backtests/LightBacktest.cs new file mode 100644 index 0000000..25ad64e --- /dev/null +++ b/src/Managing.Domain/Backtests/LightBacktest.cs @@ -0,0 +1,19 @@ +using Managing.Domain.Bots; + +namespace Managing.Domain.Backtests; + +public class LightBacktest +{ + public string Id { get; set; } = string.Empty; + public TradingBotConfig Config { get; set; } = new(); + public decimal FinalPnl { get; set; } + public int WinRate { get; set; } + public decimal GrowthPercentage { get; set; } + public decimal HodlPercentage { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public decimal? MaxDrawdown { get; set; } + public decimal Fees { get; set; } + public double? SharpeRatio { get; set; } + public double Score { get; set; } +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/BacktestRepository.cs b/src/Managing.Infrastructure.Database/BacktestRepository.cs index 732b25e..1666514 100644 --- a/src/Managing.Infrastructure.Database/BacktestRepository.cs +++ b/src/Managing.Infrastructure.Database/BacktestRepository.cs @@ -83,7 +83,7 @@ public class BacktestRepository : IBacktestRepository return backtests.Select(b => MongoMappers.Map(b)); } - public (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, + public (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(string requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") { var stopwatch = Stopwatch.StartNew(); @@ -101,14 +101,12 @@ public class BacktestRepository : IBacktestRepository .Include(b => b.WinRate) .Include(b => b.GrowthPercentage) .Include(b => b.HodlPercentage) - .Include(b => b.User) - .Include(b => b.Statistics) .Include(b => b.StartDate) .Include(b => b.EndDate) .Include(b => b.Score) - .Include(b => b.RequestId) - .Include(b => b.Metadata) - .Include(b => b.Config); + .Include(b => b.Config) + .Include(b => b.Fees) + .Include(b => b.Statistics); // Build sort definition var sortDefinition = sortBy.ToLower() switch @@ -146,7 +144,21 @@ public class BacktestRepository : IBacktestRepository Console.WriteLine( $"[BacktestRepo] Query: {afterQueryMs}ms, Count: {afterCountMs - afterQueryMs}ms, Projection: {afterProjectionMs - afterCountMs}ms, ToList: {afterToListMs - afterProjectionMs}ms, Total: {afterToListMs}ms"); - var mappedBacktests = backtests.Select(b => MongoMappers.Map(b)); + var mappedBacktests = backtests.Select(b => new LightBacktest + { + Id = b.Identifier, + Config = MongoMappers.Map(b.Config), + FinalPnl = b.FinalPnl, + WinRate = b.WinRate, + GrowthPercentage = b.GrowthPercentage, + HodlPercentage = b.HodlPercentage, + StartDate = b.StartDate, + EndDate = b.EndDate, + MaxDrawdown = b.Statistics?.MaxDrawdown, + Fees = b.Fees, + SharpeRatio = b.Statistics?.SharpeRatio != null ? (double)b.Statistics.SharpeRatio : null, + Score = b.Score + }); return (mappedBacktests, (int)totalCount); } @@ -198,7 +210,7 @@ public class BacktestRepository : IBacktestRepository } } - public (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, + public (IEnumerable Backtests, int TotalCount) GetBacktestsByUserPaginated(User user, int page, int pageSize, string sortBy = "score", string sortOrder = "desc") { var stopwatch = Stopwatch.StartNew(); @@ -216,14 +228,12 @@ public class BacktestRepository : IBacktestRepository .Include(b => b.WinRate) .Include(b => b.GrowthPercentage) .Include(b => b.HodlPercentage) - .Include(b => b.User) - .Include(b => b.Statistics) .Include(b => b.StartDate) .Include(b => b.EndDate) .Include(b => b.Score) - .Include(b => b.RequestId) - .Include(b => b.Metadata) - .Include(b => b.Config); + .Include(b => b.Config) + .Include(b => b.Fees) + .Include(b => b.Statistics); // Build sort definition var sortDefinition = sortBy.ToLower() switch @@ -261,7 +271,21 @@ public class BacktestRepository : IBacktestRepository Console.WriteLine( $"[BacktestRepo] User Query: {afterQueryMs}ms, Count: {afterCountMs - afterQueryMs}ms, Projection: {afterProjectionMs - afterCountMs}ms, ToList: {afterToListMs - afterProjectionMs}ms, Total: {afterToListMs}ms"); - var mappedBacktests = backtests.Select(b => MongoMappers.Map(b)); + var mappedBacktests = backtests.Select(b => new LightBacktest + { + Id = b.Identifier, + Config = MongoMappers.Map(b.Config), + FinalPnl = b.FinalPnl, + WinRate = b.WinRate, + GrowthPercentage = b.GrowthPercentage, + HodlPercentage = b.HodlPercentage, + StartDate = b.StartDate, + EndDate = b.EndDate, + MaxDrawdown = b.Statistics?.MaxDrawdown, + Fees = b.Fees, + SharpeRatio = b.Statistics?.SharpeRatio != null ? (double)b.Statistics.SharpeRatio : null, + Score = b.Score + }); return (mappedBacktests, (int)totalCount); } diff --git a/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs b/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs index d33ef02..1146ffa 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs @@ -26,6 +26,8 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections public MoneyManagementDto OptimizedMoneyManagement { get; internal set; } public UserDto User { get; set; } public PerformanceMetrics Statistics { get; set; } + [BsonRepresentation(BsonType.Decimal128)] + public decimal Fees { get; set; } public double Score { get; set; } public string Identifier { get; set; } public string RequestId { get; set; } diff --git a/src/Managing.WebApp/src/app/store/backtestStore.ts b/src/Managing.WebApp/src/app/store/backtestStore.ts index f4f32e0..83bb95a 100644 --- a/src/Managing.WebApp/src/app/store/backtestStore.ts +++ b/src/Managing.WebApp/src/app/store/backtestStore.ts @@ -1,11 +1,11 @@ import {create} from 'zustand' -import type {Backtest} from '../../generated/ManagingApi' +import type {LightBacktestResponse} from '../../generated/ManagingApi' interface BacktestStore { - backtests: Backtest[] + backtests: LightBacktestResponse[] isLoading: boolean - setBacktests: (backtests: Backtest[]) => void - addBacktest: (backtest: Backtest) => void + setBacktests: (backtests: LightBacktestResponse[]) => void + addBacktest: (backtest: LightBacktestResponse) => void removeBacktest: (id: string) => void setLoading: (loading: boolean) => void clearBacktests: () => void @@ -15,10 +15,10 @@ const useBacktestStore = create((set, get) => ({ backtests: [], isLoading: false, - setBacktests: (backtests: Backtest[]) => + setBacktests: (backtests: LightBacktestResponse[]) => set({ backtests }), - addBacktest: (backtest: Backtest) => + addBacktest: (backtest: LightBacktestResponse) => set((state) => ({ backtests: [...state.backtests, backtest] })), diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx index dbe7f79..506cbfe 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx @@ -84,13 +84,12 @@ const BacktestRowDetails: React.FC = ({ const candles = candlesData?.candles || currentBacktest.candles || []; const indicatorsValues = candlesData?.indicatorsValues || currentBacktest.indicatorsValues || {}; - const { - positions, - walletBalances, - signals, - statistics, - config - } = currentBacktest; + // Only destructure these properties if we have full backtest data + const positions = fullBacktestData?.positions || []; + const walletBalances = fullBacktestData?.walletBalances || []; + const signals = fullBacktestData?.signals || []; + const statistics = fullBacktestData?.statistics; + const config = currentBacktest.config; // Helper function to calculate position open time in hours const calculateOpenTimeInHours = (position: any) => { @@ -219,7 +218,7 @@ const BacktestRowDetails: React.FC = ({ // Calculate recommended cooldown based on positions that fail after a win const getCooldownRecommendations = () => { - if (positions.length < 2 || !candles || candles.length < 2) { + if (positions?.length < 2 || !candles || candles?.length < 2) { return { percentile75: "0", average: "0", median: "0" }; } @@ -343,14 +342,14 @@ const BacktestRowDetails: React.FC = ({ = ({ diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx index fa6ebee..ff47297 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx @@ -4,7 +4,7 @@ import {useExpanded, useFilters, usePagination, useSortBy, useTable,} from 'reac import useApiUrlStore from '../../../app/store/apiStore' import useBacktestStore from '../../../app/store/backtestStore' -import type {Backtest} from '../../../generated/ManagingApi' +import type {Backtest, LightBacktestResponse} from '../../../generated/ManagingApi' import {BacktestClient} from '../../../generated/ManagingApi' import {ConfigDisplayModal, IndicatorsDisplay, SelectColumnFilter} from '../../mollecules' import {UnifiedTradingModal} from '../index' @@ -130,7 +130,7 @@ const ServerSortableTable = ({ } interface BacktestTableProps { - list: Backtest[] | undefined + list: LightBacktestResponse[] | undefined isFetching?: boolean displaySummary?: boolean onSortChange?: (sortBy: string, sortOrder: 'asc' | 'desc') => void @@ -139,26 +139,10 @@ interface BacktestTableProps { -const BacktestTable: React.FC = ({list, isFetching, displaySummary = true, onSortChange, currentSort}) => { - const [rows, setRows] = useState([]) +const BacktestTable: React.FC = ({list, isFetching, onSortChange, currentSort}) => { + const [rows, setRows] = useState([]) const {apiUrl} = useApiUrlStore() const {removeBacktest} = useBacktestStore() - const [optimizedMoneyManagement, setOptimizedMoneyManagement] = useState({ - stopLoss: 0, - takeProfit: 0, - }) - const [positionTimingStats, setPositionTimingStats] = useState({ - averageOpenTime: 0, - medianOpenTime: 0, - losingPositionsAverageOpenTime: 0, - }) - const [cooldownRecommendations, setCooldownRecommendations] = useState({ - averageCooldown: 0, - medianCooldown: 0, - }) - - // Summary collapse state - const [isSummaryCollapsed, setIsSummaryCollapsed] = useState(true) // Bot configuration modal state const [showBotConfigModal, setShowBotConfigModal] = useState(false) @@ -466,146 +450,6 @@ const BacktestTable: React.FC = ({list, isFetching, displayS useEffect(() => { if (list) { setRows(list) - - // Calculate average optimized money management - if (list.length > 0) { - const optimized = list.map((b) => b.optimizedMoneyManagement); - const stopLoss = optimized.reduce((acc, curr) => acc + (curr?.stopLoss ?? 0), 0); - const takeProfit = optimized.reduce((acc, curr) => acc + (curr?.takeProfit ?? 0), 0); - - setOptimizedMoneyManagement({ - stopLoss: stopLoss / optimized.length, - takeProfit: takeProfit / optimized.length, - }); - - // Calculate position timing statistics - const allPositions = list.flatMap(backtest => backtest.positions); - const finishedPositions = allPositions.filter(p => p.status === 'Finished'); - - if (finishedPositions.length > 0) { - // Calculate position open times in hours - const openTimes = finishedPositions.map(position => { - const openTime = new Date(position.open.date); - // Find the closing trade (either stopLoss or takeProfit that was filled) - let closeTime = new Date(); - - if (position.stopLoss.status === 'Filled') { - closeTime = new Date(position.stopLoss.date); - } else if (position.takeProfit1.status === 'Filled') { - closeTime = new Date(position.takeProfit1.date); - } else if (position.takeProfit2?.status === 'Filled') { - closeTime = new Date(position.takeProfit2.date); - } - - // Return time difference in hours - return (closeTime.getTime() - openTime.getTime()) / (1000 * 60 * 60); - }); - - // Calculate average - const averageOpenTime = openTimes.reduce((sum, time) => sum + time, 0) / openTimes.length; - - // Calculate median - const sortedTimes = [...openTimes].sort((a, b) => a - b); - const medianOpenTime = sortedTimes.length % 2 === 0 - ? (sortedTimes[sortedTimes.length / 2 - 1] + sortedTimes[sortedTimes.length / 2]) / 2 - : sortedTimes[Math.floor(sortedTimes.length / 2)]; - - // Calculate average for losing positions - const losingPositions = finishedPositions.filter(p => (p.profitAndLoss?.realized ?? 0) < 0); - let losingPositionsAverageOpenTime = 0; - - if (losingPositions.length > 0) { - const losingOpenTimes = losingPositions.map(position => { - const openTime = new Date(position.open.date); - let closeTime = new Date(); - - if (position.stopLoss.status === 'Filled') { - closeTime = new Date(position.stopLoss.date); - } else if (position.takeProfit1.status === 'Filled') { - closeTime = new Date(position.takeProfit1.date); - } else if (position.takeProfit2?.status === 'Filled') { - closeTime = new Date(position.takeProfit2.date); - } - - return (closeTime.getTime() - openTime.getTime()) / (1000 * 60 * 60); - }); - - losingPositionsAverageOpenTime = losingOpenTimes.reduce((sum, time) => sum + time, 0) / losingOpenTimes.length; - } - - setPositionTimingStats({ - averageOpenTime, - medianOpenTime, - losingPositionsAverageOpenTime, - }); - } - - // Calculate cooldown recommendations across all backtests - const allCooldownValues: number[] = []; - - list.forEach(backtest => { - if (backtest.positions.length < 2 || !backtest.candles || backtest.candles.length < 2) { - return; - } - - // Determine candle timeframe in milliseconds - const candleTimeframeMs = new Date(backtest.candles[1].date).getTime() - new Date(backtest.candles[0].date).getTime(); - - const sortedPositions = [...backtest.positions].sort((a, b) => { - const dateA = new Date(a.open.date).getTime(); - const dateB = new Date(b.open.date).getTime(); - return dateA - dateB; - }); - - for (let i = 0; i < sortedPositions.length - 1; i++) { - const currentPosition = sortedPositions[i]; - const nextPosition = sortedPositions[i + 1]; - - const currentRealized = currentPosition.profitAndLoss?.realized ?? 0; - const nextRealized = nextPosition.profitAndLoss?.realized ?? 0; - - // Check if current position is winning and next position is losing - if (currentRealized > 0 && nextRealized <= 0) { - // Calculate the close time of the current (winning) position - let currentCloseDate: Date | null = null; - if (currentPosition.profitAndLoss?.realized != null) { - if (currentPosition.profitAndLoss.realized > 0) { - currentCloseDate = new Date(currentPosition.takeProfit1.date); - } else { - currentCloseDate = new Date(currentPosition.stopLoss.date); - } - } - - if (currentCloseDate) { - const nextOpenDate = new Date(nextPosition.open.date); - const gapInMs = nextOpenDate.getTime() - currentCloseDate.getTime(); - - if (gapInMs >= 0) { // Only consider positive gaps - // Convert milliseconds to number of candles - const gapInCandles = Math.floor(gapInMs / candleTimeframeMs); - allCooldownValues.push(gapInCandles); - } - } - } - } - }); - - if (allCooldownValues.length > 0) { - // Calculate average cooldown - const averageCooldown = allCooldownValues.reduce((sum, value) => sum + value, 0) / allCooldownValues.length; - - // Calculate median cooldown - const sortedCooldowns = [...allCooldownValues].sort((a, b) => a - b); - const medianCooldown = sortedCooldowns.length % 2 === 0 - ? (sortedCooldowns[sortedCooldowns.length / 2 - 1] + sortedCooldowns[sortedCooldowns.length / 2]) / 2 - : sortedCooldowns[Math.floor(sortedCooldowns.length / 2)]; - - setCooldownRecommendations({ - averageCooldown: Math.ceil(averageCooldown), - medianCooldown: Math.ceil(medianCooldown), - }); - } - } } }, [list]) @@ -617,58 +461,6 @@ const BacktestTable: React.FC = ({list, isFetching, displayS ) : ( <> - {list && list.length > 0 && displaySummary && ( -
- - - {!isSummaryCollapsed && ( -
-
-
-
Money Management
-
- SL: {optimizedMoneyManagement.stopLoss.toFixed(2)}% - TP: {optimizedMoneyManagement.takeProfit.toFixed(2)}% - R/R: {(optimizedMoneyManagement.takeProfit / optimizedMoneyManagement.stopLoss || 0).toFixed(2)} -
-
- -
-
Position Timing
-
- Avg: {positionTimingStats.averageOpenTime.toFixed(1)}h - Median: {positionTimingStats.medianOpenTime.toFixed(1)}h - Losing: {positionTimingStats.losingPositionsAverageOpenTime.toFixed(1)}h -
-
- -
-
Cooldown
-
- Avg: {cooldownRecommendations.averageCooldown} candles - Median: {cooldownRecommendations.medianCooldown} candles -
-
-
-
- )} -
- )} { const [geneticRequests, setGeneticRequests] = useState([]) const [selectedRequest, setSelectedRequest] = useState(null) const [isViewModalOpen, setIsViewModalOpen] = useState(false) - const [backtests, setBacktests] = useState([]) + const [backtests, setBacktests] = useState([]) const [isLoadingBacktests, setIsLoadingBacktests] = useState(false) const [isFormCollapsed, setIsFormCollapsed] = useState(false) @@ -824,7 +824,7 @@ const BacktestGeneticBundle: React.FC = () => {

Score vs Generation

- +
@@ -834,7 +834,7 @@ const BacktestGeneticBundle: React.FC = () => {

Fitness vs Score vs Win Rate

- +
@@ -842,18 +842,18 @@ const BacktestGeneticBundle: React.FC = () => {

Take Profit vs Stop Loss vs PnL

- +
{/* Strategy Comparison Radar Chart */}
- +
{ sortBy: 'score', sortOrder: 'desc' }) - const [backtests, setBacktests] = useState([]) + const [backtests, setBacktests] = useState([]) const [isLoading, setIsLoading] = useState(false) const { apiUrl } = useApiUrlStore() @@ -39,7 +39,7 @@ const BacktestScanner: React.FC = () => { setIsLoading(true) try { const response = await backtestClient.backtest_GetBacktestsPaginated(page, PAGE_SIZE, sort.sortBy, sort.sortOrder) - setBacktests((response.backtests as Backtest[]) || []) + setBacktests((response.backtests as LightBacktestResponse[]) || []) setTotalBacktests(response.totalCount || 0) setTotalPages(response.totalPages || 0) } catch (err) { @@ -55,7 +55,7 @@ const BacktestScanner: React.FC = () => { }, [currentPage, currentSort]) useEffect(() => { - setBacktestsFromStore(backtests) + setBacktestsFromStore(backtests as any) // Cast to any for backward compatibility setLoading(isLoading) }, [backtests, setBacktestsFromStore, setLoading, isLoading]) @@ -79,7 +79,7 @@ const BacktestScanner: React.FC = () => { const filters = formData || filterValues - const filteredBacktests = backtests.filter((backtest: any) => { + const filteredBacktests = backtests.filter((backtest: LightBacktestResponse) => { // Ensure values are numbers and handle potential null/undefined values const backtestWinRate = Number(backtest.winRate) || 0 const backtestScore = Number(backtest.score) || 0 @@ -129,7 +129,7 @@ const BacktestScanner: React.FC = () => { return } - const backTestToDelete = backtests.filter((backtest: any) => { + const backTestToDelete = backtests.filter((backtest: LightBacktestResponse) => { // Ensure values are numbers and handle potential null/undefined values const backtestWinRate = Number(backtest.winRate) || 0 const backtestScore = Number(backtest.score) || 0 @@ -198,7 +198,7 @@ const BacktestScanner: React.FC = () => {