)
}
// ── Main page ─────────────────────────────────────────────────────────────────
export default function OptionsLab() {
const { data, isLoading, refetch, isFetching } = useIvWatchlist()
const [bootstrapping, setBootstrapping] = useState(false)
const [bootstrapMsg, setBootstrapMsg] = useState(null)
const items: any[] = data?.items || []
const sellVol = items.filter(i => (i.iv_rank ?? 50) >= 80)
const buyVol = items.filter(i => i.iv_rank != null && i.iv_rank < 20)
const neutral = items.filter(i => i.iv_rank != null && i.iv_rank >= 20 && i.iv_rank < 80)
const noData = items.filter(i => i.iv_rank == null)
const handleBootstrap = async () => {
setBootstrapping(true)
setBootstrapMsg(null)
try {
await api.post('/options-vol/bootstrap-history')
setBootstrapMsg('Bootstrap lancé (~60s) — actualise dans 1 minute pour voir les IV Rank mis à jour.')
setTimeout(() => refetch(), 70_000)
} catch {
setBootstrapMsg('Erreur lors du bootstrap.')
} finally {
setBootstrapping(false)
}
}
// Show bootstrap banner if most items have no meaningful IV Rank (stuck at 50 or null)
const needsBootstrap = items.length > 0 && items.filter(i => i.iv_rank == null || i.iv_rank === 50).length > items.length * 0.6
return (
{needsBootstrap && !bootstrapMsg && (
⚠️ Historique IV insuffisant — IV Rank bloqué à 50%. Bootstrappe 1 an de données réalisées pour calibrer le Rank.
)}
{bootstrapMsg && (
ℹ️ {bootstrapMsg}
)}
Options Lab
IV Rank · IV Percentile · Term Structure · Skew · Options Flow
{/* Légende */}
IV Rank > 80% — Vendre de la vol
Credit spreads, iron condors, covered calls. La prime est élevée → avantage au vendeur.
IV Rank < 20% — Acheter de la convexité
Long calls, long puts, straddles, strangles. La prime est cheap → bon moment pour acheter du gamma.
Contango = IV courte < longue (marché calme, bon pour vendre du court terme) ·
Backwardation = IV courte > longue (stress, bon pour acheter de la protection courte) ·
Skew + = puts plus chers que calls (biais baissier institutionnel)
{isLoading ? (
{[...Array(6)].map((_, i) => )}
) : items.length === 0 ? (
Aucune donnée IV disponible
Les ETFs US sont requis (SPY, QQQ, GLD...).
L'IV Rank nécessite de l'historique — les données s'accumulent à chaque actualisation.