npp-hft-winv25-scalper/simulador_hft.html
2025-08-14 16:01:41 -03:00

480 lines
No EOL
16 KiB
HTML

<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simulador HFT WINV25</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #1a1a1a;
color: #ffffff;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.panel {
background-color: #2d2d2d;
border: 1px solid #444;
border-radius: 8px;
padding: 15px;
margin: 10px 0;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
margin-bottom: 20px;
}
.control-group {
display: flex;
flex-direction: column;
}
label {
color: #aaa;
font-size: 12px;
margin-bottom: 5px;
}
input {
background-color: #3a3a3a;
border: 1px solid #555;
color: #fff;
padding: 8px;
border-radius: 4px;
}
button {
background-color: #0066cc;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover {
background-color: #0088ff;
}
button.stop {
background-color: #cc0000;
}
button.stop:hover {
background-color: #ff0000;
}
.chart-area {
background-color: #1a1a1a;
border: 1px solid #444;
height: 300px;
display: flex;
align-items: center;
justify-content: center;
color: #666;
margin: 20px 0;
}
.logs {
background-color: #0a0a0a;
border: 1px solid #333;
height: 200px;
overflow-y: auto;
padding: 10px;
font-family: monospace;
font-size: 12px;
}
.position {
padding: 10px;
border-radius: 4px;
margin: 5px 0;
}
.position.long {
background-color: #1a4a1a;
border: 1px solid #2a7a2a;
}
.position.short {
background-color: #4a1a1a;
border: 1px solid #7a2a2a;
}
.position.neutral {
background-color: #2a2a2a;
border: 1px solid #4a4a4a;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
}
.metric {
text-align: center;
padding: 10px;
background-color: #333;
border-radius: 4px;
}
.metric-value {
font-size: 18px;
font-weight: bold;
color: #00ff88;
}
.metric-label {
font-size: 12px;
color: #aaa;
}
</style>
</head>
<body>
<div class="container">
<h1>🤖 Simulador HFT WINV25</h1>
<div class="panel">
<h3>⚙️ Configurações do Robô</h3>
<div class="controls">
<div class="control-group">
<label>Take Profit (pontos)</label>
<input type="number" id="takeProfit" value="15">
</div>
<div class="control-group">
<label>Stop Loss (pontos)</label>
<input type="number" id="stopLoss" value="10">
</div>
<div class="control-group">
<label>Volume Mínimo</label>
<input type="number" id="volumeMin" value="100">
</div>
<div class="control-group">
<label>Preço Atual</label>
<input type="number" id="currentPrice" value="130000" step="1">
</div>
<div class="control-group">
<label>Volume Atual</label>
<input type="number" id="currentVolume" value="150">
</div>
<div class="control-group">
<label>Hora Atual (HHMM)</label>
<input type="text" id="currentTime" value="1030">
</div>
</div>
<div>
<button onclick="startSimulation()">▶️ Iniciar Simulação</button>
<button onclick="stopSimulation()" class="stop">⏹️ Parar</button>
<button onclick="executeManualTrade('BUY')">📈 Compra Manual</button>
<button onclick="executeManualTrade('SELL')">📉 Venda Manual</button>
<button onclick="closePosition()">❌ Fechar Posição</button>
<button onclick="clearLogs()">🗑️ Limpar Logs</button>
</div>
</div>
<div class="panel">
<h3>📊 Status da Posição</h3>
<div id="positionStatus" class="position neutral">
<strong>Sem Posição</strong><br>
Aguardando sinal de entrada...
</div>
</div>
<div class="panel">
<h3>📈 Métricas de Performance</h3>
<div class="metrics">
<div class="metric">
<div class="metric-value" id="totalTrades">0</div>
<div class="metric-label">Total Operações</div>
</div>
<div class="metric">
<div class="metric-value" id="winRate">0%</div>
<div class="metric-label">Taxa de Acerto</div>
</div>
<div class="metric">
<div class="metric-value" id="totalPL">R$ 0</div>
<div class="metric-label">P&L Total</div>
</div>
<div class="metric">
<div class="metric-value" id="currentPL">R$ 0</div>
<div class="metric-label">P&L Atual</div>
</div>
</div>
</div>
<div class="panel">
<h3>📝 Log de Operações</h3>
<div id="logs" class="logs">
<div style="color: #888;">Simulador iniciado. Configure os parâmetros e clique em "Iniciar Simulação"</div>
</div>
</div>
</div>
<script>
// Variáveis do simulador
let isRunning = false;
let position = 0; // 0 = sem posição, >0 = comprado, <0 = vendido
let entryPrice = 0;
let trades = [];
let simulationInterval;
// Métricas
let totalTrades = 0;
let winningTrades = 0;
let totalPL = 0;
function log(message) {
const logs = document.getElementById('logs');
const timestamp = new Date().toLocaleTimeString();
logs.innerHTML += `<div>[${timestamp}] ${message}</div>`;
logs.scrollTop = logs.scrollHeight;
}
function updateMetrics() {
document.getElementById('totalTrades').textContent = totalTrades;
document.getElementById('winRate').textContent = totalTrades > 0 ?
Math.round((winningTrades / totalTrades) * 100) + '%' : '0%';
document.getElementById('totalPL').textContent = `R$ ${totalPL.toFixed(2)}`;
// P&L atual da posição
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
let currentPL = 0;
if (position > 0) {
currentPL = (currentPrice - entryPrice) * 0.20; // R$ 0,20 por ponto
} else if (position < 0) {
currentPL = (entryPrice - currentPrice) * 0.20;
}
document.getElementById('currentPL').textContent = `R$ ${currentPL.toFixed(2)}`;
}
function updatePositionStatus() {
const statusDiv = document.getElementById('positionStatus');
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
if (position === 0) {
statusDiv.className = 'position neutral';
statusDiv.innerHTML = '<strong>Sem Posição</strong><br>Aguardando sinal de entrada...';
} else if (position > 0) {
const pl = (currentPrice - entryPrice) * 0.20;
statusDiv.className = 'position long';
statusDiv.innerHTML = `
<strong>COMPRADO</strong><br>
Entrada: ${entryPrice.toFixed(0)} pontos<br>
Atual: ${currentPrice.toFixed(0)} pontos<br>
P&L: R$ ${pl.toFixed(2)}
`;
} else {
const pl = (entryPrice - currentPrice) * 0.20;
statusDiv.className = 'position short';
statusDiv.innerHTML = `
<strong>VENDIDO</strong><br>
Entrada: ${entryPrice.toFixed(0)} pontos<br>
Atual: ${currentPrice.toFixed(0)} pontos<br>
P&L: R$ ${pl.toFixed(2)}
`;
}
}
function checkHorarioOperacao() {
const timeStr = document.getElementById('currentTime').value;
const hour = parseInt(timeStr.substring(0, 2));
const minute = parseInt(timeStr.substring(2, 4));
// Horário de operação: 08:55 às 17:45
if (hour < 8 || hour > 17) return false;
if (hour === 8 && minute < 55) return false;
if (hour === 17 && minute > 45) return false;
return true;
}
function checkEntrySignal() {
if (!checkHorarioOperacao()) return null;
if (position !== 0) return null;
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
const volume = parseFloat(document.getElementById('currentVolume').value);
const minVolume = parseFloat(document.getElementById('volumeMin').value);
if (volume < minVolume) return null;
// Simular condições de entrada (simplificado)
const randomFactor = Math.random();
if (randomFactor > 0.7) {
return 'BUY';
} else if (randomFactor < 0.3) {
return 'SELL';
}
return null;
}
function executeManualTrade(signal) {
if (position !== 0) {
log('❌ Já existe uma posição aberta');
return;
}
if (!checkHorarioOperacao()) {
log('❌ Fora do horário de operação');
return;
}
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
if (signal === 'BUY') {
position = 1;
entryPrice = currentPrice;
log(`📈 COMPRA executada em ${entryPrice.toFixed(0)} pontos`);
} else {
position = -1;
entryPrice = currentPrice;
log(`📉 VENDA executada em ${entryPrice.toFixed(0)} pontos`);
}
updatePositionStatus();
}
function checkExitSignal() {
if (position === 0) return false;
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
const takeProfit = parseFloat(document.getElementById('takeProfit').value);
const stopLoss = parseFloat(document.getElementById('stopLoss').value);
if (position > 0) {
// Posição comprada
if (currentPrice >= entryPrice + takeProfit) {
executeExit('Take Profit');
return true;
} else if (currentPrice <= entryPrice - stopLoss) {
executeExit('Stop Loss');
return true;
}
} else {
// Posição vendida
if (currentPrice <= entryPrice - takeProfit) {
executeExit('Take Profit');
return true;
} else if (currentPrice >= entryPrice + stopLoss) {
executeExit('Stop Loss');
return true;
}
}
return false;
}
function executeExit(reason) {
if (position === 0) return;
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
let pl = 0;
if (position > 0) {
pl = (currentPrice - entryPrice) * 0.20;
log(`📉 Venda executada em ${currentPrice.toFixed(0)} pontos (${reason})`);
} else {
pl = (entryPrice - currentPrice) * 0.20;
log(`📈 Compra para cobrir executada em ${currentPrice.toFixed(0)} pontos (${reason})`);
}
totalTrades++;
if (pl > 0) winningTrades++;
totalPL += pl;
log(`💰 P&L: R$ ${pl.toFixed(2)} | Motivo: ${reason}`);
trades.push({
entry: entryPrice,
exit: currentPrice,
pl: pl,
reason: reason
});
position = 0;
entryPrice = 0;
updatePositionStatus();
updateMetrics();
}
function closePosition() {
if (position === 0) {
log('❌ Não há posição para fechar');
return;
}
executeExit('Fechamento Manual');
}
function simulateMarket() {
// Simular movimento de preço
const currentPrice = parseFloat(document.getElementById('currentPrice').value);
const variation = (Math.random() - 0.5) * 10; // Variação de -5 a +5 pontos
const newPrice = currentPrice + variation;
document.getElementById('currentPrice').value = newPrice.toFixed(0);
// Simular volume
const newVolume = Math.floor(Math.random() * 300) + 50;
document.getElementById('currentVolume').value = newVolume;
// Avançar tempo (simulação)
const timeStr = document.getElementById('currentTime').value;
let hour = parseInt(timeStr.substring(0, 2));
let minute = parseInt(timeStr.substring(2, 4));
minute += 1;
if (minute >= 60) {
minute = 0;
hour += 1;
}
const newTime = hour.toString().padStart(2, '0') + minute.toString().padStart(2, '0');
document.getElementById('currentTime').value = newTime;
}
function runSimulation() {
if (!isRunning) return;
// Simular mercado
simulateMarket();
// Verificar saída
if (checkExitSignal()) {
updatePositionStatus();
updateMetrics();
return;
}
// Verificar entrada
const signal = checkEntrySignal();
if (signal) {
executeManualTrade(signal);
}
updatePositionStatus();
updateMetrics();
}
function startSimulation() {
if (isRunning) return;
isRunning = true;
log('🚀 Simulação iniciada');
simulationInterval = setInterval(runSimulation, 1000); // 1 segundo
}
function stopSimulation() {
if (!isRunning) return;
isRunning = false;
clearInterval(simulationInterval);
log('⏹️ Simulação parada');
}
function clearLogs() {
document.getElementById('logs').innerHTML =
'<div style="color: #888;">Logs limpos. Simulador pronto.</div>';
}
// Inicialização
updatePositionStatus();
updateMetrics();
</script>
</body>
</html>