ACIL FM
Dark
Refresh
Current DIR:
/home/benbot/public_html/monitor
/
home
benbot
public_html
monitor
Upload
Zip Selected
Delete Selected
Pilih semua
Nama
Ukuran
Permission
Aksi
css
-
chmod
Open
Rename
Delete
.htaccess
647 B
chmod
View
DL
Edit
Rename
Delete
breadth.html
13 MB
chmod
View
DL
Edit
Rename
Delete
eslint.config.mjs
803 B
chmod
View
DL
Edit
Rename
Delete
guide_1.html
18.76 MB
chmod
View
DL
Edit
Rename
Delete
guide_market.html
18.76 MB
chmod
View
DL
Edit
Rename
Delete
guide_ranktop5.html
29.76 MB
chmod
View
DL
Edit
Rename
Delete
index.html
31.38 MB
chmod
View
DL
Edit
Rename
Delete
ls-bias.html
18.24 MB
chmod
View
DL
Edit
Rename
Delete
opsdeck-basic.html
7.11 MB
chmod
View
DL
Edit
Rename
Delete
opsdeck.html
4.96 MB
chmod
View
DL
Edit
Rename
Delete
rank_top5.html
24.79 MB
chmod
View
DL
Edit
Rename
Delete
risk.html
13.32 MB
chmod
View
DL
Edit
Rename
Delete
trade.html
13.87 MB
chmod
View
DL
Edit
Rename
Delete
Edit file: /home/benbot/public_html/monitor/guide_market.html
<!doctype html> <html lang="ko"> <head> <meta charset="utf-8" /> <title>Trading Guide — Market Breadth</title> <meta name="viewport" content="width=device-width,initial-scale=1" /> <style> :root { --bg: #0b0f14; --panel: #0f141a; --card: #0b1117; --line: #1e2a36; --ink: #e6edf3; --muted: #9fb0c3; --pos: #19c37d; --neg: #ef4444; --neu: #64748b; --pill: #1a2230; } * { box-sizing: border-box; } body { margin: 0; background: var(--bg); color: var(--ink); font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, "Malgun Gothic", sans-serif; display: flex; justify-content: center; } /* 9:16 고정 뷰포트 */ .viewport { width: min(100vw, 56.25vh); height: calc(min(100vw, 56.25vh) * 16 / 9); background: var(--bg); overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; } /* 상단바: 1줄(브랜드+시간) + 1줄(서브타이틀) */ .topbar { position: sticky; top: 0; z-index: 10; background: rgba(11, 15, 20, 0.95); backdrop-filter: blur(6px); display: flex; flex-direction: column; gap: 4px; padding: 12px 24px 10px 14px; border-bottom: 1px solid rgba(30, 42, 54, 0.4); } .top-main { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .brand-badge { background: #101a26; border: 1px solid rgba(135, 206, 250, 0.35); border-radius: 999px; padding: 5px 18px 4px; font-size: 16px; /* ← 크게 */ letter-spacing: 0.04em; text-transform: uppercase; color: #ffffff; font-weight: 700; white-space: nowrap; } /* 시간 한 줄 */ .time-pill { background: rgba(13, 19, 25, 0.4); border: 1px solid rgba(158, 176, 195, 0.25); border-radius: 999px; padding: 3px 12px 3px; font-size: 12px; color: var(--ink); white-space: nowrap; margin-left: auto; } /* 서브타이틀은 아래 작게 */ .subtitle { font-size: 12px; color: var(--muted); } .modules { display: flex; flex-direction: column; gap: 12px; padding: 12px 12px 20px; } /* 공통 카드 */ .module { display: flex; flex-direction: column; gap: 6px; } .mod-tag { font-size: 11px; background: rgba(230, 237, 243, 0.02); border: 1px solid rgba(230, 237, 243, 0.04); border-radius: 999px; padding: 2px 12px 1px; color: var(--muted); width: fit-content; } .bcard { background: var(--panel); border: 1px solid rgba(30, 42, 54, 0.6); border-radius: 16px; padding: 12px 12px 10px; display: flex; flex-direction: column; gap: 10px; } .bhead { display: flex; align-items: center; justify-content: space-between; gap: 10px; } .btitle { font-weight: 700; font-size: 14px; } .bctrl { display: flex; gap: 6px; align-items: center; } .lbl { font-size: 12px; color: var(--muted); } select { background: rgba(11, 17, 23, 0.4); border: 1px solid rgba(30, 42, 54, 0.6); border-radius: 8px; color: var(--ink); padding: 2px 6px 2px 6px; font-size: 12px; } .badge { background: rgba(154, 170, 195, 0.06); border: 1px solid rgba(154, 170, 195, 0.15); border-radius: 999px; padding: 2px 10px; font-size: 12px; color: var(--ink); } .bar { height: 14px; border-radius: 999px; overflow: hidden; border: 1px solid rgba(30, 42, 54, 0.6); background: #0e141b; position: relative; } .bar > div { height: 100%; position: absolute; top: 0; } .up { background: var(--pos); left: 0; } .mid { background: var(--neu); } .dn { background: var(--neg); } /* KPI 묶음 2열 */ .kpi-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; } .kpi { background: rgba(11, 17, 23, 0.3); border: 1px dashed rgba(30, 42, 54, 0.6); border-radius: 12px; padding: 5px 8px 4px; display: flex; justify-content: space-between; align-items: center; gap: 6px; } .kpi-label { font-size: 12px; color: var(--muted); white-space: nowrap; } .kpi-value { font-size: 13px; font-weight: 600; color: var(--ink); } @media (max-width: 480px) { .viewport { width: 100vw; height: calc(100vw * 16 / 9); } .top-main { gap: 6px; } .time-pill { font-size: 11px; padding: 3px 10px 3px; } } </style> </head> <body> <div class="viewport"> <!-- 상단 --> <div class="topbar"> <div class="top-main"> <div class="brand-badge">TRADING GUIDE</div> <div id="timePill" class="time-pill">LA (PDT) · --:--:--</div> </div> <div class="subtitle">Market Breadth Monitor</div> </div> <!-- 모듈 --> <div class="modules"> <!-- 1. SPOT --> <div class="module" id="mod-1"> <div class="mod-tag">1. SPOT 전체 — 상승/하락 비중</div> <div class="bcard"> <div class="bhead"> <div class="btitle">SPOT 전체 — 상승/하락 비중</div> <div class="bctrl"> <span class="lbl">봉 간격</span> <select id="spotTf"> <option value="1">1분</option> <option value="3">3분</option> <option value="5" selected>5분</option> <option value="10">10분</option> <option value="15">15분</option> </select> <span id="spotStatus" class="badge">워밍업</span> </div> </div> <div class="bar"> <div id="spotUp" class="up" style="width:0%"></div> <div id="spotMid" class="mid" style="width:0%"></div> <div id="spotDn" class="dn" style="width:0%"></div> </div> <div class="kpi-grid"> <div class="kpi"> <div class="kpi-label">상승(%)</div> <div class="kpi-value" id="spotUpPct">0</div> </div> <div class="kpi"> <div class="kpi-label">보합(%)</div> <div class="kpi-value" id="spotZPct">0</div> </div> <div class="kpi"> <div class="kpi-label">하락(%)</div> <div class="kpi-value" id="spotDnPct">0</div> </div> <div class="kpi"> <div class="kpi-label">상승 심볼</div> <div class="kpi-value" id="spotUpCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">보합 심볼</div> <div class="kpi-value" id="spotZCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">하락 심볼</div> <div class="kpi-value" id="spotDnCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">총 심볼</div> <div class="kpi-value" id="spotTotal">0</div> </div> <div class="kpi"> <div class="kpi-label">상태</div> <div class="kpi-value" id="spotState">-</div> </div> </div> </div> </div> <!-- 2. FUTURES --> <div class="module" id="mod-2"> <div class="mod-tag">2. USDT-Futures 전체 — 상승/하락 비중</div> <div class="bcard"> <div class="bhead"> <div class="btitle">USDT-Futures 전체 — 상승/하락 비중</div> <div class="bctrl"> <span class="lbl">봉 간격</span> <select id="futTf"> <option value="1">1분</option> <option value="3">3분</option> <option value="5" selected>5분</option> <option value="10">10분</option> <option value="15">15분</option> </select> <span id="futStatus" class="badge">워밍업</span> </div> </div> <div class="bar"> <div id="futUp" class="up" style="width:0%"></div> <div id="futMid" class="mid" style="width:0%"></div> <div id="futDn" class="dn" style="width:0%"></div> </div> <div class="kpi-grid"> <div class="kpi"> <div class="kpi-label">상승(%)</div> <div class="kpi-value" id="futUpPct">0</div> </div> <div class="kpi"> <div class="kpi-label">보합(%)</div> <div class="kpi-value" id="futZPct">0</div> </div> <div class="kpi"> <div class="kpi-label">하락(%)</div> <div class="kpi-value" id="futDnPct">0</div> </div> <div class="kpi"> <div class="kpi-label">상승 심볼</div> <div class="kpi-value" id="futUpCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">보합 심볼</div> <div class="kpi-value" id="futZCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">하락 심볼</div> <div class="kpi-value" id="futDnCnt">0</div> </div> <div class="kpi"> <div class="kpi-label">총 심볼</div> <div class="kpi-value" id="futTotal">0</div> </div> <div class="kpi"> <div class="kpi-label">상태</div> <div class="kpi-value" id="futState">-</div> </div> </div> </div> </div> <!-- 3, 4 ... 모듈 계속 추가 가능 --> </div> </div> <script> const API = "https://api.bitget.com"; const PRODUCT_TYPE = "USDT-FUTURES"; const futHist = new Map(); const spotHist = new Map(); let futWindowMin = 5; let spotWindowMin = 5; document.getElementById("futTf").addEventListener("change", (e) => { futWindowMin = +e.target.value; renderBreadth(); }); document.getElementById("spotTf").addEventListener("change", (e) => { spotWindowMin = +e.target.value; renderBreadth(); }); function trimHistory(queue, keepMin) { const cutoff = Date.now() - keepMin * 60 * 1000; while (queue.length && queue[0].ts < cutoff) queue.shift(); } function boundaryStart(min) { const tf = min * 60 * 1000; const now = Date.now(); const al = Math.floor(now / tf) * tf; return al - tf; } function baseAtOrAfter(q, t0) { if (!q || !q.length) return null; for (let i = 0; i < q.length; i++) { if (q[i].ts >= t0) return q[i].price; } return null; } function baseAtOrBefore(q, t0) { let b = null; for (let i = q.length - 1; i >= 0; i--) { if (q[i].ts <= t0) { b = q[i].price; break; } } if (b == null && q.length) b = q[0].price; return b; } function computeCounts(mapHist, min) { const t0 = boundaryStart(min); let up = 0, dn = 0, flat = 0, total = 0; for (const [, q] of mapHist.entries()) { if (!q || q.length < 2) continue; let base = baseAtOrAfter(q, t0); if (base == null) base = baseAtOrBefore(q, t0); const last = q[q.length - 1].price; if (base == null || !isFinite(last)) continue; total++; if (last > base) up++; else if (last < base) dn++; else flat++; } return { up, dn, flat, total }; } function drawBar(ids, data) { const { upEl, midEl, dnEl, upPctEl, midPctEl, dnPctEl, upCntEl, midCntEl, dnCntEl, totalEl, stateEl, } = ids; const { up, dn, flat, total } = data; const upPct = total ? Math.round((up / total) * 100) : 0; const midPct = total ? Math.round((flat / total) * 100) : 0; const dnPct = total ? Math.round((dn / total) * 100) : 0; upEl.style.width = upPct + "%"; midEl.style.left = upPct + "%"; midEl.style.width = midPct + "%"; dnEl.style.left = upPct + midPct + "%"; dnEl.style.width = dnPct + "%"; upPctEl.textContent = upPct; midPctEl.textContent = midPct; dnPctEl.textContent = dnPct; upCntEl.textContent = up; midCntEl.textContent = flat; dnCntEl.textContent = dn; totalEl.textContent = total; if (stateEl) { if (!total) stateEl.textContent = "데이터 없음"; else if (upPct > 55) stateEl.textContent = "상승 우위"; else if (dnPct > 55) stateEl.textContent = "하락 우위"; else stateEl.textContent = "중립"; } } function renderBreadth() { const fut = computeCounts(futHist, futWindowMin); const spot = computeCounts(spotHist, spotWindowMin); drawBar( { upEl: document.getElementById("futUp"), midEl: document.getElementById("futMid"), dnEl: document.getElementById("futDn"), upPctEl: document.getElementById("futUpPct"), midPctEl: document.getElementById("futZPct"), dnPctEl: document.getElementById("futDnPct"), upCntEl: document.getElementById("futUpCnt"), midCntEl: document.getElementById("futZCnt"), dnCntEl: document.getElementById("futDnCnt"), totalEl: document.getElementById("futTotal"), stateEl: document.getElementById("futState"), }, fut, ); drawBar( { upEl: document.getElementById("spotUp"), midEl: document.getElementById("spotMid"), dnEl: document.getElementById("spotDn"), upPctEl: document.getElementById("spotUpPct"), midPctEl: document.getElementById("spotZPct"), dnPctEl: document.getElementById("spotDnPct"), upCntEl: document.getElementById("spotUpCnt"), midCntEl: document.getElementById("spotZCnt"), dnCntEl: document.getElementById("spotDnCnt"), totalEl: document.getElementById("spotTotal"), stateEl: document.getElementById("spotState"), }, spot, ); } async function fetchJSON(url) { const r = await fetch(url); if (!r.ok) throw new Error(r.status); return r.json(); } async function poll() { try { const [fut, spot] = await Promise.allSettled([ fetchJSON(`${API}/api/v2/mix/market/tickers?productType=${PRODUCT_TYPE}`), fetchJSON(`${API}/api/v2/spot/market/tickers`), ]); const now = Date.now(); if (fut.status === "fulfilled" && Array.isArray(fut.value?.data)) { for (const t of fut.value.data) { const sym = String(t.symbol || t.instId || "").toUpperCase(); const px = Number(t.lastPr ?? t.last ?? t.close ?? t.lastPrice); if (!sym || !isFinite(px)) continue; if (!futHist.has(sym)) futHist.set(sym, []); const q = futHist.get(sym); q.push({ ts: now, price: px }); trimHistory(q, 20); } document.getElementById("futStatus").textContent = "업데이트"; } if (spot.status === "fulfilled" && Array.isArray(spot.value?.data)) { for (const t of spot.value.data) { const sym = String(t.symbol || t.instId || "").toUpperCase(); const px = Number(t.lastPr ?? t.last ?? t.close ?? t.lastPrice); if (!sym || !isFinite(px)) continue; if (!spotHist.has(sym)) spotHist.set(sym, []); const q = spotHist.get(sym); q.push({ ts: now, price: px }); trimHistory(q, 20); } document.getElementById("spotStatus").textContent = "업데이트"; } renderBreadth(); } catch (e) { console.error(e); } finally { setTimeout(poll, 800); } } // 상단 시간: LA 기준 한 줄로 function tick() { const pill = document.getElementById("timePill"); if (!pill) return; const now = new Date(); const laFmt = new Intl.DateTimeFormat("en-US", { timeZone: "America/Los_Angeles", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, }); const laTime = laFmt.format(now); // PDT/PST 구분 const tzNameFmt = new Intl.DateTimeFormat("en-US", { timeZone: "America/Los_Angeles", timeZoneName: "short", }); const tzParts = tzNameFmt.formatToParts(now); const tzPart = tzParts.find((p) => p.type === "timeZoneName"); const tzShort = tzPart ? tzPart.value : "PT"; pill.textContent = `LA (${tzShort}) · ${laTime}`; } setInterval(tick, 1000); tick(); // 데이터 폴링 시작 poll(); </script> </body> </html>
Simpan
Batal
Isi Zip:
Unzip
Create
Buat Folder
Buat File
Terminal / Execute
Run
Chmod Bulk
All File
All Folder
All File dan Folder
Apply