feat: wavelets
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user