Fix managing with good backtest return

This commit is contained in:
2025-11-14 14:28:13 +07:00
parent 61ade29d4e
commit 0cfc30598b
7 changed files with 44 additions and 56 deletions

View File

@@ -233,7 +233,7 @@ public class BacktestController : BaseController
/// <returns>A list of backtests associated with the specified request ID.</returns>
[HttpGet]
[Route("ByRequestId/{requestId}")]
public async Task<ActionResult<IEnumerable<Backtest>>> GetBacktestsByRequestId(string requestId)
public async Task<ActionResult<IEnumerable<LightBacktestResponse>>> GetBacktestsByRequestId(string requestId)
{
if (string.IsNullOrEmpty(requestId))
{
@@ -246,7 +246,7 @@ public class BacktestController : BaseController
}
var backtests = await _backtester.GetBacktestsByRequestIdAsync(requestGuid);
return Ok(backtests);
return Ok(backtests.Select(b => LightBacktestResponseMapper.MapFromDomain(b)));
}
/// <summary>

View File

@@ -511,6 +511,7 @@ public static class Enums
{
Score,
FinalPnl,
NetPnl,
WinRate,
GrowthPercentage,
HodlPercentage,

View File

@@ -518,6 +518,9 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
BacktestSortableColumn.FinalPnl => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.FinalPnl)
: baseQuery.OrderBy(b => b.FinalPnl),
BacktestSortableColumn.NetPnl => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.NetPnl)
: baseQuery.OrderBy(b => b.NetPnl),
BacktestSortableColumn.WinRate => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.WinRate)
: baseQuery.OrderBy(b => b.WinRate),
@@ -654,6 +657,9 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
BacktestSortableColumn.FinalPnl => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.FinalPnl)
: baseQuery.OrderBy(b => b.FinalPnl),
BacktestSortableColumn.NetPnl => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.NetPnl)
: baseQuery.OrderBy(b => b.NetPnl),
BacktestSortableColumn.WinRate => sortOrder == "desc"
? baseQuery.OrderByDescending(b => b.WinRate)
: baseQuery.OrderBy(b => b.WinRate),

View File

@@ -76,6 +76,7 @@ const ServerSortableTable = ({
const enumToColumnMapping: { [key in BacktestSortableColumn]?: string } = {
[BacktestSortableColumn.Score]: 'score',
[BacktestSortableColumn.FinalPnl]: 'finalPnl',
[BacktestSortableColumn.NetPnl]: 'netPnl',
[BacktestSortableColumn.WinRate]: 'winRate',
[BacktestSortableColumn.GrowthPercentage]: 'growthPercentage',
[BacktestSortableColumn.HodlPercentage]: 'hodlPercentage',
@@ -169,6 +170,7 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
const [rows, setRows] = useState<LightBacktestResponse[]>([])
const {apiUrl} = useApiUrlStore()
const {removeBacktest} = useBacktestStore()
console.log('list', list)
// Bot configuration modal state
const [showBotConfigModal, setShowBotConfigModal] = useState(false)
@@ -350,6 +352,7 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
const sortByMapping: { [key: string]: BacktestSortableColumn } = {
'score': BacktestSortableColumn.Score,
'finalPnl': BacktestSortableColumn.FinalPnl,
'netPnl': BacktestSortableColumn.NetPnl,
'winRate': BacktestSortableColumn.WinRate,
'growthPercentage': BacktestSortableColumn.GrowthPercentage,
'hodlPercentage': BacktestSortableColumn.HodlPercentage,
@@ -525,10 +528,10 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
columns: [
{
Cell: ({cell}: any) => (
<>{cell.row.values.finalPnl.toFixed(2)} $</>
<>{cell.row.values.netPnl.toFixed(2)} $</>
),
Header: 'Pnl $',
accessor: 'finalPnl',
accessor: 'netPnl',
disableFilters: true,
disableSortBy: false,
sortType: 'basic',

View File

@@ -800,7 +800,7 @@ export class BacktestClient extends AuthorizedApiBase {
return Promise.resolve<FileResponse>(null as any);
}
backtest_GetBacktestsByRequestId(requestId: string): Promise<Backtest[]> {
backtest_GetBacktestsByRequestId(requestId: string): Promise<LightBacktestResponse[]> {
let url_ = this.baseUrl + "/Backtest/ByRequestId/{requestId}";
if (requestId === undefined || requestId === null)
throw new Error("The parameter 'requestId' must be defined.");
@@ -821,13 +821,13 @@ export class BacktestClient extends AuthorizedApiBase {
});
}
protected processBacktest_GetBacktestsByRequestId(response: Response): Promise<Backtest[]> {
protected processBacktest_GetBacktestsByRequestId(response: Response): Promise<LightBacktestResponse[]> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as Backtest[];
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as LightBacktestResponse[];
return result200;
});
} else if (status !== 200 && status !== 204) {
@@ -835,7 +835,7 @@ export class BacktestClient extends AuthorizedApiBase {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<Backtest[]>(null as any);
return Promise.resolve<LightBacktestResponse[]>(null as any);
}
backtest_GetBacktestsByRequestIdPaginated(requestId: string, page: number | undefined, pageSize: number | undefined, sortBy: string | null | undefined, sortOrder: string | null | undefined): Promise<PaginatedBacktestsResponse> {
@@ -5010,16 +5010,6 @@ export interface DeleteBacktestsRequest {
backtestIds: string[];
}
export interface PaginatedBacktestsResponse {
backtests?: LightBacktestResponse[] | null;
totalCount?: number;
currentPage?: number;
pageSize?: number;
totalPages?: number;
hasNextPage?: boolean;
hasPreviousPage?: boolean;
}
export interface LightBacktestResponse {
id: string;
config: TradingBotConfig;
@@ -5038,9 +5028,20 @@ export interface LightBacktestResponse {
netPnl: number;
}
export interface PaginatedBacktestsResponse {
backtests?: LightBacktestResponse[] | null;
totalCount?: number;
currentPage?: number;
pageSize?: number;
totalPages?: number;
hasNextPage?: boolean;
hasPreviousPage?: boolean;
}
export enum BacktestSortableColumn {
Score = "Score",
FinalPnl = "FinalPnl",
NetPnl = "NetPnl",
WinRate = "WinRate",
GrowthPercentage = "GrowthPercentage",
HodlPercentage = "HodlPercentage",

View File

@@ -572,16 +572,6 @@ export interface DeleteBacktestsRequest {
backtestIds: string[];
}
export interface PaginatedBacktestsResponse {
backtests?: LightBacktestResponse[] | null;
totalCount?: number;
currentPage?: number;
pageSize?: number;
totalPages?: number;
hasNextPage?: boolean;
hasPreviousPage?: boolean;
}
export interface LightBacktestResponse {
id: string;
config: TradingBotConfig;
@@ -600,9 +590,20 @@ export interface LightBacktestResponse {
netPnl: number;
}
export interface PaginatedBacktestsResponse {
backtests?: LightBacktestResponse[] | null;
totalCount?: number;
currentPage?: number;
pageSize?: number;
totalPages?: number;
hasNextPage?: boolean;
hasPreviousPage?: boolean;
}
export enum BacktestSortableColumn {
Score = "Score",
FinalPnl = "FinalPnl",
NetPnl = "NetPnl",
WinRate = "WinRate",
GrowthPercentage = "GrowthPercentage",
HodlPercentage = "HodlPercentage",

View File

@@ -299,40 +299,16 @@ const BundleRequestModal: React.FC<BundleRequestModalProps> = ({
queryFn: async () => {
if (!open || !bundle) return [];
const res = await backtestClient.backtest_GetBacktestsByRequestId(bundle.requestId);
if (!res) return [];
return res.map((b: any) => {
// Map enums for ticker and timeframe
if (b.config) {
if (typeof b.config.ticker === 'number') {
b.config.ticker = Ticker[b.config.ticker as keyof typeof Ticker];
}
if (typeof b.config.timeframe === 'number') {
b.config.timeframe = Timeframe[b.config.timeframe as keyof typeof Timeframe];
}
}
return {
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 ?? null,
fees: b.fees,
sharpeRatio: b.sharpeRatio ?? null,
score: b.score ?? 0,
scoreMessage: b.scoreMessage ?? '',
};
});
if (!res) return [] as LightBacktestResponse[];
console.log('res', res)
return res as LightBacktestResponse[];
},
enabled: !!open && !!bundle,
refetchOnWindowFocus: false,
});
useEffect(() => {
if (queryBacktests) setBacktests(queryBacktests);
if (queryBacktests) setBacktests(queryBacktests as LightBacktestResponse[]);
}, [queryBacktests]);
if (!open) return null;