import { useState } from 'react' import { FlaskConical, Loader2 } from 'lucide-react' import type { BacktestResult } from '../../lib/api' import { runBacktest } from '../../lib/api' interface Props { onResult: (result: BacktestResult) => void } const INSTRUMENTS = [ 'EUR_USD', 'GBP_USD', 'USD_JPY', 'USD_CHF', 'AUD_USD', 'USD_CAD', 'GBP_JPY', 'EUR_JPY', 'SPX500_USD', 'NAS100_USD', 'XAU_USD', ] const GRANULARITIES = ['M1', 'M5', 'M15', 'M30', 'H1', 'H4', 'D'] const HTF_MAP: Record = { M1: 'M5', M5: 'M15', M15: 'H1', M30: 'H1', H1: 'H4', H4: 'D', D: 'D', } export default function BacktestForm({ onResult }: Props) { const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [form, setForm] = useState({ instrument: 'EUR_USD', granularity: 'H1', candle_count: 500, initial_balance: 10000, risk_percent: 1.0, rr_ratio: 2.0, swing_strength: 5, liquidity_tolerance_pips: 2.0, spread_pips: 1.5, }) const [strategies, setStrategies] = useState(['order_block_sweep']) const [filters, setFilters] = useState([]) const [htfEmaFast, setHtfEmaFast] = useState(20) const [htfEmaSlow, setHtfEmaSlow] = useState(50) const handleChange = (key: string, value: string | number) => { setForm((prev) => ({ ...prev, [key]: value })) } const toggleStrategy = (name: string) => { setStrategies((prev) => prev.includes(name) ? prev.filter((s) => s !== name) : [...prev, name] ) } const toggleFilter = (name: string) => { setFilters((prev) => prev.includes(name) ? prev.filter((f) => f !== name) : [...prev, name] ) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setLoading(true) setError(null) try { const result = await runBacktest({ ...form, strategies, filters, ...(filters.includes('htf_trend_filter') ? { htf_ema_fast: htfEmaFast, htf_ema_slow: htfEmaSlow } : {}), }) onResult(result) } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Erreur inconnue' setError(msg) } finally { setLoading(false) } } const Field = ({ label, name, type = 'number', options, value, onChange, }: { label: string; name: string; type?: string; options?: string[] value?: number; onChange?: (v: number) => void }) => (
{options ? ( ) : ( { const v = parseFloat(e.target.value) || 0 if (onChange) onChange(v) else handleChange(name, v) }} className="w-full bg-[#0f1117] border border-[#2a2d3e] rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-[#6366f1]" /> )}
) const Checkbox = ({ label, checked, onChange, description, }: { label: string; checked: boolean; onChange: () => void; description?: string }) => ( ) return (

Parametres du backtest

{/* Limite données info */} {(form.granularity === 'M1' || form.granularity === 'M5') && (
{form.granularity === 'M1' ? 'M1 : donnees limitees a 7 jours' : 'M5 : donnees limitees a 60 jours'}
)} {/* Stratégies */}

Strategies

toggleStrategy('order_block_sweep')} />
{/* Filtres */}

Filtres

toggleFilter('htf_trend_filter')} /> {filters.includes('htf_trend_filter') && (
)}
{error && (
{error}
)}
) }