fork download
  1.  
  2. <!DOCTYPE html>
  3. <html lang="es">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Dashboard de Monitoreo de Criptomonedas</title>
  8. <script src="https://c...content-available-to-author-only...e.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
  9. <style>
  10. body {
  11. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  12. margin: 0;
  13. padding: 0;
  14. background-color: #f5f7f9;
  15. color: #333;
  16. }
  17. .container {
  18. max-width: 1200px;
  19. margin: 0 auto;
  20. padding: 20px;
  21. }
  22. background-color: #1e293b;
  23. color: white;
  24. padding: 15px 20px;
  25. border-radius: 8px 8px 0 0;
  26. }
  27. .dashboard-title {
  28. margin: 0;
  29. font-size: 24px;
  30. display: flex;
  31. align-items: center;
  32. justify-content: space-between;
  33. }
  34. .dropdown-container {
  35. display: flex;
  36. align-items: center;
  37. }
  38. #pair-dropdown {
  39. margin-left: 10px;
  40. padding: 8px;
  41. border-radius: 4px;
  42. border: 1px solid #ccc;
  43. background: #fff;
  44. font-size: 14px;
  45. }
  46. .tabs {
  47. margin-top: 20px;
  48. display: flex;
  49. border-bottom: 1px solid #ddd;
  50. background-color: #fff;
  51. border-radius: 8px 8px 0 0;
  52. }
  53. .tab {
  54. padding: 12px 20px;
  55. cursor: pointer;
  56. background-color: #f5f7f9;
  57. border: none;
  58. outline: none;
  59. font-size: 16px;
  60. transition: background-color 0.3s;
  61. border-radius: 8px 8px 0 0;
  62. margin-right: 2px;
  63. }
  64. .tab:hover {
  65. background-color: #e9ecef;
  66. }
  67. .active-tab {
  68. background-color: #fff;
  69. border-bottom: 3px solid #3b82f6;
  70. font-weight: 600;
  71. }
  72. .tab-content {
  73. display: none;
  74. padding: 20px;
  75. background-color: #fff;
  76. border-radius: 0 0 8px 8px;
  77. box-shadow: 0 2px 4px rgba(0,0,0,0.05);
  78. }
  79. .active {
  80. display: block;
  81. }
  82. .section-title {
  83. font-size: 20px;
  84. margin-top: 0;
  85. margin-bottom: 20px;
  86. color: #1e293b;
  87. border-bottom: 1px solid #eee;
  88. padding-bottom: 10px;
  89. }
  90. .rates-grid, .prices-grid {
  91. display: grid;
  92. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  93. gap: 20px;
  94. margin-bottom: 30px;
  95. }
  96. .rate-card, .price-card {
  97. background-color: #fff;
  98. border-radius: 8px;
  99. box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  100. padding: 20px;
  101. transition: transform 0.2s;
  102. }
  103. .rate-card:hover, .price-card:hover {
  104. transform: translateY(-5px);
  105. }
  106. .card-title {
  107. font-size: 16px;
  108. margin-top: 0;
  109. color: #64748b;
  110. }
  111. .value {
  112. font-size: 24px;
  113. font-weight: 600;
  114. color: #0f172a;
  115. }
  116. .estado {
  117. display: inline-block;
  118. padding: 4px 8px;
  119. border-radius: 4px;
  120. font-size: 12px;
  121. font-weight: 600;
  122. margin-top: 10px;
  123. }
  124. .LONG {
  125. background-color: #dcfce7;
  126. color: #166534;
  127. }
  128. .SHORT {
  129. background-color: #fee2e2;
  130. color: #b91c1c;
  131. }
  132. .bid-ask {
  133. display: flex;
  134. justify-content: space-between;
  135. margin-top: 10px;
  136. }
  137. .bid, .ask {
  138. text-align: center;
  139. flex: 1;
  140. }
  141. .bid .label, .ask .label {
  142. font-size: 14px;
  143. color: #64748b;
  144. margin-bottom: 5px;
  145. }
  146. .bid .value {
  147. color: #16a34a;
  148. }
  149. .ask .value {
  150. color: #dc2626;
  151. }
  152. .log-section {
  153. margin-top: 30px;
  154. }
  155. .log-title {
  156. font-size: 18px;
  157. margin-bottom: 10px;
  158. color: #1e293b;
  159. }
  160. .event-log {
  161. background-color: #f8fafc;
  162. border: 1px solid #e2e8f0;
  163. border-radius: 8px;
  164. padding: 15px;
  165. max-height: 200px;
  166. overflow-y: auto;
  167. }
  168. .event-log ul {
  169. padding-left: 20px;
  170. margin: 0;
  171. }
  172. .event-log li {
  173. margin-bottom: 8px;
  174. color: #334155;
  175. font-size: 14px;
  176. }
  177. .charts-container {
  178. margin-top: 30px;
  179. }
  180. .chart-wrapper {
  181. background-color: #fff;
  182. border-radius: 8px;
  183. box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  184. padding: 20px;
  185. margin-bottom: 20px;
  186. }
  187. .chart-title {
  188. font-size: 18px;
  189. margin-top: 0;
  190. margin-bottom: 15px;
  191. color: #1e293b;
  192. }
  193. canvas {
  194. width: 100% !important;
  195. max-height: 300px;
  196. }
  197. @media (max-width: 768px) {
  198. .rates-grid, .prices-grid {
  199. grid-template-columns: 1fr;
  200. }
  201. .tabs {
  202. flex-direction: column;
  203. }
  204. .tab {
  205. border-radius: 0;
  206. margin-right: 0;
  207. margin-bottom: 2px;
  208. }
  209. }
  210. </style>
  211. </head>
  212. <body>
  213. <div class="container">
  214. <header>
  215. <div class="dashboard-title">
  216. <span>Dashboard de Criptomonedas</span>
  217. <div class="dropdown-container">
  218. <label for="pair-dropdown">Par:</label>
  219. <select id="pair-dropdown">
  220. <option value="BTC/USD">BTC/USD</option>
  221. <option value="ETH/USD">ETH/USD</option>
  222. <option value="SOL/USD">SOL/USD</option>
  223. <option value="XRP/USD">XRP/USD</option>
  224. </select>
  225. </div>
  226. </div>
  227. </header>
  228.  
  229. <div class="tabs">
  230. <button class="tab active-tab" data-tab="funding-tab">Tasas de Funding</button>
  231. <button class="tab" data-tab="prices-tab">Precios</button>
  232. <button class="tab" data-tab="charts-tab">Gráficos</button>
  233. </div>
  234.  
  235. <div id="funding-tab" class="tab-content active">
  236. <h2 class="section-title">Tasas de Funding: <span id="pair-title-funding">BTC/USD</span></h2>
  237.  
  238. <div class="rates-grid">
  239. <div class="rate-card">
  240. <h3 class="card-title">Exch(1) Funding Rate</h3>
  241. <div class="value" id="exch1-funding-rate">0.00%</div>
  242. <div class="estado LONG" id="exch1-funding-estado">LONG</div>
  243. </div>
  244.  
  245. <div class="rate-card">
  246. <h3 class="card-title">Exch(2) Funding Rate</h3>
  247. <div class="value" id="exch2-funding-rate">0.00%</div>
  248. <div class="estado LONG" id="exch2-funding-estado">LONG</div>
  249. </div>
  250.  
  251. <div class="rate-card">
  252. <h3 class="card-title">Delta Rate</h3>
  253. <div class="value" id="delta-rate">0.00%</div>
  254. </div>
  255. </div>
  256. </div>
  257.  
  258. <div id="prices-tab" class="tab-content">
  259. <h2 class="section-title">Precios: <span id="pair-title-prices">BTC/USD</span></h2>
  260.  
  261. <div class="prices-grid">
  262. <div class="price-card">
  263. <h3 class="card-title">Exch(1)</h3>
  264. <div class="bid-ask">
  265. <div class="bid">
  266. <div class="label">Bid (Compra)</div>
  267. <div class="value" id="exch1-bid">0.0000</div>
  268. </div>
  269. <div class="ask">
  270. <div class="label">Ask (Venta)</div>
  271. <div class="value" id="exch1-ask">0.0000</div>
  272. </div>
  273. </div>
  274. </div>
  275.  
  276. <div class="price-card">
  277. <h3 class="card-title">Exch(2)</h3>
  278. <div class="bid-ask">
  279. <div class="bid">
  280. <div class="label">Bid (Compra)</div>
  281. <div class="value" id="exch2-bid">0.0000</div>
  282. </div>
  283. <div class="ask">
  284. <div class="label">Ask (Venta)</div>
  285. <div class="value" id="exch2-ask">0.0000</div>
  286. </div>
  287. </div>
  288. </div>
  289. </div>
  290. </div>
  291.  
  292. <div id="charts-tab" class="tab-content">
  293. <h2 class="section-title">Gráficos: <span id="pair-title-charts">BTC/USD</span></h2>
  294.  
  295. <div class="charts-container">
  296. <div class="chart-wrapper">
  297. <h3 class="chart-title">Funding Rates por Intercambio</h3>
  298. <canvas id="funding-rates-chart"></canvas>
  299. </div>
  300.  
  301. <div class="chart-wrapper">
  302. <h3 class="chart-title">Delta Rate con Media Móvil</h3>
  303. <canvas id="delta-rate-chart"></canvas>
  304. </div>
  305. </div>
  306. </div>
  307.  
  308. <div class="log-section">
  309. <h3 class="log-title">Registro de Eventos</h3>
  310. <div class="event-log">
  311. <ul id="event-log-list">
  312. <!-- Los eventos se añadirán aquí dinámicamente -->
  313. </ul>
  314. </div>
  315. </div>
  316. </div>
  317.  
  318. <script>
  319. document.addEventListener('DOMContentLoaded', () => {
  320. const tabButtons = document.querySelectorAll('.tab');
  321. const tabContents = document.querySelectorAll('.tab-content');
  322. const pairDropdown = document.getElementById('pair-dropdown');
  323. const pairTitleFunding = document.getElementById('pair-title-funding');
  324. const pairTitlePrices = document.getElementById('pair-title-prices');
  325. const pairTitleCharts = document.getElementById('pair-title-charts');
  326.  
  327. const exch1FundingRateSpan = document.getElementById('exch1-funding-rate');
  328. const exch2FundingRateSpan = document.getElementById('exch2-funding-rate');
  329. const deltaRateSpan = document.getElementById('delta-rate');
  330. const exch1FundingEstadoSpan = document.getElementById('exch1-funding-estado');
  331. const exch2FundingEstadoSpan = document.getElementById('exch2-funding-estado');
  332.  
  333. const exch1BidSpan = document.getElementById('exch1-bid');
  334. const exch1AskSpan = document.getElementById('exch1-ask');
  335. const exch2BidSpan = document.getElementById('exch2-bid');
  336. const exch2AskSpan = document.getElementById('exch2-ask');
  337.  
  338. const eventLogList = document.getElementById('event-log-list');
  339.  
  340. // Datos para los gráficos
  341. const maxDataPoints = 20;
  342. const fundingRatesData = {
  343. labels: [],
  344. datasets: [
  345. {
  346. label: 'Exch(1)',
  347. data: [],
  348. borderColor: 'rgb(59, 130, 246)',
  349. backgroundColor: 'rgba(59, 130, 246, 0.1)',
  350. fill: false,
  351. tension: 0.4
  352. },
  353. {
  354. label: 'Exch(2)',
  355. data: [],
  356. borderColor: 'rgb(249, 115, 22)',
  357. backgroundColor: 'rgba(249, 115, 22, 0.1)',
  358. fill: false,
  359. tension: 0.4
  360. }
  361. ]
  362. };
  363.  
  364. const deltaRateData = {
  365. labels: [],
  366. datasets: [
  367. {
  368. label: 'Delta Rate',
  369. data: [],
  370. borderColor: 'rgb(16, 185, 129)',
  371. backgroundColor: 'rgba(16, 185, 129, 0.1)',
  372. fill: false,
  373. tension: 0.4
  374. },
  375. {
  376. label: 'Media Móvil (5 períodos)',
  377. data: [],
  378. borderColor: 'rgb(168, 85, 247)',
  379. backgroundColor: 'rgba(168, 85, 247, 0.1)',
  380. borderDash: [5, 5],
  381. fill: false,
  382. tension: 0.4
  383. }
  384. ]
  385. };
  386.  
  387. // Inicializar gráficos
  388. const fundingRatesCtx = document.getElementById('funding-rates-chart').getContext('2d');
  389. const fundingRatesChart = new Chart(fundingRatesCtx, {
  390. type: 'line',
  391. data: fundingRatesData,
  392. options: {
  393. responsive: true,
  394. maintainAspectRatio: false,
  395. interaction: {
  396. mode: 'index',
  397. intersect: false,
  398. },
  399. scales: {
  400. y: {
  401. title: {
  402. display: true,
  403. text: 'Funding Rate (%)'
  404. },
  405. ticks: {
  406. callback: function(value) {
  407. return value.toFixed(2) + '%';
  408. }
  409. }
  410. },
  411. x: {
  412. title: {
  413. display: true,
  414. text: 'Tiempo'
  415. }
  416. }
  417. },
  418. plugins: {
  419. tooltip: {
  420. callbacks: {
  421. label: function(context) {
  422. return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
  423. }
  424. }
  425. }
  426. }
  427. }
  428. });
  429.  
  430. const deltaRateCtx = document.getElementById('delta-rate-chart').getContext('2d');
  431. const deltaRateChart = new Chart(deltaRateCtx, {
  432. type: 'line',
  433. data: deltaRateData,
  434. options: {
  435. responsive: true,
  436. maintainAspectRatio: false,
  437. interaction: {
  438. mode: 'index',
  439. intersect: false,
  440. },
  441. scales: {
  442. y: {
  443. title: {
  444. display: true,
  445. text: 'Rate (%)'
  446. },
  447. ticks: {
  448. callback: function(value) {
  449. return value.toFixed(2) + '%';
  450. }
  451. }
  452. },
  453. x: {
  454. title: {
  455. display: true,
  456. text: 'Tiempo'
  457. }
  458. }
  459. },
  460. plugins: {
  461. tooltip: {
  462. callbacks: {
  463. label: function(context) {
  464. return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
  465. }
  466. }
  467. }
  468. }
  469. }
  470. });
  471.  
  472. // Funcionalidad de pestañas
  473. tabButtons.forEach(button => {
  474. button.addEventListener('click', () => {
  475. const tabId = button.dataset.tab;
  476.  
  477. tabButtons.forEach(btn => btn.classList.remove('active-tab'));
  478. tabContents.forEach(content => content.classList.remove('active'));
  479.  
  480. button.classList.add('active-tab');
  481. document.getElementById(tabId).classList.add('active');
  482. });
  483. });
  484.  
  485. // Funcionalidad del selector de pares
  486. pairDropdown.addEventListener('change', (event) => {
  487. const selectedPair = event.target.value;
  488. pairTitleFunding.textContent = selectedPair;
  489. pairTitlePrices.textContent = selectedPair;
  490. pairTitleCharts.textContent = selectedPair;
  491. // En un dashboard real, aquí se actualizarían todos los datos para el nuevo par
  492. });
  493.  
  494. // Función para calcular la media móvil
  495. function calculateMovingAverage(data, windowSize) {
  496. if (data.length < windowSize) {
  497. return Array(data.length).fill(null);
  498. }
  499.  
  500. const result = [];
  501. for (let i = 0; i < data.length; i++) {
  502. if (i < windowSize - 1) {
  503. result.push(null);
  504. } else {
  505. const windowSlice = data.slice(i - windowSize + 1, i + 1);
  506. const sum = windowSlice.reduce((acc, val) => acc + val, 0);
  507. result.push(sum / windowSize);
  508. }
  509. }
  510. return result;
  511. }
  512.  
  513. // Función para generar datos aleatorios simulados
  514. function generarDatoAleatorio() {
  515. const fundingRate = parseFloat(randomInRange(-0.005, 0.005).toFixed(4)); // Rango típico de funding rate
  516. const precioBase = 0.17; // Precio base arbitrario
  517. const spreadPorcentaje = randomInRange(0.001, 0.005); // Spread pequeño
  518. const ask = precioBase * (1 + spreadPorcentaje);
  519. const bid = precioBase * (1 - spreadPorcentaje);
  520. const deltaRate = parseFloat(randomInRange(0.03, 0.05).toFixed(2));
  521.  
  522. return {
  523. exch1_funding_rate: fundingRate * 100, // En porcentaje
  524. exch2_funding_rate: (fundingRate + randomInRange(-0.001, 0.001)) * 100, // Ligeramente diferente
  525. delta_rate: deltaRate,
  526. exch1_bid: bid.toFixed(4),
  527. exch1_ask: ask.toFixed(4),
  528. exch2_bid: (bid * (1 + randomInRange(-0.0005, 0.0005))).toFixed(4), // Ligeras diferencias
  529. exch2_ask: (ask * (1 + randomInRange(-0.0005, 0.0005))).toFixed(4),
  530. timestamp: Date.now()
  531. };
  532. }
  533.  
  534. function randomInRange(min, max) {
  535. return Math.random() * (max - min) + min;
  536. }
  537.  
  538. function actualizarDashboard() {
  539. const datos = generarDatoAleatorio();
  540.  
  541. exch1FundingRateSpan.textContent = datos.exch1_funding_rate.toFixed(2) + '%';
  542. exch2FundingRateSpan.textContent = datos.exch2_funding_rate.toFixed(2) + '%';
  543. deltaRateSpan.textContent = datos.delta_rate + '%';
  544.  
  545. exch1BidSpan.textContent = datos.exch1_bid;
  546.  
Success #stdin #stdout 0.02s 25660KB
stdin
Standard input is empty
stdout
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dashboard de Monitoreo de Criptomonedas</title>
    <script src="https://c...content-available-to-author-only...e.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f5f7f9;
            color: #333;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        header {
            background-color: #1e293b;
            color: white;
            padding: 15px 20px;
            border-radius: 8px 8px 0 0;
        }
        .dashboard-title {
            margin: 0;
            font-size: 24px;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .dropdown-container {
            display: flex;
            align-items: center;
        }
        #pair-dropdown {
            margin-left: 10px;
            padding: 8px;
            border-radius: 4px;
            border: 1px solid #ccc;
            background: #fff;
            font-size: 14px;
        }
        .tabs {
            margin-top: 20px;
            display: flex;
            border-bottom: 1px solid #ddd;
            background-color: #fff;
            border-radius: 8px 8px 0 0;
        }
        .tab {
            padding: 12px 20px;
            cursor: pointer;
            background-color: #f5f7f9;
            border: none;
            outline: none;
            font-size: 16px;
            transition: background-color 0.3s;
            border-radius: 8px 8px 0 0;
            margin-right: 2px;
        }
        .tab:hover {
            background-color: #e9ecef;
        }
        .active-tab {
            background-color: #fff;
            border-bottom: 3px solid #3b82f6;
            font-weight: 600;
        }
        .tab-content {
            display: none;
            padding: 20px;
            background-color: #fff;
            border-radius: 0 0 8px 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }
        .active {
            display: block;
        }
        .section-title {
            font-size: 20px;
            margin-top: 0;
            margin-bottom: 20px;
            color: #1e293b;
            border-bottom: 1px solid #eee;
            padding-bottom: 10px;
        }
        .rates-grid, .prices-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        .rate-card, .price-card {
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            padding: 20px;
            transition: transform 0.2s;
        }
        .rate-card:hover, .price-card:hover {
            transform: translateY(-5px);
        }
        .card-title {
            font-size: 16px;
            margin-top: 0;
            color: #64748b;
        }
        .value {
            font-size: 24px;
            font-weight: 600;
            color: #0f172a;
        }
        .estado {
            display: inline-block;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 12px;
            font-weight: 600;
            margin-top: 10px;
        }
        .LONG {
            background-color: #dcfce7;
            color: #166534;
        }
        .SHORT {
            background-color: #fee2e2;
            color: #b91c1c;
        }
        .bid-ask {
            display: flex;
            justify-content: space-between;
            margin-top: 10px;
        }
        .bid, .ask {
            text-align: center;
            flex: 1;
        }
        .bid .label, .ask .label {
            font-size: 14px;
            color: #64748b;
            margin-bottom: 5px;
        }
        .bid .value {
            color: #16a34a;
        }
        .ask .value {
            color: #dc2626;
        }
        .log-section {
            margin-top: 30px;
        }
        .log-title {
            font-size: 18px;
            margin-bottom: 10px;
            color: #1e293b;
        }
        .event-log {
            background-color: #f8fafc;
            border: 1px solid #e2e8f0;
            border-radius: 8px;
            padding: 15px;
            max-height: 200px;
            overflow-y: auto;
        }
        .event-log ul {
            padding-left: 20px;
            margin: 0;
        }
        .event-log li {
            margin-bottom: 8px;
            color: #334155;
            font-size: 14px;
        }
        .charts-container {
            margin-top: 30px;
        }
        .chart-wrapper {
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            padding: 20px;
            margin-bottom: 20px;
        }
        .chart-title {
            font-size: 18px;
            margin-top: 0;
            margin-bottom: 15px;
            color: #1e293b;
        }
        canvas {
            width: 100% !important;
            max-height: 300px;
        }
        @media (max-width: 768px) {
            .rates-grid, .prices-grid {
                grid-template-columns: 1fr;
            }
            .tabs {
                flex-direction: column;
            }
            .tab {
                border-radius: 0;
                margin-right: 0;
                margin-bottom: 2px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <div class="dashboard-title">
                <span>Dashboard de Criptomonedas</span>
                <div class="dropdown-container">
                    <label for="pair-dropdown">Par:</label>
                    <select id="pair-dropdown">
                        <option value="BTC/USD">BTC/USD</option>
                        <option value="ETH/USD">ETH/USD</option>
                        <option value="SOL/USD">SOL/USD</option>
                        <option value="XRP/USD">XRP/USD</option>
                    </select>
                </div>
            </div>
        </header>

        <div class="tabs">
            <button class="tab active-tab" data-tab="funding-tab">Tasas de Funding</button>
            <button class="tab" data-tab="prices-tab">Precios</button>
            <button class="tab" data-tab="charts-tab">Gráficos</button>
        </div>

        <div id="funding-tab" class="tab-content active">
            <h2 class="section-title">Tasas de Funding: <span id="pair-title-funding">BTC/USD</span></h2>
            
            <div class="rates-grid">
                <div class="rate-card">
                    <h3 class="card-title">Exch(1) Funding Rate</h3>
                    <div class="value" id="exch1-funding-rate">0.00%</div>
                    <div class="estado LONG" id="exch1-funding-estado">LONG</div>
                </div>
                
                <div class="rate-card">
                    <h3 class="card-title">Exch(2) Funding Rate</h3>
                    <div class="value" id="exch2-funding-rate">0.00%</div>
                    <div class="estado LONG" id="exch2-funding-estado">LONG</div>
                </div>
                
                <div class="rate-card">
                    <h3 class="card-title">Delta Rate</h3>
                    <div class="value" id="delta-rate">0.00%</div>
                </div>
            </div>
        </div>

        <div id="prices-tab" class="tab-content">
            <h2 class="section-title">Precios: <span id="pair-title-prices">BTC/USD</span></h2>
            
            <div class="prices-grid">
                <div class="price-card">
                    <h3 class="card-title">Exch(1)</h3>
                    <div class="bid-ask">
                        <div class="bid">
                            <div class="label">Bid (Compra)</div>
                            <div class="value" id="exch1-bid">0.0000</div>
                        </div>
                        <div class="ask">
                            <div class="label">Ask (Venta)</div>
                            <div class="value" id="exch1-ask">0.0000</div>
                        </div>
                    </div>
                </div>
                
                <div class="price-card">
                    <h3 class="card-title">Exch(2)</h3>
                    <div class="bid-ask">
                        <div class="bid">
                            <div class="label">Bid (Compra)</div>
                            <div class="value" id="exch2-bid">0.0000</div>
                        </div>
                        <div class="ask">
                            <div class="label">Ask (Venta)</div>
                            <div class="value" id="exch2-ask">0.0000</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div id="charts-tab" class="tab-content">
            <h2 class="section-title">Gráficos: <span id="pair-title-charts">BTC/USD</span></h2>
            
            <div class="charts-container">
                <div class="chart-wrapper">
                    <h3 class="chart-title">Funding Rates por Intercambio</h3>
                    <canvas id="funding-rates-chart"></canvas>
                </div>
                
                <div class="chart-wrapper">
                    <h3 class="chart-title">Delta Rate con Media Móvil</h3>
                    <canvas id="delta-rate-chart"></canvas>
                </div>
            </div>
        </div>

        <div class="log-section">
            <h3 class="log-title">Registro de Eventos</h3>
            <div class="event-log">
                <ul id="event-log-list">
                    <!-- Los eventos se añadirán aquí dinámicamente -->
                </ul>
            </div>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const tabButtons = document.querySelectorAll('.tab');
            const tabContents = document.querySelectorAll('.tab-content');
            const pairDropdown = document.getElementById('pair-dropdown');
            const pairTitleFunding = document.getElementById('pair-title-funding');
            const pairTitlePrices = document.getElementById('pair-title-prices');
            const pairTitleCharts = document.getElementById('pair-title-charts');

            const exch1FundingRateSpan = document.getElementById('exch1-funding-rate');
            const exch2FundingRateSpan = document.getElementById('exch2-funding-rate');
            const deltaRateSpan = document.getElementById('delta-rate');
            const exch1FundingEstadoSpan = document.getElementById('exch1-funding-estado');
            const exch2FundingEstadoSpan = document.getElementById('exch2-funding-estado');

            const exch1BidSpan = document.getElementById('exch1-bid');
            const exch1AskSpan = document.getElementById('exch1-ask');
            const exch2BidSpan = document.getElementById('exch2-bid');
            const exch2AskSpan = document.getElementById('exch2-ask');

            const eventLogList = document.getElementById('event-log-list');

            // Datos para los gráficos
            const maxDataPoints = 20;
            const fundingRatesData = {
                labels: [],
                datasets: [
                    {
                        label: 'Exch(1)',
                        data: [],
                        borderColor: 'rgb(59, 130, 246)',
                        backgroundColor: 'rgba(59, 130, 246, 0.1)',
                        fill: false,
                        tension: 0.4
                    },
                    {
                        label: 'Exch(2)',
                        data: [],
                        borderColor: 'rgb(249, 115, 22)',
                        backgroundColor: 'rgba(249, 115, 22, 0.1)',
                        fill: false,
                        tension: 0.4
                    }
                ]
            };

            const deltaRateData = {
                labels: [],
                datasets: [
                    {
                        label: 'Delta Rate',
                        data: [],
                        borderColor: 'rgb(16, 185, 129)',
                        backgroundColor: 'rgba(16, 185, 129, 0.1)',
                        fill: false,
                        tension: 0.4
                    },
                    {
                        label: 'Media Móvil (5 períodos)',
                        data: [],
                        borderColor: 'rgb(168, 85, 247)',
                        backgroundColor: 'rgba(168, 85, 247, 0.1)',
                        borderDash: [5, 5],
                        fill: false,
                        tension: 0.4
                    }
                ]
            };

            // Inicializar gráficos
            const fundingRatesCtx = document.getElementById('funding-rates-chart').getContext('2d');
            const fundingRatesChart = new Chart(fundingRatesCtx, {
                type: 'line',
                data: fundingRatesData,
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: {
                        mode: 'index',
                        intersect: false,
                    },
                    scales: {
                        y: {
                            title: {
                                display: true,
                                text: 'Funding Rate (%)'
                            },
                            ticks: {
                                callback: function(value) {
                                    return value.toFixed(2) + '%';
                                }
                            }
                        },
                        x: {
                            title: {
                                display: true,
                                text: 'Tiempo'
                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
                                }
                            }
                        }
                    }
                }
            });

            const deltaRateCtx = document.getElementById('delta-rate-chart').getContext('2d');
            const deltaRateChart = new Chart(deltaRateCtx, {
                type: 'line',
                data: deltaRateData,
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: {
                        mode: 'index',
                        intersect: false,
                    },
                    scales: {
                        y: {
                            title: {
                                display: true,
                                text: 'Rate (%)'
                            },
                            ticks: {
                                callback: function(value) {
                                    return value.toFixed(2) + '%';
                                }
                            }
                        },
                        x: {
                            title: {
                                display: true,
                                text: 'Tiempo'
                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
                                }
                            }
                        }
                    }
                }
            });

            // Funcionalidad de pestañas
            tabButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const tabId = button.dataset.tab;

                    tabButtons.forEach(btn => btn.classList.remove('active-tab'));
                    tabContents.forEach(content => content.classList.remove('active'));

                    button.classList.add('active-tab');
                    document.getElementById(tabId).classList.add('active');
                });
            });

            // Funcionalidad del selector de pares
            pairDropdown.addEventListener('change', (event) => {
                const selectedPair = event.target.value;
                pairTitleFunding.textContent = selectedPair;
                pairTitlePrices.textContent = selectedPair;
                pairTitleCharts.textContent = selectedPair;
                // En un dashboard real, aquí se actualizarían todos los datos para el nuevo par
            });

            // Función para calcular la media móvil
            function calculateMovingAverage(data, windowSize) {
                if (data.length < windowSize) {
                    return Array(data.length).fill(null);
                }
                
                const result = [];
                for (let i = 0; i < data.length; i++) {
                    if (i < windowSize - 1) {
                        result.push(null);
                    } else {
                        const windowSlice = data.slice(i - windowSize + 1, i + 1);
                        const sum = windowSlice.reduce((acc, val) => acc + val, 0);
                        result.push(sum / windowSize);
                    }
                }
                return result;
            }

            // Función para generar datos aleatorios simulados
            function generarDatoAleatorio() {
                const fundingRate = parseFloat(randomInRange(-0.005, 0.005).toFixed(4)); // Rango típico de funding rate
                const precioBase = 0.17; // Precio base arbitrario
                const spreadPorcentaje = randomInRange(0.001, 0.005); // Spread pequeño
                const ask = precioBase * (1 + spreadPorcentaje);
                const bid = precioBase * (1 - spreadPorcentaje);
                const deltaRate = parseFloat(randomInRange(0.03, 0.05).toFixed(2));

                return {
                    exch1_funding_rate: fundingRate * 100, // En porcentaje
                    exch2_funding_rate: (fundingRate + randomInRange(-0.001, 0.001)) * 100, // Ligeramente diferente
                    delta_rate: deltaRate,
                    exch1_bid: bid.toFixed(4),
                    exch1_ask: ask.toFixed(4),
                    exch2_bid: (bid * (1 + randomInRange(-0.0005, 0.0005))).toFixed(4), // Ligeras diferencias
                    exch2_ask: (ask * (1 + randomInRange(-0.0005, 0.0005))).toFixed(4),
                    timestamp: Date.now()
                };
            }

            function randomInRange(min, max) {
                return Math.random() * (max - min) + min;
            }

            function actualizarDashboard() {
                const datos = generarDatoAleatorio();

                exch1FundingRateSpan.textContent = datos.exch1_funding_rate.toFixed(2) + '%';
                exch2FundingRateSpan.textContent = datos.exch2_funding_rate.toFixed(2) + '%';
                deltaRateSpan.textContent = datos.delta_rate + '%';

                exch1BidSpan.textContent = datos.exch1_bid;