{"id":5196,"date":"2026-02-12T06:56:23","date_gmt":"2026-02-12T06:56:23","guid":{"rendered":"https:\/\/bulltradebot.com\/?page_id=5196"},"modified":"2026-02-12T06:57:09","modified_gmt":"2026-02-12T06:57:09","slug":"sound","status":"publish","type":"page","link":"https:\/\/bulltradebot.com\/en\/sound\/","title":{"rendered":"sound"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"5196\" class=\"elementor elementor-5196\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-d2a8a22 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no\" data-id=\"d2a8a22\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0983d3d\" data-id=\"0983d3d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-8e6b17f elementor-widget elementor-widget-html\" data-id=\"8e6b17f\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- ======================================================= -->\n<!-- BULL TRADING BOT + ROCKET GAME (VERSION FINAL WP)       -->\n<!-- ======================================================= -->\n\n<!-- Cargar Chart.js (Necesario para las gr\u00e1ficas) -->\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"><\/script>\n\n<!-- Contenedor Principal para aislar estilos de WordPress (Scoped) -->\n<div id=\"bullbot-rocket-wrapper\">\n\n    <!-- ======================================================= -->\n    <!-- ESTILOS CSS (SCOPED)                                -->\n    <!-- ======================================================= -->\n    <style>\n        \/* Importar fuentes para el juego *\/\n        @import url('https:\/\/fonts.googleapis.com\/css2?family=Orbitron:wght@400;900&family=Share+Tech+Mono&display=swap');\n\n        \/* Aislamiento del contenedor principal para evitar conflictos con WP *\/\n        #bullbot-rocket-wrapper {\n            background-color: #121212;\n            color: white;\n            padding: 15px;\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            width: 100%;\n            max-width: 100%;\n            overflow-x: hidden;\n            box-sizing: border-box;\n        }\n\n        \/* Reset de box-sizing SOLO dentro del wrapper *\/\n        #bullbot-rocket-wrapper * {\n            box-sizing: border-box;\n        }\n\n        \/* --- ESTILOS GENERALES DEL BOT --- *\/\n        #bullbot-rocket-wrapper #crypto-widget-container {\n            background-color: #1e1e2d;\n            color: #ffffff;\n            padding: 25px;\n            border-radius: 12px;\n            max-width: 1200px; \/* Ancho m\u00e1ximo para PC *\/\n            margin: 0 auto;\n            box-shadow: 0 4px 15px rgba(0,0,0,0.3);\n            position: relative;\n            min-height: auto;\n        }\n\n        \/* --- LOADER --- *\/\n        #bullbot-rocket-wrapper #orbidex-loader {\n            position: absolute; top: 0; left: 0; width: 100%; height: 100%;\n            background-color: #1e1e2d; z-index: 9999;\n            display: flex; flex-direction: column; justify-content: flex-start; align-items: center;\n            padding-top: 100px; border-radius: 12px; transition: opacity 0.5s ease;\n        }\n        .ai-spinner { width: 60px; height: 60px; border: 4px solid rgba(108, 92, 231, 0.2); border-radius: 50%; border-top-color: #6c5ce7; animation: spin 1s ease-in-out infinite; margin-bottom: 20px; }\n        .ai-text { font-family: monospace; font-size: 1.4rem; font-weight: bold; color: #6c5ce7; text-transform: uppercase; animation: pulse 1.5s infinite; text-align: center; }\n        .ai-subtext { font-family: monospace; font-size: 0.9rem; color: #888; margin-top: 8px; text-align: center; }\n        @keyframes spin { to { transform: rotate(360deg); } }\n        @keyframes pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } }\n\n        \/* --- HEADER --- *\/\n        .cw-app-header { text-align: center; margin-bottom: 20px; border-bottom: 1px solid #333; padding-bottom: 15px; }\n        .cw-app-title { margin: 0; font-size: 1.8rem; font-weight: 800; color: #fff; text-transform: uppercase; letter-spacing: 1px; }\n        .cw-pro-badge { color: #6c5ce7; background: rgba(108, 92, 231, 0.1); padding: 2px 8px; border-radius: 4px; font-size: 0.6em; border: 1px solid #6c5ce7; vertical-align: middle; }\n\n        \/* --- INPUTS --- *\/\n        #bullbot-rocket-wrapper select, \n        #bullbot-rocket-wrapper input:not([type=\"radio\"]):not([type=\"checkbox\"]) {\n            background-color: #2b2b40 !important; color: #fff !important; border: 1px solid #555 !important;\n            padding: 0 10px !important; border-radius: 6px !important; height: 38px !important; width: 100% !important;\n            font-size: 13px !important; outline: none !important; display: block !important;\n            margin: 0 0 5px 0 !important;\n            max-width: 100%;\n        }\n        .tp-input-mini, #tp-single-val { color: #aaa !important; font-weight: bold; }\n\n        .cw-btn { background: #444; color: white; border: 1px solid #555; padding: 0 12px; border-radius: 6px; height: 42px; width: 100%; font-weight: bold; cursor: pointer; transition: 0.3s; }\n        .cw-btn:hover { background: #555; }\n\n        \/* --- LAYOUT GRID --- *\/\n        .cw-grid { display: grid; grid-template-columns: 1fr; gap: 20px; }\n        @media(min-width: 1024px) { .cw-grid { grid-template-columns: 1.8fr 1.2fr; } }\n        \n        .cw-controls-wrapper { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; align-items: flex-end; }\n        .cw-control-group { display: flex; flex-direction: column; flex: 1; min-width: 120px; }\n        .cw-label-top { font-size: 0.75rem; color: #bbb; margin-bottom: 4px; font-weight: 600; text-transform: uppercase; display: block; }\n\n        \/* --- INFO CARD & INDICATORS --- *\/\n        .cw-info-card { background: #2b2b40; padding: 15px; border-radius: 8px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; border: 1px solid #3d3d5c; }\n        .cw-price { font-size: 1.5rem; font-weight: bold; color: #fff; }\n        .cw-trend { font-weight: bold; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; }\n        \n        .cw-indicators { \n            font-size: 0.8rem; color: #aaa; margin-bottom: 10px; background: #161621; padding: 10px; \n            border-radius: 4px; display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); gap: 8px; \n        }\n        .cw-ind-item { display: flex; flex-direction: column; border-right: 1px solid #333; padding-right: 5px; }\n        .cw-ind-item:last-child { border-right: none; }\n        .cw-ind-val-display { font-size: 0.85rem; color: #fff; font-weight: bold; font-family: monospace; }\n        .cw-ind-sub { font-size: 0.65em; color: #888; margin-top: 2px; text-transform: uppercase; }\n\n        .chart-box { background: #262636; padding: 10px; border-radius: 8px; height: 380px; position: relative; }\n\n        \/* --- BOT PANEL --- *\/\n        .bot-panel { background: #262636; padding: 15px; border-radius: 8px; border: 1px solid #6c5ce7; box-shadow: 0 0 10px rgba(108, 92, 231, 0.1); }\n        .bot-title { margin: 0 0 15px 0; font-size: 1rem; border-bottom: 1px solid #444; padding-bottom: 8px; color: white; font-weight:bold; }\n        .bot-subtitle { font-size: 0.75rem; color: #6c5ce7; font-weight: bold; text-transform: uppercase; margin: 12px 0 6px 0; letter-spacing: 1px; }\n        \n        .bot-row { display: flex; gap: 8px; margin-bottom: 8px; }\n        .bot-col { flex: 1; }\n\n        .tp-mode-selector { display: flex; gap: 15px; margin-bottom: 10px; font-size: 0.8rem; color: #ccc; }\n        .tp-mode-selector label { cursor: pointer; display: flex; align-items: center; gap: 5px; }\n        .tp-single-box { display: none; } \n        .tp-ladder-box { display: block; background: rgba(0,0,0,0.2); padding: 8px; border-radius: 6px; }\n        .tp-row-small { display: flex; gap: 5px; align-items: center; margin-bottom: 4px; font-size: 0.75rem; color: #aaa; }\n        .tp-input-mini { width: 60px !important; text-align: center; height: 30px !important; color: #aaa !important; font-weight: bold; }\n\n        .trade-direction-box { display: flex; gap: 10px; margin-bottom: 10px; }\n        .btn-direction { flex: 1; padding: 8px; border: 1px solid #444; background: #1e1e2d; color: #888; border-radius: 6px; cursor: pointer; font-weight: bold; opacity: 0.5; }\n        .btn-direction.active-long { background: #1b5e20; color: white; opacity: 1; border-color: #2e7d32; box-shadow: 0 0 8px rgba(46,125,50,0.4); }\n        .btn-direction.active-short { background: #b71c1c; color: white; opacity: 1; border-color: #c62828; box-shadow: 0 0 8px rgba(198,40,40,0.4); }\n        .btn-direction.active-auto { background: #ff9800; color: white; opacity: 1; border-color: #f57c00; box-shadow: 0 0 8px rgba(255, 152, 0, 0.4); }\n\n        .slider-container { display: flex; align-items: center; gap: 10px; background: #2b2b40; padding: 15px 10px; border-radius: 6px; border: 1px solid #555; }\n        .cw-range { -webkit-appearance: none; width: 100%; height: 8px; background: #444; border-radius: 4px; outline: none; margin: 0; cursor:pointer;}\n        .cw-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; background: #6c5ce7; border-radius: 50%; cursor: pointer; border: 2px solid #fff; box-shadow: 0 0 5px rgba(0,0,0,0.5); transition: transform 0.1s; }\n        .cw-range::-webkit-slider-thumb:hover { transform: scale(1.1); }\n        .val-display { font-family: monospace; font-size: 1.1rem; font-weight: bold; color: #6c5ce7; min-width: 50px; text-align: right; }\n\n        .cw-results { margin-top: 15px; padding: 10px; background: rgba(255,255,255,0.05); border-radius: 6px; font-size: 0.9rem; }\n        .cw-res-row { display: flex; justify-content: space-between; margin-bottom: 5px; }\n        .cw-res-val { color: #4caf50; font-weight: bold; font-size: 1.1em; }\n        .cw-res-loss { color: #ff5252; font-weight: bold; font-size: 1.1em; }\n\n        .btn-launch-bot { \n            background: linear-gradient(45deg, #6c5ce7, #a29bfe); color: #fff; border: none; font-weight: bold; margin-top: 15px; \n            box-shadow: 0 4px 10px rgba(108, 92, 231, 0.3); width: 100%; height: 45px; cursor: pointer; border-radius: 6px; transition: 0.2s; \n        }\n        .btn-launch-bot.scanning { background: linear-gradient(45deg, #1b5e20, #66bb6a); animation: pulseBtn 2s infinite; }\n        @keyframes pulseBtn { 0%{box-shadow: 0 0 0 0 rgba(102, 187, 106, 0.7);} 70%{box-shadow: 0 0 0 10px rgba(102, 187, 106, 0);} 100%{box-shadow: 0 0 0 0 rgba(102, 187, 106, 0);} }\n\n        \/* --- ORDERS TABLE --- *\/\n        .cw-orders-module { margin-top: 25px; background: #262636; padding: 15px; border-radius: 8px; border: 1px solid #3d3d5c; overflow-x: auto; }\n        .cw-orders-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }\n        .live-indicator { background: rgba(0, 188, 212, 0.15); color: #00bcd4; border: 1px solid #00bcd4; padding: 4px 10px; border-radius: 20px; font-size: 0.7rem; font-weight: bold; display: flex; align-items: center; gap: 6px; }\n        .live-dot { width: 6px; height: 6px; background: #00bcd4; border-radius: 50%; animation: blink 1.5s infinite; }\n        @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } }\n\n        \/* NUEVO ESTILO: BOTON VER GRAFICO *\/\n        .btn-view-chart {\n            background: #6c5ce7;\n            color: #fff;\n            border: none;\n            padding: 2px 6px;\n            font-size: 0.65em;\n            border-radius: 3px;\n            margin-top: 3px;\n            cursor: pointer;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n            transition: background 0.2s;\n        }\n        .btn-view-chart:hover { background: #5649c0; }\n\n        \/* STATS BAR (ACTUALIZADO A 5 Columnas) *\/\n        .cw-stats-bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 15px; background: #1e1e2d; padding: 10px; border-radius: 6px; border: 1px solid #333; }\n        .cw-stat-box { text-align: center; } \n        .cw-stat-label { font-size: 0.7rem; color: #aaa; text-transform: uppercase; margin-bottom: 4px; }\n        .cw-stat-val { font-size: 1.1rem; font-weight: bold; }\n        @media(max-width: 600px) { .cw-stats-bar { grid-template-columns: 1fr 1fr; } }\n\n        .cw-orders-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; min-width: 900px; }\n        .cw-orders-table th { text-align: left; padding: 8px; background: #1e1e2d; color: #aaa; border-bottom: 2px solid #444; }\n        .cw-orders-table td { padding: 8px; border-bottom: 1px solid #333; color: #eee; vertical-align: middle; }\n        .cw-orders-table-wrap { overflow-x: auto; }\n\n        \/* BARRA DE PROGRESO VISUAL (TABLA) *\/\n        .tracker-wrapper { position: relative; width: 100%; height: 35px; display: flex; align-items: flex-end; margin-top: 5px; }\n        .trade-tracker-container { width: 100%; height: 12px; background: #111; border-radius: 6px; position: relative; overflow: hidden; border: 1px solid #444; }\n        .tracker-center-line { position: absolute; left: 50%; height: 100%; width: 1px; background: #666; top: 0; z-index: 1; }\n        .tracker-bar { height: 100%; position: absolute; top: 0; transition: width 0.5s ease; opacity: 0.9; }\n        .tracker-bar.profit { left: 50%; background: #4caf50; } \n        .tracker-bar.loss { right: 50%; background: #ff5252; } \n        \n        .tracker-floating-price {\n            position: absolute; top: 0; font-size: 0.65em; font-weight: bold; color: #fff; background: #222;\n            padding: 1px 5px; border-radius: 3px; border: 1px solid #666;\n            transform: translateX(-50%); white-space: nowrap; z-index: 10; transition: left 0.5s ease;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.5);\n        }\n        .tracker-floating-price::after {\n            content: ''; position: absolute; bottom: -4px; left: 50%; margin-left: -4px;\n            border-width: 4px; border-style: solid; border-color: #666 transparent transparent transparent;\n        }\n        .tracker-labels { display: flex; justify-content: space-between; font-size: 0.65em; color: #888; margin-top: 2px; font-family: monospace; }\n        .tracker-labels span { flex: 1; text-align: center; }\n        .tracker-labels span:first-child { text-align: left; color: #ff5252; }\n        .tracker-labels span:last-child { text-align: right; color: #4caf50; }\n\n        .status-active { color: #4caf50; font-weight: bold; }\n        .btn-market-close { background: #f44336; color: white; border: none; padding: 4px 8px; border-radius: 3px; font-size: 0.7em; cursor: pointer; }\n        .trend-bull { color: #66bb6a; } .trend-bear { color: #ff5252; } .trend-neutral { color: #aaa; }\n        .pnl-pos { color: #4caf50 !important; } .pnl-neg { color: #ff5252 !important; }\n        .sl-secured { color: #2196f3; font-weight: bold; animation: pulseBlue 2s infinite; }\n        @keyframes pulseBlue { 0%{opacity:0.7;} 50%{opacity:1;} 100%{opacity:0.7;} }\n        \n        .cw-charts-grid { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 20px; }\n        @media(min-width: 768px) { .cw-charts-grid { grid-template-columns: 1fr 1fr; } }\n        .pnl-chart-container { height: 220px; width: 100%; background: #1e1e2d; border-radius: 6px; padding: 10px; border: 1px solid #333; }\n        .chart-title { font-size: 0.85rem; color: #aaa; margin-bottom: 10px; text-align: center; }\n\n        \/* --- ESTILOS DEL ROCKET GAME (MEJORADOS) --- *\/\n        #moon-app {\n            --bg: #0b0c10;\n            --primary: #00ff41; \n            --danger: #ff0055;\n            --gold: #ffd700;\n            --font-head: 'Orbitron', sans-serif;\n            --font-mono: 'Share Tech Mono', monospace;\n\n            position: relative;\n            width: 100%;\n            height: 500px; \n            background-color: var(--bg);\n            margin-top: 20px;\n            border: 2px solid #333;\n            box-shadow: 0 0 20px rgba(0,0,0,0.5);\n            font-family: var(--font-mono);\n            color: white;\n            overflow: hidden;\n            user-select: none;\n            -webkit-tap-highlight-color: transparent;\n            border-radius: 8px;\n        }\n        #moon-app.mode-short { --primary: #ff0055; }\n        #moon-app canvas { display: block; width: 100%; height: 100%; }\n\n        .ui-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; display: flex; flex-direction: column; justify-content: space-between; z-index: 10; }\n        \n        \/* Watermark abajo *\/\n        .watermark { position: absolute; bottom: 20px; width: 100%; text-align: center; opacity: 0.15; pointer-events: none; z-index: 0; }\n        .wm-main { font-family: var(--font-head); font-size: 2rem; font-weight: 900; }\n        .wm-sub { font-size: 0.8rem; letter-spacing: 4px; color: var(--gold); margin-top: 5px; }\n\n        .hud { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; padding: 10px; background: linear-gradient(to bottom, rgba(0,0,0,0.95), transparent); pointer-events: auto; align-items: center; }\n        .stat { background: rgba(0,0,0,0.6); padding: 5px; border-radius: 4px; border: 1px solid #333; text-align: center; display: flex; flex-direction: column; justify-content: center; }\n        .stat label { font-size: 0.5rem; color: #aaa; margin-bottom: 2px; }\n        .stat span { font-size: 0.8rem; color: white; font-weight: bold; }\n        .entry-val { color: var(--gold) !important; }\n\n        .thermo-container { position: absolute; right: 10px; top: 15%; bottom: 10%; width: 160px; pointer-events: none; display: flex; flex-direction: column; justify-content: center; }\n        .thermo-bar { position: absolute; right: 0; top: 0; bottom: 0; width: 6px; background: #222; border-radius: 3px; overflow: visible; }\n        .thermo-zero { position: absolute; top: 50%; right: -5px; width: 20px; height: 2px; background: #fff; z-index: 2; }\n        .fill-up { position: absolute; bottom: 50%; left: 0; width: 100%; height: 0%; background: var(--primary); transition: height 0.2s; box-shadow: 0 0 10px var(--primary); }\n        .fill-down { position: absolute; top: 50%; left: 0; width: 100%; height: 0%; background: var(--danger); transition: height 0.2s; box-shadow: 0 0 10px var(--danger); }\n        \n        .level-marker { position: absolute; right: 15px; font-size: 0.85rem; color: white; font-weight: bold; opacity: 0.8; transition: 0.3s; text-align: right; white-space: nowrap; text-shadow: 1px 1px 2px rgba(0,0,0,0.8); }\n        .level-marker span { display: block; font-size: 0.75rem; font-weight: normal; color: #ccc; }\n        .level-marker::after { content: ''; position: absolute; top: 50%; right: -15px; width: 10px; height: 1px; background: #fff; }\n        .level-marker.hit { opacity: 1; color: var(--gold); font-size: 1rem; text-shadow: 0 0 5px var(--gold); transform: scale(1.1); }\n        .level-marker.hit span { color: #fff; }\n\n        .center-display { flex-grow: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 5; margin-bottom: 20px; }\n        .big-mult { font-family: var(--font-head); font-size: 3rem; font-weight: 900; text-shadow: 4px 4px 0 #000; transition: color 0.1s; }\n        .status-badge { background: rgba(0,0,0,0.8); border: 1px solid #fff; padding: 5px 15px; color: #fff; letter-spacing: 2px; margin-top: 5px; font-size: 0.9rem; }\n        .realized-pnl { color: var(--gold); font-size: 0.8rem; margin-top: 5px; opacity: 0; }\n\n        \/* AJUSTES RESPONSIVE M\u00d3VIL (Optimizaci\u00f3n de encuadre) *\/\n        @media screen and (max-width: 768px) {\n            #bullbot-rocket-wrapper { padding: 5px; }\n            #bullbot-rocket-wrapper #crypto-widget-container { padding: 12px; }\n            \n            \/* Ajuste de controles para que no se salgan *\/\n            .cw-controls-wrapper { gap: 8px; }\n            .cw-control-group { flex: 1 1 45%; min-width: unset; } \/* 2 columnas en movil *\/\n            .cw-label-top { font-size: 0.7rem; }\n            \n            \/* Ajuste del juego y gr\u00e1ficas para que no sean tan altos *\/\n            #moon-app { height: 350px; margin-top: 15px; }\n            .chart-box { height: 300px; }\n            \n            \/* Ajuste de la tabla para scroll horizontal suave *\/\n            .cw-orders-module { padding: 10px; }\n            .cw-orders-table-wrap { width: 100%; overflow-x: auto; display: block; -webkit-overflow-scrolling: touch; }\n            .cw-orders-table { min-width: 800px; } \/* Asegura scroll si es necesario *\/\n            \n            \/* Ajuste de tarjetas de info *\/\n            .cw-info-card { padding: 10px; flex-direction: row; flex-wrap: wrap; }\n            .cw-price { font-size: 1.2rem; }\n            \n            \/* Ajuste de Stats *\/\n            .cw-stats-bar { grid-template-columns: 1fr 1fr; gap: 8px; }\n            .cw-stat-val { font-size: 0.95rem; }\n        }\n\n        \/* --- ESTILOS DEL DASHBOARD PREMIUM (NUEVO) --- *\/\n        .cw-dash-module {\n            margin-top: 40px;\n            border-top: 2px solid #333;\n            padding-top: 20px;\n        }\n        .cw-dash-title {\n            font-size: 1.4rem; color: #fff; margin-bottom: 20px; font-weight: 800; text-transform: uppercase;\n            border-left: 5px solid #6c5ce7; padding-left: 10px;\n        }\n        .cw-dash-grid {\n            display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px;\n        }\n        .cw-dash-card {\n            background: #2b2b40; border-radius: 8px; padding: 15px; border: 1px solid #3d3d5c;\n            display: flex; flex-direction: column;\n        }\n        .cw-dash-header {\n            display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;\n            border-bottom: 1px solid #444; padding-bottom: 10px;\n        }\n        .cw-dash-header h4 { margin: 0; color: #bbb; font-size: 0.9rem; text-transform: uppercase; }\n        .cw-dash-btn {\n            background: #6c5ce7; color: white; border: none; padding: 5px 10px; font-size: 0.75rem;\n            border-radius: 4px; cursor: pointer; text-transform: uppercase; font-weight: bold;\n            transition: background 0.2s;\n        }\n        .cw-dash-btn:hover { background: #5649c0; }\n        .cw-dash-content { min-height: 100px; font-size: 0.9rem; }\n        \n        \/* Tablas internas del dashboard *\/\n        .cw-dash-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }\n        .cw-dash-table th { text-align: left; color: #888; padding: 5px; border-bottom: 1px solid #444; }\n        .cw-dash-table td { padding: 5px; border-bottom: 1px solid #333; color: #eee; }\n        .cw-dash-val-pos { color: #4caf50; font-weight: bold; }\n        .cw-dash-val-neg { color: #ff5252; font-weight: bold; }\n\n        .dash-kpi-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }\n        .dash-kpi-item { background: #1e1e2d; padding: 10px; border-radius: 4px; text-align: center; }\n        .dash-kpi-lbl { font-size: 0.7rem; color: #888; margin-bottom: 2px; }\n        .dash-kpi-val { font-size: 1rem; font-weight: bold; color: #fff; }\n\n        \/* NUEVO: ESTILOS PARA EL M\u00d3DULO DE DETALLES DE TRADE *\/\n        .trade-detail-panel { margin-top: 20px; background: #1e1e2d; padding: 15px; border-radius: 8px; border: 1px solid #3d3d5c; }\n        .td-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }\n        .td-item { display: flex; flex-direction: column; }\n        .td-label { font-size: 0.75rem; color: #888; text-transform: uppercase; margin-bottom: 3px; }\n        .td-val { font-size: 1rem; font-weight: bold; color: #fff; font-family: monospace; }\n        .td-win { color: #4caf50; }\n        .td-loss { color: #ff5252; }\n    <\/style>\n\n    <!-- INICIO HTML DEL BOT -->\n    <div id=\"crypto-widget-container\">\n        \n        <div id=\"orbidex-loader\">\n            <div class=\"ai-spinner\"><\/div>\n            <div class=\"ai-text\" id=\"ai-status-text\">Iniciando BULL TRADING BOT...<\/div>\n            <div class=\"ai-subtext\" id=\"ai-sub-text\">Cargando m\u00f3dulos de gesti\u00f3n<\/div>\n        <\/div>\n\n        <div class=\"cw-app-header\">\n            <!-- CAMBIO 5: TITULO AI-PRO by BULL TRADING BOT -->\n            <h2 class=\"cw-app-title\"><span style=\"color:#ffffff\">AI-PRO<\/span> <span style=\"color:#888; font-size:0.7em;\">by<\/span> <span style=\"color:#4caf50\">BULL TRADING BOT<\/span><\/h2>\n        <\/div>\n\n        <div class=\"cw-controls-wrapper\">\n            <!-- NUEVO: Selector de Grupo de Activos -->\n            <div class=\"cw-control-group\">\n                <span class=\"cw-label-top\">Tipo de Activo<\/span>\n                <select id=\"cw-asset-group\" onchange=\"changeAssetGroup()\">\n                    <option value=\"CRYPTO\">Criptomonedas<\/option>\n                    <option value=\"FOREX\">Forex<\/option>\n                    <option value=\"FUNDS\">Fondos\/Comodities<\/option>\n                <\/select>\n            <\/div>\n            <div class=\"cw-control-group\">\n                <span class=\"cw-label-top\">Activo (Vista)<\/span>\n                <select id=\"cw-coin\" onchange=\"updateApp()\">\n                    <!-- Se llena dinamicamente -->\n                <\/select>\n            <\/div>\n            <div class=\"cw-control-group\">\n                <span class=\"cw-label-top\">Temporalidad (Estrategia)<\/span>\n                <select id=\"cw-interval\" onchange=\"updateApp()\">\n                    <option value=\"1m\">1 Minuto (Scalping)<\/option>\n                    <option value=\"5m\">5 Minutos (Intraday)<\/option>\n                    <option value=\"15m\">15 Minutos (Swing)<\/option>\n                    <option value=\"1h\">1 Hora (Trend)<\/option>\n                    <option value=\"4h\">4 Horas (Macro)<\/option>\n                <\/select>\n            <\/div>\n            <div class=\"cw-control-group\" style=\"flex: 0 0 auto;\">\n                <span class=\"cw-label-top\">Action<\/span>\n                <button onclick=\"updateApp()\" class=\"cw-btn\" style=\"min-width: 100px;\">\u21bb Reset<\/button>\n            <\/div>\n        <\/div>\n\n        <div class=\"cw-grid\">\n            <div>\n                <div class=\"cw-info-card\">\n                    <div><div style=\"font-size:0.85rem; color:#aaa;\">PRECIO EN VIVO<\/div><div id=\"cw-display-price\" class=\"cw-price\">---<\/div><\/div>\n                    <div style=\"text-align:right;\"><div style=\"font-size:0.85rem; color:#aaa;\">SE\u00d1AL ACTUAL<\/div><div id=\"cw-display-trend\" class=\"cw-trend trend-neutral\">ANALIZANDO...<\/div><\/div>\n                <\/div>\n\n                <div class=\"cw-indicators\" id=\"tech-panel\">\n                    <div class=\"cw-ind-item\"><span class=\"cw-ind-sub\" id=\"lbl-ema-fast\">EMA RAP<\/span><span class=\"cw-ind-val-display\" id=\"val-ema-fast\">---<\/span><\/div>\n                    <div class=\"cw-ind-item\"><span class=\"cw-ind-sub\" id=\"lbl-ema-slow\">EMA LENT<\/span><span class=\"cw-ind-val-display\" id=\"val-ema-slow\">---<\/span><\/div>\n                    <div class=\"cw-ind-item\"><span class=\"cw-ind-sub\">CONVERG<\/span><span class=\"cw-ind-val-display\" id=\"val-conv\">---<\/span><\/div>\n                    <div class=\"cw-ind-item\"><span class=\"cw-ind-sub\">RSI (14)<\/span><span class=\"cw-ind-val-display\" id=\"val-rsi\">---<\/span><\/div>\n                    <div class=\"cw-ind-item\"><span class=\"cw-ind-sub\">MACD<\/span><span class=\"cw-ind-val-display\" id=\"val-macd\">---<\/span><\/div>\n                <\/div>\n\n                <div class=\"chart-box\"><canvas id=\"cryptoChart\"><\/canvas><\/div>\n\n                <!-- JUEGO DEL COHETE -->\n                <div id=\"moon-app\">\n                    <div class=\"watermark\">\n                        <div class=\"wm-main\">ROCKET GAME<\/div>\n                        <div class=\"wm-sub\">BULL TRADING BOT<\/div>\n                    <\/div>\n                \n                    <canvas id=\"gameCanvas\"><\/canvas>\n                \n                    <div class=\"ui-layer\">\n                        <div class=\"hud\">\n                            <div class=\"stat\"><label>COIN<\/label><span id=\"ui-coin\">---<\/span><\/div>\n                            <div class=\"stat\"><label>ENTRY<\/label><span id=\"ui-entry-top\" class=\"entry-val\">---<\/span><\/div>\n                            <div class=\"stat\"><label>PRICE<\/label><span id=\"ui-price\">---<\/span><\/div>\n                            <div class=\"stat\"><label>PNL ($)<\/label><span id=\"ui-pnl\">$0.00<\/span><\/div>\n                        <\/div>\n                \n                        <div class=\"thermo-container\" id=\"thermo\">\n                            <div class=\"thermo-bar\">\n                                <div class=\"thermo-zero\"><\/div>\n                                <div class=\"fill-up\" id=\"bar-up\"><\/div>\n                                <div class=\"fill-down\" id=\"bar-down\"><\/div>\n                            <\/div>\n                        <\/div>\n                \n                        <div class=\"center-display\">\n                            <div class=\"big-mult\" id=\"ui-mult\">0.00%<\/div>\n                            <div class=\"status-badge\" id=\"ui-status\">WAITING FOR SIGNAL...<\/div>\n                            <div class=\"realized-pnl\" id=\"ui-realized\">SECURED: $0.00<\/div>\n                        <\/div>\n                    <\/div>\n                \n                    <script>\n                        window.ccGame = (function(){\n                            const SKINS = { BTC:'#f7931a', ETH:'#627eea', SOL:'#14f195', XRP:'#00aae4', DOGE:'#c2a633', ADA:'#0033ad', BNB:'#f3ba2f', BCH:'#8dc351', HBAR:'#000000' };\n                            const canvas = document.getElementById('gameCanvas');\n                            const ctx = canvas.getContext('2d');\n                            const app = document.getElementById('moon-app');\n                            \n                            let audioCtx = null;\n                            let state = 'IDLE'; \n                            let balance = 10000, bet = 1000, lev = 20, dir = 'LONG', coin = 'BTC', timeSpeed = 1;\n                            let price = 0, entry = 0, pnlPercent = 0, realizedPnl = 0, remainingSize = 100;\n                            let tpConfig = [], slPercent = 80;\n                            let chartData = [], particles = [], fireworks = [];\n                            \n                            \/\/ WEBSOCKET PARA EL JUEGO (DEDICADO)\n                            let gameWs = null;\n                            let currentOrderId = null;\n                            let forcedSymbol = null; \/\/ Nuevo: Para forzar vista en activo seleccionado\n                \n                            function init() {\n                                resize();\n                                window.addEventListener('resize', () => resize());\n                                loop();\n                                setInterval(syncWithGlobalBot, 100); \n                            }\n\n                            function connectGameSocket(symbol) {\n                                if(gameWs) gameWs.close();\n                                \/\/ FIX: Si no es crypto, no conectamos websocket de binance.\n                                if(window.ASSET_GROUPS && !window.ASSET_GROUPS['CRYPTO'].includes(symbol) && symbol !== 'PAXGUSDT') return;\n\n                                try {\n                                    let pair = symbol.toLowerCase();\n                                    gameWs = new WebSocket(`wss:\/\/stream.binance.com:9443\/ws\/${pair}@trade`);\n                                    gameWs.onmessage = e => { \n                                        let d = JSON.parse(e.data);\n                                        let liveP = parseFloat(d.p);\n                                        updateGameVisuals(liveP);\n                                    };\n                                } catch(e){}\n                            }\n                            \n                            function updateGameVisuals(livePrice) {\n                                if(state !== 'TRADE') return;\n                                \n                                price = livePrice;\n                                \n                                \/\/ Calcular PNL localmente para suavidad visual\n                                let diff = 0;\n                                if(dir === 'LONG') diff = (price - entry) \/ entry;\n                                else diff = (entry - price) \/ entry;\n                                \n                                pnlPercent = diff * 100 * lev;\n                                let activeAmount = bet * (remainingSize\/100);\n                                let floating = activeAmount * (pnlPercent\/100);\n                                let totalPnl = realizedPnl + floating;\n\n                                \/\/ USO DE NUEVA FUNCI\u00d3N DE PRECISI\u00d3N\n                                let d = 2;\n                                if(window.getPrecision) d = window.getPrecision(price, coin); \n\n                                document.getElementById('ui-price').innerText = \"$\"+price.toFixed(d);\n                                document.getElementById('ui-pnl').innerText = (totalPnl>=0?'+':'')+\"$\"+totalPnl.toFixed(2);\n                                document.getElementById('ui-mult').innerText = pnlPercent.toFixed(2)+\"%\";\n                                document.getElementById('ui-mult').style.color = pnlPercent>0 ? \"var(--primary)\" : \"var(--danger)\";\n\n                                \/\/ Push al grafico\n                                chartData.push(price);\n                                if(chartData.length > 100) chartData.shift();\n                                \n                                \/\/ Actualizar barras\n                                let maxRange = tpConfig[3] ? tpConfig[3].roe * 1.2 : 100;\n                                if(pnlPercent > 0) {\n                                    let h = (pnlPercent \/ maxRange) * 50;\n                                    document.getElementById('bar-up').style.height = Math.min(50, h) + \"%\";\n                                    document.getElementById('bar-down').style.height = \"0%\";\n                                } else {\n                                    let h = (Math.abs(pnlPercent) \/ maxRange) * 50;\n                                    document.getElementById('bar-down').style.height = Math.min(50, h) + \"%\";\n                                    document.getElementById('bar-up').style.height = \"0%\";\n                                }\n\n                                addParticle(canvas.width\/2, canvas.height-100, 'fire');\n                            }\n                \n                            function syncWithGlobalBot() {\n                                if(typeof window.demoOrders === 'undefined') return;\n                                \n                                const openOrders = window.demoOrders.filter(o => o.status === 'OPEN');\n                                \n                                \/\/ L\u00f3gica de Forced View (Bot\u00f3n GRAFICO)\n                                if (forcedSymbol) {\n                                    const forcedOrder = openOrders.find(o => o.symbol === forcedSymbol);\n                                    if(forcedOrder) {\n                                        if (currentOrderId !== forcedOrder.id) {\n                                            currentOrderId = forcedOrder.id;\n                                            startTrade(forcedOrder);\n                                        }\n                                        \/\/ Sincronizar estado si estamos en TRADE y es la orden forzada\n                                        if (state === 'TRADE' && currentOrderId === forcedOrder.id) {\n                                            syncOrderState(forcedOrder);\n                                            if(window.ASSET_GROUPS && !window.ASSET_GROUPS['CRYPTO'].includes(forcedOrder.symbol) && forcedOrder.symbol !== 'PAXGUSDT') {\n                                                if(forcedOrder.markPrice) updateGameVisuals(forcedOrder.markPrice);\n                                            }\n                                        }\n                                        return; \/\/ Salir, forzamos vista unica\n                                    } else {\n                                        \/\/ Si la orden forzada ya no existe (se cerr\u00f3), quitar forzado\n                                        forcedSymbol = null;\n                                    }\n                                }\n\n                                \/\/ L\u00f3gica Normal (Multi o Single autom\u00e1tico)\n                                if (openOrders.length > 1) {\n                                    if(state !== 'MULTI') setMultiMode();\n                                    return; \n                                }\n\n                                if(window.demoOrders.length === 0 || openOrders.length === 0) {\n                                    if(state === 'TRADE') endGame(null);\n                                    if(state !== 'IDLE' && state !== 'MULTI') resetToIdle();\n                                    return;\n                                }\n                                \n                                const activeOrder = openOrders[0];\n                                \n                                \/\/ DETECTAR NUEVA ENTRADA\n                                if (activeOrder.status === 'OPEN' && activeOrder.id !== currentOrderId) {\n                                    currentOrderId = activeOrder.id;\n                                    startTrade(activeOrder);\n                                }\n                                \n                                \/\/ ACTUALIZAR ESTADO (TPs, Secured)\n                                if (state === 'TRADE' && activeOrder.id === currentOrderId) {\n                                    if(activeOrder.status === 'OPEN') {\n                                        syncOrderState(activeOrder); \/\/ Sincroniza estado l\u00f3gico\n                                        \/\/ SIMULACION DE TICKER PARA NO-CRYPTO EN EL JUEGO\n                                        if(window.ASSET_GROUPS && !window.ASSET_GROUPS['CRYPTO'].includes(activeOrder.symbol) && activeOrder.symbol !== 'PAXGUSDT') {\n                                            \/\/ Usamos el markPrice actualizado por el bot principal como \"livePrice\"\n                                            if(activeOrder.markPrice) updateGameVisuals(activeOrder.markPrice);\n                                        }\n                                    } else {\n                                        endGame(activeOrder);\n                                        currentOrderId = null; \n                                    }\n                                }\n                            }\n\n                            function setMultiMode() {\n                                state = 'MULTI';\n                                if(gameWs) gameWs.close();\n                                chartData = [];\n                                document.getElementById('ui-status').innerText = \"MODO MULTI-ORDEN\";\n                                document.getElementById('ui-status').style.color = \"#ff9800\"; \n                                document.getElementById('ui-mult').innerText = \"VER TABLA\";\n                                document.getElementById('ui-mult').style.fontSize = \"2.5rem\";\n                                document.getElementById('ui-realized').style.opacity = 0;\n                                document.getElementById('ui-coin').innerText = \"MULTIPLE\";\n                                document.getElementById('bar-up').style.height = \"0%\";\n                                document.getElementById('bar-down').style.height = \"0%\";\n                                document.querySelectorAll('.level-marker').forEach(e=>e.remove());\n                            }\n                \n                            function startTrade(order) {\n                                state = 'TRADE';\n                                document.getElementById('ui-mult').style.fontSize = \"3rem\"; \n                                coin = order.symbol.replace('USDT',''); \/\/ Variable 'coin' used as symbol inside game\n                                dir = order.direction;\n                                entry = order.entry;\n                                bet = order.amount;\n                                lev = order.leverage;\n                                remainingSize = 100; \/\/ Reset\n                                realizedPnl = 0;\n                                \n                                chartData = [entry];\n                                particles = []; fireworks = [];\n                                \n                                \/\/ Sincronizar TPs \n                                tpConfig = order.tps.map((tp, idx) => ({\n                                    id: idx+1,\n                                    roe: Math.abs((tp.price - order.entry)\/order.entry) * 100 * lev,\n                                    price: tp.price,\n                                    vol: tp.vol,\n                                    hit: false\n                                }));\n                                \n                                \/\/ Calcular SL inicial % para visualizacion\n                                let slPctInit = Math.abs((order.entry - order.sl) \/ order.entry) * 100 * lev;\n\n                                app.className = dir === 'LONG' ? '' : 'mode-short';\n                                updateColors();\n                                document.getElementById('ui-coin').innerText = coin;\n                                document.getElementById('ui-status').innerText = \"TRACKING TRADE\";\n                                document.getElementById('ui-status').style.color = \"#fff\";\n                                \n                                \/\/ USO DE NUEVA FUNCI\u00d3N DE PRECISI\u00d3N\n                                let d = 2;\n                                if(window.getPrecision) d = window.getPrecision(entry, order.symbol);\n\n                                document.getElementById('ui-entry-top').innerText = \"$\"+entry.toFixed(d);\n                                document.getElementById('ui-realized').style.opacity = 1;\n                                document.getElementById('ui-realized').innerText = \"SECURED: $0.00\";\n                                \n                                setupThermometer(order.sl, slPctInit);\n                                initAudio();\n                                connectGameSocket(order.symbol); \/\/ Iniciar socket rapido\n                            }\n                \n                            function syncOrderState(order) {\n                                \/\/ Sincronizar solo datos de gesti\u00f3n\n                                let securedVal = order.secured || 0; \n                                \n                                \/\/ Actualizar UI Secured\n                                let secEl = document.getElementById('ui-realized');\n                                secEl.innerText = \"SECURED: $\" + securedVal.toFixed(2);\n                                if(securedVal > 0) {\n                                    secEl.style.color = \"#ffd700\"; \n                                    secEl.style.textShadow = \"0 0 5px rgba(255, 215, 0, 0.5)\";\n                                }\n                                \n                                \/\/ Check visual de TPs alcanzados\n                                order.tps.forEach((tp, i) => {\n                                    if(tp.filled && tpConfig[i] && !tpConfig[i].hit) {\n                                        tpConfig[i].hit = true;\n                                        tpConfig[i].hit = true;\n                                        document.getElementById('mk-tp-'+(i+1)).classList.add('hit');\n                                        sfx('win');\n                                        spawnFireworks();\n                                        \n                                        \/\/ Actualizar variables locales para c\u00e1lculo visual PNL\n                                        remainingSize -= tp.vol;\n                                        let gainPct = tp.pct * lev;\n                                        let gainUsd = (bet * (tp.vol\/100)) * (gainPct\/100);\n                                        realizedPnl += gainUsd;\n                                    }\n                                });\n                            }\n                \n                            function endGame(order) {\n                                if(gameWs) gameWs.close();\n                                if(!order) { resetToIdle(); return; }\n                                \n                                \/\/ Calcular Total final para mensaje (Realizado final)\n                                let finalTotal = (order.realized || 0); \n                                \n                                if(finalTotal > 0) {\n                                    state = 'WIN'; sfx('win'); \n                                    if(order.status.includes('TAKE PROFIT')) {\n                                        spawnFireworks(); spawnFireworks(); spawnFireworks(); \n                                    } else {\n                                        spawnFireworks();\n                                    }\n                                    document.getElementById('ui-status').innerText = \"PROFIT SECURED!\";\n                                    document.getElementById('ui-status').style.color = \"var(--gold)\";\n                                } else {\n                                    state = 'REKT'; sfx('crash');\n                                    document.getElementById('ui-status').innerText = \"HAS SIDO LIQUIDADO\";\n                                    document.getElementById('ui-mult').style.color = \"var(--danger)\";\n                                    for(let i=0; i<50; i++) addParticle(canvas.width\/2, canvas.height-100, 'boom');\n                                }\n                                \n                                setTimeout(() => {\n                                    if(state !== 'TRADE') resetToIdle();\n                                }, 4000);\n                            }\n                \n                            function resetToIdle() {\n                                if(state === 'TRADE') return; \n                                state = 'IDLE';\n                                if(gameWs) gameWs.close();\n                                document.getElementById('ui-mult').style.fontSize = \"3rem\";\n                                document.getElementById('ui-status').innerText = \"WAITING FOR SIGNAL...\";\n                                document.getElementById('ui-status').style.color = \"#aaa\";\n                                document.getElementById('ui-mult').innerText = \"0.00%\";\n                                document.getElementById('ui-mult').style.color = \"#fff\";\n                                document.getElementById('bar-up').style.height = \"0%\";\n                                document.getElementById('bar-down').style.height = \"0%\";\n                                document.getElementById('ui-realized').style.opacity = 0;\n                                document.getElementById('ui-coin').innerText = \"---\";\n                                chartData = [];\n                                document.querySelectorAll('.level-marker').forEach(e=>e.remove());\n                            }\n            \n                            function setupThermometer(slPrice, slPct) {\n                                document.querySelectorAll('.level-marker').forEach(e => e.remove());\n                                const container = document.getElementById('thermo');\n                                let maxRange = tpConfig[3].roe * 1.2;\n                                \n                                \/\/ USO DE NUEVA FUNCI\u00d3N DE PRECISI\u00d3N\n                                let d = 2;\n                                if(window.getPrecision) d = window.getPrecision(slPrice, coin);\n\n                                tpConfig.forEach(tp => {\n                                    let pctPos = (tp.roe \/ maxRange) * 50; \n                                    if(pctPos > 50) pctPos = 50;\n                                    let el = document.createElement('div');\n                                    el.className = 'level-marker';\n                                    el.id = 'mk-tp-'+tp.id;\n                                    \/\/ Visualizaci\u00f3n mejorada: Precio y % ROE\n                                    el.innerHTML = `TP${tp.id}<span style=\"font-size:0.75rem; color:#aaa;\">$${tp.price.toFixed(d)} (${tp.roe.toFixed(0)}%)<\/span>`;\n                                    el.style.bottom = (50 + pctPos) + \"%\"; \n                                    container.appendChild(el);\n                                });\n                \n                                let slPos = (slPercent \/ maxRange) * 50;\n                                let elSl = document.createElement('div');\n                                elSl.className = 'level-marker';\n                                \/\/ Visualizaci\u00f3n mejorada SL\n                                elSl.innerHTML = `SL<span style=\"font-size:0.75rem; color:#ff5252;\">$${slPrice.toFixed(d)} (-${slPct.toFixed(0)}%)<\/span>`;\n                                elSl.style.color = \"var(--danger)\";\n                                elSl.style.top = (50 + slPos) + \"%\";\n                                container.appendChild(elSl);\n                            }\n            \n                            function resize() {\n                                canvas.width = app.clientWidth;\n                                canvas.height = app.clientHeight;\n                            }\n                \n                            function draw() {\n                                ctx.fillStyle = 'rgba(11, 12, 16, 0.3)'; ctx.fillRect(0,0,canvas.width,canvas.height);\n                                if(chartData.length > 1) {\n                                    ctx.beginPath();\n                                    ctx.strokeStyle = app.style.getPropertyValue('--primary') || '#00ff41';\n                                    ctx.lineWidth = 3;\n                                    let minP = Math.min(...chartData), maxP = Math.max(...chartData);\n                                    let range = maxP - minP || 1;\n                                    chartData.forEach((p, i) => {\n                                        let x = (i \/ (chartData.length-1)) * canvas.width;\n                                        let y = canvas.height - ((p - minP) \/ range * (canvas.height*0.5) + canvas.height*0.2);\n                                        if(i===0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\n                                    });\n                                    ctx.stroke();\n                                    \n                                    if(state==='TRADE') {\n                                        let yE = canvas.height - ((entry - minP) \/ range * (canvas.height*0.5) + canvas.height*0.2);\n                                        ctx.strokeStyle='white'; ctx.setLineDash([5,5]); ctx.beginPath();\n                                        ctx.moveTo(0,yE); ctx.lineTo(canvas.width,yE); ctx.stroke(); ctx.setLineDash([]);\n                                        let yC = canvas.height - ((price - minP) \/ range * (canvas.height*0.5) + canvas.height*0.2);\n                                        ctx.fillStyle=app.style.getPropertyValue('--primary');\n                                        ctx.beginPath(); ctx.arc(canvas.width-10, yC, 5, 0, Math.PI*2); ctx.fill();\n                                    }\n                                }\n                                [particles, fireworks].forEach(arr => arr.forEach(p => { ctx.fillStyle = p.c; ctx.fillRect(p.x, p.y, p.s, p.s); }));\n                            }\n                \n                            function loop() { updateParticles(); draw(); requestAnimationFrame(()=>loop()); }\n                            \n                            function updateParticles() {\n                                [particles, fireworks].forEach(arr => {\n                                    for(let i=arr.length-1; i>=0; i--) {\n                                        let p = arr[i]; p.x+=p.vx; p.y+=p.vy; p.l--;\n                                        if(p.type==='fw') p.vy+=0.1;\n                                        if(p.l<=0) arr.splice(i,1);\n                                    }\n                                });\n                            }\n                \n                            function initAudio() { if(!audioCtx) audioCtx = new (window.AudioContext||window.webkitAudioContext)(); if(audioCtx.state==='suspended') audioCtx.resume(); }\n                            function sfx(t) { \n                                if(!audioCtx) return; \n                                const o=audioCtx.createOscillator(), g=audioCtx.createGain(); \n                                let dur = 0.5;\n                                if(t==='win'){o.type='square'; o.frequency.setValueAtTime(400,audioCtx.currentTime); o.frequency.linearRampToValueAtTime(800,audioCtx.currentTime+0.3);} \n                                else if(t==='crash'){ o.type='sawtooth'; dur = 3.0; o.frequency.setValueAtTime(150,audioCtx.currentTime); o.frequency.exponentialRampToValueAtTime(10,audioCtx.currentTime+dur); } \n                                g.gain.value=0.2; o.connect(g); g.connect(audioCtx.destination); o.start(); o.stop(audioCtx.currentTime+dur); \n                            }\n                            \n                            function forceReset() { resetToIdle(); }\n                            function forceView(symbol) { forcedSymbol = symbol; }\n\n                            function updateColors() { let c = dir==='LONG' ? '#00ff41' : '#ff0055'; app.style.setProperty('--primary', c); }\n                            function addParticle(x,y,t) { let c = t==='fire' ? (pnlPercent>0? (SKINS[coin] || '#fff') : '#ff0055') : 'orange'; particles.push({x:x+(Math.random()-0.5)*10, y:y, vx:(Math.random()-0.5), vy:Math.random()*5, l:10, c:c, s:3}); }\n                            function spawnFireworks() { for(let k=0; k<5; k++) { let x=Math.random()*canvas.width, y=Math.random()*(canvas.height\/2), c=`hsl(${Math.random()*360},100%,50%)`; for(let i=0; i<30; i++) fireworks.push({x:x, y:y, vx:(Math.random()-0.5)*10, vy:(Math.random()-0.5)*10, l:50, c:c, s:3, type:'fw'}); } }\n                \n                            return { init, forceReset, forceView };\n                        })();\n                \n                        \/\/ Iniciar Juego de forma segura\n                        if (document.readyState === 'loading') {\n                            document.addEventListener('DOMContentLoaded', window.ccGame.init);\n                        } else {\n                            window.ccGame.init();\n                        }\n                    <\/script>\n                <\/div>\n\n                <!-- M\u00d3DULO NUEVO: DETALLES DEL TRADE SELECCIONADO -->\n                <div id=\"trade-detail-module\" class=\"trade-detail-panel\" style=\"display:none;\">\n                    <h3 style=\"margin:0 0 15px 0; font-size:1rem; border-bottom:1px solid #444; padding-bottom:8px; color:#fff;\">DETALLES DEL TRADE SELECCIONADO<\/h3>\n                    <div class=\"td-grid\">\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Trade (Par\/Estado)<\/span>\n                            <span class=\"td-val\" id=\"td-pair\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Direcci\u00f3n<\/span>\n                            <span class=\"td-val\" id=\"td-dir\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Inicio<\/span>\n                            <span class=\"td-val\" id=\"td-start\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Cierre<\/span>\n                            <span class=\"td-val\" id=\"td-end\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Duration<\/span>\n                            <span class=\"td-val\" id=\"td-dur\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">ROI Obtenido<\/span>\n                            <span class=\"td-val\" id=\"td-roi\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">PNL Total ($\/%)<\/span>\n                            <span class=\"td-val\" id=\"td-pnl\">---<\/span>\n                        <\/div>\n                        <div class=\"td-item\">\n                            <span class=\"td-label\">Result<\/span>\n                            <span class=\"td-val\" id=\"td-res\">---<\/span>\n                        <\/div>\n                    <\/div>\n                <\/div>\n\n            <\/div>\n\n            <div class=\"bot-panel\">\n                <h3 class=\"bot-title\">CONFIGURACI\u00d3N DEL BOT<\/h3>\n                \n                <div class=\"bot-subtitle\">1. GESTI\u00d3N DE CAPITAL<\/div>\n                <div class=\"bot-row\">\n                    <!-- CAMBIO: CAPITAL FIJO Y BLOQUEADO -->\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">Capital (USD)<\/label><input type=\"number\" id=\"calc-amount\" value=\"500000\" disabled style=\"color:#aaa !important; cursor:not-allowed;\"><\/div>\n                <\/div>\n                <div class=\"bot-row\">\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">MIO ($ Max\/Ord)<\/label><input type=\"number\" id=\"bot-mio\" value=\"100\" oninput=\"calculateResults();\"><\/div>\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">MOA (Max\/Coin)<\/label><input type=\"number\" id=\"bot-moa\" value=\"2\"><\/div>\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">MAC (Activos)<\/label><input type=\"number\" id=\"bot-mac\" value=\"3\"><\/div>\n                <\/div>\n\n                <div class=\"bot-subtitle\">2. DIRECCI\u00d3N & MERCADO<\/div>\n                <div class=\"cw-input-group\">\n                    <div class=\"trade-direction-box\">\n                        <button id=\"btn-long\" class=\"btn-direction active-long\" onclick=\"setDirection('LONG')\">LONG \ud83d\udfe2<\/button>\n                        <button id=\"btn-short\" class=\"btn-direction\" onclick=\"setDirection('SHORT')\">SHORT \ud83d\udd34<\/button>\n                        <button id=\"btn-auto\" class=\"btn-direction\" onclick=\"setDirection('AUTO')\">AUTO \ud83e\udd16<\/button>\n                    <\/div>\n                <\/div>\n                <div class=\"bot-row\">\n                    <div class=\"bot-col\">\n                        <label class=\"cw-label-top\">Mercado<\/label>\n                        <select id=\"calc-mode\" onchange=\"toggleMode()\"><option value=\"FUTURES\">FUTURES<\/option><option value=\"SPOT\">SPOT<\/option><\/select>\n                    <\/div>\n                <\/div>\n                \n                <div class=\"cw-input-group\">\n                    <label class=\"cw-label-top\">Apalancamiento (Leverage)<\/label>\n                    <div class=\"slider-container\">\n                        <input type=\"range\" id=\"leverage-slider\" class=\"cw-range\" min=\"1\" max=\"150\" value=\"10\" oninput=\"updateLeverageDisplay(this.value)\">\n                        <span id=\"lev-val\" class=\"val-display\">10x<\/span>\n                    <\/div>\n                <\/div>\n\n                <div class=\"bot-subtitle\">3. ESTRATEGIA (TAKE PROFIT)<\/div>\n                <div class=\"cw-input-group\">\n                    <select id=\"bot-preset\" onchange=\"applyStrategyPreset()\">\n                        <option value=\"SCALPER\">SCALPER PRO (Scalping 1m)<\/option> <!-- NEW -->\n                        <option value=\"FAST\">FAST PROFIT (Intraday 5m)<\/option>\n                        <option value=\"SWING_SHORT\">SWING SHORT (Swing 15m)<\/option> <!-- NEW -->\n                        <option value=\"ROCKIE\">ROCKIE TRADER (Trend 1h)<\/option>\n                        <option value=\"HOLDER\">HOLDER TRADER (Macro 4h)<\/option>\n                    <\/select>\n                <\/div>\n\n                <div class=\"tp-mode-selector\">\n                    <label><input type=\"radio\" name=\"tp-mode\" value=\"single\" onclick=\"toggleTPMode('single')\"> TP \u00danico<\/label>\n                    <label><input type=\"radio\" name=\"tp-mode\" value=\"multi\" checked onclick=\"toggleTPMode('multi')\"> TP Escalonado<\/label>\n                <\/div>\n\n                <div id=\"tp-single-box\" class=\"tp-single-box\">\n                    <label class=\"cw-label-top\">% Profit Meta<\/label>\n                    <input type=\"number\" id=\"tp-single-val\" class=\"tp-input-mini\" value=\"1.5\" step=\"0.1\" style=\"width:100% !important; color:#aaa;\" oninput=\"calculateResults()\">\n                <\/div>\n\n                <div id=\"tp-ladder-box\" class=\"tp-ladder-box\">\n                    <div class=\"tp-row-small\"><span style=\"width:30px\">TP1<\/span> <input type=\"number\" id=\"tp1-pct\" class=\"tp-input-mini\" value=\"0.25\"> % Dist \u2b95 <input type=\"number\" id=\"tp1-vol\" class=\"tp-input-mini\" value=\"50\"> % Vol<\/div>\n                    <div class=\"tp-row-small\"><span style=\"width:30px\">TP2<\/span> <input type=\"number\" id=\"tp2-pct\" class=\"tp-input-mini\" value=\"0.45\"> % Dist \u2b95 <input type=\"number\" id=\"tp2-vol\" class=\"tp-input-mini\" value=\"25\"> % Vol<\/div>\n                    <div class=\"tp-row-small\"><span style=\"width:30px\">TP3<\/span> <input type=\"number\" id=\"tp3-pct\" class=\"tp-input-mini\" value=\"0.65\"> % Dist \u2b95 <input type=\"number\" id=\"tp3-vol\" class=\"tp-input-mini\" value=\"15\"> % Vol<\/div>\n                    <div class=\"tp-row-small\"><span style=\"width:30px\">TP4<\/span> <input type=\"number\" id=\"tp4-pct\" class=\"tp-input-mini\" value=\"0.87\"> % Dist \u2b95 <input type=\"number\" id=\"tp4-vol\" class=\"tp-input-mini\" value=\"10\"> % Vol<\/div>\n                <\/div>\n\n                <div class=\"bot-subtitle\">4. GESTI\u00d3N RIESGO<\/div>\n                <div class=\"slider-container\">\n                    <span style=\"font-size:0.8rem; color:#ff5252; min-width:30px;\">SL<\/span>\n                    <input type=\"range\" id=\"sl-slider\" class=\"cw-range\" min=\"0.1\" max=\"50\" step=\"0.1\" value=\"2\" oninput=\"document.getElementById('sl-val').innerText=this.value+'%'; calculateResults();\">\n                    <span id=\"sl-val\" class=\"val-display\" style=\"color:#ff5252\">2%<\/span>\n                <\/div>\n\n                <div class=\"bot-subtitle\">5. TRAILING (OPCIONAL)<\/div>\n                <div class=\"bot-row\">\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">Trailing SL (%)<\/label><input type=\"number\" id=\"input-trailing-sl\" value=\"0\" step=\"0.1\"><\/div>\n                    <div class=\"bot-col\"><label class=\"cw-label-top\">Trailing TP (%)<\/label><input type=\"number\" id=\"input-trailing-tp\" value=\"0\" step=\"0.1\"><\/div>\n                <\/div>\n\n                <div class=\"cw-results\">\n                    <div class=\"cw-res-row\"><span>Precio TP Objetivo:<\/span><span id=\"res-tp-price\" style=\"color:white; font-weight:bold;\">---<\/span><\/div>\n                    <div class=\"cw-res-row\"><span>Ganancia (Est):<\/span><span id=\"res-profit\" class=\"cw-res-val\">---<\/span><\/div>\n                    <hr style=\"border-color:#444; opacity:0.3; margin: 5px 0;\">\n                    <div class=\"cw-res-row\"><span>Precio SL Riesgo:<\/span><span id=\"res-sl-price\" style=\"color:white; font-weight:bold;\">---<\/span><\/div>\n                    <div class=\"cw-res-row\"><span>P\u00e9rdida (Est):<\/span><span id=\"res-loss\" class=\"cw-res-loss\">---<\/span><\/div>\n                <\/div>\n\n                <button id=\"btn-bot-toggle\" onclick=\"toggleBotExecution()\" class=\"btn-launch-bot\">\ud83e\udd16 LANZAR BOT<\/button>\n                <div id=\"scan-status\" style=\"text-align:center; font-size:0.8em; color:#aaa; margin-top:5px; height:20px;\"><\/div>\n            <\/div>\n        <\/div>\n\n        <!-- ===================================================================== -->\n        <!-- M\u00d3DULO ACTUALIZADO: ORDENES ACTIVAS & HISTORIAL (CON MONTO ASEGURADO) -->\n        <!-- ===================================================================== -->\n        <div class=\"cw-orders-module\">\n            <div class=\"cw-orders-header\">\n                <h3 style=\"margin:0; font-size:1.1rem; color:white;\">ORDENES ACTIVAS & HISTORIAL<\/h3>\n                <div class=\"live-indicator\"><div class=\"live-dot\"><\/div> MONITORIZANDO<\/div>\n            <\/div>\n            \n            <!-- AQUI LA ACTUALIZACION: GRID DE 5 COLUMNAS PARA INCLUIR EL ASEGURADO TOTAL -->\n            <div class=\"cw-stats-bar\" style=\"grid-template-columns: repeat(5, 1fr);\">\n                <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">Trades<\/div><div class=\"cw-stat-val\" id=\"stat-total-trades\">0<\/div><\/div>\n                <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">Win Rate<\/div><div class=\"cw-stat-val\" id=\"stat-winrate\" style=\"color:#00bcd4;\">0%<\/div><\/div>\n                <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">PNL Flotante<\/div><div class=\"cw-stat-val\" id=\"stat-pnl-floating\">$0.00<\/div><\/div>\n                <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">PNL Realizado<\/div><div class=\"cw-stat-val\" id=\"stat-pnl-realized\">$0.00<\/div><\/div>\n                <!-- NUEVO CAMPO AGREGADO -->\n                <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">Total Asegurado<\/div><div class=\"cw-stat-val\" id=\"stat-secured\" style=\"color:#ffd700; text-shadow:0 0 5px rgba(255, 215, 0, 0.3);\">$0.00<\/div><\/div>\n            <\/div>\n            \n            <div class=\"cw-orders-table-wrap\">\n                <table class=\"cw-orders-table\">\n                    <thead>\n                        <tr>\n                            <th>Date<br>Hora<\/th>\n                            <th>Pair<\/th>\n                            <th>Tipo<\/th>\n                            <th>Entrada<\/th>\n                            <th>Monto\/Lev<\/th>\n                            <th>TP \/ SL<\/th>\n                            <th>Flotante(%)<\/th> \n                            <th>Flotante($)<\/th> \n                            <th>Asegurado($)<\/th> \n                            <th>TOTAL($)<\/th>\n                            <th>Progreso Visual<\/th>\n                            <th>Estado\/Acci\u00f3n<\/th>\n                        <\/tr>\n                    <\/thead>\n                    <tbody id=\"cw-orders-body\"><tr><td colspan=\"12\" class=\"cw-orders-empty\">El bot est\u00e1 inactivo.<\/td><\/tr><\/tbody>\n                <\/table>\n            <\/div>\n            <div style=\"text-align:right;\"><button onclick=\"clearHistory()\" style=\"background:none; border:none; color:#ff5252; cursor:pointer; text-decoration:underline; font-size:0.8em;\">Limpiar Historial<\/button><\/div>\n            \n            <div class=\"cw-charts-grid\">\n                <div class=\"pnl-chart-container\"><div class=\"chart-title\">Ganancia vs P\u00e9rdida Diaria (%)<\/div><canvas id=\"chartWinLoss\"><\/canvas><\/div>\n                <div class=\"pnl-chart-container\"><div class=\"chart-title\">Rendimiento Neto Diaria ($)<\/div><canvas id=\"chartDailyUsd\"><\/canvas><\/div>\n            <\/div>\n        <\/div>\n\n        <!-- M\u00d3DULO DE BACKTESTING -->\n        <div class=\"cw-orders-module\" id=\"backtest-module\" style=\"margin-top: 20px; border-color: #ff9800;\">\n            <div class=\"cw-orders-header\">\n                <h3 style=\"margin:0; font-size:1.1rem; color:#ff9800;\">\ud83e\uddea Laboratorio de Backtesting<\/h3>\n            <\/div>\n            <div class=\"cw-controls-wrapper\">\n                <!-- Controls for Backtest -->\n                <div class=\"cw-control-group\">\n                     <span class=\"cw-label-top\">Velas Hist\u00f3ricas<\/span>\n                     <select id=\"bt-candles\">\n                         <option value=\"500\">\u00daltimas 500<\/option>\n                         <option value=\"1000\">\u00daltimas 1000<\/option>\n                     <\/select>\n                <\/div>\n                <div class=\"cw-control-group\">\n                     <span class=\"cw-label-top\">Action<\/span>\n                     <button onclick=\"runBacktest()\" class=\"cw-btn\" style=\"background: #ff9800; border-color: #f57c00;\">\u25b6 Iniciar Test<\/button>\n                <\/div>\n            <\/div>\n            <div id=\"bt-results\" class=\"cw-stats-bar\" style=\"display:none; grid-template-columns: repeat(3, 1fr);\">\n                <!-- Results go here -->\n            <\/div>\n            \n            <!-- CONTENEDOR DEL ANALISTA VIRTUAL -->\n            <div id=\"bt-analyst-report\" style=\"margin-top:15px; background:rgba(0,0,0,0.3); padding:10px; border-radius:6px; display:none;\"><\/div>\n\n            <!-- Nueva Gr\u00e1fica de Equidad -->\n            <div style=\"height: 200px; margin-top: 15px; display:none;\" id=\"bt-chart-container\">\n                <canvas id=\"bt-chart\"><\/canvas>\n            <\/div>\n            <div id=\"bt-log\" style=\"max-height: 150px; overflow-y: auto; background: rgba(0,0,0,0.2); padding: 10px; font-size: 0.75rem; font-family: monospace; display:none; margin-top:10px; border-radius:6px; color:#aaa;\"><\/div>\n        <\/div>\n\n        <!-- ======================================================= -->\n        <!-- NUEVO DASHBOARD PREMIUM MODULAR                         -->\n        <!-- ======================================================= -->\n        <div class=\"cw-dash-module\" id=\"cw-dashboard-container\">\n            <h3 class=\"cw-dash-title\">AI-PRO ANALYTICS DASHBOARD<\/h3>\n            \n            <div class=\"cw-dash-grid\">\n                \n                <!-- BLOQUE 1: KPIs GLOBALES -->\n                <div class=\"cw-dash-card\">\n                    <div class=\"cw-dash-header\">\n                        <h4>KPIs Globales del Sistema<\/h4>\n                        <button class=\"cw-dash-btn\" onclick=\"renderDashBlock1()\">Generar este m\u00f3dulo<\/button>\n                    <\/div>\n                    <div id=\"dash-content-1\" class=\"cw-dash-content\">\n                        <p style=\"color:#666; text-align:center;\">Esperando generaci\u00f3n...<\/p>\n                    <\/div>\n                <\/div>\n\n                <!-- BLOQUE 2: RANKING GANANCIA NETA -->\n                <div class=\"cw-dash-card\">\n                    <div class=\"cw-dash-header\">\n                        <h4>Ranking Ganancia Neta (Por Par)<\/h4>\n                        <button class=\"cw-dash-btn\" onclick=\"renderDashBlock2()\">Generar este m\u00f3dulo<\/button>\n                    <\/div>\n                    <div id=\"dash-content-2\" class=\"cw-dash-content\">\n                        <p style=\"color:#666; text-align:center;\">Esperando generaci\u00f3n...<\/p>\n                    <\/div>\n                <\/div>\n\n                <!-- BLOQUE 3: EFICIENCIA -->\n                <div class=\"cw-dash-card\">\n                    <div class=\"cw-dash-header\">\n                        <h4>Eficiencia por Par (Profit\/Trades)<\/h4>\n                        <button class=\"cw-dash-btn\" onclick=\"renderDashBlock3()\">Generar este m\u00f3dulo<\/button>\n                    <\/div>\n                    <div id=\"dash-content-3\" class=\"cw-dash-content\">\n                        <p style=\"color:#666; text-align:center;\">Esperando generaci\u00f3n...<\/p>\n                    <\/div>\n                <\/div>\n\n                <!-- BLOQUE 4: RIESGO CRITICO -->\n                <div class=\"cw-dash-card\">\n                    <div class=\"cw-dash-header\">\n                        <h4>Riesgo Cr\u00edtico y Drawdown<\/h4>\n                        <button class=\"cw-dash-btn\" onclick=\"renderDashBlock4()\">Generar este m\u00f3dulo<\/button>\n                    <\/div>\n                    <div id=\"dash-content-4\" class=\"cw-dash-content\">\n                        <p style=\"color:#666; text-align:center;\">Esperando generaci\u00f3n...<\/p>\n                    <\/div>\n                <\/div>\n\n                 <!-- BLOQUE 5: DIRECCION -->\n                 <div class=\"cw-dash-card\">\n                    <div class=\"cw-dash-header\">\n                        <h4>An\u00e1lisis de Direcci\u00f3n (Long\/Short)<\/h4>\n                        <button class=\"cw-dash-btn\" onclick=\"renderDashBlock5()\">Generar este m\u00f3dulo<\/button>\n                    <\/div>\n                    <div id=\"dash-content-5\" class=\"cw-dash-content\">\n                        <p style=\"color:#666; text-align:center;\">Esperando generaci\u00f3n...<\/p>\n                    <\/div>\n                <\/div>\n\n            <\/div>\n        <\/div>\n\n        <!-- ======================================================= -->\n        <!-- M\u00d3DULO ADICIONAL: GENERADOR DE GR\u00c1FICOS AVANZADOS       -->\n        <!-- ======================================================= -->\n        <div class=\"cw-dash-module\" id=\"cw-adv-charts-container\">\n            <h3 class=\"cw-dash-title\">GENERADOR DE GR\u00c1FICOS AVANZADOS<\/h3>\n            <div class=\"cw-controls-wrapper\">\n                 <div class=\"cw-control-group\" style=\"flex:2;\">\n                     <span class=\"cw-label-top\">Tipo de Gr\u00e1fico<\/span>\n                     <select id=\"adv-chart-type\">\n                         <option value=\"1\">1. Ranking ponderado por n\u00famero de trades<\/option>\n                         <option value=\"2\">2. An\u00e1lisis de riesgo por par (Drawdown)<\/option>\n                         <option value=\"3\">3. Top 3 pares para maximizar ganancias<\/option>\n                         <option value=\"4\">4. Eficiencia por par (Profit\/Trade)<\/option>\n                         <option value=\"5\">5. Riesgo por par (P\u00e9rdidas vs ganancias)<\/option>\n                         <option value=\"6\">6. Distribuci\u00f3n por tipo de cierre<\/option>\n                         <option value=\"7\">7. Direcci\u00f3n (Long vs Short)<\/option>\n                     <\/select>\n                 <\/div>\n                 <div class=\"cw-control-group\">\n                     <span class=\"cw-label-top\">Action<\/span>\n                     <button class=\"cw-btn\" onclick=\"generateAdvancedChart()\" style=\"background: #6c5ce7;\">\ud83d\udcca Generar Gr\u00e1fico<\/button>\n                 <\/div>\n            <\/div>\n            <div class=\"pnl-chart-container\" style=\"height: 400px; margin-top: 15px;\">\n                 <canvas id=\"advChartCanvas\"><\/canvas>\n            <\/div>\n        <\/div>\n\n    <\/div>\n\n    <!-- SCRIPT DEL BOT (L\u00d3GICA COMPLETA) -->\n    <script>\n        \/\/ --- VARIABLES GLOBALES ---\n        let myChart = null; let chartInstance1 = null; let chartInstance2 = null;\n        let btChartInstance = null;\n        let advChartInstance = null; \/\/ Variable para el gr\u00e1fico avanzado\n        let currentPrice = 0; let priceSocket = null;\n        let currentDirection = 'LONG';\n        let currentAlgoScore = 0; \n        \n        \/\/ --- SOLUCI\u00d3N ERROR DE CONTAMINACI\u00d3N DE PRECIO ---\n        \/\/ Almacenamos el s\u00edmbolo al que pertenece el precio actual global\n        let currentPriceSymbol = null; \n        let currentDetailSymbol = null; \/\/ Added variable\n\n        \/\/ --- DEFINICI\u00d3N DE ACTIVOS POR GRUPOS ---\n        window.ASSET_GROUPS = {\n            'CRYPTO': ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'ADAUSDT', 'BNBUSDT', 'BCHUSDT', 'HBARUSDT', 'PAXGUSDT'],\n            'FOREX': ['EUR\/USD', 'GBP\/USD', 'USD\/JPY', 'USD\/CHF', 'AUD\/USD', 'USD\/CAD', 'NZD\/USD', 'EUR\/GBP', 'EUR\/JPY', 'GBP\/JPY'],\n            'FUNDS': ['GLD', 'SLV', 'USO', 'UNG', 'DBA', 'DBC', 'PPLT', 'PALL', 'CORN', 'WEAT'] \/\/ ETFs y Commodities\n        };\n\n        \/\/ Hacer demoOrders globalmente accesible\n        window.demoOrders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n        \n        let demoOrders = window.demoOrders; \/\/ Referencia local para compatibilidad\n        \n        let isBotRunning=false; let botConfig={};\n        \n        \/\/ API KEY Twelve Data (Demo)\n        const TD_API_KEY = 'df7d19ff87624ab69b6dee0182dd68de'; \n\n        let currentGroup = 'CRYPTO';\n        let scanIndex=0; let technicalData={};\n\n        \/\/ --- UTILS & CORE FUNCTIONS ---\n        function calcEMA(p, per){let k=2\/(per+1);let e=[p[0]];for(let i=1;i<p.length;i++)e.push(p[i]*k+e[i-1]*(1-k));return e;}\n        \n        function calcRSI(p, per) {\n            let r = [];\n            let gains = 0, losses = 0;\n            \/\/ First RSI (SMA)\n            for (let i = 1; i <= per; i++) {\n                let change = p[i] - p[i - 1];\n                if (change > 0) gains += change;\n                else losses -= change;\n            }\n            let avgGain = gains \/ per;\n            let avgLoss = losses \/ per;\n            for(let i=0; i<per; i++) r.push(50); \n            let rs = avgGain \/ avgLoss;\n            r.push(avgLoss === 0 ? 100 : 100 - (100 \/ (1 + rs)));\n            \/\/ Wilder's Smoothing\n            for (let i = per + 1; i < p.length; i++) {\n                let change = p[i] - p[i - 1];\n                let g = change > 0 ? change : 0;\n                let l = change < 0 ? -change : 0;\n                avgGain = ((avgGain * (per - 1)) + g) \/ per; \/\/ Fixed: removed let\n                avgLoss = ((avgLoss * (per - 1)) + l) \/ per; \/\/ Fixed: removed let\n                rs = avgGain \/ avgLoss;\n                r.push(avgLoss === 0 ? 100 : 100 - (100 \/ (1 + rs)));\n            }\n            return r;\n        }\n\n        \/\/ --- NUEVA FUNCI\u00d3N PARA GESTIONAR DECIMALES ---\n        function getPrecision(price, symbol) {\n            if(!symbol) return 2;\n            \n            \/\/ Check Forex\n            if(window.ASSET_GROUPS['FOREX'].includes(symbol)) {\n                \/\/ JPY pairs usually have 2-3 decimals, others 5\n                if(symbol.includes('JPY')) return 3;\n                return 5;\n            }\n            \n            \/\/ Check Crypto\n            if(window.ASSET_GROUPS['CRYPTO'].includes(symbol) || symbol === 'PAXGUSDT') {\n                 if (price < 0.0001) return 8; \/\/ Shiba, Pepe etc\n                 if (price < 1) return 6;      \/\/ ADA, XRP\n                 if (price < 10) return 4;     \/\/ DOT, LINK\n                 return 2;                     \/\/ BTC, ETH\n            }\n\n            \/\/ Funds usually 2 decimals\n            return 2;\n        }\n\n        function calcMACD(p,f,s,sig){let ef=calcEMA(p,f),es=calcEMA(p,s),m=[],sg=[];for(let i=0;i<p.length;i++)m.push(ef[i]-es[i]);sg=calcEMA(m,sig);return{macd:m,signal:sg};}\n\n        function startLiveTicker(s) { \n            if(priceSocket) priceSocket.close();\n            if(window.simInterval) clearInterval(window.simInterval); \n            \n            \/\/ LOGICA TICKER: BINANCE vs TWELVE DATA (WSS)\n            if (window.ASSET_GROUPS['CRYPTO'].includes(s) || s === 'PAXGUSDT') {\n                try {\n                    priceSocket=new WebSocket(`wss:\/\/stream.binance.com:9443\/ws\/${s.toLowerCase()}@trade`); \n                    priceSocket.onmessage=e=>{ \n                        currentPrice=parseFloat(JSON.parse(e.data).p); \n                        currentPriceSymbol = s; \/\/ ACTUALIZAR SIMBOLO DE PRECIO ACTUAL\n                        let d = getPrecision(currentPrice, s); \n                        document.getElementById('cw-display-price').innerText=`$${currentPrice.toFixed(d)}`; \n                        calculateResults(); \n                    };\n                } catch(e) { console.log('Binance WS Error', e); }\n            } else {\n                try {\n                    priceSocket = new WebSocket(`wss:\/\/ws.twelvedata.com\/v1\/quotes?apikey=${TD_API_KEY}`);\n                    priceSocket.onopen = () => {\n                        const subscribeMsg = { \"action\": \"subscribe\", \"params\": { \"symbols\": s } };\n                        priceSocket.send(JSON.stringify(subscribeMsg));\n                    };\n                    priceSocket.onmessage = e => {\n                        const data = JSON.parse(e.data);\n                        if (data.event === 'price') {\n                            currentPrice = parseFloat(data.price);\n                            currentPriceSymbol = s; \/\/ ACTUALIZAR SIMBOLO DE PRECIO ACTUAL\n                            let d = getPrecision(currentPrice, s);\n                            document.getElementById('cw-display-price').innerText = `$${currentPrice.toFixed(d)}`;\n                            calculateResults();\n                        } else if(data.status === 'error') {\n                            console.log('TD WS Error:', data.message);\n                            \/\/ Fallback visual si falla el socket (ej. clave demo limitada)\n                            let d = getPrecision(currentPrice, s);\n                            document.getElementById('cw-display-price').innerText = `(REST) $${currentPrice.toFixed(d)}`;\n                        }\n                    };\n                    priceSocket.onerror = (err) => console.log('TD WS Connection Error', err);\n                } catch(e) { console.log('TD WS Exception', e); }\n            }\n        }\n\n        \/\/ PLUGIN MARCA DE AGUA\n        const watermarkPlugin = {\n            id: 'watermark',\n            beforeDraw: (chart) => {\n                const ctx = chart.ctx;\n                const width = chart.width;\n                const height = chart.height;\n                ctx.save();\n                ctx.globalCompositeOperation = 'destination-over';\n                ctx.fillStyle = 'rgba(255, 255, 255, 0.04)'; \/\/ Muy sutil\n                ctx.font = 'bold 30px Arial';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'middle';\n                ctx.fillText('BULL TRADING BOT', width \/ 2, height \/ 2);\n                ctx.restore();\n            }\n        };\n\n        function renderChart(l,d,ef,es,fl,sl){ \n            const ctx=document.getElementById('cryptoChart').getContext('2d'); if(myChart)myChart.destroy();\n            const labels = l.map(ts => { const dt = new Date(ts); return dt.getDate()+'\/'+(dt.getMonth()+1)+' '+dt.getHours()+':'+dt.getMinutes(); });\n            myChart=new Chart(ctx,{\n                type:'line',\n                data:{\n                    labels:labels,\n                    datasets:[\n                        {label:'Precio',data:d,borderColor:'#fff',borderWidth:2,pointRadius:0,pointHoverRadius:4,tension:0.1,order:1},\n                        {label:fl,data:ef,borderColor:'#00bcd4',borderWidth:1.5,pointRadius:0,borderDash:[5,5],order:2},\n                        {label:sl,data:es,borderColor:'#ff5252',borderWidth:1.5,pointRadius:0,order:3}\n                    ]\n                },\n                options:{\n                    responsive:true, maintainAspectRatio:false,\n                    interaction:{mode:'index',intersect:false},\n                    plugins:{\n                        legend:{labels:{color:'#aaa',font:{size:10}}},\n                        tooltip:{\n                            backgroundColor:'rgba(20,20,30,0.9)',titleColor:'#fff',bodyColor:'#ccc',borderColor:'#444',borderWidth:1,padding:10,displayColors:true,\n                            callbacks:{title:c=>c[0].label}\n                        }\n                    },\n                    scales:{x:{display:false},y:{grid:{color:'#333'},ticks:{color:'#666'},position:'right'}}\n                },\n                plugins: [watermarkPlugin] \/\/ ACTIVAMOS LA MARCA DE AGUA\n            }); \n        }\n\n        \/\/ --- CHANGE ASSET GROUP MODIFIED ---\n        function changeAssetGroup(preventUpdate = false) { \n            const groupSelect = document.getElementById('cw-asset-group');\n            currentGroup = groupSelect.value;\n            const coinSelect = document.getElementById('cw-coin');\n            coinSelect.innerHTML = ''; \n\n            const assets = window.ASSET_GROUPS[currentGroup];\n            assets.forEach(asset => {\n                const opt = document.createElement('option');\n                opt.value = asset;\n                opt.innerText = asset;\n                coinSelect.appendChild(opt);\n            });\n            if(!preventUpdate) updateApp(); \n        }\n\n        async function updateApp(silent = false) {\n            const symbol = document.getElementById('cw-coin').value;\n            const interval = document.getElementById('cw-interval').value;\n            \n            try {\n                let closes = [], times = [];\n                const limit = 500; \n\n                if (window.ASSET_GROUPS['CRYPTO'].includes(symbol) || symbol === 'PAXGUSDT') {\n                    const res = await fetch(`https:\/\/api.binance.com\/api\/v3\/klines?symbol=${symbol}&interval=${interval}&limit=${limit}`);\n                    const data = await res.json();\n                    closes = data.map(d => parseFloat(d[4]));\n                    times = data.map(d => d[0]);\n                } else {\n                    let tdInterval = '1h';\n                    if(interval === '1m') tdInterval = '1min';\n                    if(interval === '5m') tdInterval = '5min';\n                    if(interval === '15m') tdInterval = '15min';\n                    if(interval === '1h') tdInterval = '1h'; \n                    if(interval === '4h') tdInterval = '4h'; \n                    \n                    const url = `https:\/\/api.twelvedata.com\/time_series?symbol=${symbol}&interval=${tdInterval}&apikey=${TD_API_KEY}&outputsize=${limit}`;\n                    const res = await fetch(url);\n                    const data = await res.json();\n                    \n                    if(data.status === 'error' || !data.values) {\n                        console.log(\"TD Error:\", data.message);\n                        return;\n                    }\n                    const values = data.values.reverse();\n                    times = values.map(v => new Date(v.datetime).getTime());\n                    closes = values.map(v => parseFloat(v.close));\n                }\n\n                \/\/ --- FIX: RACE CONDITION CHECK ---\n                if(document.getElementById('cw-coin').value !== symbol) return;\n\n                if(closes.length === 0) return;\n\n                currentPrice = closes[closes.length-1];\n                currentPriceSymbol = symbol; \/\/ ACTUALIZAR SIMBOLO AL CARGAR REST\n                let d = getPrecision(currentPrice, symbol); \n                \n                let fastEma, slowEma, fastLbl, slowLbl;\n                const ema7=calcEMA(closes,7), ema9=calcEMA(closes,9), ema21=calcEMA(closes,21), ema50=calcEMA(closes,50);\n                \n                if(interval==='1m'){ fastEma=ema7; slowEma=ema21; fastLbl=\"EMA 7\"; slowLbl=\"EMA 21\"; }\n                else if(interval==='5m'){ fastEma=ema9; slowEma=ema21; fastLbl=\"EMA 9\"; slowLbl=\"EMA 21\"; }\n                else { fastEma=ema21; slowEma=ema50; fastLbl=\"EMA 21\"; slowLbl=\"EMA 50\"; }\n\n                const rsi = calcRSI(closes, 14);\n                const macdData = calcMACD(closes, 12, 26, 9);\n\n                document.getElementById('lbl-ema-fast').innerText=fastLbl; \n                document.getElementById('val-ema-fast').innerText=fastEma[fastEma.length-1].toFixed(d);\n                document.getElementById('lbl-ema-slow').innerText=slowLbl; \n                document.getElementById('val-ema-slow').innerText=slowEma[slowEma.length-1].toFixed(d);\n                \n                const conv = document.getElementById('val-conv');\n                if(fastEma[fastEma.length-1]>slowEma[slowEma.length-1]){conv.innerText=\"ALCISTA\";conv.style.color=\"#4caf50\";}else{conv.innerText=\"BAJISTA\";conv.style.color=\"#ff5252\";}\n                document.getElementById('val-rsi').innerText=rsi[rsi.length-1].toFixed(1);\n                document.getElementById('val-macd').innerText=macdData.macd[macdData.macd.length-1].toFixed(4);\n\n                const trendEl = document.getElementById('cw-display-trend');\n                const priceEl = document.getElementById('cw-display-price');\n                const trendElC = trendEl.className = \"cw-trend\"; \n\n                let fVal = fastEma[fastEma.length-1];\n                let sVal = slowEma[slowEma.length-1];\n                let rVal = rsi[rsi.length-1];\n\n                \/\/ NUEVA LOGICA: ESTADO DE TENDENCIA (CONFIRMADO\/ESPERANDO)\n                if(fVal > sVal) {\n                    priceEl.style.color = \"#4caf50\"; \n                    if(rVal > 55) { \/\/ Confirmacion RSI > 55\n                        trendEl.innerText = \"ALCISTA (CONFIRMADO)\";\n                        trendEl.style.color = \"#4caf50\";\n                        trendEl.classList.add('trend-bull'); \n                    } else {\n                        trendEl.innerText = \"ALCISTA (ESPERANDO)\";\n                        trendEl.style.color = \"#a5d6a7\"; \/\/ Verde mas claro\n                        trendEl.classList.add('trend-bull');\n                    }\n                } else if (fVal < sVal) {\n                    priceEl.style.color = \"#ff5252\"; \n                    if(rVal < 45) { \/\/ Confirmacion RSI < 45\n                        trendEl.innerText = \"BAJISTA (CONFIRMADO)\";\n                        trendEl.style.color = \"#ff5252\";\n                        trendEl.classList.add('trend-bear');\n                    } else {\n                        trendEl.innerText = \"BAJISTA (ESPERANDO)\";\n                        trendEl.style.color = \"#ef9a9a\"; \/\/ Rojo mas claro\n                        trendEl.classList.add('trend-bear');\n                    }\n                } else {\n                    priceEl.style.color = \"#ffffff\"; \n                    trendEl.innerText = \"NEUTRAL (LATERAL)\";\n                    trendEl.style.color = \"#ffffff\";\n                    trendEl.classList.add('trend-neutral');\n                }\n\n                \/\/ FIX: FORZAR ACTUALIZACI\u00d3N VISUAL INMEDIATA CON DATOS REST (FALLBACK SI WS TARDA)\n                document.getElementById('cw-display-price').innerText = `$${currentPrice.toFixed(d)}`;\n\n                \/\/ Solo redibujar si no es actualizaci\u00f3n silenciosa o si los datos han cambiado\n                renderChart(times, closes, fastEma, slowEma, fastLbl, slowLbl);\n                \n                if(!silent) startLiveTicker(symbol);\n                calculateResults(); \n\n            } catch(e){ console.error(e); }\n        }\n\n        \/\/ --- NUEVA FUNCI\u00d3N PARA VER EL ACTIVO DESDE LA TABLA ---\n        function viewOnChart(symbol) {\n            \/\/ Determinar grupo\n            let foundGroup = null;\n            for (const [grp, list] of Object.entries(window.ASSET_GROUPS)) {\n                if (list.includes(symbol)) { foundGroup = grp; break; }\n            }\n            if(!foundGroup) foundGroup = 'CRYPTO'; \/\/ Default fallback\n\n            \/\/ Actualizar selectores\n            document.getElementById('cw-asset-group').value = foundGroup;\n            changeAssetGroup(true); \/\/ Modified call: prevent intermediate update\n            document.getElementById('cw-coin').value = symbol;\n            \n            \/\/ Forzar actualizaci\u00f3n y scroll\n            updateApp();\n            document.querySelector('.chart-box').scrollIntoView({ behavior: 'smooth' });\n\n            \/\/ NUEVO: FORZAR JUEGO A ESTE ACTIVO\n            window.ccGame.forceView(symbol);\n\n            \/\/ NUEVO: ACTUALIZAR M\u00d3DULO DE DETALLES\n            currentDetailSymbol = symbol; \/\/ Guardar referencia para auto-update\n            updateTradeDetails(symbol);\n        }\n\n        function updateTradeDetails(symbol) {\n            const module = document.getElementById('trade-detail-module');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            \n            \/\/ Buscar la orden m\u00e1s reciente para este s\u00edmbolo\n            const order = orders.find(o => o.symbol === symbol);\n            \n            if (order) {\n                module.style.display = 'block';\n                \n                \/\/ Formatear Fecha\n                const dtStart = new Date(order.timestamp).toLocaleString();\n                \n                \/\/ Duraci\u00f3n: Si es OPEN, es (Ahora - Inicio). Si no, \"Finalizado\" (o N\/D)\n                let duration = \"---\";\n                let endTime = \"---\";\n                if(order.status === 'OPEN') {\n                    const diffMs = Date.now() - order.timestamp;\n                    const diffMins = Math.floor(diffMs \/ 60000);\n                    const hrs = Math.floor(diffMins \/ 60);\n                    const mins = diffMins % 60;\n                    duration = `${hrs}h ${mins}m (En curso)`;\n                    endTime = \"En curso \u23f3\";\n                } else {\n                    duration = \"Finalizado\"; \n                    endTime = \"No registrado\"; \/\/ Como no guardamos fecha cierre, ponemos esto\n                }\n\n                \/\/ ROI y PNL\n                let totalPnL = (order.realized || 0) + (order.floatingUsd || 0);\n                let roi = (totalPnL \/ order.amount) * 100;\n                \n                let resText = \"NEUTRAL\";\n                let resClass = \"\";\n                if(totalPnL > 0) { resText = \"GANANCIA \ud83c\udfc6\"; resClass = \"td-win\"; }\n                else if(totalPnL < 0) { resText = \"P\u00c9RDIDA \ud83d\udc80\"; resClass = \"td-loss\"; }\n\n                \/\/ Actualizar DOM\n                document.getElementById('td-pair').innerHTML = `<span style=\"color:#00bcd4\">${order.symbol}<\/span> <small>(${order.status})<\/small>`;\n                document.getElementById('td-dir').innerText = order.direction;\n                document.getElementById('td-dir').style.color = order.direction === 'LONG' ? '#66bb6a' : '#ff5252';\n                \n                document.getElementById('td-start').innerText = dtStart;\n                document.getElementById('td-end').innerText = endTime;\n                document.getElementById('td-dur').innerText = duration;\n                \n                document.getElementById('td-roi').innerText = roi.toFixed(2) + \"%\";\n                document.getElementById('td-roi').className = \"td-val \" + resClass;\n                \n                document.getElementById('td-pnl').innerText = `$${totalPnL.toFixed(2)}`;\n                document.getElementById('td-pnl').className = \"td-val \" + resClass;\n                \n                document.getElementById('td-res').innerText = resText;\n                document.getElementById('td-res').className = \"td-val \" + resClass;\n\n            } else {\n                module.style.display = 'none';\n            }\n        }\n\n        \/\/ --- INTERFACE LOGIC ---\n        function updateLeverageDisplay(val) {\n            document.getElementById('lev-val').innerText = val + 'x';\n            calculateResults();\n        }\n\n        function toggleTPMode(mode) {\n            if(mode === 'single') { document.getElementById('tp-single-box').style.display='block'; document.getElementById('tp-ladder-box').style.display='none'; } \n            else { document.getElementById('tp-single-box').style.display='none'; document.getElementById('tp-ladder-box').style.display='block'; }\n            calculateResults();\n        }\n\n        function toggleMode(){ \n            const m=document.getElementById('calc-mode').value; \n            const s=document.getElementById('leverage-slider'); \n            if(m==='SPOT'){s.value=1; s.disabled=true; document.getElementById('lev-val').innerText='1x'; setDirection('LONG');}\n            else{s.disabled=false;} \n            calculateResults();\n        }\n\n        function setDirection(d){ \n            if(document.getElementById('calc-mode').value==='SPOT'&&d==='SHORT')return; \n            if(document.getElementById('calc-mode').value==='SPOT'&&d==='AUTO')return; \n            \n            currentDirection=d; \n            document.getElementById('btn-long').className=d==='LONG'?'btn-direction active-long':'btn-direction'; \n            document.getElementById('btn-short').className=d==='SHORT'?'btn-direction active-short':'btn-direction'; \n            document.getElementById('btn-auto').className=d==='AUTO'?'btn-direction active-auto':'btn-direction'; \n            calculateResults();\n        }\n\n        function calculateResults() {\n            if(!currentPrice) return;\n            const amt = parseFloat(document.getElementById('bot-mio').value) || 0;\n            const margin = parseFloat(document.getElementById('leverage-slider').value) || 1;\n            \n            let tpPercent = 0;\n            const isMulti = document.querySelector('input[name=\"tp-mode\"]:checked').value === 'multi';\n            if(isMulti) {\n                tpPercent = parseFloat(document.getElementById('tp4-pct').value) || 0; \n            } else {\n                tpPercent = parseFloat(document.getElementById('tp-single-val').value) || 0;\n            }\n\n            const slPercent = parseFloat(document.getElementById('sl-slider').value) || 0;\n\n            let tpP, slP;\n            if (currentDirection === 'LONG') {\n                tpP = currentPrice * (1 + (tpPercent \/ 100)); \n                slP = currentPrice * (1 - (slPercent \/ 100));\n            } else {\n                tpP = currentPrice * (1 - (tpPercent \/ 100)); \n                slP = currentPrice * (1 + (slPercent \/ 100));\n            }\n            \n            const estimatedProfit = amt * (tpPercent \/ 100) * margin;\n            const estimatedLoss = amt * (slPercent \/ 100) * margin;\n\n            \/\/ UPDATED PRECISION\n            let symbol = document.getElementById('cw-coin').value;\n            let d = getPrecision(currentPrice, symbol);\n            \n            document.getElementById('res-tp-price').innerText = `$${tpP.toFixed(d)}`;\n            document.getElementById('res-sl-price').innerText = `$${slP.toFixed(d)}`;\n            document.getElementById('res-profit').innerText = `+$${estimatedProfit.toFixed(2)}`;\n            document.getElementById('res-loss').innerText = `-$${estimatedLoss.toFixed(2)}`;\n        }\n\n        function applyStrategyPreset() {\n            const strategy = document.getElementById('bot-preset').value;\n            if(strategy === 'SCALPER') { setTPs(0.15, 0.25, 0.35, 0.5); document.getElementById('cw-interval').value = '1m'; }\n            else if(strategy === 'FAST') { setTPs(0.25, 0.45, 0.65, 0.87); document.getElementById('cw-interval').value = '5m'; }\n            else if(strategy === 'SWING_SHORT') { setTPs(0.5, 0.9, 1.4, 2.0); document.getElementById('cw-interval').value = '15m'; }\n            else if(strategy === 'ROCKIE') { setTPs(1.0, 1.5, 2.0, 3.0); document.getElementById('cw-interval').value = '1h'; }\n            else if(strategy === 'HOLDER') { setTPs(4.0, 6.0, 8.0, 10.0); document.getElementById('cw-interval').value = '4h'; }\n            updateApp(); \n        }\n        function setTPs(t1, t2, t3, t4) {\n            document.getElementById('tp1-pct').value = t1; document.getElementById('tp2-pct').value = t2;\n            document.getElementById('tp3-pct').value = t3; document.getElementById('tp4-pct').value = t4;\n        }\n\n        function toggleBotExecution() {\n            const btn = document.getElementById('btn-bot-toggle');\n            const statusEl = document.getElementById('scan-status');\n            \n            if(!isBotRunning) {\n                \/\/ --- NUEVA FUNCIONALIDAD: Solicitar permisos de notificaci\u00f3n ---\n                if (\"Notification\" in window) {\n                    if (Notification.permission !== \"granted\" && Notification.permission !== \"denied\") {\n                        Notification.requestPermission();\n                    }\n                }\n                \/\/ ---------------------------------------------------------------\n                \n                const MIO = parseFloat(document.getElementById('bot-mio').value);\n                const MOA = parseFloat(document.getElementById('bot-moa').value);\n                const MAC = parseFloat(document.getElementById('bot-mac').value);\n                const leverage = parseFloat(document.getElementById('leverage-slider').value);\n                const interval = document.getElementById('cw-interval').value;\n                const trailingSlPct = parseFloat(document.getElementById('input-trailing-sl').value) || 0;\n                const trailingTpPct = parseFloat(document.getElementById('input-trailing-tp').value) || 0;\n                \n                const isMulti = document.querySelector('input[name=\"tp-mode\"]:checked').value === 'multi';\n                let tpConfig = [];\n                let maxTpDist = 0;\n                if(isMulti) {\n                    let totalVol = 0;\n                    for(let i=1; i<=4; i++) {\n                        const pct = parseFloat(document.getElementById(`tp${i}-pct`).value);\n                        const vol = parseFloat(document.getElementById(`tp${i}-vol`).value);\n                        totalVol+=vol;\n                        tpConfig.push({ pct: pct, vol: vol, filled: false, price: 0 });\n                        if(pct>maxTpDist) maxTpDist=pct;\n                    }\n                    if(totalVol!==100){alert(\"Suma TP volumen debe ser 100%\"); return;}\n                } else {\n                    const pct = parseFloat(document.getElementById('tp-single-val').value);\n                    tpConfig.push({ pct: pct, vol: 100, filled: false, price: 0 });\n                    maxTpDist = pct;\n                }\n\n                const slPct = parseFloat(document.getElementById('sl-slider').value);\n\n                botConfig = { MIO, MOA, MAC, leverage, interval, slPct, tpConfig, maxTpDist, direction: currentDirection, trailingSlPct, trailingTpPct };\n\n                isBotRunning = true;\n                btn.innerText = \"\ud83d\uded1 DETENER BOT\";\n                btn.classList.add('scanning');\n                btn.style.background = \"#ff5252\";\n                statusEl.innerText = \"\ud83d\udce1 ESCANEANDO MERCADO...\";\n                statusEl.style.color = \"#4caf50\";\n\n            } else {\n                isBotRunning = false;\n                btn.innerText = \"\ud83e\udd16 LANZAR BOT\";\n                btn.classList.remove('scanning');\n                btn.style.background = \"linear-gradient(45deg, #6c5ce7, #a29bfe)\";\n                statusEl.innerText = \"\";\n            }\n        }\n\n        async function scanMarketOpportunity() {\n            if(!isBotRunning) return;\n\n            const activeSymbols = new Set(demoOrders.filter(o => o.status === 'OPEN').map(o => o.symbol));\n            if(activeSymbols.size >= botConfig.MAC) {\n                document.getElementById('scan-status').innerText = `MAC Lleno. Esperando cierres...`;\n                return;\n            }\n\n            \/\/ MODIFICACI\u00d3N: Usar la lista del grupo actual, no forzar Crypto\n            const assetList = window.ASSET_GROUPS[currentGroup];\n            if (!assetList || assetList.length === 0) return;\n            \n            \/\/ Aseguramos que el \u00edndice no se salga de rango si cambiamos de grupo\n            scanIndex = scanIndex % assetList.length;\n            const coinToScan = assetList[scanIndex];\n            scanIndex = (scanIndex + 1) % assetList.length;\n            \n            \/\/ CAMBIO: Prevenir Duplicados (Solo 1 trade por activo)\n            const ordersForThisCoin = demoOrders.filter(o => o.symbol === coinToScan && o.status === 'OPEN').length;\n            if(ordersForThisCoin > 0) return; \/\/ Si ya hay una orden abierta para este par, saltamos\n\n            try {\n                let closes = [];\n                let price = 0;\n                const limit = 500; \n\n                \/\/ L\u00f3gica de Obtenci\u00f3n de Datos para Escaneo (Binance vs TD)\n                if (window.ASSET_GROUPS['CRYPTO'].includes(coinToScan) || coinToScan === 'PAXGUSDT') {\n                    const res = await fetch(`https:\/\/api.binance.com\/api\/v3\/klines?symbol=${coinToScan}&interval=${botConfig.interval}&limit=${limit}`);\n                    const data = await res.json();\n                    closes = data.map(d => parseFloat(d[4]));\n                } else {\n                    \/\/ Twelve Data Fetch for Scanner\n                    let tdInterval = '1h';\n                    if(botConfig.interval === '1m') tdInterval = '1min';\n                    if(botConfig.interval === '5m') tdInterval = '5min';\n                    if(botConfig.interval === '15m') tdInterval = '15min';\n                    \n                    const url = `https:\/\/api.twelvedata.com\/time_series?symbol=${coinToScan}&interval=${tdInterval}&apikey=${TD_API_KEY}&outputsize=${limit}`;\n                    const res = await fetch(url);\n                    const data = await res.json();\n                    \n                    if(data.status === 'error' || !data.values) {\n                        console.log(\"TD Scanner Error:\", data.message);\n                        return; \/\/ Skip this asset if error\n                    }\n                    const values = data.values.reverse();\n                    closes = values.map(v => parseFloat(v.close));\n                }\n\n                if (closes.length === 0) return;\n                price = closes[closes.length-1];\n\n                \/\/ Calculo indicadores rapido\n                let fastEma, slowEma;\n                const ema7=calcEMA(closes,7), ema9=calcEMA(closes,9), ema21=calcEMA(closes,21), ema50=calcEMA(closes,50);\n                const rsi = calcRSI(closes, 14);\n                \n                if(botConfig.interval==='1m'){ fastEma=ema7; slowEma=ema21; }\n                else if(botConfig.interval==='5m'){ fastEma=ema9; slowEma=ema21; }\n                else { fastEma=ema21; slowEma=ema50; }\n\n                const d = { emaFast: fastEma[fastEma.length-1], emaSlow: slowEma[slowEma.length-1], rsi: rsi[rsi.length-1] };\n\n                \/\/ LOGICA AUTO: Determinaci\u00f3n Din\u00e1mica de Direcci\u00f3n\n                let executionDirection = botConfig.direction;\n                if(executionDirection === 'AUTO') {\n                    if(d.emaFast > d.emaSlow) executionDirection = 'LONG';\n                    else if(d.emaFast < d.emaSlow) executionDirection = 'SHORT';\n                    else return; \/\/ Neutral, no operamos\n                }\n\n                let signal = 0; \n                if(executionDirection === 'LONG') {\n                    if(d.emaFast > d.emaSlow && d.rsi > 45 && d.rsi < 70) signal = 1;\n                } else if(executionDirection === 'SHORT') {\n                    if(d.emaFast < d.emaSlow && d.rsi < 55 && d.rsi > 30) signal = -1;\n                }\n\n                if(signal !== 0) {\n                    let slPrice = 0;\n                    let myTps = JSON.parse(JSON.stringify(botConfig.tpConfig));\n                    \n                    if(executionDirection === 'LONG') {\n                        slPrice = price * (1 - botConfig.slPct\/100);\n                        myTps.forEach(tp => tp.price = price * (1 + tp.pct\/100));\n                    } else {\n                        slPrice = price * (1 + botConfig.slPct\/100);\n                        myTps.forEach(tp => tp.price = price * (1 - tp.pct\/100));\n                    }\n\n                    let maxTpP = myTps[myTps.length-1].price;\n\n                    const newOrder = {\n                        id: Date.now(), timestamp: Date.now(),\n                        symbol: coinToScan, direction: executionDirection,\n                        entry: price, amount: botConfig.MIO, leverage: botConfig.leverage,\n                        tps: myTps, sl: slPrice, maxTpPrice: maxTpP,\n                        status: 'OPEN', pnlUsd: 0, pnlPercent: 0,\n                        markPrice: price,\n                        highestPrice: price, \n                        lowestPrice: price,\n                        trailingSl: botConfig.trailingSlPct,\n                        trailingTp: botConfig.trailingTpPct,\n                        secured: 0, \n                        realized: 0, \n                        locked: 0,    \n                        floatingUsd: 0,\n                        floatingPct: 0\n                    };\n\n                    demoOrders.unshift(newOrder);\n                    localStorage.setItem('bullBotAlgorithmic_orders', JSON.stringify(demoOrders));\n                    renderBotTable();\n                    processDailyStats(demoOrders);\n                    \n                    document.getElementById('scan-status').innerText = `\u00a1ENTRADA EN ${coinToScan}!`;\n                    document.getElementById('scan-status').style.color = \"#ffff00\";\n\n                    \/\/ --- NUEVA FUNCIONALIDAD: Lanzar Notificaci\u00f3n Nativa ---\n                    if (\"Notification\" in window && Notification.permission === \"granted\") {\n                        try {\n                            new Notification(\"\ud83d\ude80 \u00a1Nueva Se\u00f1al Ejecutada!\", {\n                                body: `El bot acaba de entrar en ${executionDirection} para el par ${coinToScan} a un precio de $${price.toFixed(getPrecision(price, coinToScan))}.`\n                            });\n                        } catch(notifErr) { console.log(\"Notificaci\u00f3n fallida\", notifErr); }\n                    }\n                    \/\/ -------------------------------------------------------\n                }\n\n            } catch(e) { console.log(\"Error scan\", e); }\n        }\n\n        async function refreshOpenOrders() {\n            if(demoOrders.length === 0) return;\n            \n            \/\/ Optimizacion: Obtener el simbolo activo actual\n            const activeSymbol = document.getElementById('cw-coin').value;\n\n            for (let order of demoOrders) {\n                if(order.status !== 'OPEN') continue;\n\n                \/\/ CAMBIO: L\u00f3gica de actualizaci\u00f3n de precio Prioritaria\n                let updatedPrice = null;\n\n                \/\/ ESTRATEGIA 1: Usar WebSocket Activo (M\u00e1s r\u00e1pido, sin bloqueos CORS\/Limites)\n                \/\/ BLINDAJE: Solo si el s\u00edmbolo del gr\u00e1fico es el de la orden Y el precio global actual corresponde a ese s\u00edmbolo.\n                if (order.symbol === activeSymbol && currentPrice > 0 && currentPriceSymbol === activeSymbol) {\n                    updatedPrice = currentPrice;\n                } \n                \/\/ ESTRATEGIA 2: Fetch (API REST) para \u00f3rdenes en segundo plano (de otros activos)\n                else {\n                    if (window.ASSET_GROUPS['CRYPTO'].includes(order.symbol) || order.symbol === 'PAXGUSDT') {\n                        try {\n                            const res = await fetch(`https:\/\/api.binance.com\/api\/v3\/ticker\/price?symbol=${order.symbol}`);\n                            const d = await res.json();\n                            updatedPrice = parseFloat(d.price);\n                        } catch(e) {}\n                    } else {\n                        \/\/ L\u00f3gica para actualizar Forex\/Fondos usando TD\n                        try {\n                            const url = `https:\/\/api.twelvedata.com\/price?symbol=${order.symbol}&apikey=${TD_API_KEY}`;\n                            const res = await fetch(url);\n                            const d = await res.json();\n                            if(d.price) updatedPrice = parseFloat(d.price);\n                        } catch(e) {}\n                    }\n                }\n\n                if (updatedPrice) {\n                    const now = updatedPrice;\n                    order.markPrice = now; \n\n                    \/\/ --- TRACKING HIGH\/LOW WATERMARK FOR TSL ---\n                    if (now > (order.highestPrice || 0)) order.highestPrice = now;\n                    if (now < (order.lowestPrice || Infinity)) order.lowestPrice = now;\n\n                    \/\/ --- LOGICA AVANZADA DE TRAILING STOP LOSS (TSL) ---\n                    \/\/ MODIFICACI\u00d3N: Solo activar si TP1 ya fue alcanzado (Dormido hasta TP1)\n                    if (order.trailingSl > 0 && order.tps[0].filled) {\n                        let dynamicSL = order.sl;\n                        if (order.direction === 'LONG') {\n                            \/\/ SL persigue al precio m\u00e1s alto\n                            let potentialSL = order.highestPrice * (1 - order.trailingSl \/ 100);\n                            if (potentialSL > order.sl) {\n                                order.sl = potentialSL;\n                                order.slLabel = \"TSL \ud83d\udcc8\";\n                            }\n                        } else {\n                            \/\/ SL persigue al precio m\u00e1s bajo\n                            let potentialSL = order.lowestPrice * (1 + order.trailingSl \/ 100);\n                            if (potentialSL < order.sl) {\n                                order.sl = potentialSL;\n                                order.slLabel = \"TSL \ud83d\udcc9\";\n                            }\n                        }\n                    }\n\n                    let calcPrice = now;\n\n                    \/\/ EJECUCI\u00d3N DE STOP LOSS CON L\u00d3GICA DE CIERRE EXACTO\n                    if((order.direction==='LONG' && now<=order.sl) || (order.direction==='SHORT' && now>=order.sl)) {\n                        let isProfitableSL = false;\n                        if(order.direction === 'LONG' && order.sl >= order.entry) isProfitableSL = true;\n                        if(order.direction === 'SHORT' && order.sl <= order.entry) isProfitableSL = true;\n\n                        order.status = isProfitableSL ? \"TRAIL STOP \ud83d\udee1\ufe0f\" : \"STOP LOSS \ud83d\uded1\";\n                        calcPrice = order.sl; \n                    }\n\n                    \/\/ --- LOGICA DE TP Y TRAILING STOP (ESCALERA) ---\n                    let allFilled = true;\n                    let highestFilledIndex = -1;\n                    \n                    order.tps.forEach((tp, idx) => {\n                        \/\/ 1. Detecci\u00f3n inicial del TP\n                        if (!tp.filled) {\n                            let hitTP = (order.direction === 'LONG' && now >= tp.price) || (order.direction === 'SHORT' && now <= tp.price);\n                            \n                            if (hitTP) {\n                                \/\/ L\u00d3GICA H\u00cdBRIDA: TP1 es Fijo + Break Even\n                                if (idx === 0) {\n                                    tp.filled = true; \/\/ Cierre inmediato\n                                    \n                                    \/\/ Mover SL a Break Even (solo si no es mejor ya)\n                                    if (order.direction === 'LONG') {\n                                        if (order.sl < order.entry) { \n                                            order.sl = order.entry; \n                                            order.slLabel = \"B.E. \ud83d\udee1\ufe0f\";\n                                        }\n                                    } else {\n                                        if (order.sl > order.entry) { \n                                            order.sl = order.entry; \n                                            order.slLabel = \"B.E. \ud83d\udee1\ufe0f\";\n                                        } \n                                    } \n                                } \n                                \/\/ TP2, TP3, TP4: L\u00f3gica normal o Trailing\n                                else {\n                                    if (order.trailingTp === 0) {\n                                        \/\/ Sin TTP: Cierre inmediato\n                                        tp.filled = true;\n                                    } else if (!tp.triggered) {\n                                        \/\/ Con TTP: Activar vigilancia (Trigger)\n                                        tp.triggered = true;\n                                        tp.peakPrice = now; \n                                    }\n                                }\n                            }\n                        }\n\n                        \/\/ 2. L\u00f3gica de Persecuci\u00f3n (Trailing Take Profit)\n                        if (tp.triggered && !tp.filled) {\n                            \/\/ Actualizar pico m\u00e1ximo\/m\u00ednimo alcanzado\n                            if (order.direction === 'LONG' && now > tp.peakPrice) tp.peakPrice = now;\n                            if (order.direction === 'SHORT' && now < tp.peakPrice) tp.peakPrice = now;\n\n                            \/\/ Calcular precio de activaci\u00f3n de salida (Callback)\n                            let callbackDist = tp.peakPrice * (order.trailingTp \/ 100);\n                            let exitPrice = (order.direction === 'LONG') \n                                ? tp.peakPrice - callbackDist \n                                : tp.peakPrice + callbackDist;\n\n                            \/\/ Verificar si el precio retrocedi\u00f3 lo suficiente para cerrar\n                            if ((order.direction === 'LONG' && now <= exitPrice) ||\n                                (order.direction === 'SHORT' && now >= exitPrice)) {\n                                tp.filled = true; \/\/ Cierre y cobro\n                                \n                                \/\/ --- CIERRE EN CASCADA (Force Close All) ---\n                                \/\/ Si este TP cierra por retroceso, cerramos todos los siguientes al mismo precio\n                                for (let k = idx + 1; k < order.tps.length; k++) {\n                                    let nextTp = order.tps[k];\n                                    if (!nextTp.filled) {\n                                        nextTp.filled = true;\n                                        \/\/ Ajustamos el % de ganancia al precio real de salida (now)\n                                        \/\/ para no calcular ganancia irreal del TP4 original\n                                        if(order.direction === 'LONG') nextTp.pct = ((now - order.entry) \/ order.entry) * 100;\n                                        else nextTp.pct = ((order.entry - now) \/ order.entry) * 100;\n                                    }\n                                }\n                            }\n                        }\n\n                        if (!tp.filled) allFilled = false;\n                        if (tp.filled) highestFilledIndex = idx;\n                    });\n\n                    \/\/ Mover SL (Solo si TSL no lo ha movido ya m\u00e1s arriba\/abajo)\n                    \/\/ La l\u00f3gica TSL tiene prioridad si calcula un SL mejor, pero mantenemos la escalera como base\n                    if (order.trailingSl === 0) { \/\/ Solo usar escalera si no hay TSL din\u00e1mico\n                        let newSL = order.sl;\n                        let slLabel = order.slLabel;\n\n                        if(highestFilledIndex === 0) { \n                            newSL = order.entry;\n                            slLabel = \"B.E. \ud83d\udee1\ufe0f\";\n                        } else if(highestFilledIndex > 0) { \n                            newSL = order.tps[highestFilledIndex - 1].price;\n                            slLabel = \"TRAIL \ud83d\ude80\";\n                        }\n\n                        if(order.direction === 'LONG') {\n                            if(newSL > order.sl) { order.sl = newSL; order.slLabel = slLabel; }\n                        } else {\n                            if(newSL < order.sl) { order.sl = newSL; order.slLabel = slLabel; }\n                        }\n                    }\n\n                    \/\/ --- C\u00c1LCULO DE GANANCIA ASEGURADA (BOLSILLO + CANDADO) ---\n                    let realizedProfit = 0;\n                    let remainingVol = 100;\n\n                    \/\/ A. Sumar lo ya cobrado en TPs\n                    order.tps.forEach(tp => {\n                        if(tp.filled) {\n                            let gainPct = tp.pct * order.leverage; \n                            let gainUsd = (order.amount * (tp.vol\/100)) * (gainPct\/100);\n                            realizedProfit += gainUsd;\n                            remainingVol -= tp.vol;\n                        }\n                    });\n\n                    order.realized = realizedProfit; \n                    order.secured = realizedProfit; \n\n                    \/\/ --- C\u00c1LCULO DE FLOTANTE NETO ---\n                    let activeAmount = order.amount * (remainingVol \/ 100);\n                    let rawPct = 0;\n                    if(order.direction === 'LONG') rawPct = (calcPrice - order.entry) \/ order.entry;\n                    else rawPct = (order.entry - calcPrice) \/ order.entry;\n                    \n                    order.floatingPct = rawPct * order.leverage * 100;\n                    order.floatingUsd = activeAmount * (order.floatingPct \/ 100);\n\n                    if (order.status !== 'OPEN') {\n                        order.realized += order.floatingUsd;\n                        order.secured = order.realized;\n                        order.floatingUsd = 0;\n                        order.floatingPct = 0;\n                    }\n\n                    if(allFilled) order.status = \"TAKE PROFIT \ud83c\udfaf\";\n\n                } \n            }\n            localStorage.setItem('bullBotAlgorithmic_orders', JSON.stringify(demoOrders));\n            renderBotTable();\n            processDailyStats(demoOrders);\n        }\n\n        function renderBotTable() {\n            const tbody = document.getElementById('cw-orders-body');\n            tbody.innerHTML = \"\";\n            if(demoOrders.length === 0) { tbody.innerHTML = '<tr><td colspan=\"12\" class=\"cw-orders-empty\">Historial vac\u00edo.<\/td><\/tr>'; return; }\n\n            demoOrders.forEach(order => {\n                const row = document.createElement('tr');\n                \n                let progressPct = 0;\n                let barClass = 'profit';\n                let currentP = order.markPrice || order.entry;\n                \n                \/\/ CAMBIO: L\u00d3GICA DE BARRA VISUAL CORREGIDA\n                \/\/ Se calcula directamente usando (Precio Actual - Entrada) vs (MaxTP\/SL)\n                \/\/ Evitando dependencias de floatingPct que pueden causar saltos\n                if (order.status === 'OPEN') {\n                    let diff = 0;\n                    let distToMaxTP = Math.abs(order.maxTpPrice - order.entry);\n                    let distToSL = Math.abs(order.entry - order.sl);\n\n                    if (order.direction === 'LONG') diff = currentP - order.entry;\n                    else diff = order.entry - currentP;\n\n                    if (diff >= 0) {\n                        progressPct = (diff \/ distToMaxTP) * 100;\n                        if (progressPct > 100) progressPct = 100;\n                    } else {\n                        \/\/ diff es negativo\n                        progressPct = (diff \/ distToSL) * 100; \n                        if (progressPct < -100) progressPct = -100;\n                    }\n                } \n                else if (order.status.includes('TAKE PROFIT')) { progressPct = 100; } \n                else if (order.status.includes('STOP LOSS')) { progressPct = -100; }\n\n                let barWidth = Math.abs(progressPct) \/ 2; \n                if(progressPct < 0) barClass = 'loss'; \n                \n                let labelLeft = progressPct >= 0 ? (50 + barWidth) : (50 - barWidth);\n                \n                \/\/ UPDATED PRECISION\n                let d = getPrecision(order.entry, order.symbol); \n                let floatingLabel = `<div class=\"tracker-floating-price\" style=\"left:${labelLeft}%\">${currentP.toFixed(d)}<\/div>`;\n\n                const progressBarHtml = `\n                    <div class=\"tracker-wrapper\">\n                        ${floatingLabel}\n                        <div class=\"trade-tracker-container\">\n                            <div class=\"tracker-center-line\"><\/div>\n                            <div class=\"tracker-bar ${barClass}\" style=\"width:${barWidth}%;\"><\/div>\n                        <\/div>\n                    <\/div>\n                    <div class=\"tracker-labels\">\n                        <span>${order.sl ? order.sl.toFixed(d) : '-'}<\/span>\n                        <span style=\"color:#fff;\">${order.entry.toFixed(d)}<\/span>\n                        <span>${order.maxTpPrice.toFixed(d)}<\/span>\n                    <\/div>\n                `;\n\n                let floatClass = order.floatingUsd >= 0 ? 'pnl-pos' : 'pnl-neg';\n                let floatClassPct = order.floatingPct >= 0 ? 'pnl-pos' : 'pnl-neg';\n                \n                let totalVal = (order.realized || 0) + (order.floatingUsd || 0);\n                let totalClass = totalVal >= 0 ? 'pnl-pos' : 'pnl-neg';\n\n                let actionBtn = \"\";\n                if(order.status === 'OPEN') actionBtn = `<button class=\"btn-market-close\" onclick=\"closeManual(${order.id})\">CERRAR<\/button>`;\n\n                const dt = new Date(order.timestamp);\n                const dateStr = dt.toLocaleDateString() + '<br>' + dt.toLocaleTimeString();\n\n                let slText = `$${order.sl.toFixed(d)}`;\n                let slClass = 'pnl-neg';\n                if(order.slLabel) {\n                    slText = `${order.slLabel} $${order.sl.toFixed(d)}`;\n                    slClass = 'sl-secured';\n                }\n                \n                let statusExtra = \"\";\n                if (order.trailingTp > 0) {\n                      let activeTrigger = order.tps.find(t => t.triggered && !t.filled);\n                      if (activeTrigger) statusExtra = `<br><span style=\"font-size:0.7em;color:#ff9800;\">TTP ACTIVADO \u23f3<\/span>`;\n                }\n\n                const tpSlDisplay = `\n                    <span class=\"pnl-pos\">TP: $${order.tps[order.tps.length-1].price.toFixed(d)}<\/span><br>\n                    <span class=\"${slClass}\">SL: ${slText}<\/span>\n                `;\n\n                \/\/ BOTON GRAFICO A\u00d1ADIDO AQUI\n                row.innerHTML = `\n                    <td style=\"font-size:0.7em\">${dateStr}<\/td>\n                    <td style=\"font-weight:bold; color:#00bcd4;\">\n                        ${order.symbol}<br>\n                        <button class=\"btn-view-chart\" onclick=\"viewOnChart('${order.symbol}')\">GRAFICO<\/button>\n                    <\/td>\n                    <td style=\"color:${order.direction==='LONG'?'#66bb6a':'#ff5252'}\">${order.direction}<\/td>\n                    <td>$${order.entry.toFixed(d)}<\/td>\n                    <td>$${order.amount} <span style=\"color:#aaa\">x${order.leverage}<\/span><\/td>\n                    <td style=\"font-size:0.75em; line-height:1.2\">${tpSlDisplay}<\/td>\n                    <td class=\"${floatClassPct}\">${order.floatingPct ? order.floatingPct.toFixed(2) : '0.00'}%<\/td>\n                    <td class=\"${floatClass}\">$${order.floatingUsd ? order.floatingUsd.toFixed(2) : '0.00'}<\/td>\n                    <td style=\"font-weight:bold; color:#ffd700;\">$${order.secured ? order.secured.toFixed(2) : '0.00'}<\/td>\n                    <td style=\"font-weight:bold; font-size:1.1em; color:#ffffff;\">$${totalVal.toFixed(2)}<\/td>\n                    <td style=\"width:220px;\">${progressBarHtml}<\/td>\n                    <td style=\"font-size:0.8em; text-align:center;\">${order.status} ${actionBtn} ${statusExtra}<\/td>\n                `;\n                tbody.appendChild(row);\n            });\n        }\n\n        function closeManual(id) {\n            const idx = demoOrders.findIndex(o => o.id === id);\n            if(idx !== -1 && demoOrders[idx].status === 'OPEN') {\n                demoOrders[idx].status = 'MANUAL \u270b';\n                \/\/ Al cerrar manual, el flotante pasa a realizado final\n                demoOrders[idx].realized += demoOrders[idx].floatingUsd;\n                demoOrders[idx].secured = demoOrders[idx].realized;\n                demoOrders[idx].floatingUsd = 0;\n                demoOrders[idx].floatingPct = 0;\n                \n                localStorage.setItem('bullBotAlgorithmic_orders', JSON.stringify(demoOrders));\n                \/\/ Cambio: Actualizar UI Inmediatamente al cerrar\n                renderBotTable(); \n                processDailyStats(demoOrders); \n                refreshOpenOrders();\n            }\n        }\n        function clearHistory() { \n            demoOrders=[]; \n            localStorage.removeItem('bullBotAlgorithmic_orders'); \n            renderBotTable(); \n            processDailyStats([]);\n            \/\/ CAMBIO: Forzar reset del juego inmediatamente al limpiar historial\n            if(window.ccGame) window.ccGame.forceReset();\n        }\n\n        function renderDualCharts(l, w, loss, n) {\n            const sl = l.length>0?l:['Sin Datos'];\n            if(chartInstance1) chartInstance1.destroy(); if(chartInstance2) chartInstance2.destroy();\n            chartInstance1=new Chart(document.getElementById('chartWinLoss'), {type:'bar', data:{labels:sl, datasets:[{label:'Win %',data:w,backgroundColor:'#4caf50'},{label:'Loss %',data:loss,backgroundColor:'#ff5252'}]}, options:{responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{x:{display:false}, y:{grid:{color:'#333'}, ticks:{color:'#888'}}}}});\n            chartInstance2=new Chart(document.getElementById('chartDailyUsd'), {type:'bar', data:{labels:sl, datasets:[{label:'Net $',data:n,backgroundColor:n.map(v=>v>=0?'#4caf50':'#ff5252')}]}, options:{responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{x:{ticks:{color:'#888'}}, y:{grid:{color:'#333'}, ticks:{color:'#888'}}}}});\n        }\n\n        \/\/ FUNCION ACTUALIZADA: CALCULA TOTAL ASEGURADO\n        function processDailyStats(orders) {\n            let totalFloating=0; let totalRealized=0; let totalSecured=0; \/\/ <-- NUEVA VARIABLE\n            let wins=0; let closed=0; const dailyData={};\n            \n            orders.forEach(o => {\n                \/\/ Asegurar que son n\u00fameros para evitar errores de suma\n                let fUsd = parseFloat(o.floatingUsd) || 0;\n                let rUsd = parseFloat(o.realized) || 0;\n                let sUsd = parseFloat(o.secured) || 0; \/\/ <-- NUEVA CAPTURA\n                let fPct = parseFloat(o.floatingPct) || 0;\n\n                \/\/ Sumar flotantes solo de ordenes abiertas\n                if(o.status === 'OPEN') {\n                    totalFloating += fUsd;\n                } else {\n                    closed++;\n                    \/\/ Para el winrate, ver si el total realizado fue positivo\n                    if(rUsd > 0) wins++;\n                }\n                \n                \/\/ Sumar realizado de todas (incluyendo parciales de abiertas si los hubiera, o total de cerradas)\n                totalRealized += rUsd;\n                totalSecured += sUsd; \/\/ <-- SUMAR AL TOTAL ASEGURADO\n\n                const dKey=new Date(o.timestamp).toLocaleDateString();\n                if(!dailyData[dKey]) dailyData[dKey]={win:0,loss:0,net:0,ts:o.timestamp};\n                \n                \/\/ Graficas diarias basadas en resultado total (Realizado + Flotante)\n                let tradeTotal = rUsd + fUsd;\n                dailyData[dKey].net += tradeTotal;\n                \n                if(tradeTotal > 0) dailyData[dKey].win += fPct; \n                else dailyData[dKey].loss += fPct;\n            });\n\n            document.getElementById('stat-total-trades').innerText=orders.length;\n            \n            \/\/ Actualizar Stats Bar con Flotante y Realizado separado\n            document.getElementById('stat-pnl-floating').innerText=`$${totalFloating.toFixed(2)}`;\n            document.getElementById('stat-pnl-floating').style.color=totalFloating>=0?'#4caf50':'#ff5252';\n            \n            document.getElementById('stat-pnl-realized').innerText=`$${totalRealized.toFixed(2)}`;\n            document.getElementById('stat-pnl-realized').style.color=totalRealized>=0?'#4caf50':'#ff5252';\n\n            \/\/ <-- ACTUALIZAR NUEVO ELEMENTO DOM\n            document.getElementById('stat-secured').innerText=`$${totalSecured.toFixed(2)}`;\n\n            document.getElementById('stat-winrate').innerText=closed>0?(wins\/closed*100).toFixed(0)+'%':'0%';\n            \n            const sDates=Object.keys(dailyData).sort((a,b)=>dailyData[a].ts-dailyData[b].ts);\n            renderDualCharts(sDates, sDates.map(d=>dailyData[d].win), sDates.map(d=>dailyData[d].loss), sDates.map(d=>dailyData[d].net));\n        }\n\n        async function runBacktest() {\n            \/\/ Get Config from Main UI\n            const symbol = document.getElementById('cw-coin').value;\n            const interval = document.getElementById('cw-interval').value;\n            const limit = parseInt(document.getElementById('bt-candles').value);\n            const amount = parseFloat(document.getElementById('calc-amount').value);\n            const lev = parseFloat(document.getElementById('leverage-slider').value);\n            const slPct = parseFloat(document.getElementById('sl-slider').value);\n            const trailingSl = parseFloat(document.getElementById('input-trailing-sl').value) || 0;\n            const trailingTp = parseFloat(document.getElementById('input-trailing-tp').value) || 0;\n            const direction = currentDirection;\n\n            \/\/ Get TP Config\n            let tps = [];\n            const isMulti = document.querySelector('input[name=\"tp-mode\"]:checked').value === 'multi';\n            if(isMulti) {\n                for(let i=1; i<=4; i++) {\n                    tps.push({\n                        pct: parseFloat(document.getElementById(`tp${i}-pct`).value),\n                        vol: parseFloat(document.getElementById(`tp${i}-vol`).value)\n                    });\n                }\n            } else {\n                tps.push({ pct: parseFloat(document.getElementById('tp-single-val').value), vol: 100 });\n            }\n\n            const logEl = document.getElementById('bt-log');\n            const resEl = document.getElementById('bt-results');\n            const chartCont = document.getElementById('bt-chart-container');\n            const reportEl = document.getElementById('bt-analyst-report'); \n            \n            logEl.style.display = 'block'; resEl.style.display = 'grid'; chartCont.style.display = 'block'; reportEl.style.display = 'none';\n            logEl.innerHTML = `> Iniciando Backtest en ${symbol} (${interval}) - ${limit} velas...<br>`;\n\n            try {\n                let closes = [], times = [];\n                if (window.ASSET_GROUPS['CRYPTO'].includes(symbol) || symbol === 'PAXGUSDT') {\n                    const res = await fetch(`https:\/\/api.binance.com\/api\/v3\/klines?symbol=${symbol}&interval=${interval}&limit=${limit}`);\n                    const data = await res.json();\n                    closes = data.map(d => parseFloat(d[4]));\n                    times = data.map(d => d[0]);\n                } else {\n                    let tdInterval = '1h';\n                    if(interval === '1m') tdInterval = '1min';\n                    if(interval === '5m') tdInterval = '5min';\n                    if(interval === '15m') tdInterval = '15min';\n                    if(interval === '4h') tdInterval = '4h';\n                    \n                    const url = `https:\/\/api.twelvedata.com\/time_series?symbol=${symbol}&interval=${tdInterval}&apikey=${TD_API_KEY}&outputsize=${limit}`;\n                    const res = await fetch(url);\n                    const data = await res.json();\n                    \n                    if(data.status === 'error' || !data.values) throw new Error(\"Datos TD no disponibles en Demo para este par.\");\n                    \n                    const values = data.values.reverse();\n                    times = values.map(v => new Date(v.datetime).getTime());\n                    closes = values.map(v => parseFloat(v.close));\n                }\n                \n                const opens = closes; \n                const highs = closes;\n                const lows = closes;\n                \n                let fastEma, slowEma;\n                if(interval==='1m'){ fastEma=calcEMA(closes,7); slowEma=calcEMA(closes,21); }\n                else if(interval==='5m'){ fastEma=calcEMA(closes,9); slowEma=calcEMA(closes,21); }\n                else { fastEma=calcEMA(closes,21); slowEma=calcEMA(closes,50); }\n                const rsi = calcRSI(closes, 14);\n\n                let balance = 0; \n                let trades = 0;\n                let wins = 0;\n                let activeTrade = null;\n                let maxDrawdown = 0;\n                let peakBalance = 0;\n                \n                let equityCurve = [amount]; \n                let equityLabels = ['Inicio'];\n                let equityMeta = [{date: new Date(times[50]).toLocaleString(), price: closes[50]}];\n\n                for(let i=50; i<closes.length-1; i++) {\n                    const price = closes[i];\n                    \n                    if(activeTrade) {\n                        let low = lows[i]; \n                        let high = highs[i];\n                        \n                        let slHit = (activeTrade.dir === 'LONG' && low <= activeTrade.sl) || (activeTrade.dir === 'SHORT' && high >= activeTrade.sl);\n                        \n                        if(slHit) {\n                            let lossVal = activeTrade.amount * (Math.abs(activeTrade.entry - activeTrade.sl)\/activeTrade.entry) * lev;\n                            activeTrade.pnl -= lossVal; \n                            balance -= lossVal; \n                            logEl.innerHTML += `<span style=\"color:#ff5252\">\u2716 SL\/TrailSL Hit<\/span> PnL: ${balance.toFixed(2)}<br>`;\n                            activeTrade = null;\n                            \n                            equityCurve.push(amount + balance);\n                            equityLabels.push('Trade ' + trades);\n                            equityMeta.push({ date: new Date(times[i]).toLocaleString(), price: closes[i] });\n                            continue;\n                        }\n\n                        if(activeTrade.dir === 'LONG') {\n                            if(high > activeTrade.highest) {\n                                activeTrade.highest = high;\n                                if(trailingSl > 0) activeTrade.sl = Math.max(activeTrade.sl, high * (1 - trailingSl\/100));\n                            }\n                        } else {\n                            if(low < activeTrade.lowest) {\n                                activeTrade.lowest = low;\n                                if(trailingSl > 0) activeTrade.sl = Math.min(activeTrade.sl, low * (1 + trailingSl\/100));\n                            }\n                        }\n\n                        if(!activeTrade.tp1Filled) {\n                            let tp1Price = activeTrade.tps[0].price;\n                            if((activeTrade.dir==='LONG' && high >= tp1Price) || (activeTrade.dir==='SHORT' && low <= tp1Price)) {\n                                activeTrade.tp1Filled = true;\n                                let gain = (amount * (activeTrade.tps[0].vol\/100)) * (activeTrade.tps[0].pct * lev \/ 100);\n                                balance += gain;\n                                activeTrade.sl = activeTrade.entry; \n                                logEl.innerHTML += `<span style=\"color:#4caf50\">\u2714 TP1 Hit (BE Active)<\/span><br>`;\n                                \n                                equityCurve.push(amount + balance);\n                                equityLabels.push('TP1');\n                                equityMeta.push({ date: new Date(times[i]).toLocaleString(), price: closes[i] });\n                            }\n                        }\n                        \n                        if(trailingTp > 0 && activeTrade.tp1Filled) {\n                            let exitP = activeTrade.dir==='LONG' ? activeTrade.highest*(1-trailingTp\/100) : activeTrade.lowest*(1+trailingTp\/100);\n                            let trailHit = (activeTrade.dir==='LONG' && low <= exitP) || (activeTrade.dir==='SHORT' && high >= exitP);\n                            if(trailHit) {\n                                let remainingVol = 100 - activeTrade.tps[0].vol; \n                                let gainPct = (activeTrade.dir==='LONG' ? (exitP - activeTrade.entry)\/activeTrade.entry : (activeTrade.entry - exitP)\/activeTrade.entry) * 100 * lev;\n                                balance += (amount * (remainingVol\/100)) * (gainPct\/100);\n                                activeTrade = null;\n                                wins++;\n                                logEl.innerHTML += `<span style=\"color:#ffd700\">\u2605 Trailing Close All<\/span><br>`;\n                                \n                                equityCurve.push(amount + balance);\n                                equityLabels.push('Close All');\n                                equityMeta.push({ date: new Date(times[i]).toLocaleString(), price: closes[i] });\n                                continue;\n                            }\n                        }\n                    }\n\n                    if(!activeTrade) {\n                        let signal = 0;\n                        if(direction === 'LONG') {\n                            if(fastEma[i] > slowEma[i] && rsi[i] > 45 && rsi[i] < 70 && fastEma[i-1] <= slowEma[i-1]) signal = 1;\n                        } else {\n                            if(fastEma[i] < slowEma[i] && rsi[i] < 55 && rsi[i] > 30 && fastEma[i-1] >= slowEma[i-1]) signal = -1;\n                        }\n\n                        if(signal !== 0) {\n                            trades++;\n                            let slP = signal === 1 ? price * (1 - slPct\/100) : price * (1 + slPct\/100);\n                            let myTps = tps.map(t => ({ \n                                price: signal === 1 ? price * (1 + t.pct\/100) : price * (1 - t.pct\/100),\n                                pct: t.pct, vol: t.vol \n                            }));\n                            \n                            activeTrade = {\n                                entry: price, dir: direction, amount: amount, sl: slP, slDist: slPct*lev,\n                                tps: myTps, highest: price, lowest: price, tp1Filled: false, pnl: 0\n                            };\n                            logEl.innerHTML += `> Entrada ${direction} en ${price}<br>`;\n                        }\n                    }\n                    \n                    if(balance > peakBalance) peakBalance = balance;\n                    let dd = peakBalance - balance;\n                    if(dd > maxDrawdown) maxDrawdown = dd;\n                }\n\n                let totalROI = (balance \/ amount) * 100;\n                let ddPct = (maxDrawdown \/ amount) * 100; \n                let stars = 0;\n                let title = \"\";\n                let analysisText = \"\";\n                let recommendation = \"\";\n                let color = \"\";\n\n                if (balance > 0) {\n                    if (totalROI > 10 && ddPct < 20) {\n                        stars = 3;\n                        title = \"\u2b50\u2b50\u2b50 EXCELENTE\";\n                        color = \"#4caf50\";\n                        analysisText = `Estrategia s\u00f3lida. Has generado un retorno del <b>${totalROI.toFixed(2)}%<\/b> con un Drawdown controlado del ${ddPct.toFixed(2)}%.`;\n                        recommendation = \"Mant\u00e9n esta configuraci\u00f3n. Considera aumentar progresivamente el capital.\";\n                    } else {\n                        stars = 2;\n                        title = \"\u2b50\u2b50 BUENA (CON RIESGO)\";\n                        color = \"#ff9800\";\n                        analysisText = `La estrategia es rentable (${totalROI.toFixed(2)}%), pero el riesgo es elevado (Drawdown: ${ddPct.toFixed(2)}%).`;\n                        if (ddPct > 30) recommendation = \"\u26a0\ufe0f Alerta: Tu Drawdown es alto. Reduce el apalancamiento o ajusta el Stop Loss.\";\n                        else recommendation = \"Intenta filtrar mejor las entradas para subir ese Win Rate.\";\n                    }\n                } else {\n                    stars = 1;\n                    title = \"\u2b50 CONSIDERAR \/ PELIGRO\";\n                    color = \"#ff5252\";\n                    analysisText = `Resultado negativo. PnL: $${balance.toFixed(2)}. La estrategia no es rentable en estas condiciones.`;\n                    recommendation = \"Detente. No uses dinero real. Revisa la direcci\u00f3n de la tendencia o reduce el apalancamiento dr\u00e1sticamente.\";\n                }\n\n                reportEl.style.display = 'block';\n                reportEl.style.borderLeft = `4px solid ${color}`;\n                reportEl.innerHTML = `\n                    <h4 style=\"margin:0 0 5px 0; color:${color};\">${title}<\/h4>\n                    <p style=\"font-size:0.85rem; margin:0 0 5px 0; color:#ddd;\">${analysisText}<\/p>\n                    <p style=\"font-size:0.8rem; margin:0; color:#aaa; font-style:italic;\">\ud83d\udca1 Consejo: ${recommendation}<\/p>\n                `;\n\n                resEl.innerHTML = `\n                    <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">PnL Neto<\/div><div class=\"cw-stat-val\" style=\"color:${balance>=0?'#4caf50':'#ff5252'}\">$${balance.toFixed(2)}<\/div><\/div>\n                    <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">Trades<\/div><div class=\"cw-stat-val\">${trades}<\/div><\/div>\n                    <div class=\"cw-stat-box\"><div class=\"cw-stat-label\">Max Drawdown<\/div><div class=\"cw-stat-val\" style=\"color:#ff5252\">$${maxDrawdown.toFixed(2)}<\/div><\/div>\n                `;\n                logEl.innerHTML += `> Fin del test.`;\n                \n                const ctxBt = document.getElementById('bt-chart').getContext('2d');\n                if(btChartInstance) btChartInstance.destroy();\n                \n                btChartInstance = new Chart(ctxBt, {\n                    type: 'line',\n                    data: {\n                        labels: equityLabels,\n                        datasets: [{\n                            label: 'Curva de Equidad ($)',\n                            data: equityCurve,\n                            borderColor: '#ff9800',\n                            backgroundColor: 'rgba(255, 152, 0, 0.1)',\n                            fill: true,\n                            tension: 0.2,\n                            pointRadius: 2\n                        }]\n                    },\n                    plugins: [{\n                        id: 'watermark',\n                        beforeDraw: (chart) => {\n                            const ctx = chart.ctx;\n                            const width = chart.width;\n                            const height = chart.height;\n                            ctx.save();\n                            ctx.globalAlpha = 0.1;\n                            ctx.font = 'bold 16px Arial';\n                            ctx.fillStyle = 'white';\n                            ctx.textAlign = 'center';\n                            ctx.textBaseline = 'middle';\n                            ctx.fillText('Backtesting: BULL TRADING BOT by ORBIDEX IA', width \/ 2, height \/ 2);\n                            ctx.restore();\n                        }\n                    }],\n                    options: {\n                        responsive: true,\n                        maintainAspectRatio: false,\n                        plugins: {\n                            legend: { display: false },\n                            title: { display: true, text: 'Crecimiento de Capital', color: '#888' },\n                            tooltip: {\n                                callbacks: {\n                                    afterBody: function(context) {\n                                        const idx = context[0].dataIndex;\n                                        const meta = equityMeta[idx];\n                                        if(meta) return [`\ud83d\udcc5 ${meta.date}`, `\ud83d\udcb0 Precio Asset: $${meta.price}`];\n                                        return [];\n                                    }\n                                }\n                            }\n                        },\n                        scales: {\n                            x: { display: false },\n                            y: { grid: { color: '#333' }, ticks: { color: '#888' } }\n                        }\n                    }\n                });\n\n            } catch(e) {\n                logEl.innerHTML = \"Error: \" + e.message;\n            }\n        }\n\n        \/\/ ======================================================================================\n        \/\/ === NUEVAS FUNCIONES DASHBOARD (MODULAR) =============================================\n        \/\/ ======================================================================================\n\n        \/\/ --- BLOQUE 1: KPIs GLOBALES ---\n        window.renderDashBlock1 = function() {\n            const container = document.getElementById('dash-content-1');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            if(orders.length === 0) { container.innerHTML = '<p style=\"color:#aaa;\">No hay datos para generar KPIs.<\/p>'; return; }\n\n            let netProfit = 0;\n            let closedTrades = 0;\n            let wins = 0;\n            let maxWin = 0;\n            let maxLoss = 0;\n\n            orders.forEach(o => {\n                if(o.status !== 'OPEN') {\n                    closedTrades++;\n                    const profit = (o.realized || 0);\n                    netProfit += profit;\n                    if(profit > 0) wins++;\n                    if(profit > maxWin) maxWin = profit;\n                    if(profit < maxLoss) maxLoss = profit;\n                }\n            });\n\n            const winrate = closedTrades > 0 ? ((wins \/ closedTrades) * 100).toFixed(1) + '%' : '0%';\n            const avgProfit = closedTrades > 0 ? (netProfit \/ closedTrades).toFixed(2) : '0.00';\n\n            container.innerHTML = `\n                <div class=\"dash-kpi-grid\">\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Beneficio Neto<\/div>\n                        <div class=\"dash-kpi-val\" style=\"color:${netProfit>=0?'#4caf50':'#ff5252'}\">$${netProfit.toFixed(2)}<\/div>\n                    <\/div>\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Winrate Global<\/div>\n                        <div class=\"dash-kpi-val\" style=\"color:#00bcd4\">${winrate}<\/div>\n                    <\/div>\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Media\/Trade<\/div>\n                        <div class=\"dash-kpi-val\">$${avgProfit}<\/div>\n                    <\/div>\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Trades Cerrados<\/div>\n                        <div class=\"dash-kpi-val\">${closedTrades}<\/div>\n                    <\/div>\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Max Win<\/div>\n                        <div class=\"dash-kpi-val\" style=\"color:#4caf50\">$${maxWin.toFixed(2)}<\/div>\n                    <\/div>\n                    <div class=\"dash-kpi-item\">\n                        <div class=\"dash-kpi-lbl\">Max Loss<\/div>\n                        <div class=\"dash-kpi-val\" style=\"color:#ff5252\">$${maxLoss.toFixed(2)}<\/div>\n                    <\/div>\n                <\/div>\n            `;\n        }\n\n        \/\/ --- BLOQUE 2: RANKING GANANCIA NETA POR PAR ---\n        window.renderDashBlock2 = function() {\n            const container = document.getElementById('dash-content-2');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            if(orders.length === 0) { container.innerHTML = '<p style=\"color:#aaa;\">Sin datos.<\/p>'; return; }\n\n            const map = {};\n            orders.forEach(o => {\n                if(!map[o.symbol]) map[o.symbol] = 0;\n                map[o.symbol] += (o.realized || 0);\n                if(o.status === 'OPEN') map[o.symbol] += (o.floatingUsd || 0); \/\/ Incluir flotante para total real\n            });\n\n            const sorted = Object.keys(map).sort((a,b) => map[b] - map[a]);\n\n            let html = '<table class=\"cw-dash-table\"><thead><tr><th>Par<\/th><th>Total ($)<\/th><\/tr><\/thead><tbody>';\n            sorted.forEach(sym => {\n                const val = map[sym];\n                const cls = val >= 0 ? 'cw-dash-val-pos' : 'cw-dash-val-neg';\n                html += `<tr><td>${sym}<\/td><td class=\"${cls}\">$${val.toFixed(2)}<\/td><\/tr>`;\n            });\n            html += '<\/tbody><\/table>';\n            container.innerHTML = html;\n        }\n\n        \/\/ --- BLOQUE 3: EFICIENCIA POR PAR (PROFIT \/ TRADES) ---\n        window.renderDashBlock3 = function() {\n            const container = document.getElementById('dash-content-3');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            if(orders.length === 0) { container.innerHTML = '<p style=\"color:#aaa;\">Sin datos.<\/p>'; return; }\n\n            const map = {};\n            orders.forEach(o => {\n                if(!map[o.symbol]) map[o.symbol] = { pnl: 0, count: 0 };\n                map[o.symbol].pnl += (o.realized || 0) + (o.floatingUsd || 0);\n                map[o.symbol].count++;\n            });\n\n            let html = '<table class=\"cw-dash-table\"><thead><tr><th>Par<\/th><th>Trades<\/th><th>Eficiencia<\/th><\/tr><\/thead><tbody>';\n            Object.keys(map).forEach(sym => {\n                const eff = map[sym].pnl \/ map[sym].count;\n                const cls = eff >= 0 ? 'cw-dash-val-pos' : 'cw-dash-val-neg';\n                html += `<tr><td>${sym}<\/td><td>${map[sym].count}<\/td><td class=\"${cls}\">$${eff.toFixed(2)} \/ trade<\/td><\/tr>`;\n            });\n            html += '<\/tbody><\/table>';\n            container.innerHTML = html;\n        }\n\n        \/\/ --- BLOQUE 4: RIESGO CRITICO (Drawdown Trade y Riesgo Neto) ---\n        window.renderDashBlock4 = function() {\n            const container = document.getElementById('dash-content-4');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            if(orders.length === 0) { container.innerHTML = '<p style=\"color:#aaa;\">Sin datos.<\/p>'; return; }\n\n            \/\/ Calcular peor trade (DD Trade) y Riesgo Neto por par\n            const map = {};\n            orders.forEach(o => {\n                if(!map[o.symbol]) map[o.symbol] = { net: 0, worst: 0 };\n                const totalVal = (o.realized || 0) + (o.floatingUsd || 0);\n                map[o.symbol].net += totalVal;\n                if(totalVal < map[o.symbol].worst) map[o.symbol].worst = totalVal;\n            });\n\n            \/\/ Ordenar por riesgo neto (ganancia - p\u00e9rdida)\n            const sorted = Object.keys(map).sort((a,b) => map[b].net - map[a].net);\n\n            let html = '<table class=\"cw-dash-table\"><thead><tr><th>Par<\/th><th>Riesgo Neto<\/th><th>DD Max (Trade)<\/th><\/tr><\/thead><tbody>';\n            sorted.forEach(sym => {\n                const d = map[sym];\n                const clsNet = d.net >= 0 ? 'cw-dash-val-pos' : 'cw-dash-val-neg';\n                html += `<tr>\n                    <td>${sym}<\/td>\n                    <td class=\"${clsNet}\">$${d.net.toFixed(2)}<\/td>\n                    <td style=\"color:#ff5252\">$${d.worst.toFixed(2)}<\/td>\n                <\/tr>`;\n            });\n            html += '<\/tbody><\/table>';\n            container.innerHTML = html;\n        }\n\n        \/\/ --- BLOQUE 5: ANALISIS DE DIRECCION ---\n        window.renderDashBlock5 = function() {\n            const container = document.getElementById('dash-content-5');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n            if(orders.length === 0) { container.innerHTML = '<p style=\"color:#aaa;\">Sin datos.<\/p>'; return; }\n\n            let longStats = { count: 0, wins: 0 };\n            let shortStats = { count: 0, wins: 0 };\n\n            orders.forEach(o => {\n                const isWin = ((o.realized || 0) + (o.floatingUsd || 0)) > 0;\n                if(o.direction === 'LONG') {\n                    longStats.count++;\n                    if(isWin) longStats.wins++;\n                } else {\n                    shortStats.count++;\n                    if(isWin) shortStats.wins++;\n                }\n            });\n\n            const longWr = longStats.count > 0 ? ((longStats.wins\/longStats.count)*100).toFixed(1) : 0;\n            const shortWr = shortStats.count > 0 ? ((shortStats.wins\/shortStats.count)*100).toFixed(1) : 0;\n            \n            let conclusion = \"NEUTRAL\";\n            if(parseFloat(longWr) > parseFloat(shortWr)) conclusion = \"MEJOR EN LONG \ud83d\udfe2\";\n            else if(parseFloat(shortWr) > parseFloat(longWr)) conclusion = \"MEJOR EN SHORT \ud83d\udd34\";\n\n            container.innerHTML = `\n                <div style=\"display:flex; justify-content:space-around; margin-bottom:10px;\">\n                    <div style=\"text-align:center;\">\n                        <div style=\"color:#66bb6a; font-weight:bold;\">LONG<\/div>\n                        <div style=\"font-size:1.2rem;\">${longStats.count}<\/div>\n                        <div style=\"font-size:0.8rem; color:#aaa;\">WR: ${longWr}%<\/div>\n                    <\/div>\n                    <div style=\"text-align:center;\">\n                        <div style=\"color:#ff5252; font-weight:bold;\">SHORT<\/div>\n                        <div style=\"font-size:1.2rem;\">${shortStats.count}<\/div>\n                        <div style=\"font-size:0.8rem; color:#aaa;\">WR: ${shortWr}%<\/div>\n                    <\/div>\n                <\/div>\n                <div style=\"text-align:center; padding:10px; background:rgba(255,255,255,0.05); border-radius:4px;\">\n                    <small>CONCLUSI\u00d3N:<\/small><br>\n                    <strong style=\"color:#ffd700;\">${conclusion}<\/strong>\n                <\/div>\n            `;\n        }\n\n        \/\/ ======================================================================================\n        \/\/ === NUEVA FUNCIONALIDAD: GENERADOR DE GR\u00c1FICOS AVANZADOS =============================\n        \/\/ ======================================================================================\n        \n        window.generateAdvancedChart = function() {\n            const type = document.getElementById('adv-chart-type').value;\n            const ctx = document.getElementById('advChartCanvas').getContext('2d');\n            const orders = JSON.parse(localStorage.getItem('bullBotAlgorithmic_orders')) || [];\n\n            if(advChartInstance) advChartInstance.destroy();\n\n            \/\/ Configuraci\u00f3n del Watermark\n            const watermarkPluginLocal = {\n                id: 'watermarkAdv',\n                beforeDraw: (chart) => {\n                    const ctx = chart.ctx;\n                    const width = chart.width;\n                    const height = chart.height;\n                    ctx.save();\n                    ctx.globalCompositeOperation = 'destination-over';\n                    ctx.fillStyle = 'rgba(255, 255, 255, 0.05)';\n                    ctx.font = 'bold 20px Arial';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    ctx.fillText('AI\u2011PRO by BULL TRADING BOT', width \/ 2, height \/ 2);\n                    ctx.restore();\n                }\n            };\n\n            let labels = [], data = [], colors = [], labelText = '';\n            let datasets = []; \/\/ Para gr\u00e1ficos agrupados\n\n            \/\/ L\u00f3gica seg\u00fan tipo de gr\u00e1fico\n            if (type === \"1\") { \/\/ Ranking por N\u00b0 Trades\n                labelText = 'N\u00famero de Trades';\n                const map = {};\n                orders.forEach(o => { map[o.symbol] = (map[o.symbol] || 0) + 1; });\n                const sorted = Object.keys(map).sort((a,b) => map[b] - map[a]);\n                labels = sorted;\n                data = sorted.map(k => map[k]);\n                colors = '#6c5ce7';\n            } \n            else if (type === \"2\") { \/\/ An\u00e1lisis de riesgo (Drawdown max por par)\n                labelText = 'M\u00e1ximo Drawdown ($)';\n                const map = {};\n                orders.forEach(o => {\n                    let val = (o.realized || 0) + (o.floatingUsd || 0);\n                    if(!map[o.symbol]) map[o.symbol] = 0;\n                    if(val < map[o.symbol]) map[o.symbol] = val; \/\/ Guardar el peor valor (m\u00e1s negativo)\n                });\n                labels = Object.keys(map);\n                data = Object.values(map); \/\/ Valores negativos\n                colors = '#ff5252';\n            }\n            else if (type === \"3\") { \/\/ Top 3 Pares (Ganancias)\n                labelText = 'Ganancia Total ($)';\n                const map = {};\n                orders.forEach(o => {\n                    let val = (o.realized || 0) + (o.floatingUsd || 0);\n                    if(val > 0) map[o.symbol] = (map[o.symbol] || 0) + val;\n                });\n                const sorted = Object.keys(map).sort((a,b) => map[b] - map[a]).slice(0, 3);\n                labels = sorted;\n                data = sorted.map(k => map[k]);\n                colors = '#4caf50';\n            }\n            else if (type === \"4\") { \/\/ Eficiencia (Profit \/ Trade)\n                labelText = 'Profit Promedio por Trade ($)';\n                const map = {};\n                orders.forEach(o => {\n                    if(!map[o.symbol]) map[o.symbol] = { sum: 0, count: 0 };\n                    map[o.symbol].sum += ((o.realized || 0) + (o.floatingUsd || 0));\n                    map[o.symbol].count++;\n                });\n                labels = Object.keys(map);\n                data = labels.map(k => map[k].sum \/ map[k].count);\n                colors = data.map(v => v >= 0 ? '#4caf50' : '#ff5252');\n            }\n            else if (type === \"5\") { \/\/ Riesgo (P\u00e9rdidas vs Ganancias) - Stacked\/Grouped\n                const map = {};\n                orders.forEach(o => {\n                    if(!map[o.symbol]) map[o.symbol] = { gain: 0, loss: 0 };\n                    let val = (o.realized || 0) + (o.floatingUsd || 0);\n                    if(val >= 0) map[o.symbol].gain += val;\n                    else map[o.symbol].loss += Math.abs(val);\n                });\n                labels = Object.keys(map);\n                datasets = [\n                    { label: 'Ganancia Total', data: labels.map(k => map[k].gain), backgroundColor: '#4caf50' },\n                    { label: 'P\u00e9rdida Total', data: labels.map(k => map[k].loss), backgroundColor: '#ff5252' }\n                ];\n            }\n            else if (type === \"6\") { \/\/ Distribuci\u00f3n de Cierres\n                labelText = 'Cantidad';\n                const map = { 'TP': 0, 'SL': 0, 'Trailing': 0, 'Manual': 0 };\n                orders.forEach(o => {\n                    if(o.status.includes('TAKE PROFIT')) map['TP']++;\n                    else if(o.status.includes('STOP LOSS')) map['SL']++;\n                    else if(o.status.includes('TRAIL') || o.status.includes('TTP')) map['Trailing']++;\n                    else if(o.status.includes('MANUAL')) map['Manual']++;\n                });\n                labels = Object.keys(map);\n                data = Object.values(map);\n                colors = ['#4caf50', '#ff5252', '#ff9800', '#2196f3'];\n            }\n            else if (type === \"7\") { \/\/ Direcci\u00f3n (Long vs Short)\n                labelText = 'Cantidad de Trades';\n                let long = 0, short = 0;\n                orders.forEach(o => { if(o.direction === 'LONG') long++; else short++; });\n                labels = ['LONG', 'SHORT'];\n                data = [long, short];\n                colors = ['#66bb6a', '#ff5252'];\n            }\n\n            \/\/ Construir dataset standard si no es agrupado (caso 5)\n            if(type !== \"5\") {\n                datasets = [{\n                    label: labelText,\n                    data: data,\n                    backgroundColor: colors,\n                    borderWidth: 0\n                }];\n            }\n\n            advChartInstance = new Chart(ctx, {\n                type: 'bar',\n                data: {\n                    labels: labels,\n                    datasets: datasets\n                },\n                options: {\n                    responsive: true,\n                    maintainAspectRatio: false,\n                    plugins: {\n                        legend: { display: (type === \"5\"), labels: { color: '#ccc' } },\n                        title: { display: true, text: 'An\u00e1lisis Gr\u00e1fico AI-PRO', color: '#fff', font: { size: 14 } }\n                    },\n                    scales: {\n                        x: { ticks: { color: '#aaa' }, grid: { color: '#333' } },\n                        y: { ticks: { color: '#aaa' }, grid: { color: '#333' } }\n                    }\n                },\n                plugins: [watermarkPluginLocal]\n            });\n        }\n        \n        \/\/ Expose functions to global scope for HTML onclick handlers\n        window.updateApp = updateApp;\n        window.updateLeverageDisplay = updateLeverageDisplay;\n        window.toggleTPMode = toggleTPMode;\n        window.toggleMode = toggleMode;\n        window.setDirection = setDirection;\n        window.calculateResults = calculateResults;\n        window.applyStrategyPreset = applyStrategyPreset;\n        window.toggleBotExecution = toggleBotExecution;\n        window.closeManual = closeManual;\n        window.clearHistory = clearHistory;\n        window.runBacktest = runBacktest;\n        window.changeAssetGroup = changeAssetGroup; \n        window.getPrecision = getPrecision;\n        window.viewOnChart = viewOnChart;\n        \/\/ Nueva funcion expuesta\n        window.generateAdvancedChart = generateAdvancedChart;\n\n        \/\/ --- INICIALIZACION SEGURA ---\n        document.addEventListener('DOMContentLoaded', function() {\n            const loader = document.getElementById('orbidex-loader');\n            \n            \/\/ Safe Boot Sequence\n            try {\n                \/\/ 1. Initial Data Setup\n                changeAssetGroup();\n                applyStrategyPreset();\n\n                \/\/ 2. Scheduled Updates\n                setTimeout(() => { \n                    try { document.getElementById('ai-status-text').innerText = \"Cargando Motor Algor\u00edtmico...\"; } catch(e){}\n                }, 1000);\n                \n                setTimeout(() => { \n                    try { \n                        document.getElementById('ai-status-text').innerText = \"Sincronizando Feed...\"; \n                        startBackgroundTasks(); \n                    } catch(e){}\n                }, 2000);\n\n            } catch(e) {\n                console.error(\"Critical Boot Error:\", e);\n                \/\/ Even on error, force clear loader\n            } finally {\n                \/\/ 3. Force Loader Removal (Always)\n                setTimeout(() => { \n                    if(loader) {\n                        loader.style.opacity='0'; \n                        setTimeout(()=>{ loader.style.display='none'; }, 500); \n                    }\n                }, 3000);\n            }\n        });\n\n        function startBackgroundTasks() {\n            setInterval(refreshOpenOrders, 2000); \n            setInterval(scanMarketOpportunity, 4000); \n            \n            \/\/ --- ACTUALIZACION AUTOMATICA DE GRAFICO CADA 5 SEGUNDOS ---\n            setInterval(() => {\n                 updateApp(true); \/\/ true = silent update (sin reiniciar ticker innecesariamente)\n                 if(currentDetailSymbol) updateTradeDetails(currentDetailSymbol); \/\/ Auto-update detalles\n            }, 5000);\n        }\n    <\/script>\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Iniciando BULL TRADING BOT&#8230; Cargando m\u00f3dulos de gesti\u00f3n AI-PRO by BULL TRADING BOT Tipo de Activo CriptomonedasForexFondos\/Comodities Activo (Vista) Temporalidad (Estrategia) 1 Minuto (Scalping)5 Minutos (Intraday)15 Minutos (Swing)1 Hora (Trend)4 Horas (Macro) Acci\u00f3n \u21bb Reset PRECIO EN VIVO&#8212; SE\u00d1AL ACTUALANALIZANDO&#8230; EMA RAP&#8212; EMA LENT&#8212; CONVERG&#8212; RSI (14)&#8212; MACD&#8212; ROCKET GAME BULL TRADING BOT COIN&#8212; ENTRY&#8212;<\/p>","protected":false},"author":7,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-5196","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/pages\/5196","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/comments?post=5196"}],"version-history":[{"count":3,"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/pages\/5196\/revisions"}],"predecessor-version":[{"id":5199,"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/pages\/5196\/revisions\/5199"}],"wp:attachment":[{"href":"https:\/\/bulltradebot.com\/en\/wp-json\/wp\/v2\/media?parent=5196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}