New paste Repaste Download
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CR1 WHALE TERMINAL PRO</title>
    
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg-main: #020204;
            --bg-card: rgba(10, 14, 26, 0.45);
            --bg-card-hover: rgba(14, 20, 38, 0.6);
            --neon-cyan: #06b6d4;
            --neon-purple: #a855f7;
            --neon-green: #10b981;
            --neon-red: #f43f5e;
            --neon-gold: #f59e0b;
            --text-main: #f3f4f6;
            --text-muted: #6b7280;
            --border-glow: rgba(168, 85, 247, 0.2);
        }
        *, *::before, *::after {
            box-sizing: border-box;
        }
        body {
            background-color: var(--bg-main);
            /* Мягкий виньетный градиент для фокуса по центру */
            background-image:
                radial-gradient(circle at center, rgba(2, 2, 4, 0.2) 0%, rgba(2, 2, 4, 0.8) 100%),
                url('space-bg.webp');
            background-size: cover;
            background-position: center center;
            background-attachment: fixed;
            background-repeat: no-repeat;
            
            color: var(--text-main);
            font-family: 'Inter', system-ui, sans-serif;
            margin: 0;
            padding: 25px;
            overflow-x: hidden;
            min-height: 100vh;
        }
        /* ТЕМАТИЧЕСКИЙ ЛОГОТИП И ШАПКА */
        header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 25px;
            background: var(--bg-card);
            padding: 15px 25px;
            border-radius: 16px;
            border: 1px solid rgba(255, 255, 255, 0.05);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255,255,255,0.05);
        }
        .brand-wrapper {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        /* Премиальный SVG Логотип (Плавник Кита + Радар) */
        .logo-svg {
            width: 32px;
            height: 32px;
            fill: none;
            stroke: url(#logoGradient);
            stroke-width: 2.5;
            filter: drop-shadow(0 0 8px rgba(6, 182, 212, 0.6));
        }
        h1 {
            margin: 0;
            font-size: 20px;
            font-weight: 800;
            letter-spacing: 0.07em;
            background: linear-gradient(135deg, #ffffff 30%, var(--neon-cyan) 70%, var(--neon-purple) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        /* ПУЛЬСИРУЮЩИЙ БАДЖ STATUS */
        .status-container {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        .status-badge {
            font-weight: 700;
            background: rgba(0, 0, 0, 0.5);
            border: 1px solid rgba(244, 63, 94, 0.2);
            padding: 8px 16px;
            border-radius: 8px;
            font-size: 11px;
            color: var(--neon-red);
            letter-spacing: 0.1em;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .status-dot {
            width: 6px;
            height: 6px;
            background-color: var(--neon-red);
            border-radius: 50%;
        }
        /* Когда статус ONLINE — включаем анимацию пульсации */
        .status-online {
            color: var(--neon-green) !important;
            border-color: rgba(16, 185, 129, 0.3) !important;
        }
        .status-online .status-dot {
            background-color: var(--neon-green);
            box-shadow: 0 0 10px var(--neon-green);
            animation: pulseGlow 2s infinite;
        }
        @keyframes pulseGlow {
            0% { transform: scale(1); opacity: 1; }
            50% { transform: scale(1.3); opacity: 0.5; box-shadow: 0 0 16px var(--neon-green); }
            100% { transform: scale(1); opacity: 1; }
        }
        .btn-test {
            background: rgba(168, 85, 247, 0.1);
            color: var(--neon-purple);
            border: 1px solid rgba(168, 85, 247, 0.4);
            padding: 8px 18px;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 700;
            font-size: 11px;
            letter-spacing: 0.05em;
            transition: all 0.3s ease;
        }
        .btn-test:hover {
            background: var(--neon-purple);
            color: #fff;
            box-shadow: 0 0 20px rgba(168, 85, 247, 0.5);
        }
        /* МОДУЛЬНЫЙ ТЕРМИНАЛЬНЫЙ ЛЕЙАУТ */
        .terminal-workspace {
            display: grid;
            grid-template-columns: 360px 1fr;
            gap: 25px;
            width: 100%;
        }
        .workspace-left {
            display: flex;
            flex-direction: column;
            gap: 25px;
        }
        .workspace-right {
            display: flex;
            flex-direction: column;
            gap: 25px;
        }
        .grid-tables {
            display: grid;
            grid-template-columns: 1fr 1fr 1fr;
            gap: 25px;
        }
        
        /* ПРЕМИАЛЬНАЯ СТЕКЛЯННАЯ КАРТОЧКА */
        .card {
            background: var(--bg-card);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            border-radius: 16px;
            border: 1px solid rgba(255, 255, 255, 0.04);
            padding: 20px;
            box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.02);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }
        .card:hover {
            border-color: rgba(255, 255, 255, 0.08);
            background: var(--bg-card-hover);
            box-shadow: 0 30px 60px rgba(0, 0, 0, 0.6);
        }
        .card h2 {
            margin-top: 0;
            font-size: 11px;
            text-transform: uppercase;
            color: #9ca3af;
            letter-spacing: 0.15em;
            font-weight: 800;
            margin-bottom: 20px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.06);
            padding-bottom: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        /* ТАБЛИЦЫ С МОНОШИРИННЫМИ ЦИФРАМИ */
        table { width: 100%; border-collapse: collapse; }
        th {
            color: var(--text-muted);
            padding: 10px 8px;
            text-align: left;
            font-size: 10px;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.08em;
        }
        td {
            padding: 12px 8px;
            font-size: 13px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.03);
            font-family: 'JetBrains Mono', monospace; /* Идеальные ровные колонки цифр */
        }
        
        .row-ice { color: var(--neon-green); font-weight: 700; background: rgba(16, 185, 129, 0.04); transition: all 0.5s ease; }
        
        .badge-round { background: rgba(0, 0, 0, 0.4); color: #e5e7eb; padding: 4px 8px; border-radius: 6px; font-weight: 700; border: 1px solid rgba(255,255,255,0.06); }
        .badge-status { background: rgba(6, 182, 212, 0.12); color: var(--neon-cyan); padding: 4px 8px; border-radius: 6px; font-size: 11px; font-weight: 700; border: 1px solid rgba(6,182,212,0.2); }
        .badge-super { background: rgba(244, 63, 94, 0.12); color: var(--neon-red); padding: 4px 8px; border-radius: 6px; font-size: 11px; font-weight: 800; border: 1px solid rgba(244,63,94,0.25); box-shadow: 0 0 15px rgba(244, 63, 94, 0.1); }
        /* ВВОД ДАННЫХ И СТАТИСТИКА КИТА */
        .input-box-custom { background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.04); border-radius: 12px; padding: 14px; margin-bottom: 15px; }
        label { display: block; font-size: 10px; color: var(--text-muted); margin-bottom: 8px; font-weight: 700; letter-spacing: 0.1em; }
        input { background: rgba(0, 0, 0, 0.6); border: 1px solid rgba(255, 255, 255, 0.08); color: #fff; padding: 12px; border-radius: 8px; width: 100%; font-size: 14px; font-family: 'JetBrains Mono', monospace; outline: none; transition: border-color 0.3s; }
        input:focus { border-color: var(--neon-purple); box-shadow: 0 0 15px rgba(168, 85, 247, 0.15); }
        
        .btn-action { background: linear-gradient(135deg, #a855f7 0%, #7e22ce 100%); color: #fff; border: none; padding: 14px; border-radius: 8px; cursor: pointer; font-weight: 700; width: 100%; letter-spacing: 0.05em; transition: transform 0.2s, box-shadow 0.2s; }
        .btn-action:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(168, 85, 247, 0.3); }
        .btn-clear { background: transparent; color: #4b5563; border: 1px solid rgba(255, 255, 255, 0.04); margin-top: 10px; font-size: 10px; padding: 8px; border-radius: 8px; cursor: pointer; width: 100%; text-transform: uppercase; letter-spacing: 0.05em; transition: all 0.2s; }
        .btn-clear:hover { color: var(--neon-red); border-color: rgba(244, 63, 94, 0.2); background: rgba(244, 63, 94, 0.02); }
        
        /* МИНИ-МЕТРИКИ КИТА */
        .pnl-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px; }
        .stat-box { background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.03); padding: 15px; border-radius: 12px; text-align: center; border-left: 3px solid #374151; }
        .stat-box.blue { border-left-color: var(--neon-cyan); }
        .stat-box.orange { border-left-color: var(--neon-gold); }
        .stat-val { font-size: 20px; font-weight: 700; margin-top: 6px; font-family: 'JetBrains Mono', monospace; }
        
        /* КОНТЕЙНЕР ДЛЯ ТРЕЙДИНГВЬЮ ГРАФИКА */
        #chartWrapper {
            width: 100%;
            height: 420px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 16px;
            border: 1px solid rgba(255, 255, 255, 0.04);
            position: relative;
            overflow: hidden;
            box-shadow: inset 0 0 30px rgba(0,0,0,0.6);
        }
    </style>
</head>
<body>
    <svg style="display: none;">
        <defs>
            <linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" stop-color="#06b6d4" />
                <stop offset="100%" stop-color="#a855f7" />
            </linearGradient>
        </defs>
    </svg>
    <header>
        <div class="brand-wrapper">
            <svg class="logo-svg" viewBox="0 0 24 24">
                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>
            </svg>
            <h1>CR1 ALGO-RADAR <span style="font-size: 11px; color: var(--text-muted); font-weight: 400; margin-left: 10px; letter-spacing: 0;">QUANTUM LAB</span></h1>
        </div>
        <div class="status-container">
            <button class="btn-test" onclick="simulateLiveFeed()">🧪 Имитировать Айсберг Юаня</button>
            <span class="status-badge" id="netStatus"><div class="status-dot"></div>DISCONNECTED</span>
        </div>
    </header>
    <div class="terminal-workspace">
        
        <div class="workspace-left">
            <div class="card" style="border: 1px solid var(--border-glow);">
                <h2>🐋 ТРЕКЕР КИТА (CR1 / Si)</h2>
                
                <div class="pnl-stats">
                    <div class="stat-box blue"><label>Объем сессии</label><div class="stat-val" id="totalVol" style="color: var(--neon-cyan);">0</div></div>
                    <div class="stat-box orange"><label>AVG Цена входа</label><div class="stat-val" id="avgPrice" style="color: var(--neon-gold);">-</div></div>
                </div>
                <div class="input-box-custom">
                    <label>ЦЕНА ОЧЕРЕДНОГО АЙСБЕРГА / СТУПЕНИ</label>
                    <input type="number" id="whalePrice" value="12.265" step="0.001">
                </div>
                
                <div class="input-box-custom">
                    <label>НАКОПЛЕННЫЙ ОБЪЕМ (ЛОТЫ)</label>
                    <input type="number" id="whaleVolume" value="85000">
                </div>
                <button class="btn-action" onclick="sendWhaleTrade()">Внести пачку в SQLite</button>
                <button class="btn-clear" onclick="clearWhalePosition()">Сбросить историю входов</button>
            </div>
            <div class="card">
                <h2>📊 РЕЗУЛЬТАТ СТРАТЕГИИ</h2>
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                    <span style="font-size: 12px; color: var(--text-muted);">Текущий фьючерс Cr:</span>
                    <span id="marketPrice" style="font-family: 'JetBrains Mono'; font-weight: 700;">12.315</span>
                </div>
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <span style="font-size: 12px; color: var(--text-muted);">Текущий PnL позиции:</span>
                    <span id="pnlStatus" style="font-family: 'JetBrains Mono'; font-weight: 800; font-size: 18px;">0 п.</span>
                </div>
            </div>
        </div>
        <div class="workspace-right">
            
            <div class="grid-tables">
                <div class="card">
                    <h2>🔥 HFT-ПОТОК РОБОТОВ <span style="color: var(--neon-cyan);">●</span></h2>
                    <table id="volumeTable">
                        <thead><tr><th>Время</th><th>Инструмент</th><th>Объем</th><th>Дельта ОИ</th></tr></thead>
                        <tbody>
                            <tr><td>13:40:12</td><td>CR-6.26</td><td style="color:var(--neon-cyan)">1 450</td><td>+210</td></tr>
                            <tr><td>13:40:15</td><td>CR-6.26</td><td style="color:var(--neon-cyan)">890</td><td>-40</td></tr>
                        </tbody>
                    </table>
                </div>
                <div class="card">
                    <h2>🧊 ЖУРНАЛ АЙСБЕРГОВ (Cr1) <span style="color: var(--neon-purple);">●</span></h2>
                    <table id="icebergTable">
                        <thead><tr><th>Время</th><th>Цена</th><th>Скрытый Объем</th><th>Статус ОИ</th></tr></thead>
                        <tbody></tbody>
                    </table>
                </div>
                <div class="card">
                    <h2>🎯 СТАКАН: КРУГЛЫЕ ПЛОТНОСТИ <span style="color: var(--neon-green);">●</span></h2>
                    <table id="roundTable">
                        <thead><tr><th>Уровень Cr1</th><th>Плотность</th><th>Ранг</th></tr></thead>
                        <tbody>
                            <tr><td><span class="badge-round">12.250</span></td><td style="color:var(--neon-green); font-weight:700;">4 250</td><td><span class="badge-status">Крупный</span></td></tr>
                            <tr><td><span class="badge-round">12.300</span></td><td style="color:var(--neon-red); font-weight:800;">14 800</td><td><span class="badge-super">КИТ В СТАКАНЕ</span></td></tr>
                            <tr><td><span class="badge-round">12.350</span></td><td style="color:var(--neon-green); font-weight:700;">3 110</td><td><span class="badge-status">Крупный</span></td></tr>
                        </tbody>
                    </table>
                </div>
            </div>
            <div id="chartWrapper">
                <div class="tradingview-widget-container" style="height:100%; width:100%;">
                    <div id="tradingview_chart" style="height:100%; width:100%;"></div>
                    <script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
                    <script type="text/javascript">
                    new TradingView.widget({
                        "autosize": true,
                        "symbol": "MOEX:CNYRUB",
                        "interval": "1",         
                        "timezone": "Exchange",
                        "theme": "dark",         
                        "style": "1",            
                        "locale": "ru",
                        "toolbar_bg": "#f1f3f6",
                        "enable_publishing": false,
                        "hide_side_toolbar": false,
                        "allow_symbol_change": true,
                        "container_id": "tradingview_chart"
                    });
                    </script>
                </div>
            </div>
        </div>
    </div>
    <script>
        const ws = new WebSocket("ws://127.0.0.1:8000/ws");
        
        let marketPrice = 12.315;
        let whaleAvgPrice = 0;
        let totalVolume = 0;
        ws.onopen = () => {
            const badge = document.getElementById("netStatus");
            badge.innerHTML = '<div class="status-dot"></div>ONLINE';
            badge.classList.add("status-online");
        };
        ws.onclose = () => {
            const badge = document.getElementById("netStatus");
            badge.innerHTML = '<div class="status-dot"></div>DISCONNECTED';
            badge.classList.remove("status-online");
        };
        ws.onmessage = (event) => {
            const msg = JSON.parse(event.data);
            if (msg.type === "whale_update") {
                totalVolume = msg.total || 0;
                whaleAvgPrice = msg.avg > 100 ? parseFloat(document.getElementById('whalePrice').value) : (msg.avg || 0);
                let currentMarket = msg.market > 100 ? marketPrice : msg.market;
                document.getElementById('totalVol').innerText = totalVolume.toLocaleString();
                document.getElementById('avgPrice').innerText = whaleAvgPrice > 0 ? whaleAvgPrice.toFixed(3) : '-';
                document.getElementById('marketPrice').innerText = currentMarket.toFixed(3);
                
                let pnlBox = document.getElementById('pnlStatus');
                if (totalVolume === 0) {
                    pnlBox.innerText = "0 п."; pnlBox.style.color = "var(--text-main)";
                    return;
                }
                let diffPoints = Math.round((currentMarket - whaleAvgPrice) * 1000);
                if (diffPoints >= 0) {
                    pnlBox.innerText = "+" + diffPoints + " п."; pnlBox.style.color = "var(--neon-green)";
                } else {
                    pnlBox.innerText = diffPoints + " п."; pnlBox.style.color = "var(--neon-red)";
                }
            }
        };
        function sendWhaleTrade() {
            const p = document.getElementById('whalePrice').value;
            const v = document.getElementById('whaleVolume').value;
            if (p && v && ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify({ "type": "add_whale", "price": parseFloat(p), "vol": parseInt(v) }));
            } else if (ws.readyState !== WebSocket.OPEN) { alert("Нет подключения к Python-серверу!"); }
        }
        function clearWhalePosition() {
            if (ws.readyState === WebSocket.OPEN && confirm("Очистить базу данных SQLite?")) {
                ws.send(JSON.stringify({ "type": "clear_whale" }));
            }
        }
        function simulateLiveFeed() {
            const prices = ["12.260", "12.285", "12.310"];
            const vols = ["15,400 🧊", "22,000 🧊", "9,800 лотов"];
            const oiData = ["🟢 +1,250", "🟢 +3,400", "🔴 -850"];
            const rIdx = Math.floor(Math.random() * 3);
            const tbody = document.getElementById("icebergTable").getElementsByTagName('tbody')[0];
            const row = tbody.insertRow(0);
            row.className = "row-ice";
            row.innerHTML = `<td>${new Date().toLocaleTimeString()}</td><td><b style="color:var(--neon-purple)">${prices[rIdx]}</b></td><td>${vols[rIdx]}</td><td style="font-size:11px;">${oiData[rIdx]}</td>`;
            
            row.style.opacity = "0";
            setTimeout(() => { row.style.opacity = "1"; }, 50);
            if (tbody.rows.length > 5) tbody.deleteRow(5);
        }
    </script>
</body>
</html>
Filename: None. Size: 21kb. View raw, , hex, or download this file.

This paste expires on 2026-05-31 20:07:38.486038+00:00. Pasted through web.