"use client"; import { CURRENCY_META } from "@/lib/constants"; import type { Currency } from "@/lib/types"; interface MyfxSymbol { name: string; longPercentage: number; shortPercentage: number; totalPositions: number; } interface Props { symbols: MyfxSymbol[] | null; } // Toutes les 28 combinaisons (C(8,2)) des 8 devises — base/quote dans l'ordre standard Forex const PAIRS: { base: Currency; quote: Currency; std: string }[] = [ // Majeures USD { base: "EUR", quote: "USD", std: "EURUSD" }, { base: "GBP", quote: "USD", std: "GBPUSD" }, { base: "USD", quote: "JPY", std: "USDJPY" }, { base: "USD", quote: "CHF", std: "USDCHF" }, { base: "USD", quote: "CAD", std: "USDCAD" }, { base: "AUD", quote: "USD", std: "AUDUSD" }, { base: "NZD", quote: "USD", std: "NZDUSD" }, // Crosses EUR { base: "EUR", quote: "GBP", std: "EURGBP" }, { base: "EUR", quote: "JPY", std: "EURJPY" }, { base: "EUR", quote: "CHF", std: "EURCHF" }, { base: "EUR", quote: "CAD", std: "EURCAD" }, { base: "EUR", quote: "AUD", std: "EURAUD" }, { base: "EUR", quote: "NZD", std: "EURNZD" }, // Crosses GBP { base: "GBP", quote: "JPY", std: "GBPJPY" }, { base: "GBP", quote: "CHF", std: "GBPCHF" }, { base: "GBP", quote: "CAD", std: "GBPCAD" }, { base: "GBP", quote: "AUD", std: "GBPAUD" }, { base: "GBP", quote: "NZD", std: "GBPNZD" }, // Crosses AUD { base: "AUD", quote: "JPY", std: "AUDJPY" }, { base: "AUD", quote: "CAD", std: "AUDCAD" }, { base: "AUD", quote: "CHF", std: "AUDCHF" }, { base: "AUD", quote: "NZD", std: "AUDNZD" }, // Crosses CAD { base: "CAD", quote: "JPY", std: "CADJPY" }, // Crosses CHF { base: "CHF", quote: "JPY", std: "CHFJPY" }, // Crosses NZD { base: "NZD", quote: "JPY", std: "NZDJPY" }, { base: "NZD", quote: "CAD", std: "NZDCAD" }, { base: "NZD", quote: "CHF", std: "NZDCHF" }, // Croisée manquante CAD/CHF { base: "CAD", quote: "CHF", std: "CADCHF" }, ]; // Groupes pour l'affichage const GROUPS = [ { label: "Majeures USD", pairs: ["EURUSD","GBPUSD","USDJPY","USDCHF","USDCAD","AUDUSD","NZDUSD"] }, { label: "Crosses EUR", pairs: ["EURGBP","EURJPY","EURCHF","EURCAD","EURAUD","EURNZD"] }, { label: "Crosses GBP", pairs: ["GBPJPY","GBPCHF","GBPCAD","GBPAUD","GBPNZD"] }, { label: "Crosses AUD/NZD",pairs: ["AUDJPY","AUDCAD","AUDCHF","AUDNZD","NZDJPY","NZDCAD","NZDCHF"] }, { label: "Crosses CAD/CHF",pairs: ["CADJPY","CHFJPY","CADCHF"] }, ]; function SentimentBar({ longPct }: { longPct: number }) { const isContrarian = longPct >= 70 || longPct <= 30; return (
{longPct}%
{100 - longPct}% {isContrarian && ( )}
); } export default function SentimentPairsTab({ symbols }: Props) { const symMap: Record = {}; for (const s of symbols ?? []) symMap[s.name] = s; const pairMap: Record = {}; for (const p of PAIRS) pairMap[p.std] = { base: p.base, quote: p.quote }; return (

Sentiment retail — toutes les paires

Source : Myfxbook Community Outlook · {symbols ? `${Object.keys(symMap).length} paires disponibles` : "chargement…"} · Long = retail haussier sur la devise de base · ⚠ = signal contrarien (>70% ou <30%)

{GROUPS.map((group) => (
{/* Group header */}
{group.label}
{group.pairs.map((pairName) => { const def = pairMap[pairName]; const sym = symMap[pairName]; const baseMeta = def ? CURRENCY_META[def.base] : null; const quoteMeta = def ? CURRENCY_META[def.quote] : null; return ( {/* Pair name */} {/* Sentiment bar */} {/* Total positions */} ); })}
Paire Long L / Short S Positions totales
{baseMeta?.flag} {quoteMeta?.flag} {pairName}
{sym ? ( ) : ( Non disponible sur Myfxbook )} {sym ? ( {sym.totalPositions.toLocaleString("fr-FR")} ) : ( )}
))}
Long % = % des positions retail haussières sur la devise de base de la paire · Données Myfxbook Community Outlook
); }