<title>📊 RALF ULTRA · TRAILING STOP · PREÇO JUSTO · OPERAÇÕES · STATUS</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: radial-gradient(circle at 20% 30%, #0a0c12, #020408);
color: #eef2ff;
font-family: 'Segoe UI', 'Inter', system-ui, sans-serif;
padding: 16px;
min-height: 100vh;
}
.container {
max-width: 1600px;
margin: 0 auto;
}
.painel-ralf {
background: linear-gradient(145deg, #0f172a, #080c16);
border-radius: 24px;
border: 1px solid #f59e0b;
overflow: hidden;
}
/* CABEÇALHO */
.header {
background: linear-gradient(135deg, #1a2333, #0f172a);
padding: 16px 24px;
border-bottom: 2px solid #f59e0b;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
}
.header h2 { font-size: 1rem; background: linear-gradient(135deg, #f59e0b, #22c55e); -webkit-background-clip: text; background-clip: text; color: transparent; }
.modo-container { display: flex; gap: 10px; background: #1e293b; padding: 6px; border-radius: 60px; }
.modo-btn { padding: 8px 20px; border-radius: 40px; border: none; font-weight: bold; font-size: 0.8rem; cursor: pointer; background: #334155; color: #94a3b8; }
.modo-btn.real.ativo { background: #22c55e; color: black; }
.modo-btn.simulador.ativo { background: #f59e0b; color: black; }
.capital-panel { background: #1e293b; padding: 6px 16px; border-radius: 40px; font-size: 0.8rem; }
.toggle-ralf { display: flex; align-items: center; gap: 12px; background: #1e293b; padding: 6px 16px; border-radius: 40px; }
.switch-ralf { width: 50px; height: 24px; background: #334155; border-radius: 30px; cursor: pointer; position: relative; transition: 0.2s; }
.switch-ralf.active { background: #22c55e; }
.switch-ralf::after { content: ""; width: 20px; height: 20px; background: white; border-radius: 50%; position: absolute; top: 2px; left: 3px; transition: 0.2s; }
.switch-ralf.active::after { left: 27px; }
/* BLOCOS DE INFORMAÇÕES CENTRALIZADAS */
.info-central {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
padding: 20px 24px;
background: #0f172a;
border-bottom: 1px solid #1e293b;
}
.info-card {
background: #1e293b;
border-radius: 16px;
padding: 12px;
text-align: center;
}
.info-titulo { font-size: 0.65rem; color: #94a3b8; margin-bottom: 5px; }
.info-valor { font-size: 1.3rem; font-weight: bold; }
.info-status { font-size: 0.7rem; margin-top: 5px; }
.operacoes-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 12px;
padding: 16px 24px;
background: #0f172a;
border-bottom: 1px solid #1e293b;
}
.operacao-card {
background: #1e293b;
border-radius: 12px;
padding: 10px;
text-align: center;
}
.operacao-numero { font-size: 1.5rem; font-weight: bold; }
.operacao-verde { color: #22c55e; }
.operacao-vermelho { color: #ef4444; }
/* TRAILING STOP */
.trailing-stop {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 24px;
background: #0f172a;
border-bottom: 1px solid #1e293b;
flex-wrap: wrap;
gap: 15px;
}
.stop-control {
display: flex;
align-items: center;
gap: 10px;
}
.stop-switch {
width: 50px;
height: 24px;
background: #334155;
border-radius: 30px;
cursor: pointer;
position: relative;
transition: 0.2s;
}
.stop-switch.active { background: #22c55e; }
.stop-switch::after { content: ""; width: 20px; height: 20px; background: white; border-radius: 50%; position: absolute; top: 2px; left: 3px; transition: 0.2s; }
.stop-switch.active::after { left: 27px; }
.stop-input { background: #1e293b; border: 1px solid #334155; border-radius: 20px; padding: 6px 12px; color: white; width: 80px; text-align: center; }
/* PREÇO JUSTO */
.preco-justo-card {
background: linear-gradient(135deg, #1a2333, #0f172a);
border-radius: 16px;
padding: 12px 24px;
margin: 0 24px 16px 24px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
border: 1px solid #3b82f6;
}
/* GRÁFICO COM CONTROLE DE MINIMIZAR */
.grafico-container {
padding: 20px 24px;
}
.grafico-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.grafico-controls button {
background: #1e293b;
border: none;
border-radius: 8px;
padding: 6px 12px;
color: white;
cursor: pointer;
margin-left: 8px;
}
.candle-wrapper {
background: #0a0c18;
border-radius: 16px;
padding: 16px;
transition: all 0.3s ease;
overflow: hidden;
}
.candle-wrapper.minimizado {
height: 80px;
padding: 8px;
}
.candle-wrapper.minimizado canvas {
height: 60px !important;
}
canvas { width: 100%; height: 450px; background: #0a0c18; border-radius: 12px; transition: height 0.3s; }
/* LEGENDAS */
.legendas { display: flex; justify-content: center; gap: 30px; margin-top: 12px; font-size: 0.65rem; flex-wrap: wrap; }
/* MERCADO */
.mercado-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
padding: 16px 24px;
background: #0f172a;
border-top: 1px solid #1e293b;
}
.mercado-card { background: #1e293b; border-radius: 12px; padding: 10px; }
.mercado-titulo { font-size: 0.65rem; color: #94a3b8; margin-bottom: 8px; border-bottom: 1px solid #334155; padding-bottom: 4px; }
.mercado-item { display: flex; justify-content: space-between; padding: 4px 0; font-size: 0.65rem; }
.cruzamento { font-weight: bold; font-size: 0.8rem; margin-top: 5px; }
.historico-area {
padding: 12px 24px;
background: #0f172a;
border-top: 1px solid #1e293b;
max-height: 100px;
overflow-y: auto;
font-size: 0.65rem;
}
.rodape { padding: 12px; text-align: center; font-size: 0.65rem; color: #475569; border-top: 1px solid #1e293b; }
@media (max-width: 768px) {
.info-central, .operacoes-grid, .mercado-grid { grid-template-columns: repeat(2, 1fr); }
}
</style>
📊 RALF ULTRA · TRAILING STOP · PREÇO JUSTO · OPERAÇÕES · STATUS
💰 CONTA REAL
🎮 SIMULADOR
💰 SALDO: R$ 10.000
<!-- BLOCO 1: INFORMAÇÕES CENTRAIS (Ativo, Preço, Status) -->
<div class="info-central">
<div class="info-card">
<div class="info-titulo">🎯 ATIVO OPERADO</div>
<div class="info-valor" id="ativoOperado">📈 WIN (ÍNDICE)</div>
<div class="info-status" id="statusAtivo">🟢 ATIVO</div>
</div>
<div class="info-card">
<div class="info-titulo">📊 PREÇO ATUAL</div>
<div class="info-valor" id="precoAtualDisplay">118.340</div>
<div class="info-status" id="variacaoDisplay">▲ +0.23%</div>
</div>
<div class="info-card">
<div class="info-titulo">📈 ÍNDICE (WIN)</div>
<div class="info-valor" id="statusIndice">🟢 SOBREVENDIDO</div>
<div class="info-status">RSI: <span id="rsiIndice">32.5</span></div>
</div>
<div class="info-card">
<div class="info-titulo">💵 DÓLAR (WDO)</div>
<div class="info-valor" id="statusDolar">🔴 SOBRECOMPRADO</div>
<div class="info-status">RSI: <span id="rsiDolar">72.3</span></div>
</div>
</div>
<!-- BLOCO 2: OPERAÇÕES (Vencedoras, Perdedoras, Ganho/Perda Diária, Abertas) -->
<div class="operacoes-grid">
<div class="operacao-card">
<div class="info-titulo">✅ OPERAÇÕES VENCEDORAS</div>
<div class="operacao-numero operacao-verde" id="opsVencedoras">0</div>
</div>
<div class="operacao-card">
<div class="info-titulo">❌ OPERAÇÕES PERDEDORAS</div>
<div class="operacao-numero operacao-vermelho" id="opsPerdedoras">0</div>
</div>
<div class="operacao-card">
<div class="info-titulo">📈 GANHO DIÁRIO</div>
<div class="operacao-numero operacao-verde" id="ganhoDiario">R$ 0,00</div>
</div>
<div class="operacao-card">
<div class="info-titulo">📉 PERDA DIÁRIA</div>
<div class="operacao-numero operacao-vermelho" id="perdaDiaria">R$ 0,00</div>
</div>
<div class="operacao-card">
<div class="info-titulo">🔄 OPERAÇÕES ABERTAS</div>
<div class="operacao-numero" id="opsAbertas">0</div>
</div>
<div class="operacao-card">
<div class="info-titulo">🎯 TAXA ACERTO</div>
<div class="operacao-numero operacao-verde" id="taxaAcerto">0%</div>
</div>
</div>
<!-- BLOCO 3: TRAILING STOP TÉCNICO -->
<div class="trailing-stop">
<div class="stop-control">
<span>🛡️ TRAILING STOP TÉCNICO</span>
<div id="trailingStopSwitch" class="stop-switch"></div>
<span id="trailingStopStatus">DESLIGADO</span>
</div>
<div class="stop-control">
<span>📏 DISTÂNCIA (pontos):</span>
<input type="number" id="trailingDistancia" class="stop-input" value="50" step="10">
<span>📊 STOP ATUAL:</span>
<span id="stopAtual" style="background:#1e293b; padding:4px 12px; border-radius:20px;">---</span>
</div>
</div>
<!-- BLOCO 4: PREÇO JUSTO + MÉTRICAS -->
<div class="preco-justo-card">
<div><span>💰 PREÇO JUSTO: </span><strong id="precoJusto">118.200</strong></div>
<div><span>📊 MÉDIA MÓVEL 20: </span><strong id="media20">118.150</strong></div>
<div><span>📈 RESISTÊNCIA: </span><strong id="resistencia">118.600</strong></div>
<div><span>📉 SUPORTE: </span><strong id="suporte">118.080</strong></div>
<div><span>⚡ DISTORÇÃO: </span><strong id="distorcao">-0.12%</strong></div>
</div>
<!-- GRÁFICO COM CONTROLE DE MINIMIZAR -->
<div class="grafico-container">
<div class="grafico-header">
<span>📊 GRÁFICO DE VELAS + BANDAS + HISTOGRAMA RSI</span>
<div class="grafico-controls">
<button id="minimizarGrafico">─ MINIMIZAR</button>
<button id="maximizarGrafico">🗖 MAXIMIZAR</button>
<button id="toggleBandasBtn">📉 ESCONDER BANDAS</button>
</div>
</div>
<div id="candleWrapper" class="candle-wrapper">
<canvas id="candleCanvas" width="1200" height="450"></canvas>
</div>
<div class="legendas">
<span>🟡 SUPERIOR (Máx)</span>
<span>⚪ CENTRAL (Exaustão)</span>
<span>🟣 INFERIOR (Mín)</span>
<span>🟢 Candle COMPRA</span>
<span>🔴 Candle VENDA</span>
<span>📊 Histograma RSI</span>
</div>
</div>
<!-- ANÁLISE DE MERCADO -->
<div class="mercado-grid">
<div class="mercado-card">
<div class="mercado-titulo">🇧🇷 AÇÕES BR</div>
<div class="mercado-item"><span>PETR4</span><span id="petr4">▲ +2.34%</span></div>
<div class="mercado-item"><span>VALE3</span><span id="vale3">▲ +1.87%</span></div>
<div class="mercado-item"><span>ITUB4</span><span id="itub4">▲ +1.23%</span></div>
</div>
<div class="mercado-card">
<div class="mercado-titulo">🇺🇸 AÇÕES EUA</div>
<div class="mercado-item"><span>NASDAQ</span><span id="nasdaq">▲ +0.87%</span></div>
<div class="mercado-item"><span>S&P500</span><span id="sp500">▲ +0.54%</span></div>
<div class="mercado-item"><span>DOW</span><span id="dow">● -0.12%</span></div>
</div>
<div class="mercado-card">
<div class="mercado-titulo">🇪🇺 AÇÕES EUROPA</div>
<div class="mercado-item"><span>DAX</span><span id="dax">▲ +0.45%</span></div>
<div class="mercado-item"><span>FTSE</span><span id="ftse">▲ +0.32%</span></div>
<div class="mercado-item"><span>EUROSTOXX</span><span id="euro">▲ +0.28%</span></div>
</div>
<div class="mercado-card">
<div class="mercado-titulo">📉 5 CURVAS JUROS</div>
<div class="mercado-item"><span>DI1F26</span><span id="di26">12.24%</span></div>
<div class="mercado-item"><span>DI1F27</span><span id="di27">12.34%</span></div>
<div class="mercado-item"><span>DI1F28</span><span id="di28">12.41%</span></div>
<div class="mercado-item"><span>DI1F29</span><span id="di29">12.48%</span></div>
<div class="mercado-item"><span>DI1F30</span><span id="di30">12.52%</span></div>
</div>
<div class="mercado-card">
<div class="mercado-titulo">💰 COMMODITIES</div>
<div class="mercado-item"><span>PETRÓLEO</span><span id="wti">▲ $78.63</span></div>
<div class="mercado-item"><span>OURO</span><span id="ouro">▲ $2,344</span></div>
<div class="mercado-item"><span>SOJA</span><span id="soja">▲ $12.45</span></div>
</div>
</div>
<!-- HISTÓRICO -->
<div class="historico-area" id="historicoTrades">
<div>🟢 Sistema inicializado. Aguardando sinais do mercado...</div>
</div>
<div class="rodape">
🧠 RALF ULTRA · TRAILING STOP · PREÇO JUSTO · STATUS SOBREVENDIDO/SOBRECOMPRADO · PIP SONORO
</div>
</div>
<script>
// ========== CONFIGURAÇÕES ==========
let modoReal = true;
let pipAtivo = true;
let trailingStopAtivo = false;
let bandasVisiveis = true;
let audioCtx = null;
let capital = 10000;
let operacoesVencedoras = 0;
let operacoesPerdedoras = 0;
let ganhoDiario = 0;
let perdaDiaria = 0;
let opsAbertas = 0;
let ativoAtual = "WIN (ÍNDICE)";
let precoEntradaAtual = 0;
let stopAtual = 0;
// Preços
let precoIndice = 118340;
let precoDolar = 5.2345;
let precoUSD_MXN = 20.45;
let historicoPrecos = [];
let historicoRSI = [];
// Bandas VIVAS
let bandaSuperior = 118600;
let bandaCentral = 118340;
let bandaInferior = 118080;
// RSI
let rsiIndice = 50;
let rsiDolar = 50;
// Tendência de juros
let tendenciaJuros = "ALTA";
// Velas
let velas = [];
let ultimoSinal = "";
// ========== SOM PIP ==========
function tocarPip(texto) {
if (!pipAtivo) return;
try {
if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
if (audioCtx.state === 'suspended') audioCtx.resume();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.frequency.value = 880;
gain.gain.value = 0.25;
osc.start();
gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 0.4);
osc.stop(audioCtx.currentTime + 0.4);
console.log(`🔊 PIP: ${texto}`);
// Adicionar ao histórico
let trades = JSON.parse(localStorage.getItem('tradesList') || '[]');
trades.unshift({
hora: new Date().toLocaleTimeString('pt-BR'),
tipo: texto,
preco: precoIndice.toFixed(0)
});
if (trades.length > 20) trades.pop();
localStorage.setItem('tradesList', JSON.stringify(trades));
atualizarHistorico();
} catch(e) {}
}
function atualizarHistorico() {
const trades = JSON.parse(localStorage.getItem('tradesList') || '[]');
const div = document.getElementById('historicoTrades');
if (trades.length === 0) {
div.innerHTML = '
🟢 Aguardando sinais do mercado...
';
return;
}
div.innerHTML = trades.map(t =>
`
[${t.hora}] ${t.tipo} @ ${t.preco}
`
).join('');
}
// ========== CALCULAR RSI ==========
function calcularRSI(precos, periodo = 14) {
if (precos.length < periodo + 1) return 50;
let ganhos = 0, perdas = 0;
for (let i = precos.length - periodo; i < precos.length; i++) {
let diff = precos[i] - precos[i-1];
if (diff > 0) ganhos += diff;
else perdas += Math.abs(diff);
}
let forcaRelativa = ganhos / (perdas === 0 ? 1 : perdas);
return 100 - (100 / (1 + forcaRelativa));
}
// ========== ATUALIZAR BLOCO DE OPERAÇÕES ==========
function atualizarBlocoOperacoes() {
document.getElementById('opsVencedoras').innerHTML = operacoesVencedoras;
document.getElementById('opsPerdedoras').innerHTML = operacoesPerdedoras;
document.getElementById('ganhoDiario').innerHTML = `R$ ${ganhoDiario.toFixed(2)}`;
document.getElementById('perdaDiaria').innerHTML = `R$ ${perdaDiaria.toFixed(2)}`;
document.getElementById('opsAbertas').innerHTML = opsAbertas;
let totalOps = operacoesVencedoras + operacoesPerdedoras;
let taxa = totalOps > 0 ? (operacoesVencedoras / totalOps * 100).toFixed(1) : 0;
document.getElementById('taxaAcerto').innerHTML = `${taxa}%`;
document.getElementById('ativoOperado').innerHTML = ativoAtual;
}
// ========== TRAILING STOP ==========
function verificarTrailingStop() {
if (!trailingStopAtivo || precoEntradaAtual === 0) return false;
let distancia = parseFloat(document.getElementById('trailingDistancia').value) || 50;
let novoStop = precoIndice - distancia;
if (novoStop > stopAtual) {
stopAtual = novoStop;
document.getElementById('stopAtual').innerHTML = stopAtual.toFixed(0);
tocarPip(`🛡️ TRAILING STOP ajustado para ${stopAtual.toFixed(0)}`);
}
if (precoIndice <= stopAtual && opsAbertas > 0) {
opsAbertas--;
let resultado = precoIndice - precoEntradaAtual;
if (resultado > 0) {
operacoesVencedoras++;
ganhoDiario += resultado;
} else {
operacoesPerdedoras++;
perdaDiaria += Math.abs(resultado);
}
capital += resultado;
precoEntradaAtual = 0;
stopAtual = 0;
atualizarBlocoOperacoes();
document.getElementById('capitalDisplay').innerHTML = `R$ ${capital.toFixed(2)}`;
tocarPip(`🔴 STOP atingido! Operação encerrada.`);
return true;
}
return false;
}
// ========== EXECUTAR OPERAÇÃO ==========
function executarOperacao(tipo, preco) {
if (opsAbertas > 0) {
tocarPip("
⚠️ Já existe operação aberta!");
return;
}
opsAbertas = 1;
precoEntradaAtual = preco;
stopAtual = preco - (parseFloat(document.getElementById('trailingDistancia').value) || 50);
document.getElementById('stopAtual').innerHTML = stopAtual.toFixed(0);
tocarPip(`${tipo} ${ativoAtual} @ ${preco.toFixed(0)}`);
}
// ========== ATUALIZAR MERCADO ==========
function atualizarMercado() {
// Simular tendência de juros
tendenciaJuros = Math.random() > 0.45 ? "ALTA" : "BAIXA";
// Atualizar preços
let variacaoIndice = (Math.random() - 0.5) * 80;
if (tendenciaJuros === "ALTA") variacaoIndice -= 25;
else variacaoIndice += 25;
precoIndice += variacaoIndice;
precoIndice = Math.min(119800, Math.max(117000, precoIndice));
precoDolar += (Math.random() - 0.5) * 0.015;
precoDolar = Math.min(5.50, Math.max(5.10, precoDolar));
historicoPrecos.push(precoIndice);
if (historicoPrecos.length > 50) historicoPrecos.shift();
// Calcular RSI
rsiIndice = calcularRSI(historicoPrecos, 14);
rsiDolar = 50 + (Math.random() - 0.5) * 40;
// Atualizar status
document.getElementById('precoAtualDisplay').innerHTML = precoIndice.toFixed(0);
document.getElementById('statusIndice').innerHTML = rsiIndice < 30 ? "🟢 SOBREVENDIDO" : (rsiIndice > 70 ? "🔴 SOBRECOMPRADO" : "⚪ NEUTRO");
document.getElementById('statusIndice').style.color = rsiIndice < 30 ? "#22c55e" : (rsiIndice > 70 ? "#ef4444" : "#fbbf24");
document.getElementById('rsiIndice').innerHTML = rsiIndice.toFixed(1);
document.getElementById('statusDolar').innerHTML = rsiDolar < 30 ? "🟢 SOBREVENDIDO" : (rsiDolar > 70 ? "🔴 SOBRECOMPRADO" : "⚪ NEUTRO");
document.getElementById('rsiDolar').innerHTML = rsiDolar.toFixed(1);
// Sinal automático baseado no RSI
if (rsiIndice < 30 && ultimoSinal !== "COMPRA") {
ultimoSinal = "COMPRA";
if (opsAbertas === 0) {
executarOperacao("🟢 COMPRA", precoIndice);
}
} else if (rsiIndice > 70 && ultimoSinal !== "VENDA") {
ultimoSinal = "VENDA";
if (opsAbertas === 0) {
executarOperacao("🔴 VENDA", precoIndice);
}
}
// Verificar trailing stop
verificarTrailingStop();
// Atualizar bandas
let ultimosPrecos = historicoPrecos.slice(-20);
let maxima = Math.max(...ultimosPrecos);
let minima = Math.min(...ultimosPrecos);
let media = ultimosPrecos.reduce((a,b)=>a+b,0)/ultimosPrecos.length;
bandaSuperior = maxima;
bandaCentral = media;
bandaInferior = minima;
// Preço justo
let precoJusto = media * 0.998;
let resistencia = maxima;
let suporte = minima;
let distorcao = ((precoIndice - precoJusto) / precoJusto * 100).toFixed(2);
document.getElementById('precoJusto').innerHTML = precoJusto.toFixed(0);
document.getElementById('media20').innerHTML = media.toFixed(0);
document.getElementById('resistencia').innerHTML = resistencia.toFixed(0);
document.getElementById('suporte').innerHTML = suporte.toFixed(0);
document.getElementById('distorcao').innerHTML = `${distorcao}%`;
// Gerar vela
let variacao = (Math.random() - 0.5) * 60;
let open = precoIndice;
let close = precoIndice + variacao;
let high = Math.max(open, close) + Math.random() * 30;
let low = Math.min(open, close) - Math.random() * 30;
let cor = "NEUTRO";
if (rsiIndice < 30) cor = "COMPRA";
else if (rsiIndice > 70) cor = "VENDA";
velas.push({ open, high, low, close, cor });
if (velas.length > 50) velas.shift();
historicoRSI.push(rsiIndice);
if (historicoRSI.length > 50) historicoRSI.shift();
// Atualizar ações
document.getElementById('petr4').innerHTML = tendenciaJuros === "ALTA" ? "▲ +1.23%" : "▼ -0.87%";
document.getElementById('nasdaq').innerHTML = tendenciaJuros === "ALTA" ? "▼ -0.34%" : "▲ +0.76%";
desenharGrafico();
atualizarBlocoOperacoes();
document.getElementById('capitalDisplay').innerHTML = `R$ ${capital.toFixed(2)}`;
// Atualizar stop display
if (precoEntradaAtual > 0) {
document.getElementById('stopAtual').innerHTML = stopAtual.toFixed(0);
}
}
// ========== DESENHAR GRÁFICO ==========
function desenharGrafico() {
const canvas = document.getElementById('candleCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const width = canvas.clientWidth;
const height = canvas.clientHeight;
canvas.width = width;
canvas.height = height;
ctx.clearRect(0, 0, width, height);
if (velas.length === 0) return;
let todosPrecos = velas.flatMap(v => [v.high, v.low]);
let maxVal = Math.max(...todosPrecos, bandaSuperior);
let minVal = Math.min(...todosPrecos, bandaInferior);
let range = maxVal - minVal;
if (range === 0) range = 1;
let candleWidth = width / velas.length * 0.7;
let spacing = width / velas.length * 0.3;
let histHeight = 60;
let histY = height - 45;
let graficoHeight = height - histHeight - 50;
function yPos(valor) { return graficoHeight - ((valor - minVal) / range) * (graficoHeight - 20); }
// Velas
for (let i = 0; i < velas.length; i++) {
const v = velas[i];
let x = i * (candleWidth + spacing) + spacing / 2;
let yHigh = yPos(v.high);
let yLow = yPos(v.low);
let yOpen = yPos(v.open);
let yClose = yPos(v.close);
ctx.beginPath();
ctx.moveTo(x + candleWidth/2, yHigh);
ctx.lineTo(x + candleWidth/2, yLow);
ctx.strokeStyle = '#888';
ctx.stroke();
let isGreen = v.close >= v.open;
let cor = v.cor === "COMPRA" ? '#22c55e' : (v.cor === "VENDA" ? '#ef4444' : (isGreen ? '#4ade80' : '#f87171'));
ctx.fillStyle = cor;
ctx.fillRect(x, Math.min(yOpen, yClose), candleWidth, Math.abs(yClose - yOpen));
}
// Bandas (se visíveis)
if (bandasVisiveis) {
ctx.setLineDash([6, 6]);
ctx.beginPath(); ctx.strokeStyle = '#f59e0b'; ctx.lineWidth = 2.5;
let ySup = yPos(bandaSuperior);
ctx.moveTo(0, ySup); ctx.lineTo(width, ySup); ctx.stroke();
ctx.fillStyle = '#f59e0b'; ctx.fillText(`🟡 MÁX: ${bandaSuperior.toFixed(0)}`, 10, ySup - 5);
ctx.beginPath(); ctx.strokeStyle = '#ffffff'; ctx.lineWidth = 2;
let yCen = yPos(bandaCentral);
ctx.moveTo(0, yCen); ctx.lineTo(width, yCen); ctx.stroke();
ctx.fillStyle = '#ffffff'; ctx.fillText(`⚪ CENTRAL: ${bandaCentral.toFixed(0)}`, 10, yCen - 5);
ctx.beginPath(); ctx.strokeStyle = '#a855f7'; ctx.lineWidth = 2.5;
let yInf = yPos(bandaInferior);
ctx.moveTo(0, yInf); ctx.lineTo(width, yInf); ctx.stroke();
ctx.fillStyle = '#a855f7'; ctx.fillText(`🟣 MÍN: ${bandaInferior.toFixed(0)}`, 10, yInf - 5);
ctx.setLineDash([]);
}
// Histograma RSI
if (historicoRSI.length > 0) {
let histWidth = (width / Math.min(historicoRSI.length, 50)) * 0.7;
let histSpacing = width / Math.min(historicoRSI.length, 50) * 0.3;
for (let i = 0; i < Math.min(historicoRSI.length, 50); i++) {
let rsiVal = historicoRSI[i];
let barHeight = (rsiVal / 100) * histHeight;
let x = i * (histWidth + histSpacing) + histSpacing / 2;
let y = histY - barHeight;
if (rsiVal < 30) ctx.fillStyle = '#22c55e';
else if (rsiVal > 70) ctx.fillStyle = '#ef4444';
else ctx.fillStyle = '#fbbf24';
ctx.fillRect(x, y, histWidth, barHeight);
}
}
ctx.fillStyle = '#94a3b8';
ctx.font = '8px monospace';
ctx.fillText(`📊 RSI: ${rsiIndice.toFixed(1)} | <30 COMPRA | >70 VENDA`, 10, height - 8);
// Preço atual
let yPreco = yPos(precoIndice);
ctx.beginPath(); ctx.strokeStyle = '#22c55e'; ctx.lineWidth = 1.5; ctx.setLineDash([4, 6]);
ctx.moveTo(0, yPreco); ctx.lineTo(width, yPreco); ctx.stroke();
ctx.fillStyle = '#22c55e'; ctx.fillText(`💰 ${precoIndice.toFixed(0)}`, width - 80, yPreco - 5);
ctx.setLineDash([]);
}
// ========== EVENTOS ==========
document.getElementById('modoRealBtn').addEventListener('click', () => {
modoReal = true;
document.getElementById('modoRealBtn').classList.add('ativo');
document.getElementById('modoSimuladorBtn').classList.remove('ativo');
});
document.getElementById('modoSimuladorBtn').addEventListener('click', () => {
modoReal = false;
capital = 10000;
document.getElementById('capitalDisplay').innerHTML = `R$ ${capital.toFixed(2)}`;
document.getElementById('modoRealBtn').classList.remove('ativo');
document.getElementById('modoSimuladorBtn').classList.add('ativo');
});
document.getElementById('pipSwitch').addEventListener('click', function() {
pipAtivo = !pipAtivo;
this.classList.toggle('active', pipAtivo);
});
document.getElementById('trailingStopSwitch').addEventListener('click', function() {
trailingStopAtivo = !trailingStopAtivo;
this.classList.toggle('active', trailingStopAtivo);
document.getElementById('trailingStopStatus').innerHTML = trailingStopAtivo ? "LIGADO" : "DESLIGADO";
document.getElementById('trailingStopStatus').style.color = trailingStopAtivo ? "#22c55e" : "#ef4444";
});
document.getElementById('toggleBandasBtn').addEventListener('click', function() {
bandasVisiveis = !bandasVisiveis;
this.innerHTML = bandasVisiveis ? "📉 ESCONDER BANDAS" : "📈 MOSTRAR BANDAS";
desenharGrafico();
});
document.getElementById('minimizarGrafico').addEventListener('click', () => {
document.getElementById('candleWrapper').classList.add('minimizado');
desenharGrafico();
});
document.getElementById('maximizarGrafico').addEventListener('click', () => {
document.getElementById('candleWrapper').classList.remove('minimizado');
desenharGrafico();
});
// ========== INICIALIZAR ==========
for (let i = 0; i < 30; i++) {
historicoPrecos.push(118000 + (Math.random() - 0.5) * 800);
historicoRSI.push(40 + Math.random() * 40);
velas.push({
open: 118000 + (Math.random() - 0.5) * 800,
high: 118500 + Math.random() * 300,
low: 117500 - Math.random() * 300,
close: 118000 + (Math.random() - 0.5) * 800,
cor: "NEUTRO"
});
}
precoIndice = historicoPrecos[historicoPrecos.length - 1];
setInterval(atualizarMercado, 3000);
atualizarMercado();
atualizarHistorico();
window.addEventListener('resize', () => desenharGrafico());
</script>
📊 RALF ULTRA · TRAILING STOP · PREÇO JUSTO · OPERAÇÕES · STATUS