"use strict"; const topStrategyGrid = document.getElementById("topStrategyGrid"); const rankingPreview = document.getElementById("rankingPreview"); const rankingDescription = document.getElementById("rankingDescription"); function escapeHtml(value) { return String(value ?? "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function formatNumber(value, digits = 0) { const number = Number(value); if (!Number.isFinite(number)) { return "-"; } return number.toLocaleString("ko-KR", { minimumFractionDigits: digits, maximumFractionDigits: digits, }); } function strategyName(strategy) { return strategy.display_name || strategy.strategy_display_name_ko || strategy.strategy_name || strategy.public_strategy_code || strategy.strategy_code || "전략1 BTC 라이브"; } function publicStrategiesOnly(strategies) { return strategies.filter((strategy) => { const code = strategy.actual_strategy_code || strategy.public_strategy_code || strategy.strategy_code; return code === "live_strategy1_btc" && strategy.publish_status === "published" && strategy.visibility === "public" && strategy.is_public_simulation_visible === true && strategy.is_temp !== true && strategy.is_admin_only !== true; }); } function renderPreview(strategies) { if (!rankingPreview) { return; } if (!strategies.length) { rankingPreview.innerHTML = '
공개 전략 정보가 없습니다.
'; return; } rankingPreview.innerHTML = strategies.map((strategy) => `
${escapeHtml(strategy.rank || 1)}
${escapeHtml(strategyName(strategy))} ${escapeHtml(strategy.market || "KRW-BTC")}
${formatNumber(strategy.recent_win_rate_pct, 1)}%
`).join(""); } function renderCards(strategies) { if (!topStrategyGrid) { return; } if (!strategies.length) { topStrategyGrid.innerHTML = `

공개 전략 정보가 없습니다.

라이브 퍼블리싱된 전략이 준비되면 이 영역에 표시됩니다.

`; return; } topStrategyGrid.innerHTML = strategies.map((strategy) => { const pnl = Number(strategy.recent_realized_pnl_krw) || 0; const pnlClass = pnl > 0 ? "positive" : pnl < 0 ? "negative" : "neutral"; const code = strategy.public_strategy_code || strategy.strategy_code || "live_strategy1_btc"; return `
${escapeHtml(strategy.rank || 1)}위 ${escapeHtml(strategy.market || "KRW-BTC")}

${escapeHtml(strategyName(strategy))}

${escapeHtml(strategy.strategy_description_ko || "전략1 BTC 라이브 공개 시뮬레이션 결과입니다.")}

최근 승률
${formatNumber(strategy.recent_win_rate_pct, 1)}%
최근 실현손익
${pnl > 0 ? "+" : ""}${formatNumber(pnl)} KRW
집계 거래
${formatNumber(strategy.recent_trade_count)}건
공개 태그
라이브 퍼블리싱
시뮬레이션 성과 보기
`; }).join(""); } async function loadTopStrategies() { try { const response = await fetch("/api/public/top-strategies?market_type=crypto&market=KRW-BTC", { headers: {Accept: "application/json"}, cache: "no-store", }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const payload = await response.json(); const strategies = publicStrategiesOnly(Array.isArray(payload.strategies) ? payload.strategies : []); const tradeLimit = Number(payload.ranking?.recent_trade_limit) || 30; if (rankingDescription) { rankingDescription.textContent = `라이브 퍼블리싱된 공개 전략의 최근 청산 ${tradeLimit}건을 기준으로 표시합니다.`; } renderPreview(strategies); renderCards(strategies); } catch (error) { console.error(error); if (rankingPreview) { rankingPreview.innerHTML = '
공개 전략 정보를 불러오지 못했습니다.
'; } if (topStrategyGrid) { topStrategyGrid.innerHTML = `

공개 전략 정보를 불러오지 못했습니다.

잠시 후 다시 확인해 주세요.

`; } } } loadTopStrategies();