feat: wavelets

This commit is contained in:
OpenSquared
2026-07-19 16:34:53 +02:00
parent 9079d4e9c5
commit e61bc50106
2 changed files with 46 additions and 5 deletions

View File

@@ -66,6 +66,7 @@ export default function WaveletsSimulation() {
const [modes, setModes] = useState<Set<WaveletPositionMode>>(new Set(['both']))
const [takeProfits, setTakeProfits] = useState<number[]>([0])
const [stopLosses, setStopLosses] = useState<number[]>([0])
const [filterBand, setFilterBand] = useState<number | null>(null)
const [simName, setSimName] = useState(() => `Run ${new Date().toISOString().slice(0, 16).replace('T', ' ')}`)
// ── Run state ────────────────────────────────────────────────────────────────
@@ -103,7 +104,7 @@ export default function WaveletsSimulation() {
const form = {
instruments: [...selectedInstruments], period, levels, wavelets: [...wavelets],
lookbacks, bands: [...bands], kinds: [...kinds], modes: [...modes],
takeProfits, stopLosses, method,
takeProfits, stopLosses, method, filterBand,
}
const created = await api.post('/wavelet/simulations', { name: simName, form, results: [] }).then(r => r.data)
setActiveSimId(created.id)
@@ -124,6 +125,7 @@ export default function WaveletsSimulation() {
try { await api.patch(`/wavelet/simulations/${created.id}`, { append_results: batch }) } catch { /* non-blocking */ }
},
method,
filterBand,
)
setRunning(false)
qc.invalidateQueries({ queryKey: ['wavelet-simulations'] })
@@ -286,6 +288,22 @@ export default function WaveletsSimulation() {
</div>
</div>
<div>
<div className="text-slate-500 text-xs mb-1" title="Un retournement (extremum, seuil...) d'une bande à tester ne se déclenche que si cette bande secondaire confirme la même direction (pente positive pour un achat/cover, négative pour une vente/short) — ex. creux de bande 1 achète seulement si bande 3 monte.">
Filtre de tendance (bande de confirmation)
</div>
<div className="flex gap-2 flex-wrap text-xs">
<label className="flex items-center gap-1 cursor-pointer">
<input type="radio" checked={filterBand === null} onChange={() => setFilterBand(null)} /> Aucun
</label>
{ALL_BANDS.slice(0, levels).map(b => (
<label key={b} className="flex items-center gap-1 cursor-pointer">
<input type="radio" checked={filterBand === b} onChange={() => setFilterBand(b)} /> Bande {b}
</label>
))}
</div>
</div>
<div>
<div className="text-slate-500 text-xs mb-1">Types de déclencheur</div>
<div className="flex gap-3 flex-wrap text-xs">