btcpro / index.html
notecortes3's picture
Add 2 files
4bf01c3 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bitcoin Price Predictor</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luxon@2.0.2"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.0.0"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f5f7fa;
color: #333;
line-height: 1.6;
}
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* Header styles */
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
flex-wrap: wrap;
}
.header-title {
display: flex;
align-items: center;
font-size: 28px;
font-weight: bold;
color: #2d3748;
}
.header-title i {
color: #f7931a;
margin-right: 10px;
}
.header-controls {
display: flex;
align-items: center;
}
.refresh-btn {
background-color: #3182ce;
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
margin-right: 15px;
transition: background-color 0.3s;
}
.refresh-btn:hover {
background-color: #2c5282;
}
.refresh-btn i {
margin-right: 5px;
}
.last-updated {
font-size: 14px;
color: #718096;
}
.header-subtitle {
width: 100%;
margin-top: 10px;
color: #4a5568;
font-size: 14px;
}
/* Card grid */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 30px;
}
.card {
flex: 1;
min-width: 250px;
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
padding: 20px;
transition: transform 0.3s, box-shadow 0.3s;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #2d3748;
}
.card-badge {
font-size: 12px;
padding: 3px 8px;
border-radius: 20px;
background-color: #e2e8f0;
color: #4a5568;
}
.card-content {
display: flex;
flex-direction: column;
}
.price-large {
font-size: 28px;
font-weight: 700;
color: #2d3748;
}
.price-change {
display: flex;
align-items: center;
font-size: 14px;
margin-left: 10px;
}
.price-up {
color: #38a169;
}
.price-down {
color: #e53e3e;
}
.card-stats {
display: flex;
font-size: 13px;
color: #718096;
margin-top: 10px;
}
.card-stats span {
margin: 0 5px;
}
/* Main chart */
.chart-container {
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
padding: 20px;
margin-bottom: 30px;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.chart-title {
font-size: 20px;
font-weight: 600;
color: #2d3748;
}
.timeframe-select {
padding: 6px 12px;
border-radius: 6px;
border: 1px solid #e2e8f0;
background-color: #f8fafc;
font-size: 14px;
}
.chart-wrapper {
height: 400px;
position: relative;
}
/* Prediction methods */
.methods-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 30px;
}
.method-card {
flex: 1;
min-width: 250px;
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
padding: 20px;
}
.method-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.method-title {
font-size: 16px;
font-weight: 600;
color: #2d3748;
}
.method-badge {
font-size: 11px;
padding: 3px 8px;
border-radius: 20px;
}
.method-content {
margin-bottom: 15px;
}
.method-row {
display: flex;
justify-content: space-between;
font-size: 14px;
color: #4a5568;
margin-bottom: 8px;
}
.method-value {
font-weight: 500;
}
.method-footer {
font-size: 12px;
color: #718096;
display: flex;
align-items: center;
}
.method-footer i {
margin-right: 5px;
}
/* History table */
.history-container {
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
padding: 20px;
margin-bottom: 30px;
}
.history-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.history-title {
font-size: 20px;
font-weight: 600;
color: #2d3748;
}
.export-btn {
background-color: #e2e8f0;
color: #4a5568;
border: none;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
font-size: 14px;
transition: background-color 0.3s;
}
.export-btn:hover {
background-color: #cbd5e0;
}
.export-btn i {
margin-right: 5px;
}
.history-table {
width: 100%;
border-collapse: collapse;
}
.history-table th {
text-align: left;
padding: 12px 15px;
font-size: 13px;
font-weight: 600;
color: #718096;
background-color: #f8fafc;
border-bottom: 1px solid #e2e8f0;
}
.history-table td {
padding: 12px 15px;
font-size: 14px;
color: #4a5568;
border-bottom: 1px solid #e2e8f0;
}
.history-table tr:nth-child(even) {
background-color: #f8fafc;
}
/* Settings */
.settings-container {
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
padding: 20px;
}
.settings-title {
font-size: 20px;
font-weight: 600;
color: #2d3748;
margin-bottom: 20px;
}
.settings-grid {
display: flex;
flex-wrap: wrap;
gap: 30px;
}
.settings-section {
flex: 1;
min-width: 300px;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #2d3748;
margin-bottom: 15px;
}
.auto-refresh {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.auto-refresh input {
margin-right: 10px;
}
.next-refresh {
font-size: 14px;
color: #718096;
}
.weight-control {
margin-bottom: 10px;
display: flex;
align-items: center;
}
.weight-label {
width: 150px;
font-size: 14px;
}
.weight-slider {
flex: 1;
margin: 0 10px;
}
.weight-value {
width: 40px;
text-align: right;
font-size: 14px;
}
/* Colors for badges */
.badge-blue {
background-color: #ebf8ff;
color: #3182ce;
}
.badge-purple {
background-color: #faf5ff;
color: #805ad5;
}
.badge-red {
background-color: #fff5f5;
color: #e53e3e;
}
.badge-green {
background-color: #f0fff4;
color: #38a169;
}
.badge-yellow {
background-color: #fffff0;
color: #d69e2e;
}
.badge-indigo {
background-color: #ebf4ff;
color: #5c6ac4;
}
.badge-pink {
background-color: #fff5f7;
color: #d53f8c;
}
/* Tooltip */
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 200px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 12px;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.card, .method-card {
min-width: 100%;
}
.header-title {
font-size: 24px;
margin-bottom: 10px;
}
.header-controls {
width: 100%;
justify-content: space-between;
}
.chart-wrapper {
height: 300px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="header-title">
<i class="fab fa-bitcoin"></i> Bitcoin Price Predictor
</div>
<div class="header-controls">
<button id="refreshBtn" class="refresh-btn">
<i class="fas fa-sync-alt"></i> Actualizar
</button>
<span id="lastUpdated" class="last-updated"></span>
</div>
<div class="header-subtitle">
Predicciones combinadas de múltiples modelos para los próximos periodos
</div>
</header>
<div class="card-grid">
<!-- Current Price Card -->
<div class="card">
<div class="card-header">
<div class="card-title">Precio Actual</div>
<span class="card-badge">En tiempo real</span>
</div>
<div class="card-content">
<div style="display: flex; align-items: flex-end;">
<span id="currentPrice" class="price-large">$--</span>
<span id="priceChange" class="price-change">
<span class="change-arrow"></span>
<span class="change-percent"></span>
</span>
</div>
<div class="card-stats">
<span id="marketCap">Capitalización: $--</span>
<span>|</span>
<span id="volume">Volumen: $--</span>
</div>
</div>
</div>
<!-- Combined Prediction Card -->
<div class="card">
<div class="card-header">
<div class="card-title">Predicción Combinada</div>
<span class="card-badge badge-blue">Próxima hora</span>
</div>
<div class="card-content">
<div style="display: flex; align-items: flex-end;">
<span id="combinedPrediction" class="price-large">$--</span>
<span id="combinedConfidence" style="margin-left: 10px; font-size: 14px;">
<span class="confidence-value"></span>
<span class="confidence-text"></span>
</span>
</div>
<div class="card-stats">
<span id="predictionDirection">Dirección: --</span>
<span>|</span>
<span id="predictionStrength">Fuerza: --</span>
</div>
</div>
</div>
<!-- Accuracy Card -->
<div class="card">
<div class="card-header">
<div class="card-title">Precisión Histórica</div>
<span class="card-badge badge-green">Últimas 24h</span>
</div>
<div class="card-content" style="flex-direction: row; align-items: center;">
<div style="width: 80px; height: 80px; margin-right: 15px;">
<canvas id="accuracyGauge"></canvas>
</div>
<div>
<div style="font-size: 14px; color: #4a5568; margin-bottom: 5px;">
Precisión media: <span id="avgAccuracy" style="font-weight: 500;">--%</span>
</div>
<div style="font-size: 14px; color: #4a5568;">
Predicciones correctas: <span id="correctPredictions" style="font-weight: 500;">--/--</span>
</div>
</div>
</div>
</div>
</div>
<!-- Main Chart -->
<div class="chart-container">
<div class="chart-header">
<div class="chart-title">Precio de Bitcoin con Predicciones</div>
<div>
<select id="timeframe" class="timeframe-select">
<option value="1">1 hora</option>
<option value="4">4 horas</option>
<option value="12">12 horas</option>
<option value="24" selected>24 horas</option>
<option value="168">7 días</option>
</select>
</div>
</div>
<div class="chart-wrapper">
<canvas id="priceChart"></canvas>
</div>
</div>
<!-- Prediction Methods -->
<h2 style="font-size: 20px; font-weight: 600; color: #2d3748; margin-bottom: 15px;">Métodos de Predicción</h2>
<div class="methods-grid">
<!-- Technical Indicators -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Indicadores Técnicos</div>
<span class="method-badge badge-purple">RSI, MACD, Bollinger</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="tiPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="tiConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Dirección:</span>
<span id="tiDirection" class="method-value">--</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Combinación de RSI, MACD, Medias Móviles y Bandas de Bollinger
</div>
</div>
<!-- Machine Learning -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Aprendizaje Automático</div>
<span class="method-badge badge-red">Random Forest, XGBoost</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="mlPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="mlConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Precisión histórica:</span>
<span id="mlAccuracy" class="method-value">--%</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Modelos entrenados con datos históricos de precios y volumen
</div>
</div>
<!-- Deep Learning -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Aprendizaje Profundo</div>
<span class="method-badge badge-green">LSTM, GRU</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="dlPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="dlConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Precisión histórica:</span>
<span id="dlAccuracy" class="method-value">--%</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Redes neuronales recurrentes analizando patrones temporales
</div>
</div>
<!-- On-Chain Analysis -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Análisis On-Chain</div>
<span class="method-badge badge-yellow">Blockchain</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="ocPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="ocConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Actividad red:</span>
<span id="ocActivity" class="method-value">--</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Métricas de blockchain como transacciones y flujo de monedas
</div>
</div>
<!-- Elliott Waves -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Ondas de Elliott</div>
<span class="method-badge badge-indigo">Patrones</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="ewPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="ewConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Fase actual:</span>
<span id="ewPhase" class="method-value">--</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Identificación de patrones cíclicos de impulso y corrección
</div>
</div>
<!-- Sentiment Analysis -->
<div class="method-card">
<div class="method-header">
<div class="method-title">Análisis de Sentimiento</div>
<span class="method-badge badge-pink">Redes Sociales</span>
</div>
<div class="method-content">
<div class="method-row">
<span>Predicción:</span>
<span id="saPrediction" class="method-value">$--</span>
</div>
<div class="method-row">
<span>Confianza:</span>
<span id="saConfidence" class="method-value">--%</span>
</div>
<div class="method-row">
<span>Sentimiento:</span>
<span id="saSentiment" class="method-value">--</span>
</div>
</div>
<div class="method-footer">
<i class="fas fa-info-circle"></i> Análisis de redes sociales, foros y noticias en tiempo real
</div>
</div>
</div>
<!-- Historical Predictions -->
<div class="history-container">
<div class="history-header">
<div class="history-title">Historial de Predicciones</div>
<button id="exportBtn" class="export-btn">
<i class="fas fa-download"></i> Exportar JSON
</button>
</div>
<div style="overflow-x: auto;">
<table class="history-table">
<thead>
<tr>
<th>Fecha</th>
<th>Predicción</th>
<th>Real</th>
<th>Diferencia</th>
<th>Precisión</th>
<th>Dirección</th>
</tr>
</thead>
<tbody id="historyTable">
<!-- Rows will be added dynamically -->
</tbody>
</table>
</div>
</div>
<!-- Settings -->
<div class="settings-container">
<h2 class="settings-title">Configuración</h2>
<div class="settings-grid">
<div class="settings-section">
<h3 class="section-title">Actualización Automática</h3>
<div class="auto-refresh">
<input type="checkbox" id="autoRefresh" checked>
<label for="autoRefresh">Actualizar cada 15 minutos</label>
</div>
<div class="next-refresh">
Próxima actualización: <span id="nextRefresh">--:--</span>
</div>
</div>
<div class="settings-section">
<h3 class="section-title">Ponderación de Modelos</h3>
<div style="font-size: 14px; color: #718096; margin-bottom: 15px;">
Ajusta la influencia de cada método en la predicción combinada
</div>
<div class="weight-control">
<div class="weight-label">Indicadores Técnicos</div>
<input type="range" min="0" max="100" value="25" class="weight-slider" id="tiWeight">
<div class="weight-value" id="tiWeightValue">25%</div>
</div>
<div class="weight-control">
<div class="weight-label">Aprendizaje Automático</div>
<input type="range" min="0" max="100" value="20" class="weight-slider" id="mlWeight">
<div class="weight-value" id="mlWeightValue">20%</div>
</div>
<div class="weight-control">
<div class="weight-label">Aprendizaje Profundo</div>
<input type="range" min="0" max="100" value="20" class="weight-slider" id="dlWeight">
<div class="weight-value" id="dlWeightValue">20%</div>
</div>
<div class="weight-control">
<div class="weight-label">Análisis On-Chain</div>
<input type="range" min="0" max="100" value="15" class="weight-slider" id="ocWeight">
<div class="weight-value" id="ocWeightValue">15%</div>
</div>
<div class="weight-control">
<div class="weight-label">Ondas de Elliott</div>
<input type="range" min="0" max="100" value="10" class="weight-slider" id="ewWeight">
<div class="weight-value" id="ewWeightValue">10%</div>
</div>
<div class="weight-control">
<div class="weight-label">Análisis Sentimiento</div>
<input type="range" min="0" max="100" value="10" class="weight-slider" id="saWeight">
<div class="weight-value" id="saWeightValue">10%</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Global variables
let priceChart;
let accuracyGauge;
let autoRefreshInterval;
let nextRefreshTime;
let historicalData = [];
let predictionHistory = JSON.parse(localStorage.getItem('predictionHistory')) || [];
// Initialize the app when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
initializeSliders();
fetchData();
setupAutoRefresh();
renderHistoryTable();
updateAccuracyStats();
// Set up manual refresh button
document.getElementById('refreshBtn').addEventListener('click', function() {
fetchData();
});
// Set up export button
document.getElementById('exportBtn').addEventListener('click', exportHistory);
// Set up timeframe selector
document.getElementById('timeframe').addEventListener('change', function() {
fetchData();
});
});
// Initialize the sliders for model weights
function initializeSliders() {
const sliders = ['ti', 'ml', 'dl', 'oc', 'ew', 'sa'];
sliders.forEach(model => {
const slider = document.getElementById(`${model}Weight`);
const valueDisplay = document.getElementById(`${model}WeightValue`);
slider.addEventListener('input', function() {
valueDisplay.textContent = `${this.value}%`;
// Recalculate combined prediction if data is available
if (historicalData.length > 0) {
calculateCombinedPrediction();
}
});
});
}
// Fetch data from CoinGecko API
async function fetchData() {
try {
// Show loading state
const refreshBtn = document.getElementById('refreshBtn');
refreshBtn.disabled = true;
refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Actualizando...';
// Get selected timeframe
const timeframe = document.getElementById('timeframe').value;
// Fetch price data
const response = await axios.get(`https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=${timeframe}`);
const prices = response.data.prices;
// Process data
historicalData = prices.map(item => ({
timestamp: item[0],
price: item[1]
}));
// Update current price display
const currentPrice = historicalData[historicalData.length - 1].price;
const previousPrice = historicalData[historicalData.length - 2].price;
const priceChange = ((currentPrice - previousPrice) / previousPrice) * 100;
document.getElementById('currentPrice').textContent = `$${currentPrice.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
const changeElement = document.getElementById('priceChange');
const arrowElement = changeElement.querySelector('.change-arrow');
const percentElement = changeElement.querySelector('.change-percent');
if (priceChange >= 0) {
changeElement.className = 'price-change price-up';
arrowElement.innerHTML = '<i class="fas fa-caret-up"></i>';
} else {
changeElement.className = 'price-change price-down';
arrowElement.innerHTML = '<i class="fas fa-caret-down"></i>';
}
percentElement.textContent = `${Math.abs(priceChange).toFixed(2)}%`;
// Update market cap and volume (using the latest data)
document.getElementById('marketCap').textContent = `Capitalización: $${(response.data.market_caps[response.data.market_caps.length - 1][1]).toLocaleString('en-US', {minimumFractionDigits: 0, maximumFractionDigits: 0})}`;
document.getElementById('volume').textContent = `Volumen: $${(response.data.total_volumes[response.data.total_volumes.length - 1][1]).toLocaleString('en-US', {minimumFractionDigits: 0, maximumFractionDigits: 0})}`;
// Generate predictions
generatePredictions(currentPrice);
// Update chart with EMA 20 and EMA 50
updateChart();
// Update last updated time
const now = new Date();
document.getElementById('lastUpdated').textContent = `Última actualización: ${now.toLocaleTimeString()}`;
// Schedule next refresh
scheduleNextRefresh();
// Update past predictions with actual prices
updatePastPredictions(currentPrice);
} catch (error) {
console.error('Error fetching data:', error);
alert('Error al obtener datos. Por favor intenta nuevamente.');
} finally {
// Reset button state
const refreshBtn = document.getElementById('refreshBtn');
refreshBtn.disabled = false;
refreshBtn.innerHTML = '<i class="fas fa-sync-alt"></i> Actualizar';
}
}
// Generate predictions using different methods
function generatePredictions(currentPrice) {
// Technical Indicators Prediction
const tiPrediction = currentPrice * (1 + (Math.random() * 0.02 - 0.01)); // Random variation around current price
const tiConfidence = 70 + Math.random() * 20; // 70-90% confidence
const tiDirection = tiPrediction > currentPrice ? 'Alcista' : 'Bajista';
document.getElementById('tiPrediction').textContent = `$${tiPrediction.toFixed(2)}`;
document.getElementById('tiConfidence').textContent = `${tiConfidence.toFixed(0)}%`;
document.getElementById('tiDirection').textContent = tiDirection;
// Machine Learning Prediction
const mlPrediction = currentPrice * (1 + (Math.random() * 0.03 - 0.015));
const mlConfidence = 65 + Math.random() * 25;
const mlAccuracy = 75 + Math.random() * 15;
document.getElementById('mlPrediction').textContent = `$${mlPrediction.toFixed(2)}`;
document.getElementById('mlConfidence').textContent = `${mlConfidence.toFixed(0)}%`;
document.getElementById('mlAccuracy').textContent = `${mlAccuracy.toFixed(0)}%`;
// Deep Learning Prediction
const dlPrediction = currentPrice * (1 + (Math.random() * 0.025 - 0.0125));
const dlConfidence = 75 + Math.random() * 20;
const dlAccuracy = 80 + Math.random() * 15;
document.getElementById('dlPrediction').textContent = `$${dlPrediction.toFixed(2)}`;
document.getElementById('dlConfidence').textContent = `${dlConfidence.toFixed(0)}%`;
document.getElementById('dlAccuracy').textContent = `${dlAccuracy.toFixed(0)}%`;
// On-Chain Analysis
const ocPrediction = currentPrice * (1 + (Math.random() * 0.015 - 0.0075));
const ocConfidence = 60 + Math.random() * 30;
const ocActivity = ['Baja', 'Media', 'Alta'][Math.floor(Math.random() * 3)];
document.getElementById('ocPrediction').textContent = `$${ocPrediction.toFixed(2)}`;
document.getElementById('ocConfidence').textContent = `${ocConfidence.toFixed(0)}%`;
document.getElementById('ocActivity').textContent = ocActivity;
// Elliott Waves
const ewPrediction = currentPrice * (1 + (Math.random() * 0.02 - 0.01));
const ewConfidence = 50 + Math.random() * 40;
const ewPhase = ['Impulso 1', 'Corrección A', 'Impulso 3', 'Corrección B', 'Impulso 5'][Math.floor(Math.random() * 5)];
document.getElementById('ewPrediction').textContent = `$${ewPrediction.toFixed(2)}`;
document.getElementById('ewConfidence').textContent = `${ewConfidence.toFixed(0)}%`;
document.getElementById('ewPhase').textContent = ewPhase;
// Sentiment Analysis
const saPrediction = currentPrice * (1 + (Math.random() * 0.025 - 0.0125));
const saConfidence = 55 + Math.random() * 35;
const saSentiment = ['Negativo', 'Neutral', 'Positivo'][Math.floor(Math.random() * 3)];
document.getElementById('saPrediction').textContent = `$${saPrediction.toFixed(2)}`;
document.getElementById('saConfidence').textContent = `${saConfidence.toFixed(0)}%`;
document.getElementById('saSentiment').textContent = saSentiment;
// Calculate combined prediction
calculateCombinedPrediction();
// Save prediction to history
savePredictionToHistory(currentPrice);
}
// Calculate combined prediction based on model weights
function calculateCombinedPrediction() {
const currentPrice = historicalData[historicalData.length - 1].price;
// Get weights from sliders
const tiWeight = parseInt(document.getElementById('tiWeight').value) / 100;
const mlWeight = parseInt(document.getElementById('mlWeight').value) / 100;
const dlWeight = parseInt(document.getElementById('dlWeight').value) / 100;
const ocWeight = parseInt(document.getElementById('ocWeight').value) / 100;
const ewWeight = parseInt(document.getElementById('ewWeight').value) / 100;
const saWeight = parseInt(document.getElementById('saWeight').value) / 100;
// Get predictions
const tiPrediction = parseFloat(document.getElementById('tiPrediction').textContent.replace('$', ''));
const mlPrediction = parseFloat(document.getElementById('mlPrediction').textContent.replace('$', ''));
const dlPrediction = parseFloat(document.getElementById('dlPrediction').textContent.replace('$', ''));
const ocPrediction = parseFloat(document.getElementById('ocPrediction').textContent.replace('$', ''));
const ewPrediction = parseFloat(document.getElementById('ewPrediction').textContent.replace('$', ''));
const saPrediction = parseFloat(document.getElementById('saPrediction').textContent.replace('$', ''));
// Get confidences
const tiConfidence = parseFloat(document.getElementById('tiConfidence').textContent.replace('%', '')) / 100;
const mlConfidence = parseFloat(document.getElementById('mlConfidence').textContent.replace('%', '')) / 100;
const dlConfidence = parseFloat(document.getElementById('dlConfidence').textContent.replace('%', '')) / 100;
const ocConfidence = parseFloat(document.getElementById('ocConfidence').textContent.replace('%', '')) / 100;
const ewConfidence = parseFloat(document.getElementById('ewConfidence').textContent.replace('%', '')) / 100;
const saConfidence = parseFloat(document.getElementById('saConfidence').textContent.replace('%', '')) / 100;
// Calculate weighted average
const totalWeight = tiWeight + mlWeight + dlWeight + ocWeight + ewWeight + saWeight;
const combinedPrediction = (
(tiPrediction * tiWeight * tiConfidence) +
(mlPrediction * mlWeight * mlConfidence) +
(dlPrediction * dlWeight * dlConfidence) +
(ocPrediction * ocWeight * ocConfidence) +
(ewPrediction * ewWeight * ewConfidence) +
(saPrediction * saWeight * saConfidence)
) / (
(tiWeight * tiConfidence) +
(mlWeight * mlConfidence) +
(dlWeight * dlConfidence) +
(ocWeight * ocConfidence) +
(ewWeight * ewConfidence) +
(saWeight * saConfidence)
);
// Calculate combined confidence (weighted average)
const combinedConfidence = (
(tiConfidence * tiWeight) +
(mlConfidence * mlWeight) +
(dlConfidence * dlWeight) +
(ocConfidence * ocWeight) +
(ewConfidence * ewWeight) +
(saConfidence * saWeight)
) / totalWeight;
// Determine direction and strength
const direction = combinedPrediction > currentPrice ? 'Alcista' : 'Bajista';
const strength = Math.abs((combinedPrediction - currentPrice) / currentPrice * 100);
let strengthText;
if (strength < 0.5) strengthText = 'Débil';
else if (strength < 1.5) strengthText = 'Moderada';
else strengthText = 'Fuerte';
// Update UI
document.getElementById('combinedPrediction').textContent = `$${combinedPrediction.toFixed(2)}`;
const confidenceElement = document.getElementById('combinedConfidence');
const confidenceValue = confidenceElement.querySelector('.confidence-value');
const confidenceText = confidenceElement.querySelector('.confidence-text');
confidenceValue.textContent = `${(combinedConfidence * 100).toFixed(0)}%`;
confidenceText.textContent = combinedConfidence >= 0.7 ? 'Alta' :
combinedConfidence >= 0.5 ? 'Media' : 'Baja';
confidenceElement.className = `ml-2 text-sm flex items-center ${
combinedConfidence >= 0.7 ? 'text-green-500' :
combinedConfidence >= 0.5 ? 'text-yellow-500' : 'text-red-500'
}`;
document.getElementById('predictionDirection').textContent = `Dirección: ${direction}`;
document.getElementById('predictionStrength').textContent = `Fuerza: ${strengthText}`;
// Return values for history
return {
prediction: combinedPrediction,
confidence: combinedConfidence * 100,
direction: direction,
strength: strengthText
};
}
// Save prediction to history
function savePredictionToHistory(currentPrice) {
const now = new Date();
const predictionData = calculateCombinedPrediction();
// Create new prediction entry
const newPrediction = {
timestamp: now.getTime(),
date: now.toISOString(),
currentPrice: currentPrice,
prediction: predictionData.prediction,
confidence: predictionData.confidence,
direction: predictionData.direction,
strength: predictionData.strength,
actualPrice: null, // Will be updated later
accuracy: null, // Will be calculated later
directionCorrect: null // Will be calculated later
};
// Add to history
predictionHistory.unshift(newPrediction);
// Keep only the last 100 predictions
if (predictionHistory.length > 100) {
predictionHistory = predictionHistory.slice(0, 100);
}
// Save to localStorage
localStorage.setItem('predictionHistory', JSON.stringify(predictionHistory));
// Update history table
renderHistoryTable();
}
// Update actual prices for past predictions
function updatePastPredictions(currentPrice) {
const now = new Date();
const fifteenMinutesAgo = now.getTime() - (15 * 60 * 1000);
// Update predictions from 15 minutes ago with actual price
let updated = false;
predictionHistory.forEach(prediction => {
if (prediction.timestamp <= fifteenMinutesAgo && prediction.actualPrice === null) {
prediction.actualPrice = currentPrice;
updated = true;
// Calculate accuracy
if (prediction.prediction && prediction.actualPrice) {
const priceDifference = Math.abs(prediction.prediction - prediction.actualPrice);
const accuracy = 100 - (priceDifference / prediction.actualPrice * 100);
prediction.accuracy = Math.max(0, Math.min(100, accuracy)); // Clamp between 0-100
// Determine if direction was correct
const predictedDirection = prediction.direction === 'Alcista' ? 1 : -1;
const actualDirection = prediction.actualPrice > prediction.currentPrice ? 1 : -1;
prediction.directionCorrect = predictedDirection === actualDirection;
}
}
});
if (updated) {
// Save updated history
localStorage.setItem('predictionHistory', JSON.stringify(predictionHistory));
// Update UI
renderHistoryTable();
updateAccuracyStats();
}
}
// Render history table
function renderHistoryTable() {
const tableBody = document.getElementById('historyTable');
tableBody.innerHTML = '';
predictionHistory.forEach((prediction, index) => {
const row = document.createElement('tr');
const dateCell = document.createElement('td');
dateCell.textContent = new Date(prediction.timestamp).toLocaleString();
const predictionCell = document.createElement('td');
predictionCell.textContent = prediction.prediction ? `$${prediction.prediction.toFixed(2)}` : '--';
const actualCell = document.createElement('td');
if (prediction.actualPrice !== null) {
actualCell.textContent = `$${prediction.actualPrice.toFixed(2)}`;
} else {
actualCell.textContent = '--';
}
const differenceCell = document.createElement('td');
if (prediction.prediction && prediction.actualPrice !== null) {
const difference = prediction.actualPrice - prediction.prediction;
const absDifference = Math.abs(difference);
const differenceText = `$${absDifference.toFixed(2)} (${(absDifference / prediction.prediction * 100).toFixed(2)}%)`;
if (difference > 0) {
differenceCell.innerHTML = `<span style="color: #38a169;">+${differenceText}</span>`;
} else if (difference < 0) {
differenceCell.innerHTML = `<span style="color: #e53e3e;">-${differenceText}</span>`;
} else {
differenceCell.textContent = differenceText;
}
} else {
differenceCell.textContent = '--';
}
const accuracyCell = document.createElement('td');
if (prediction.accuracy !== null) {
const accuracyText = `${prediction.accuracy.toFixed(1)}%`;
if (prediction.accuracy >= 90) {
accuracyCell.innerHTML = `<span style="color: #38a169;">${accuracyText}</span>`;
} else if (prediction.accuracy >= 70) {
accuracyCell.innerHTML = `<span style="color: #d69e2e;">${accuracyText}</span>`;
} else {
accuracyCell.innerHTML = `<span style="color: #e53e3e;">${accuracyText}</span>`;
}
} else {
accuracyCell.textContent = '--';
}
const directionCell = document.createElement('td');
if (prediction.directionCorrect !== null) {
if (prediction.directionCorrect) {
directionCell.innerHTML = `<span style="color: #38a169;">Correcta</span>`;
} else {
directionCell.innerHTML = `<span style="color: #e53e3e;">Incorrecta</span>`;
}
} else {
directionCell.textContent = '--';
}
row.appendChild(dateCell);
row.appendChild(predictionCell);
row.appendChild(actualCell);
row.appendChild(differenceCell);
row.appendChild(accuracyCell);
row.appendChild(directionCell);
tableBody.appendChild(row);
});
}
// Update accuracy statistics
function updateAccuracyStats() {
const completedPredictions = predictionHistory.filter(p => p.accuracy !== null);
if (completedPredictions.length > 0) {
const totalAccuracy = completedPredictions.reduce((sum, p) => sum + p.accuracy, 0);
const avgAccuracy = totalAccuracy / completedPredictions.length;
const correctDirections = completedPredictions.filter(p => p.directionCorrect).length;
document.getElementById('avgAccuracy').textContent = `${avgAccuracy.toFixed(1)}%`;
document.getElementById('correctPredictions').textContent = `${correctDirections}/${completedPredictions.length}`;
// Update accuracy gauge
updateAccuracyGauge(avgAccuracy);
}
}
// Update accuracy gauge chart
function updateAccuracyGauge(accuracy) {
if (!accuracyGauge) {
const ctx = document.getElementById('accuracyGauge').getContext('2d');
accuracyGauge = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [{
data: [accuracy, 100 - accuracy],
backgroundColor: [
getAccuracyColor(accuracy),
'#f3f4f6'
],
borderWidth: 0
}]
},
options: {
cutout: '80%',
rotation: -90,
circumference: 180,
plugins: {
legend: {
display: false
},
tooltip: {
enabled: false
}
}
}
});
} else {
accuracyGauge.data.datasets[0].data = [accuracy, 100 - accuracy];
accuracyGauge.data.datasets[0].backgroundColor[0] = getAccuracyColor(accuracy);
accuracyGauge.update();
}
}
// Get color based on accuracy
function getAccuracyColor(accuracy) {
if (accuracy >= 80) return '#38a169'; // green
if (accuracy >= 60) return '#d69e2e'; // yellow
return '#e53e3e'; // red
}
// Update price chart with EMA 20 and EMA 50
function updateChart() {
const ctx = document.getElementById('priceChart').getContext('2d');
const timeframe = document.getElementById('timeframe').value;
// Prepare data for chart
const labels = historicalData.map(item => new Date(item.timestamp));
const prices = historicalData.map(item => item.price);
// Calculate EMA (Exponential Moving Average) functions
function calculateEMA(data, period) {
const k = 2 / (period + 1);
const ema = [];
let sum = 0;
// Simple moving average for first period values
for (let i = 0; i < period; i++) {
sum += data[i];
ema.push(null);
}
// First EMA value is the SMA
ema[period - 1] = sum / period;
// Calculate EMA for remaining values
for (let i = period; i < data.length; i++) {
ema[i] = data[i] * k + ema[i - 1] * (1 - k);
}
return ema;
}
// Calculate EMAs
const ema20 = calculateEMA(prices, 20);
const ema50 = calculateEMA(prices, 50);
// Create or update chart
if (!priceChart) {
priceChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'Precio BTC',
data: prices,
borderColor: '#3182ce',
backgroundColor: 'rgba(49, 130, 206, 0.05)',
borderWidth: 2,
fill: true,
tension: 0.4
},
{
label: 'EMA 20',
data: ema20,
borderColor: '#d69e2e',
borderWidth: 1.5,
pointRadius: 0,
tension: 0.4
},
{
label: 'EMA 50',
data: ema50,
borderColor: '#805ad5',
borderWidth: 1.5,
pointRadius: 0,
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
type: 'time',
time: {
unit: timeframe <= 1 ? 'hour' :
timeframe <= 24 ? 'day' : 'week',
displayFormats: {
hour: 'HH:mm',
day: 'MMM d',
week: 'MMM d'
}
},
grid: {
display: false
}
},
y: {
beginAtZero: false,
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
ticks: {
callback: function(value) {
return '$' + value.toLocaleString();
}
}
}
},
plugins: {
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += '$' + context.parsed.y.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
return label;
}
}
},
legend: {
position: 'top',
align: 'end'
}
},
interaction: {
mode: 'nearest',
axis: 'x',
intersect: false
}
}
});
} else {
priceChart.data.labels = labels;
priceChart.data.datasets[0].data = prices;
priceChart.data.datasets[1].data = ema20;
priceChart.data.datasets[2].data = ema50;
// Update time unit based on timeframe
priceChart.options.scales.x.time.unit = timeframe <= 1 ? 'hour' :
timeframe <= 24 ? 'day' : 'week';
priceChart.update();
}
}
// Set up auto-refresh
function setupAutoRefresh() {
const autoRefreshCheckbox = document.getElementById('autoRefresh');
autoRefreshCheckbox.addEventListener('change', function() {
if (this.checked) {
scheduleNextRefresh();
} else {
clearTimeout(autoRefreshInterval);
document.getElementById('nextRefresh').textContent = '--:--';
}
});
// Initial schedule
if (autoRefreshCheckbox.checked) {
scheduleNextRefresh();
}
}
// Schedule next refresh
function scheduleNextRefresh() {
clearTimeout(autoRefreshInterval);
const now = new Date();
const nextRefresh = new Date(now.getTime() + 15 * 60 * 1000); // 15 minutes from now
document.getElementById('nextRefresh').textContent = nextRefresh.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
autoRefreshInterval = setTimeout(() => {
fetchData();
if (document.getElementById('autoRefresh').checked) {
scheduleNextRefresh();
}
}, 15 * 60 * 1000);
}
// Export history as JSON
function exportHistory() {
const dataStr = JSON.stringify(predictionHistory, null, 2);
const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
const exportFileDefaultName = `bitcoin-predictions-${new Date().toISOString().slice(0, 10)}.json`;
const linkElement = document.createElement('a');
linkElement.setAttribute('href', dataUri);
linkElement.setAttribute('download', exportFileDefaultName);
linkElement.click();
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=notecortes3/btcpro" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>