Add name to backtest filters

This commit is contained in:
2025-10-14 18:38:27 +07:00
parent 74adad5834
commit a462fc9948
6 changed files with 32 additions and 2 deletions

View File

@@ -137,6 +137,7 @@ interface BacktestTableProps {
currentSort?: { sortBy: BacktestSortableColumn; sortOrder: 'asc' | 'desc' }
onBacktestDeleted?: () => void // Callback when a backtest is deleted
onFiltersChange?: (filters: {
nameContains?: string | null
scoreMin?: number | null
scoreMax?: number | null
winrateMin?: number | null
@@ -148,6 +149,7 @@ interface BacktestTableProps {
durationMaxDays?: number | null
}) => void
filters?: {
nameContains?: string | null
scoreMin?: number | null
scoreMax?: number | null
winrateMin?: number | null
@@ -185,6 +187,7 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
const [scoreMax, setScoreMax] = useState<number>(100)
const [winMin, setWinMin] = useState<number>(0)
const [winMax, setWinMax] = useState<number>(100)
const [nameContains, setNameContains] = useState<string>('')
const [maxDrawdownMax, setMaxDrawdownMax] = useState<number | ''>('')
const [tickersInput, setTickersInput] = useState<string>('')
const [selectedIndicators, setSelectedIndicators] = useState<string[]>([])
@@ -194,6 +197,7 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
const applyFilters = () => {
if (!onFiltersChange) return
onFiltersChange({
nameContains: nameContains.trim() || null,
scoreMin,
scoreMax,
winrateMin: winMin,
@@ -223,6 +227,7 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
// Sync incoming filters prop to local sidebar state
useEffect(() => {
if (!filters) return
setNameContains(filters.nameContains ?? '')
if (typeof filters.scoreMin === 'number') setScoreMin(filters.scoreMin)
if (typeof filters.scoreMax === 'number') setScoreMax(filters.scoreMax)
if (typeof filters.winrateMin === 'number') setWinMin(filters.winrateMin)
@@ -600,6 +605,18 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, onSortCh
</div>
</div>
{/* Name contains */}
<div className="mb-6">
<div className="mb-2 font-medium">Name contains</div>
<input
type="text"
placeholder="e.g. MyBundleTest"
className="input input-bordered input-sm w-full"
value={nameContains}
onChange={e => setNameContains(e.target.value)}
/>
</div>
{/* Tickers */}
<div className="mb-6">
<div className="mb-2 font-medium">Tickers</div>

View File

@@ -665,7 +665,7 @@ export class BacktestClient extends AuthorizedApiBase {
return Promise.resolve<PaginatedBacktestsResponse>(null as any);
}
backtest_GetBacktestsPaginated(page: number | undefined, pageSize: number | undefined, sortBy: BacktestSortableColumn | undefined, sortOrder: string | null | undefined, scoreMin: number | null | undefined, scoreMax: number | null | undefined, winrateMin: number | null | undefined, winrateMax: number | null | undefined, maxDrawdownMax: number | null | undefined, tickers: string | null | undefined, indicators: string | null | undefined, durationMinDays: number | null | undefined, durationMaxDays: number | null | undefined): Promise<PaginatedBacktestsResponse> {
backtest_GetBacktestsPaginated(page: number | undefined, pageSize: number | undefined, sortBy: BacktestSortableColumn | undefined, sortOrder: string | null | undefined, scoreMin: number | null | undefined, scoreMax: number | null | undefined, winrateMin: number | null | undefined, winrateMax: number | null | undefined, maxDrawdownMax: number | null | undefined, tickers: string | null | undefined, indicators: string | null | undefined, durationMinDays: number | null | undefined, durationMaxDays: number | null | undefined, name: string | null | undefined): Promise<PaginatedBacktestsResponse> {
let url_ = this.baseUrl + "/Backtest/Paginated?";
if (page === null)
throw new Error("The parameter 'page' cannot be null.");
@@ -699,6 +699,8 @@ export class BacktestClient extends AuthorizedApiBase {
url_ += "durationMinDays=" + encodeURIComponent("" + durationMinDays) + "&";
if (durationMaxDays !== undefined && durationMaxDays !== null)
url_ += "durationMaxDays=" + encodeURIComponent("" + durationMaxDays) + "&";
if (name !== undefined && name !== null)
url_ += "name=" + encodeURIComponent("" + name) + "&";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {

View File

@@ -28,6 +28,7 @@ const BacktestScanner: React.FC = () => {
// Filters state coming from BacktestTable sidebar
const [filters, setFilters] = useState<{
nameContains?: string | null
scoreMin?: number | null
scoreMax?: number | null
winrateMin?: number | null
@@ -57,6 +58,7 @@ const BacktestScanner: React.FC = () => {
PAGE_SIZE,
currentSort.sortBy,
currentSort.sortOrder,
// filters
filters.scoreMin ?? null,
filters.scoreMax ?? null,
filters.winrateMin ?? null,
@@ -66,6 +68,7 @@ const BacktestScanner: React.FC = () => {
(filters.indicators && filters.indicators.length ? filters.indicators.join(',') : null),
filters.durationMinDays ?? null,
filters.durationMaxDays ?? null,
filters.nameContains ?? null,
)
return {
backtests: (response.backtests as LightBacktestResponse[]) || [],