// AVANT MARKETS — Mi Portafolio screen // Donut chart for sector distribution function Donut({ slices }) { // slices: [{ pct, color }] const r = 60; const cx = 80, cy = 80; const circ = 2 * Math.PI * r; let offset = 0; return ( {slices.map((s, i) => { const len = (s.pct / 100) * circ; const dasharray = `${len} ${circ - len}`; const dashoffset = -offset; offset += len; return ( ); })} 8 ACTIVOS ); } function Sparkline({ values, positive }) { const d = sparkPath(values); return ( ); } function Portfolio({ onOpenTicker }) { const data = buildPortfolio(); // Sector distribution const sectorMap = {}; data.holdings.forEach(h => { const s = h.info.sector; sectorMap[s] = (sectorMap[s] || 0) + h.value; }); const sectorTotal = Object.values(sectorMap).reduce((a, b) => a + b, 0); const sectorColors = ["#c8ff1f", "#2bd8e6", "#9b5cff", "#ff8a3d", "#ff4d7a", "#5cffaa", "#ffd84d"]; const sectors = Object.entries(sectorMap) .map(([name, v], i) => ({ name, pct: (v / sectorTotal) * 100, color: sectorColors[i % sectorColors.length] })) .sort((a, b) => b.pct - a.pct); // Top movers across the market (all tickers) const movers = Object.values(TICKERS) .slice() .sort((a, b) => Math.abs(b.changePct) - Math.abs(a.changePct)) .slice(0, 6); return (
{/* Top summary + distribution */}
Valor total del portafolio
{fmtMoney(data.computedTotal)} USD
Hoy = 0 ? "" : " neg")}> {data.todayChange >= 0 ? "▲" : "▼"} {fmtSigned(data.todayChange)} USD ({fmtPct(data.todayChangePct)})
Rendimiento total = 0 ? "" : " neg")}> {data.allTimeReturn >= 0 ? "▲" : "▼"} {fmtSigned(data.allTimeReturn)} USD ({fmtPct(data.allTimeReturnPct)})
Efectivo disponible {fmtMoney(data.cashAvailable)} USD

Distribución por sector

{sectors.map(s => (
{s.name} {s.pct.toFixed(1).replace(".", ",")}%
))}
{/* Holdings table */}

Mis posiciones

Exportar CSV
{data.holdings.map(h => { const pos = h.pl >= 0; const todayPos = h.info.change >= 0; return ( onOpenTicker(h.ticker)}> ); })}
Activo Cantidad Precio prom. Precio actual Valor G/P total Hoy Peso 7D
{h.ticker.slice(0, 2)}
{h.ticker} {h.info.name}
{h.qty} {fmtMoney(h.avgCost)} {fmtMoney(h.info.price)} {fmtMoney(h.value)} {fmtSigned(h.pl, 0)} ({fmtPct(h.plPct, 1)}) {fmtPct(h.info.changePct)} {h.weight.toFixed(1).replace(".", ",")}%
{/* Activity + movers */}

Actividad reciente

Historial
{ACTIVITY.map((a, i) => { const t = TICKERS[a.ticker]; let title, amount, sub; if (a.type === "buy") { title = `Compra · ${a.ticker}`; sub = `${a.qty} acciones a ${fmtMoney(a.price)} USD`; amount = `−${fmtMoney(a.qty * a.price)} USD`; } else if (a.type === "sell") { title = `Venta · ${a.ticker}`; sub = `${a.qty} acciones a ${fmtMoney(a.price)} USD`; amount = `+${fmtMoney(a.qty * a.price)} USD`; } else { title = `Dividendo · ${a.ticker}`; sub = `${a.qty} acciones`; amount = `+${fmtMoney(a.amount)} USD`; } return (
{a.type === "buy" ? "BUY" : a.type === "sell" ? "SELL" : "DIV"}
{title} {sub}
{amount}
{a.time}
); })}

Mayores movimientos

Ver mercado
{movers.map(m => { const pos = m.change >= 0; return (
onOpenTicker(m.ticker)}>
{m.ticker.slice(0, 2)}
{m.ticker} {m.name}
{fmtMoney(m.price)}
{fmtPct(m.changePct)}
); })}
); } Object.assign(window, { Portfolio });