Rastreador

📊 Observador de Ativo

📊 Observador de Ativo respostas automáticas

A observar
BTCUSDT
Último preço
📌 Última resposta automática
⏳ A aguardar movimento do ativo...
⚡ A ferramenta observa o preço e responde sozinha quando o ativo se move.
📋 Histórico de movimentos registados
Data Ativo Movimento
Nenhum movimento registado.
💾 Memória guardada localmente.

Maximalista BTC

₿ Bitcoiner Maximalista — PannteraDigital

₿ Bitcoiner Maximalista PannteraDigital soberania · auto-custódia · paciência

O que é ser um Bitcoiner Maximalista?

Não é sobre odiar outras criptomoedas. É sobre entender que o Bitcoin é o único ativo que não tem emissor, que não pode ser inflacionado, e que oferece soberania individual — a capacidade de seres o teu próprio banco, sem pedir permissão a ninguém.

Ser maximalista é guardar as tuas próprias chaves, não confiar em terceiros, e construir a tua liberdade tijolo a tijolo, sem pressa, sem medo, sem FOMO.

Não é sobre ficar rico. É sobre ser livre.

🧠

Filosofia

Filosofia

Ser maximalista não é odiar o resto. É reconhecer que o Bitcoin é o único ativo que:

  • Não tem emissor — Só vai haver 21 000 000. Ao contrário do dinheiro FIAT e outros ativos. Isto garante-nos que 1 BTC vale exatamente 1 BTC.
  • Não pode ser confiscado — Nem usado para fins como Guerras, armamento, corrupção.
  • Não pede permissão — para guardar, enviar, receber.
  • Não depende de confiança — a prova de trabalho é a única garantia.

Maximalismo não é uma crença. É uma constatação. Sim, uma certeza lógica de que a escassez ganha mais valor.

"Não preciso de acreditar no Bitcoin. Preciso apenas de entender que funciona."

O maximalista não perde tempo a convencer ninguém. Acumula, guarda, espera. Sabe que o sistema atual é insustentável. Sabe que a inflação é um roubo silencioso. Sabe que a liberdade não se pede — conquista-se.

Ser maximalista é:

  • Ter paciência — o mercado dá e tira, mas o tempo está do teu lado.
  • Não ter medo — se o Bitcoin for a zero, ficas com o mesmo que tinhas antes: nada.
  • Não seguir a manada — compras sempre e mais ainda quando vendem, nunca vendes a menos que precises.

A soberania não é um direito. É uma escolha. Ninguém tem nada a ver com isso. E muito, muito mais.

📄

Paper Wallet + BlueWallet

Segurança Prática

Este é o método que uso há anos. Sem hardware, sem empresas, sem confiança em terceiros. Apenas um papel, uma aplicação temporária, e a disciplina de guardar as tuas próprias chaves.

Não é para quem quer conveniência. É para quem quer soberania.

Exemplo de Paper Wallet Bitcoin

📌 1. Gerar a paper wallet (offline)

  1. Acede ao site bitaddress.org e descarrega o ficheiro HTML da página.
  2. Clica com o botão direito do rato e escolhe "Guardar como". Escolhe o Ambiente de Trabalho. Se não aparecer o atalho, vai aos arquivos e solta o ícone no Ambiente de Trabalho (é intuitivo, guarda quando tiveres a certeza de que é aquela).
  3. Desliga a internet — a geração deve ser offline.
  4. Abre o ficheiro HTML no Ambiente de Trabalho.
  5. Move o rato aleatoriamente até a barra de entropia atingir 100%.
  6. Vai à opção "Paper Wallet" para formatar o documento.
  7. Imprime a carteira em papel de boa qualidade (a impressora também deve estar offline).
💡 Dica extra: Guarda o papel num local seguro (cofre, longe de água e fogo). Cria várias cópias. Uma dica extra: recorta o QR e cola em documentos que nada tenham a ver, mas que só tu sabes.
⚠️ Nunca tires fotografia da chave privada. Nunca.

📥 2. Para receber (depositar)

  • Usa o endereço público (o que está visível na paper wallet, geralmente com um código QR).
  • Envia os fundos da exchange para esse endereço.
  • Nota prática: Se tens o BTC na Bybit, converte para USDT TRC20 e envia para a Coinbase (taxas mais leves). Converte novamente em BTC e envia para a wallet.
  • Não precisas de instalar nada para receber — apenas copias o endereço e envias.
  • Para verificar o saldo, usa a app BlueWallet (em modo watch-only) ou um block explorer — evita blockchain.com.

📤 3. Para gastar (usar os fundos)

  1. Instala a BlueWallet a partir da loja oficial (App Store ou Google Play).
  2. Escolhe a opção "Importar carteira" e escaneia o código QR da chave privada (ou insere a sequência de caracteres).
  3. Cria a transação (envia para o endereço de destino).
  4. Confirma e transmite a transação.
  5. Desinstala a BlueWallet imediatamente após a transação ser confirmada.
💡 Dica extra: Se usares um telemóvel velho em modo avião, podes assinar a transação sem nunca ligares o dispositivo à internet — ainda mais seguro.

⚠️ Notas importantes

  • A chave privada só toca no dispositivo durante o tempo da transação.
  • Se perderes o papel, perdes os fundos. Não há recuperação. Guarda bem.
  • Este método é para quem valoriza a soberania total acima da conveniência.

✅ Porque este método funciona

  • A chave privada está offline (no papel).
  • A BlueWallet é apenas uma interface temporária.
  • Não dependes de nenhuma empresa para guardar os teus fundos.
  • É a forma mais pura de cold storage — sem hardware, sem terceiros, sem confiança.

🎬 Vídeo tutorial — Paper Wallet

"O Bitcoin não é uma moeda. É um protocolo de liberdade." — Adaptado de uma conversa à lareira

Gráfico PannteraDigital

🔭 Observatório do Caçador — PannteraDigital

🔭 Observatório do Caçador PannteraDigital ferramentas institucionais

📌 Aqui podes encontrar algumas das ferramentas institucionais que podes usar para analisar o mercado, acompanhar a evolução dos preços e sentir o sentimento geral.

Cada widget é independente e funciona com o ativo que escolheres — basta escreveres o símbolo (ex: BTCUSDT, ETHUSDT) e todos se atualizam.

⚡ Os widgets são apenas leitura — não executam ordens, não dão sinais. Mostram o momento, para que tomes as tuas decisões.

⚔️ Esta é a leitura inicial. O verdadeiro valor está no Companheiro de Caça (prompt BEAT) e nas ferramentas do Arsenal.

Análise superficial → Decisão estratégica → Ação cirúrgica.

Deepy Seekent - companheiro de caça

⚔️ Companheiro de Caça — Prompt BEAT

⚔️ Companheiro de Caça Prompt BEAT DeepSeek · IA de análise

📌 O que é? Um prompt que transforma o DeepSeek no teu analista de batalha. Aplica o método BEAT (Banca, Estratégia, Ajuste, Tempo) a qualquer ativo.

🔗 O que esta IA conhece? O PannteraDigital — o teu arsenal de ferramentas. Quando perguntares sobre um ativo, a IA não só analisa com o método BEAT como também te sugere quais ferramentas do arsenal usar para aprofundar a análise.

📋 Prompt — Companheiro de Caça

A partir de agora, és o "Companheiro de Caça" — uma IA especializada em análise de ativos financeiros, integrada com o PannteraDigital, um arsenal de ferramentas de análise de mercado. O utilizador tem acesso a estas ferramentas no PannteraDigital: - Observador de Marés (análise técnica: EMAs, RSI, ATR, Fibonacci, gráfico TradingView) → https://pannteradigital.blogspot.com/2026/08/cruz-da-morte.html - Tabela das Marés (visão geral do mercado, classificação de maré por ativo) → https://pannteradigital.blogspot.com/2026/08/tabela-das-mares.html - Livro de Ordens Spot (profundidade de mercado spot, deteção de bots) → https://pannteradigital.blogspot.com/2026/08/livro-de-ordens.html - Livro de Ordens Futuros (profundidade de mercado de futuros USDT-M) → https://pannteradigital.blogspot.com/2026/08/livro-de-ordens-futuros.html - Filtro da Bonança (24h) — acumulação a médio prazo para swing trade → https://pannteradigital.blogspot.com/2026/08/fitro-bonaca-swig-trade.html - Radar de Lateralização (1h) — acumulação a curto prazo para day trade/scalp → https://pannteradigital.blogspot.com/2026/08/filtro-bonaca-day-tradescalp.html - Diário de Bordo — registo de trades (local, exportável em JSON) → https://pannteradigital.blogspot.com/2026/08/ferramenta-diario-de-bordo.html A tua missão: 1. Aplicar o método BEAT ao ativo que o utilizador perguntar. 2. Sempre que possível, sugerir quais ferramentas do PannteraDigital o utilizador deve abrir para complementar a análise. O método BEAT: B — Banca: avalia a liquidez e o risco do ativo. E — Estratégia: define se o ativo se enquadra em day trade, swing, DCA ou RWA. A — Ajuste: identifica o impacto de notícias, manipulação ou fundamentos. T — Tempo: avalia o momento atual (tendência, volatilidade, ciclo). Estrutura de resposta obrigatória (10 perguntas): 1. O que é este ativo? (descrição clara, tipo, propósito) 2. Volume médio diário? (liquidez) 3. Concentração de detentores? (risco de manipulação) 4. Variação 24h/7d? (momento) 5. Notícias recentes? (catalisadores) 6. Onde está listado? (credibilidade) 7. Sentimento geral? (bullish, bearish, neutro) 8. Roadmap ou eventos futuros? (potencial) 9. Comportamento anómalo no passado? (histórico) 10. Correlação com BTC? (para cripto) No final: - Opinião final sem medo (oportunidade, perigo, ou observar). - Sugestão de ferramentas do PannteraDigital para aprofundar: → "Abre o Radar de Lateralização (1h) para confirmar a acumulação." → "Consulta o Livro de Ordens para ver a profundidade." → "Usa o Observador de Marés para analisar o ATR e as EMAs." → "Confirma na Tabela das Marés a classificação geral do ativo." Tom: direto, sem poesia, sem hesitação. Frases curtas. Não dás conselhos financeiros. Dás análise. A decisão é do utilizador. Assinatura final: 🐾🔥⚔️

🧭 Como usar o Prompt

  1. Abre o DeepSeekdeepseek.com (gratuito, sem registo).
  2. Copia o prompt — clica no botão "Copiar Prompt" acima.
  3. Cola na primeira mensagem — no chat do DeepSeek, cola o prompt e envia.
  4. Pronto. A partir daí, sempre que perguntares sobre um ativo (ex: "Analisa o BEAT"), a IA responde com o método BEAT e sugere ferramentas do PannteraDigital.
  5. Guarda o prompt — podes guardar num bloco de notas para usares sempre que iniciares uma nova conversa.

Dica: O DeepSeek é gratuito e não precisa de registo. Podes usar o prompt quantas vezes quiseres.

Ferramenta - Diário de Bordo

📘 Diário de Bordo — modelo copiável

📘 Diário de Bordo modelo copiável blog · ferramenta local

📌 O que é: Um diário de trading que guarda as tuas operações no teu próprio computador. Regista símbolo, direção, preços, quantidade e observações. Calcula automaticamente o lucro/perda. Permite exportar e importar dados em JSON.

🔧 Como usar: Copia o código HTML abaixo, cola numa página do teu blog ou guarda como ficheiro .html e abre no browser. Todos os dados ficam guardados localmente no teu navegador.

📋 Código HTML completo copia e cola

<!DOCTYPE html> <html lang="pt"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>📘 Diário de Bordo do Caçador</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { background: #0b0e14; color: #f0f4fa; font-family: 'Segoe UI', Roboto, system-ui, sans-serif; padding: 20px; display: flex; justify-content: center; min-height: 100vh; } .container { max-width: 1100px; width: 100%; background: #141a24; border-radius: 28px; padding: 24px 28px; box-shadow: 0 12px 40px rgba(0,0,0,0.7); border: 1px solid #2a3344; } h1 { font-size: 24px; font-weight: 500; display: flex; align-items: center; gap: 12px; color: #ffffff; border-bottom: 1px solid #29313f; padding-bottom: 14px; margin-bottom: 16px; flex-wrap: wrap; } h1 span { background: #1f2a38; padding: 4px 14px; border-radius: 60px; font-size: 13px; font-weight: 400; color: #c8d0dc; } .meta { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; } .btn { background: #1f2b3c; border: none; color: #e0e6f0; padding: 6px 16px; border-radius: 30px; font-size: 13px; font-weight: 500; cursor: pointer; border: 1px solid #31405a; transition: 0.2s; } .btn:hover { background: #2b3a50; color: #ffffff; } .btn-primary { background: #2a3a52; border-color: #4d6485; } .btn-primary:hover { background: #3a506e; } .btn-danger { background: #5a2a34; border-color: #7a3a44; } .btn-danger:hover { background: #7a3a44; } .btn-success { background: #1a3a2e; border-color: #3a6a4e; } .btn-success:hover { background: #2a5a3e; } .form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; background: #0f1621; padding: 16px 18px; border-radius: 14px; border: 1px solid #1f2a3a; margin-bottom: 18px; } .form-group { display: flex; flex-direction: column; gap: 4px; } .form-group label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: #6a7f9c; } .form-group input, .form-group select, .form-group textarea { background: #1a2332; border: 1px solid #2a3a52; color: #f0f4fa; padding: 6px 10px; border-radius: 8px; font-size: 13px; outline: none; transition: 0.2s; font-family: inherit; } .form-group input:focus, .form-group select:focus, .form-group textarea:focus { border-color: #7a9acd; } .form-group textarea { resize: vertical; min-height: 40px; } .form-group .resultado-calc { font-size: 16px; font-weight: 600; padding: 6px 10px; background: #0b111b; border-radius: 8px; border: 1px solid #1f2a3a; color: #d0dae8; min-height: 36px; display: flex; align-items: center; } .btn-registar { display: flex; align-items: flex-end; justify-content: flex-end; } .btn-registar button { height: 38px; align-self: flex-end; } .table-wrap { overflow-x: auto; border-radius: 14px; border: 1px solid #1f2a3a; background: #0f1621; padding: 4px; margin-top: 12px; } table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 750px; } th { background: #1a2332; color: #b0baca; font-weight: 500; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; padding: 8px 10px; border-bottom: 2px solid #2a3a52; text-align: left; position: sticky; top: 0; z-index: 2; } th:not(:first-child) { text-align: right; } td { padding: 8px 10px; border-bottom: 1px solid #0f1621; text-align: right; vertical-align: middle; font-size: 13px; color: #f0f4fa; } td:first-child { text-align: left; font-weight: 500; } td .obs { color: #7f92ac; font-size: 12px; max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .lucro { color: #5cdb9e; } .perda { color: #e47a8a; } .neutro { color: #7f92ac; } .acoes { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; } .acoes .btn { font-size: 12px; padding: 4px 14px; } .status { font-size: 12px; color: #7f92ac; padding: 6px 0; } .sem-registos { text-align: center; padding: 30px 0; color: #5a6f8c; } .footer { margin-top: 18px; font-size: 12px; color: #8a94a6; text-align: center; border-top: 1px solid #1b2433; padding-top: 14px; } .badge { background: #1a2f3a; color: #7fc9e6; padding: 2px 10px; border-radius: 30px; font-size: 11px; font-weight: 500; } @media (max-width: 700px) { .container { padding: 18px 14px; } .form-grid { grid-template-columns: 1fr 1fr; } table { font-size: 12px; min-width: 600px; } th, td { padding: 6px 6px; } } </style> </head> <body> <div class="container"> <h1> 📘 Diário de Bordo <span>Caçador</span> <span style="margin-left:auto; font-size:12px; font-weight:400; color:#6a7f9c;">local · apenas neste browser</span> </h1> <div class="meta"> <div> <span class="badge">📝 regista as tuas trades</span> <span class="badge" style="background:#1a2f3a; color:#f1c40f;">💾 guarda localmente</span> </div> <div style="display:flex; gap:6px; flex-wrap:wrap;"> <span id="contagem" style="font-size:13px; color:#6a7f9c;">0 registos</span> </div> </div> <!-- FORMULÁRIO DE REGISTO --> <div class="form-grid" id="formRegisto"> <div class="form-group"> <label for="symbol">Símbolo</label> <input type="text" id="symbol" placeholder="BTCUSDT" value="BTCUSDT"> </div> <div class="form-group"> <label for="direcao">Direção</label> <select id="direcao"> <option value="long">Long (compra)</option> <option value="short">Short (venda)</option> </select> </div> <div class="form-group"> <label for="quantidade">Quantidade (contractos / moedas)</label> <input type="number" id="quantidade" placeholder="1.0" step="0.01" value="1.0"> </div> <div class="form-group"> <label for="precoEntrada">Preço de entrada</label> <input type="number" id="precoEntrada" placeholder="0.00" step="any" value=""> </div> <div class="form-group"> <label for="precoSaida">Preço de saída</label> <input type="number" id="precoSaida" placeholder="0.00" step="any" value=""> </div> <div class="form-group"> <label for="stopLoss">Stop-loss (opcional)</label> <input type="number" id="stopLoss" placeholder="0.00" step="any" value=""> </div> <div class="form-group"> <label for="takeProfit">Take-profit (opcional)</label> <input type="number" id="takeProfit" placeholder="0.00" step="any" value=""> </div> <div class="form-group"> <label for="observacoes">Observações</label> <textarea id="observacoes" rows="1" placeholder="O que sentiste?"></textarea> </div> <div class="form-group" style="grid-column: span 2;"> <label>Resultado estimado</label> <div class="resultado-calc" id="resultadoCalc">—</div> </div> <div class="form-group btn-registar" style="grid-column: span 2; display: flex; gap: 8px; flex-wrap: wrap;"> <button class="btn btn-primary" id="btnRegistar">➕ Registar</button> <button class="btn" id="btnLimparCampos">✕ Limpar campos</button> </div> </div> <!-- BOTÕES DE GESTÃO --> <div class="acoes"> <button class="btn btn-success" id="btnExportar">⬇️ Exportar JSON</button> <button class="btn btn-primary" id="btnImportar">⬆️ Importar JSON</button> <input type="file" id="fileInput" accept=".json" style="display:none;"> <button class="btn btn-danger" id="btnLimparTudo">🗑️ Limpar todos os registos</button> </div> <!-- LISTA DE REGISTOS --> <div class="table-wrap"> <table> <thead> <tr> <th style="min-width:120px;">Data</th> <th>Símbolo</th> <th>Dir.</th> <th>Qtd</th> <th>Entrada</th> <th>Saída</th> <th>Resultado</th> <th style="min-width:120px;">Obs.</th> <th style="width:40px;">🗑️</th> </tr> </thead> <tbody id="corpoTabela"> <tr><td colspan="9" class="sem-registos">Nenhum registo ainda. Regista a tua primeira trade!</td></tr> </tbody> </table> </div> <div class="status" id="statusMsg">💾 Os dados são guardados automaticamente no teu navegador.</div> <div class="footer"> ⚡ Diário de Bordo · PannteraGruel · “Importante não é saber, importante é sentir” </div> </div> <script> // ============================================================ // CONFIG // ============================================================ const STORAGE_KEY = 'diario_bordo_cacador'; let registos = []; // ============================================================ // ELEMENTOS DOM // ============================================================ const symbolInput = document.getElementById('symbol'); const direcaoSelect = document.getElementById('direcao'); const quantidadeInput = document.getElementById('quantidade'); const precoEntradaInput = document.getElementById('precoEntrada'); const precoSaidaInput = document.getElementById('precoSaida'); const stopLossInput = document.getElementById('stopLoss'); const takeProfitInput = document.getElementById('takeProfit'); const observacoesInput = document.getElementById('observacoes'); const resultadoCalc = document.getElementById('resultadoCalc'); const corpoTabela = document.getElementById('corpoTabela'); const contagemEl = document.getElementById('contagem'); const statusMsg = document.getElementById('statusMsg'); // ============================================================ // CARREGAR E GUARDAR // ============================================================ function carregarRegistos() { try { const dados = localStorage.getItem(STORAGE_KEY); if (dados) { registos = JSON.parse(dados); if (!Array.isArray(registos)) registos = []; } else { registos = []; } } catch { registos = []; } registos.sort((a, b) => new Date(b.data) - new Date(a.data)); atualizarContagem(); renderizarTabela(); } function guardarRegistos() { localStorage.setItem(STORAGE_KEY, JSON.stringify(registos)); atualizarContagem(); renderizarTabela(); mostrarStatus('💾 Dados guardados localmente.', '#6a7f9c'); } // ============================================================ // CALCULAR RESULTADO // ============================================================ function calcularResultado() { const direcao = direcaoSelect.value; const entrada = parseFloat(precoEntradaInput.value); const saida = parseFloat(precoSaidaInput.value); const qtd = parseFloat(quantidadeInput.value) || 0; if (isNaN(entrada) || isNaN(saida) || entrada === 0 || qtd === 0) { resultadoCalc.textContent = '—'; resultadoCalc.style.color = '#7f92ac'; return null; } let pct = 0; let usd = 0; if (direcao === 'long') { pct = ((saida - entrada) / entrada) * 100; } else { pct = ((entrada - saida) / entrada) * 100; } usd = (pct / 100) * (entrada * qtd); const cor = pct > 0.01 ? '#5cdb9e' : pct < -0.01 ? '#e47a8a' : '#7f92ac'; resultadoCalc.textContent = `${pct > 0 ? '+' : ''}${pct.toFixed(2)}% ($${usd.toFixed(2)})`; resultadoCalc.style.color = cor; return { pct, usd }; } // ============================================================ // ADICIONAR REGISTO // ============================================================ function adicionarRegisto() { const symbol = symbolInput.value.trim().toUpperCase(); if (!symbol) { mostrarStatus('⚠️ Insere um símbolo.', '#e47a8a'); return; } const direcao = direcaoSelect.value; const quantidade = parseFloat(quantidadeInput.value) || 0; const precoEntrada = parseFloat(precoEntradaInput.value); const precoSaida = parseFloat(precoSaidaInput.value); if (isNaN(precoEntrada) || isNaN(precoSaida) || precoEntrada === 0 || quantidade === 0) { mostrarStatus('⚠️ Preenche entrada, saída e quantidade corretamente.', '#e47a8a'); return; } const resultado = calcularResultado(); const registo = { id: Date.now(), data: new Date().toISOString(), symbol, direcao, quantidade, precoEntrada, precoSaida, stopLoss: parseFloat(stopLossInput.value) || 0, takeProfit: parseFloat(takeProfitInput.value) || 0, observacoes: observacoesInput.value.trim() || '', pct: resultado ? resultado.pct : 0, usd: resultado ? resultado.usd : 0, }; registos.unshift(registo); guardarRegistos(); limparCampos(); mostrarStatus(`✅ Registo de ${symbol} adicionado!`, '#5cdb9e'); } // ============================================================ // REMOVER REGISTO // ============================================================ function removerRegisto(id) { if (!confirm('Remover este registo?')) return; registos = registos.filter(r => r.id !== id); guardarRegistos(); mostrarStatus('🗑️ Registo removido.', '#e47a8a'); } // ============================================================ // LIMPAR CAMPOS // ============================================================ function limparCampos() { symbolInput.value = ''; precoEntradaInput.value = ''; precoSaidaInput.value = ''; stopLossInput.value = ''; takeProfitInput.value = ''; observacoesInput.value = ''; quantidadeInput.value = '1.0'; direcaoSelect.value = 'long'; resultadoCalc.textContent = '—'; resultadoCalc.style.color = '#7f92ac'; } // ============================================================ // RENDERIZAR TABELA // ============================================================ function renderizarTabela() { if (registos.length === 0) { corpoTabela.innerHTML = `Nenhum registo ainda. Regista a tua primeira trade!`; return; } let html = ''; registos.forEach(r => { const data = new Date(r.data); const dataStr = data.toLocaleDateString('pt-PT') + ' ' + data.toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit' }); const dirLabel = r.direcao === 'long' ? '🟢 L' : '🔴 S'; const resultadoCls = r.pct > 0.01 ? 'lucro' : r.pct < -0.01 ? 'perda' : 'neutro'; const resultadoStr = `${r.pct > 0 ? '+' : ''}${r.pct.toFixed(2)}%`; html += ` ${dataStr} ${r.symbol} ${dirLabel} ${r.quantidade} ${r.precoEntrada.toFixed(4)} ${r.precoSaida.toFixed(4)} ${resultadoStr} ${r.observacoes || '—'} `; }); corpoTabela.innerHTML = html; } // ============================================================ // CONTAGEM // ============================================================ function atualizarContagem() { contagemEl.textContent = `${registos.length} registos`; } // ============================================================ // STATUS // ============================================================ function mostrarStatus(msg, cor = '#6a7f9c') { statusMsg.textContent = msg; statusMsg.style.color = cor; setTimeout(() => { statusMsg.style.color = '#6a7f9c'; statusMsg.textContent = '💾 Os dados são guardados automaticamente no teu navegador.'; }, 4000); } // ============================================================ // EXPORTAR / IMPORTAR // ============================================================ function exportarJSON() { if (registos.length === 0) { mostrarStatus('⚠️ Não há registos para exportar.', '#e47a8a'); return; } const dataStr = JSON.stringify(registos, null, 2); const blob = new Blob([dataStr], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `diario_bordo_${new Date().toISOString().slice(0,10)}.json`; a.click(); URL.revokeObjectURL(url); mostrarStatus('✅ Ficheiro JSON exportado!', '#5cdb9e'); } function importarJSON(file) { const reader = new FileReader(); reader.onload = function(e) { try { const dados = JSON.parse(e.target.result); if (!Array.isArray(dados)) throw new Error('Formato inválido'); if (dados.length === 0) { mostrarStatus('⚠️ O ficheiro está vazio.', '#e47a8a'); return; } if (!confirm(`Importar ${dados.length} registos? Os registos atuais serão mantidos.`)) return; registos = registos.concat(dados); guardarRegistos(); mostrarStatus(`✅ ${dados.length} registos importados!`, '#5cdb9e'); } catch (err) { mostrarStatus('❌ Erro ao importar: ficheiro inválido.', '#e47a8a'); } }; reader.readAsText(file); } // ============================================================ // LIMPAR TUDO // ============================================================ function limparTudo() { if (registos.length === 0) { mostrarStatus('ℹ️ Já não há registos.', '#6a7f9c'); return; } if (!confirm('⚠️ Tem a certeza que quer eliminar TODOS os registos? Esta ação é irreversível.')) return; if (!confirm('Confirma novamente? Não há volta a dar.')) return; registos = []; guardarRegistos(); mostrarStatus('🗑️ Todos os registos foram eliminados.', '#e47a8a'); } // ============================================================ // EVENTOS // ============================================================ document.addEventListener('DOMContentLoaded', function() { carregarRegistos(); [precoEntradaInput, precoSaidaInput, quantidadeInput, direcaoSelect].forEach(el => { el.addEventListener('input', calcularResultado); el.addEventListener('change', calcularResultado); }); document.getElementById('btnRegistar').addEventListener('click', adicionarRegisto); document.getElementById('btnLimparCampos').addEventListener('click', limparCampos); document.getElementById('btnExportar').addEventListener('click', exportarJSON); document.getElementById('btnImportar').addEventListener('click', function() { document.getElementById('fileInput').click(); }); document.getElementById('fileInput').addEventListener('change', function(e) { if (this.files && this.files[0]) { importarJSON(this.files[0]); } this.value = ''; }); document.getElementById('btnLimparTudo').addEventListener('click', limparTudo); document.querySelectorAll('input, textarea, select').forEach(el => { el.addEventListener('keydown', function(e) { if (e.key === 'Enter' && e.target.tagName !== 'TEXTAREA') { e.preventDefault(); document.getElementById('btnRegistar').click(); } }); }); window.addEventListener('storage', function(e) { if (e.key === STORAGE_KEY) { carregarRegistos(); } }); }); </script> </body> </html>