<!DOCTYPE html>
<html lang="ru"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Order-Flow — накопленная стата</title>
<style>
:root{--bg:#0a0e17;--card:rgba(255,255,255,.04);--border:rgba(255,255,255,.09);
--txt:#e6edf3;--muted:#8b98a9;--green:#21d07a;--red:#f6465d;--blue:#3b82f6;--amber:#f59e0b;--purple:#8b5cf6}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
background:radial-gradient(1200px 600px at 80% -10%,rgba(16,185,129,.10),transparent),
radial-gradient(900px 500px at 0% 0%,rgba(59,130,246,.08),transparent),var(--bg);
color:var(--txt);min-height:100vh;padding:24px 16px;line-height:1.5}
.wrap{max-width:1040px;margin:0 auto}
header{margin-bottom:14px}
h1{font-size:23px;font-weight:700;letter-spacing:-.5px}
h1 .em{background:linear-gradient(90deg,#10b981,var(--blue));-webkit-background-clip:text;background-clip:text;color:transparent}
.sub{color:var(--muted);font-size:12.5px;margin-top:5px}
.glass{background:var(--card);border:1px solid var(--border);border-radius:14px}
.warn{padding:13px 16px;margin-bottom:16px;border-left:3px solid var(--amber);font-size:12.5px;background:rgba(245,158,11,.06)}
.warn b{color:var(--amber)}
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
.kpi{padding:15px;text-align:center}
.kpi .lbl{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.4px}
.kpi .val{font-size:25px;font-weight:800;margin:5px 0 1px}
.kpi .sm{font-size:11px;color:var(--muted)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}
.panel{padding:16px 18px}
.panel h2{font-size:14px;font-weight:600;margin-bottom:10px}
table{width:100%;border-collapse:collapse;font-size:12.5px}
th,td{text-align:right;padding:6px 6px}
th:first-child,td:first-child{text-align:left}
th{color:var(--muted);font-weight:500;font-size:10.5px;text-transform:uppercase;letter-spacing:.3px;border-bottom:1px solid var(--border)}
tr+tr td{border-top:1px solid rgba(255,255,255,.045)}
td{font-variant-numeric:tabular-nums}
.pos{color:var(--green)}.neg{color:var(--red)}.mut{color:var(--muted)}
.dirbar{display:flex;height:30px;border-radius:8px;overflow:hidden;margin-bottom:8px}
.dirbar .l{background:rgba(33,208,122,.5);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}
.dirbar .s{background:rgba(246,70,93,.5);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}
.spark{display:flex;align-items:flex-end;gap:6px;height:90px;margin-top:6px}
.spark .col{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px}
.spark .b{width:100%;max-width:60px;border-radius:5px 5px 0 0;background:linear-gradient(180deg,#10b981,rgba(16,185,129,.35))}
.spark .dt{font-size:10px;color:var(--muted)}
.chips{display:flex;flex-wrap:wrap;gap:7px}
.chip{padding:6px 10px;font-size:12px;font-weight:600;border-radius:9px;background:rgba(255,255,255,.04);border:1px solid var(--border)}
.chip .n{color:var(--muted);font-weight:500;margin-left:5px}
.cap{font-size:11.5px;color:var(--muted);margin-top:10px;line-height:1.6}
.foot{color:var(--muted);font-size:11px;margin-top:8px;text-align:center}
</style></head>
<body><div class="wrap">
<header>
<h1>📖 Order-Flow — <span class="em">накопленная стата (live)</span></h1>
<div class="sub" id="sub"></div>
</header>
<div class="warn glass" id="warn"></div>
<div class="kpis" id="kpis"></div>
<div class="grid2">
<div class="panel glass">
<h2>📈 По направлению</h2>
<div class="dirbar" id="dirbar"></div>
<div class="cap" id="dirCap"></div>
</div>
<div class="panel glass">
<h2>🎚 По confidence (сила дисбаланса)</h2>
<table id="conf"><thead><tr><th>Бакет</th><th>Сигналов</th><th>ср.MFE</th><th>ср.MAE</th></tr></thead><tbody></tbody></table>
</div>
</div>
<div class="panel glass" style="margin-bottom:14px">
<h2>⏱ По часам (UTC)</h2>
<div class="spark" id="spark"></div>
</div>
<div class="panel glass" style="margin-bottom:14px">
<h2>🔥 Топ символов</h2>
<div class="chips" id="sym"></div>
</div>
<div class="panel glass">
<h2>🔬 Ранний MFE/MAE <span class="mut" style="font-weight:400">— насколько цена ходит после сигнала</span></h2>
<table id="mfe"><thead><tr><th>Метрика</th><th>Значение</th><th></th></tr></thead><tbody></tbody></table>
<div class="cap" id="mfeCap"></div>
</div>
<div class="foot" id="foot"></div>
</div>
<script>
const D = {"o": {"n": 125, "first": "2026-06-03 06:51:14", "last": "2026-06-03 08:22:17", "resolved": 0, "wins": 0}, "dir": {"LONG": 80, "SHORT": 45}, "conf": [{"b": "50-59", "n": 108, "mfe": 1.121, "mae": -2.373, "res": 0, "wins": 0}, {"b": "60-69", "n": 12, "mfe": 1.403, "mae": -5.25, "res": 0, "wins": 0}, {"b": "70-79", "n": 4, "mfe": 0.945, "mae": -1.67, "res": 0, "wins": 0}, {"b": "80-89", "n": 1, "mfe": 0.718, "mae": -1.301, "res": 0, "wins": 0}], "sym": [{"s": "EDGEUSDT", "n": 18, "conf": 51.0}, {"s": "SOXLUSDT", "n": 14, "conf": 54.8}, {"s": "LABUSDT", "n": 11, "conf": 58.1}, {"s": "FETUSDT", "n": 9, "conf": 51.1}, {"s": "PORTALUSDT", "n": 8, "conf": 51.8}, {"s": "BCHUSDT", "n": 7, "conf": 63.5}, {"s": "HOMEUSDT", "n": 7, "conf": 56.3}, {"s": "HUSDT", "n": 5, "conf": 58.7}, {"s": "HYPEUSDT", "n": 5, "conf": 56.8}, {"s": "LITUSDT", "n": 5, "conf": 53.7}, {"s": "EPICUSDT", "n": 4, "conf": 53.4}, {"s": "ICPUSDT", "n": 4, "conf": 53.1}], "hour": [{"h": "2026-06-03 06", "n": 14}, {"h": "2026-06-03 07", "n": 87}, {"h": "2026-06-03 08", "n": 24}], "mfe": {"avg_mfe": 1.139, "avg_mae": -2.618, "n": 125}, "avg_abs_imb": 0.419};
const pct=(v)=>v==null?'—':(v>0?'+':'')+v.toFixed(2)+'%';
const sgn=v=>v>0?'pos':v<0?'neg':'mut';
const o=D.o, tot=o.n;
const dur = '≈1.5 ч';
document.getElementById('sub').textContent =
`${tot} сигналов · период ${o.first.slice(11,16)}–${o.last.slice(11,16)} UTC (${dur}) · ср.|дисбаланс| ${(D.avg_abs_imb*100).toFixed(0)}% · резолв ${o.resolved}`;
document.getElementById('warn').innerHTML =
`⚠️ <b>Это снимок за ~1.5 часа, исходов ПОКА 0</b> (TP/SL дозревают до суток). <b>Выводов по прибыльности здесь делать НЕЛЬЗЯ</b> — это просто что накопилось: объём, распределение, активность. MFE/MAE ниже — сырые, окна сделок ещё открыты.`;
const kpis=[
{l:'Сигналов',v:tot,c:'var(--txt)'},
{l:'LONG / SHORT',v:`${D.dir.LONG||0}/${D.dir.SHORT||0}`,c:'var(--txt)'},
{l:'Ср. |дисбаланс|',v:(D.avg_abs_imb*100).toFixed(0)+'%',c:'#10b981'},
{l:'Резолв',v:o.resolved,c:'var(--muted)'},
];
document.getElementById('kpis').innerHTML=kpis.map(k=>
`<div class="kpi glass"><div class="lbl">${k.l}</div><div class="val" style="color:${k.c}">${k.v}</div></div>`).join('');
// direction
const L=D.dir.LONG||0, S=D.dir.SHORT||0, T=L+S;
document.getElementById('dirbar').innerHTML=
`<div class="l" style="width:${100*L/T}%">🟢 ${L}</div><div class="s" style="width:${100*S/T}%">🔴 ${S}</div>`;
document.getElementById('dirCap').innerHTML=`LONG ${(100*L/T).toFixed(0)}% / SHORT ${(100*S/T).toFixed(0)}%. Перекос в LONG = рынок чаще показывал bid-давление в этом окне.`;
// confidence
document.querySelector('#conf tbody').innerHTML=D.conf.map(c=>
`<tr><td>${c.b}</td><td>${c.n}</td><td class="${sgn(c.mfe)}">${pct(c.mfe)}</td><td class="${sgn(c.mae)}">${pct(c.mae)}</td></tr>`).join('');
// hours
const maxH=Math.max(...D.hour.map(h=>h.n));
document.getElementById('spark').innerHTML=D.hour.map(h=>
`<div class="col"><div style="font-size:11px;color:var(--muted)">${h.n}</div><div class="b" style="height:${Math.max(8,70*h.n/maxH)}px"></div><div class="dt">${h.h.slice(11)}:00</div></div>`).join('');
// symbols
document.getElementById('sym').innerHTML=D.sym.map(s=>
`<span class="chip">${s.s.replace('USDT','')}<span class="n">${s.n} · conf ${s.conf}</span></span>`).join('');
// mfe/mae
document.querySelector('#mfe tbody').innerHTML=
`<tr><td>Ср. макс. ход В ПЛЮС (MFE)</td><td class="pos" style="font-weight:700">${pct(D.mfe.avg_mfe)}</td><td class="mut">в сторону сигнала</td></tr>`+
`<tr><td>Ср. макс. ход В МИНУС (MAE)</td><td class="neg" style="font-weight:700">${pct(D.mfe.avg_mae)}</td><td class="mut">против сигнала</td></tr>`;
document.getElementById('mfeCap').innerHTML=
`⚠️ Сейчас MAE (${pct(D.mfe.avg_mae)}) глубже MFE (${pct(D.mfe.avg_mfe)}) — но это <b>сырые открытые окна за <2ч</b>, а не результат сделок с TP/SL 1.5%/0.5%. С реальным стопом 0.5% большинство просадок обрезалось бы. Честная картина будет после резолва (часы-дни) и на бОльшей выборке.`;
document.getElementById('foot').textContent='Источник: signal_log (orderflow_imbalance) · live snapshot · Бендер';
</script>
</body></html>