| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Bybit OrderBook Data Fetcher</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <script> |
| tailwind.config = { |
| theme: { |
| extend: { |
| colors: { |
| primary: '#1e293b', |
| secondary: '#0f172a', |
| accent: '#3b82f6', |
| bid: '#10b981', |
| ask: '#ef4444' |
| } |
| } |
| } |
| } |
| </script> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
| |
| body { |
| font-family: 'Inter', sans-serif; |
| background-color: #0f172a; |
| color: #e2e8f0; |
| } |
| |
| .orderbook-container { |
| height: 600px; |
| overflow-y: auto; |
| } |
| |
| .orderbook-row { |
| transition: all 0.3s ease; |
| } |
| |
| .orderbook-row:hover { |
| background-color: rgba(59, 130, 246, 0.1); |
| } |
| |
| .depth-bar { |
| height: 100%; |
| position: absolute; |
| top: 0; |
| left: 0; |
| z-index: 0; |
| opacity: 0.2; |
| } |
| |
| .loading-bar { |
| height: 4px; |
| background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ec4899); |
| width: 0%; |
| transition: width 0.5s ease; |
| } |
| |
| .pulse { |
| animation: pulse 2s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { opacity: 0.5; } |
| 50% { opacity: 1; } |
| 100% { opacity: 0.5; } |
| } |
| </style> |
| </head> |
| <body class="min-h-screen"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <header class="mb-10 text-center"> |
| <h1 class="text-3xl md:text-4xl font-bold mb-2">Bybit OrderBook Data Fetcher</h1> |
| <p class="text-gray-400 mb-6">Real-time order book data with support for 1000 depth levels</p> |
| |
| <div class="bg-blue-900/30 border border-blue-700 rounded-lg p-4 max-w-3xl mx-auto"> |
| <div class="flex items-start"> |
| <i class="fas fa-info-circle text-blue-400 mt-1 mr-3"></i> |
| <div> |
| <h3 class="font-semibold text-blue-300 mb-1">API Update Information</h3> |
| <ul class="text-sm text-gray-300 space-y-1"> |
| <li><span class="text-yellow-400">Aug 21, 2025:</span> OrderBook REST API now supports 1,000 depth levels (up from 500 for futures and 200 for spot)</li> |
| <li><span class="text-red-400">Sep 11, 2025:</span> WebSocket Futures OrderBook (500 depth levels) will be offline</li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </header> |
| |
| |
| <div class="bg-primary rounded-xl p-6 mb-8 shadow-xl"> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> |
| <div> |
| <label class="block text-sm font-medium mb-2">Select Symbol</label> |
| <div class="relative"> |
| <select id="symbol-select" class="w-full bg-secondary border border-gray-700 rounded-lg py-3 px-4 appearance-none focus:outline-none focus:ring-2 focus:ring-accent"> |
| <option>BTCUSDT</option> |
| <option>ETHUSDT</option> |
| <option>BNBUSDT</option> |
| <option>XRPUSDT</option> |
| <option>ADAUSDT</option> |
| <option>DOGEUSDT</option> |
| <option>MATICUSDT</option> |
| <option>SOLUSDT</option> |
| </select> |
| <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-400"> |
| <i class="fas fa-chevron-down"></i> |
| </div> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium mb-2">Depth Levels</label> |
| <div class="relative"> |
| <select id="depth-select" class="w-full bg-secondary border border-gray-700 rounded-lg py-3 px-4 appearance-none focus:outline-none focus:ring-2 focus:ring-accent"> |
| <option value="10">10 Levels</option> |
| <option value="50">50 Levels</option> |
| <option value="100" selected>100 Levels</option> |
| <option value="500">500 Levels</option> |
| <option value="1000">1000 Levels (New)</option> |
| </select> |
| <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-400"> |
| <i class="fas fa-chevron-down"></i> |
| </div> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium mb-2">Fetch Type</label> |
| <div class="flex space-x-4"> |
| <button id="rest-btn" class="flex-1 bg-accent text-white py-3 px-4 rounded-lg font-medium hover:bg-blue-500 transition">REST API</button> |
| <button id="ws-btn" class="flex-1 bg-gray-700 text-gray-300 py-3 px-4 rounded-lg font-medium hover:bg-gray-600 transition">WebSocket</button> |
| </div> |
| </div> |
| </div> |
| |
| <div class="mt-6 flex justify-center"> |
| <button id="fetch-btn" class="bg-gradient-to-r from-blue-600 to-indigo-700 hover:from-blue-500 hover:to-indigo-600 text-white font-bold py-3 px-8 rounded-full shadow-lg transform hover:scale-105 transition-all duration-300"> |
| <i class="fas fa-sync-alt mr-2"></i> Fetch Order Book Data |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="loading-bar rounded-full mb-6" id="loading-bar"></div> |
| |
| |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> |
| |
| <div class="bg-primary rounded-xl p-6 shadow-xl"> |
| <div class="flex justify-between items-center mb-6"> |
| <h2 class="text-xl font-bold">Order Book <span id="symbol-display" class="text-accent">BTCUSDT</span></h2> |
| <div class="flex items-center space-x-2"> |
| <span class="px-3 py-1 bg-gray-800 rounded-full text-sm">Level <span id="depth-display">100</span></span> |
| <span id="connection-status" class="px-3 py-1 bg-green-900/30 text-green-400 rounded-full text-sm">Connected</span> |
| </div> |
| </div> |
| |
| <div class="orderbook-container rounded-lg overflow-hidden border border-gray-800"> |
| |
| <div class="bg-gradient-to-r from-red-900/20 to-transparent p-3 text-sm font-medium"> |
| <div class="grid grid-cols-3 gap-4"> |
| <div>Price (USDT)</div> |
| <div class="text-right">Amount (BTC)</div> |
| <div class="text-right">Total (USDT)</div> |
| </div> |
| </div> |
| |
| <div id="asks-container"> |
| |
| </div> |
| |
| |
| <div class="bg-gray-900 py-3 text-center border-y border-gray-800"> |
| <div class="text-2xl font-bold text-gray-200">$61,842.35</div> |
| <div class="text-sm text-gray-500">Market Price</div> |
| </div> |
| |
| |
| <div class="bg-gradient-to-r from-green-900/20 to-transparent p-3 text-sm font-medium"> |
| <div class="grid grid-cols-3 gap-4"> |
| <div>Price (USDT)</div> |
| <div class="text-right">Amount (BTC)</div> |
| <div class="text-right">Total (USDT)</div> |
| </div> |
| </div> |
| |
| <div id="bids-container"> |
| |
| </div> |
| </div> |
| |
| <div class="mt-4 flex justify-between text-sm text-gray-500"> |
| <div><i class="fas fa-circle text-green-500 mr-1"></i> Bids (Buy Orders)</div> |
| <div>Asks <i class="fas fa-circle text-red-500 ml-1"></i> (Sell Orders)</div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-primary rounded-xl p-6 shadow-xl"> |
| <div class="flex justify-between items-center mb-6"> |
| <h2 class="text-xl font-bold">API Response</h2> |
| <button id="copy-response" class="text-sm bg-gray-800 hover:bg-gray-700 py-1 px-3 rounded-lg flex items-center"> |
| <i class="far fa-copy mr-1"></i> Copy |
| </button> |
| </div> |
| |
| <div class="bg-secondary border border-gray-800 rounded-lg p-4 h-96 overflow-auto"> |
| <pre id="response-output" class="text-sm text-gray-300 whitespace-pre-wrap">{/* API response will appear here */}</pre> |
| </div> |
| |
| <div class="mt-4 bg-gray-900/50 rounded-lg p-4"> |
| <h3 class="font-bold mb-2">API Documentation</h3> |
| <ul class="text-sm space-y-1"> |
| <li class="flex items-start"> |
| <i class="fas fa-link text-accent mt-1 mr-2 text-xs"></i> |
| <a href="https://bybit-exchange.github.io/docs/v5/market/orderbook" target="_blank" class="text-blue-400 hover:underline">OrderBook REST API</a> |
| </li> |
| <li class="flex items-start"> |
| <i class="fas fa-link text-accent mt-1 mr-2 text-xs"></i> |
| <a href="https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook" target="_blank" class="text-blue-400 hover:underline">WebSocket OrderBook</a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| |
| |
| <footer class="mt-12 text-center text-gray-500 text-sm"> |
| <p>Data provided by Bybit API • As of August 2025, REST API supports 1000 depth levels • WebSocket will be upgraded</p> |
| <p class="mt-2">© 2025 OrderBook Data Fetcher | This is a demo application</p> |
| </footer> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const fetchBtn = document.getElementById('fetch-btn'); |
| const copyBtn = document.getElementById('copy-response'); |
| const restBtn = document.getElementById('rest-btn'); |
| const wsBtn = document.getElementById('ws-btn'); |
| const symbolSelect = document.getElementById('symbol-select'); |
| const depthSelect = document.getElementById('depth-select'); |
| const symbolDisplay = document.getElementById('symbol-display'); |
| const depthDisplay = document.getElementById('depth-display'); |
| const asksContainer = document.getElementById('asks-container'); |
| const bidsContainer = document.getElementById('bids-container'); |
| const responseOutput = document.getElementById('response-output'); |
| const loadingBar = document.getElementById('loading-bar'); |
| const connectionStatus = document.getElementById('connection-status'); |
| |
| |
| let currentFetchType = 'rest'; |
| let wsConnected = false; |
| let simulatedData = null; |
| |
| |
| updateFetchType('rest'); |
| symbolSelect.addEventListener('change', updateSymbolDisplay); |
| depthSelect.addEventListener('change', updateDepthDisplay); |
| restBtn.addEventListener('click', () => updateFetchType('rest')); |
| wsBtn.addEventListener('click', () => updateFetchType('websocket')); |
| fetchBtn.addEventListener('click', fetchOrderBookData); |
| copyBtn.addEventListener('click', copyResponse); |
| updateSymbolDisplay(); |
| updateDepthDisplay(); |
| |
| |
| async function fetchOrderBookData() { |
| const symbol = symbolSelect.value; |
| const depth = depthSelect.value; |
| symbolDisplay.textContent = symbol; |
| depthDisplay.textContent = depth; |
| |
| |
| loadingBar.style.width = '30%'; |
| loadingBar.classList.add('pulse'); |
| |
| try { |
| |
| await new Promise(resolve => setTimeout(resolve, 800)); |
| |
| if (currentFetchType === 'rest') { |
| |
| simulatedData = generateOrderBookData(symbol, depth); |
| displayOrderBook(simulatedData); |
| displayResponse(simulatedData); |
| loadingBar.style.width = '100%'; |
| connectionStatus.textContent = 'Connected (REST)'; |
| connectionStatus.className = 'px-3 py-1 bg-green-900/30 text-green-400 rounded-full text-sm'; |
| } else { |
| |
| if (!wsConnected) { |
| simulateWebSocketConnection(); |
| } else { |
| |
| simulatedData = generateOrderBookData(symbol, depth); |
| displayOrderBook(simulatedData); |
| displayResponse(simulatedData); |
| } |
| loadingBar.style.width = '100%'; |
| connectionStatus.textContent = 'Connected (WebSocket)'; |
| connectionStatus.className = 'px-3 py-1 bg-green-900/30 text-green-400 rounded-full text-sm'; |
| } |
| } catch (error) { |
| loadingBar.style.width = '0%'; |
| loadingBar.classList.remove('pulse'); |
| connectionStatus.textContent = 'Connection Error'; |
| connectionStatus.className = 'px-3 py-1 bg-red-900/30 text-red-400 rounded-full text-sm'; |
| alert('Error fetching data: ' + error.message); |
| } |
| |
| |
| setTimeout(() => { |
| loadingBar.classList.remove('pulse'); |
| }, 500); |
| } |
| |
| |
| function simulateWebSocketConnection() { |
| connectionStatus.textContent = 'Connecting...'; |
| connectionStatus.className = 'px-3 py-1 bg-yellow-900/30 text-yellow-400 rounded-full text-sm'; |
| |
| setTimeout(() => { |
| wsConnected = true; |
| simulatedData = generateOrderBookData(symbolSelect.value, depthSelect.value); |
| displayOrderBook(simulatedData); |
| displayResponse(simulatedData); |
| |
| |
| setInterval(() => { |
| if (wsConnected && currentFetchType === 'websocket') { |
| simulatedData = generateOrderBookData(symbolSelect.value, depthSelect.value); |
| displayOrderBook(simulatedData); |
| displayResponse(simulatedData); |
| } |
| }, 3000); |
| }, 1500); |
| } |
| |
| |
| function updateFetchType(type) { |
| currentFetchType = type; |
| if (type === 'rest') { |
| restBtn.classList.remove('bg-gray-700', 'text-gray-300'); |
| restBtn.classList.add('bg-accent', 'text-white'); |
| wsBtn.classList.remove('bg-accent', 'text-white'); |
| wsBtn.classList.add('bg-gray-700', 'text-gray-300'); |
| } else { |
| wsBtn.classList.remove('bg-gray-700', 'text-gray-300'); |
| wsBtn.classList.add('bg-accent', 'text-white'); |
| restBtn.classList.remove('bg-accent', 'text-white'); |
| restBtn.classList.add('bg-gray-700', 'text-gray-300'); |
| } |
| } |
| |
| |
| function updateSymbolDisplay() { |
| symbolDisplay.textContent = symbolSelect.value; |
| } |
| |
| |
| function updateDepthDisplay() { |
| depthDisplay.textContent = depthSelect.value; |
| } |
| |
| |
| function generateOrderBookData(symbol, depth) { |
| const data = { |
| symbol: symbol, |
| asks: [], |
| bids: [], |
| timestamp: new Date().toISOString(), |
| seq: Math.floor(Math.random() * 1000000), |
| u: Math.floor(Math.random() * 1000000) |
| }; |
| |
| const basePrice = 61842.35; |
| const priceStep = 0.5; |
| const amountMin = 0.1; |
| const amountMax = 5.0; |
| |
| |
| for (let i = 0; i < depth; i++) { |
| const price = basePrice + (i * priceStep); |
| const amount = (Math.random() * (amountMax - amountMin) + amountMin).toFixed(6); |
| const total = (price * amount).toFixed(2); |
| data.asks.push([price.toFixed(2), amount, total]); |
| } |
| |
| |
| for (let i = 0; i < depth; i++) { |
| const price = basePrice - (i * priceStep); |
| const amount = (Math.random() * (amountMax - amountMin) + amountMin).toFixed(6); |
| const total = (price * amount).toFixed(2); |
| data.bids.push([price.toFixed(2), amount, total]); |
| } |
| |
| return data; |
| } |
| |
| |
| function displayOrderBook(data) { |
| |
| asksContainer.innerHTML = ''; |
| bidsContainer.innerHTML = ''; |
| |
| |
| let maxTotal = 0; |
| [...data.asks, ...data.bids].forEach(order => { |
| const total = parseFloat(order[2]); |
| if (total > maxTotal) maxTotal = total; |
| }); |
| |
| |
| data.asks.slice().reverse().forEach(ask => { |
| const [price, amount, total] = ask; |
| const percentage = (total / maxTotal * 100).toFixed(2); |
| |
| const row = document.createElement('div'); |
| row.className = 'orderbook-row relative p-3 text-sm border-b border-gray-800 hover:bg-gray-800/50'; |
| row.innerHTML = ` |
| <div class="depth-bar bg-red-500" style="width: ${percentage}%"></div> |
| <div class="grid grid-cols-3 gap-4 relative z-10"> |
| <div class="text-red-400 font-medium">${price}</div> |
| <div class="text-right">${amount}</div> |
| <div class="text-right">${total}</div> |
| </div> |
| `; |
| asksContainer.appendChild(row); |
| }); |
| |
| |
| data.bids.forEach(bid => { |
| const [price, amount, total] = bid; |
| const percentage = (total / maxTotal * 100).toFixed(2); |
| |
| const row = document.createElement('div'); |
| row.className = 'orderbook-row relative p-3 text-sm border-b border-gray-800 hover:bg-gray-800/50'; |
| row.innerHTML = ` |
| <div class="depth-bar bg-green-500" style="width: ${percentage}%"></div> |
| <div class="grid grid-cols-3 gap-4 relative z-10"> |
| <div class="text-green-400 font-medium">${price}</div> |
| <div class="text-right">${amount}</div> |
| <div class="text-right">${total}</div> |
| </div> |
| `; |
| bidsContainer.appendChild(row); |
| }); |
| } |
| |
| |
| function displayResponse(data) { |
| responseOutput.textContent = JSON.stringify(data, null, 2); |
| } |
| |
| |
| function copyResponse() { |
| const text = responseOutput.textContent; |
| navigator.clipboard.writeText(text).then(() => { |
| const originalText = copyBtn.innerHTML; |
| copyBtn.innerHTML = '<i class="fas fa-check mr-1"></i> Copied!'; |
| setTimeout(() => { |
| copyBtn.innerHTML = originalText; |
| }, 2000); |
| }); |
| } |
| |
| |
| fetchOrderBookData(); |
| }); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=olywwe/https-huggingface-co-spaces-olywwe-bibytprivate" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |