Skip to content
LAM
Read Home Blog
Make Projects HTML Tools Games
Touch grass Notes Resume Links
Home Blog HTML Projects
Tools Games Notes Resume Links
Back Penguin Trader – 100 ➜ 1,000,000 (Fictional Dashboard) AI
Download Open
Show description 2,346 chars · AI

Penguin Trader – 100 ➜ 1,000,000 (Fictional Dashboard)

Penguin Trader – 100 ➜ 1,000,000 (Fictional Dashboard)









🐧


Fictional Future Track

Penguin Trader 100 ➜ 1,000,000 (Mock)


Dark-mode trading profile projecting a purely hypothetical journey from
$100 to $1,000,000 over ~90 days
by rotating through AI / infra / quantum-aligned coins and parking in a stablecoin between swings.








Starting Bankroll
$100



Projected Peak
$1,001,175



Time Window
~90 days • 19 major swings



Reality Check
Unrealistic • For visualization only











Fictional 90-Day Equity Curve

“Inner gut” future path · not financial advice



The equity curve and trades below are fully fabricated using exaggerated win rates
and compounding. Real trading is far more random, slower and usually much harsher.





Projected Win Rate
~84% (16 wins / 3 losses)



Largest Single Drawdown
-17.6%



Largest Single Upswing
+138.2%



Stablecoin Parking
USDC (between entries)















Live Price Board (CoinGecko)

AI / Infra / Quantum / Data favorites



This table queries CoinGecko’s /simple/price endpoint in the browser.
You can adapt it to use your own API key or backend proxy if you hit rate limits.




Endpoint
/api/v3/simple/price



Quote Currency
USD



Refresh
Every 30 seconds








Coin

Symbol

Price (USD)

24h %

Last Update







Fetching prices from CoinGecko...








If you have a CoinGecko key, you can swap the URL to
https://pro-api.coingecko.com/api/v3/simple/price and attach your key as
documented in their API reference. Key handling should be done server-side for production.










Penguin Trader – Fictional Trade Log (100 ➜ 1,001,175)

Strategic swings into narrative coins, stables in between



Each row shows one major rotational swing: buy a coin on a local dip based on “future
knowledge”, ride it, exit back into a stablecoin, then wait for the next asymmetric bet.
Returns are deliberately extreme to illustrate compounding.






#

Window (Day)

Coin

Action

Return %

Equity Before

Equity After

Comment














Coin Tracks – Synthetic 90-Day Paths

Price fiction for the 10 core coins used in the script



These charts are synthetic “what-if” paths generated client-side.…

Penguin Trader – 100 ➜ 1,000,000 (Fictional Dashboard)

28,729 bytes · HTML source
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Penguin Trader – 100 ➜ 1,000,000 (Fictional Dashboard)</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <!-- Chart.js for charts -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    :root {
      --bg: #05070a;
      --bg-soft: #10141c;
      --bg-softer: #131824;
      --accent: #48d5ff;
      --accent-soft: rgba(72, 213, 255, 0.25);
      --accent-warn: #ff6b81;
      --text-main: #f3f6ff;
      --text-muted: #8a93b2;
      --success: #00d68f;
      --danger: #ff4b5c;
      --border-soft: #222838;
      --card-radius: 14px;
      --shadow-soft: 0 16px 40px rgba(0, 0, 0, 0.65);
      --font-main: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text",
        "Segoe UI", sans-serif;
      --font-mono: "JetBrains Mono", Menlo, Monaco, Consolas, monospace;
    }

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      background: radial-gradient(circle at top, #141a2b 0, #05070a 40%, #010103 100%);
      color: var(--text-main);
      font-family: var(--font-main);
      line-height: 1.5;
      padding: 24px;
    }

    .shell {
      max-width: 1320px;
      margin: 0 auto 80px;
    }

    header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 24px;
    }

    .title-block {
      display: flex;
      gap: 16px;
      align-items: center;
    }

    .penguin-avatar {
      width: 72px;
      height: 72px;
      border-radius: 24px;
      background: radial-gradient(circle at 30% 20%, #ffffff 0, #c7e9ff 22%, #0b1528 60%, #020308 100%);
      display: flex;
      align-items: center;
      justify-content: center;
      box-shadow: 0 0 30px rgba(72, 213, 255, 0.35);
      border: 1px solid rgba(255, 255, 255, 0.08);
      font-size: 42px;
    }

    .title-text h1 {
      font-size: 26px;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .badge {
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.18em;
      padding: 4px 10px;
      border-radius: 999px;
      background: linear-gradient(90deg, rgba(72, 213, 255, 0.22), rgba(0, 214, 143, 0.18));
      border: 1px solid rgba(72, 213, 255, 0.3);
      color: var(--text-main);
    }

    .title-text p {
      color: var(--text-muted);
      margin-top: 4px;
      font-size: 13px;
    }

    .header-stats {
      display: flex;
      gap: 18px;
      flex-wrap: wrap;
    }

    .stat-pill {
      min-width: 120px;
      padding: 10px 16px;
      border-radius: 999px;
      border: 1px solid var(--border-soft);
      background: radial-gradient(circle at top left, rgba(72, 213, 255, 0.18), rgba(7, 10, 20, 0.9));
      font-size: 12px;
    }

    .stat-pill strong {
      display: block;
      font-size: 13px;
    }

    .layout-grid {
      display: grid;
      grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
      gap: 20px;
      margin-bottom: 20px;
      align-items: start;
    }

    @media (max-width: 960px) {
      .layout-grid {
        grid-template-columns: minmax(0, 1fr);
      }
      header {
        flex-direction: column;
        align-items: flex-start;
      }
      body {
        padding: 16px;
      }
    }

    .card {
      background: linear-gradient(145deg, rgba(11, 16, 28, 0.98), rgba(8, 10, 20, 0.98));
      border-radius: var(--card-radius);
      border: 1px solid var(--border-soft);
      box-shadow: var(--shadow-soft);
      padding: 16px 18px 18px;
      position: relative;
      overflow: hidden;
    }

    .card::before {
      content: "";
      position: absolute;
      inset: -40%;
      opacity: 0.08;
      background: radial-gradient(circle at top right, rgba(72, 213, 255, 1), transparent 55%);
      pointer-events: none;
    }

    .card-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 10px;
      position: relative;
      z-index: 1;
    }

    .card-header h2 {
      font-size: 15px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.14em;
      color: #dfe5ff;
    }

    .card-header span {
      font-size: 11px;
      color: var(--text-muted);
    }

    .disclaimer {
      font-size: 11px;
      color: var(--text-muted);
      margin-bottom: 8px;
      position: relative;
      z-index: 1;
    }

    .tag {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      padding: 3px 8px;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.06);
      font-size: 10px;
      color: var(--text-muted);
    }

    .tag-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
    }

    table {
      width: 100%;
      border-collapse: collapse;
      font-size: 12px;
      position: relative;
      z-index: 1;
    }

    thead tr {
      background: rgba(14, 20, 38, 0.9);
    }

    th,
    td {
      padding: 6px 6px;
      text-align: right;
      white-space: nowrap;
      border-bottom: 1px solid rgba(35, 40, 60, 0.95);
    }

    th:first-child,
    td:first-child {
      text-align: left;
    }

    th {
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.14em;
      color: var(--text-muted);
      position: sticky;
      top: 0;
      background: rgba(10, 14, 26, 0.96);
      backdrop-filter: blur(12px);
    }

    tbody tr:nth-child(odd) {
      background: rgba(7, 11, 22, 0.9);
    }

    tbody tr:nth-child(even) {
      background: rgba(5, 8, 17, 0.9);
    }

    tbody tr:hover {
      background: rgba(31, 70, 120, 0.55);
    }

    .text-green {
      color: var(--success);
    }

    .text-red {
      color: var(--danger);
    }

    .text-muted {
      color: var(--text-muted);
    }

    .pill {
      padding: 3px 8px;
      border-radius: 999px;
      border: 1px solid rgba(255, 255, 255, 0.08);
      font-size: 11px;
      display: inline-flex;
      align-items: center;
      gap: 4px;
    }

    .pill--buy {
      border-color: rgba(0, 214, 143, 0.7);
      background: rgba(0, 214, 143, 0.07);
      color: var(--success);
    }

    .pill--sell {
      border-color: rgba(255, 75, 92, 0.7);
      background: rgba(255, 75, 92, 0.04);
      color: var(--danger);
    }

    .pill--stable {
      border-color: rgba(148, 163, 184, 0.7);
      background: rgba(148, 163, 184, 0.04);
      color: var(--text-muted);
    }

    .chart-shell {
      margin-top: 8px;
      position: relative;
      z-index: 1;
    }

    .chart-shell canvas {
      width: 100%;
      height: 240px;
    }

    .metrics-row {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 6px;
      position: relative;
      z-index: 1;
    }

    .metric {
      padding: 6px 9px;
      border-radius: 9px;
      border: 1px solid rgba(39, 46, 72, 0.95);
      background: rgba(8, 10, 18, 0.96);
      font-size: 11px;
      color: var(--text-muted);
    }

    .metric strong {
      display: block;
      color: #e5ecff;
    }

    .grid-charts {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
      gap: 14px;
      margin-top: 10px;
      position: relative;
      z-index: 1;
    }

    .mini-chart-card {
      border-radius: 12px;
      border: 1px solid rgba(34, 40, 60, 0.96);
      background: radial-gradient(circle at top left, rgba(72, 213, 255, 0.16), rgba(5, 7, 13, 0.96));
      padding: 8px 9px 10px;
    }

    .mini-chart-header {
      display: flex;
      justify-content: space-between;
      align-items: baseline;
      margin-bottom: 4px;
      font-size: 11px;
    }

    .mini-chart-header span.symbol {
      font-weight: 600;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: #f0f4ff;
    }

    .mini-chart-header span.name {
      color: var(--text-muted);
      font-size: 10px;
    }

    .mini-chart-header span.note {
      font-size: 10px;
      color: var(--text-muted);
    }

    .mini-chart-card canvas {
      width: 100%;
      height: 130px;
    }

    .subnote {
      font-size: 10px;
      color: var(--text-muted);
      margin-top: 4px;
    }

    .footer-note {
      font-size: 11px;
      color: var(--text-muted);
      margin-top: 18px;
      max-width: 900px;
    }

    code {
      font-family: var(--font-mono);
      font-size: 11px;
      background: rgba(10, 14, 26, 0.92);
      padding: 2px 5px;
      border-radius: 4px;
      border: 1px solid rgba(51, 65, 85, 0.7);
    }
  </style>
</head>
<body>
<div class="shell">
  <header>
    <div class="title-block">
      <div class="penguin-avatar">🐧</div>
      <div class="title-text">
        <div class="badge">Fictional Future Track</div>
        <h1>Penguin Trader <span style="font-size:13px;color:var(--accent)">100 ➜ 1,000,000 (Mock)</span></h1>
        <p>
          Dark-mode trading profile projecting a purely hypothetical journey from
          <strong>$100</strong> to <strong>$1,000,000</strong> over ~90 days
          by rotating through AI / infra / quantum-aligned coins and parking in a stablecoin between swings.
        </p>
      </div>
    </div>
    <div class="header-stats">
      <div class="stat-pill">
        <span class="text-muted">Starting Bankroll</span>
        <strong>$100</strong>
      </div>
      <div class="stat-pill">
        <span class="text-muted">Projected Peak</span>
        <strong>$1,001,175</strong>
      </div>
      <div class="stat-pill">
        <span class="text-muted">Time Window</span>
        <strong>~90 days • 19 major swings</strong>
      </div>
      <div class="stat-pill">
        <span class="text-muted">Reality Check</span>
        <strong style="color:#ffb454">Unrealistic • For visualization only</strong>
      </div>
    </div>
  </header>

  <div class="layout-grid">
    <!-- Left: Equity + trade journey -->
    <section class="card">
      <div class="card-header">
        <h2>Fictional 90-Day Equity Curve</h2>
        <span>“Inner gut” future path · not financial advice</span>
      </div>
      <p class="disclaimer">
        The equity curve and trades below are fully fabricated using exaggerated win rates
        and compounding. Real trading is far more random, slower and usually much harsher.
      </p>

      <div class="metrics-row">
        <div class="metric">
          <span>Projected Win Rate</span>
          <strong>~84% (16 wins / 3 losses)</strong>
        </div>
        <div class="metric">
          <span>Largest Single Drawdown</span>
          <strong class="text-red">-17.6%</strong>
        </div>
        <div class="metric">
          <span>Largest Single Upswing</span>
          <strong class="text-green">+138.2%</strong>
        </div>
        <div class="metric">
          <span>Stablecoin Parking</span>
          <strong>USDC (between entries)</strong>
        </div>
      </div>

      <div class="chart-shell">
        <canvas id="equityChart"></canvas>
      </div>
    </section>

    <!-- Right: Live price board -->
    <section class="card">
      <div class="card-header">
        <h2>Live Price Board (CoinGecko)</h2>
        <span>AI / Infra / Quantum / Data favorites</span>
      </div>
      <div class="disclaimer">
        This table queries CoinGecko’s <code>/simple/price</code> endpoint in the browser.
        You can adapt it to use your own API key or backend proxy if you hit rate limits.
      </div>
      <div class="metrics-row">
        <div class="metric">
          <span>Endpoint</span>
          <strong><code>/api/v3/simple/price</code></strong>
        </div>
        <div class="metric">
          <span>Quote Currency</span>
          <strong>USD</strong>
        </div>
        <div class="metric">
          <span>Refresh</span>
          <strong>Every 30 seconds</strong>
        </div>
      </div>

      <table id="livePriceTable" style="margin-top:10px;">
        <thead>
        <tr>
          <th>Coin</th>
          <th>Symbol</th>
          <th>Price (USD)</th>
          <th>24h %</th>
          <th>Last Update</th>
        </tr>
        </thead>
        <tbody>
        <tr>
          <td colspan="5" class="text-muted" style="text-align:center;padding:14px;">
            Fetching prices from CoinGecko...
          </td>
        </tr>
        </tbody>
      </table>

      <div class="subnote">
        If you have a CoinGecko key, you can swap the URL to
        <code>https://pro-api.coingecko.com/api/v3/simple/price</code> and attach your key as
        documented in their API reference. Key handling should be done server-side for production.
      </div>
    </section>
  </div>

  <!-- Trade history -->
  <section class="card" style="margin-top:20px;">
    <div class="card-header">
      <h2>Penguin Trader – Fictional Trade Log (100 ➜ 1,001,175)</h2>
      <span>Strategic swings into narrative coins, stables in between</span>
    </div>
    <p class="disclaimer">
      Each row shows one major rotational swing: buy a coin on a local dip based on “future
      knowledge”, ride it, exit back into a stablecoin, then wait for the next asymmetric bet.
      Returns are deliberately extreme to illustrate compounding.
    </p>

    <table id="tradeTable">
      <thead>
      <tr>
        <th>#</th>
        <th>Window (Day)</th>
        <th>Coin</th>
        <th>Action</th>
        <th>Return %</th>
        <th>Equity Before</th>
        <th>Equity After</th>
        <th>Comment</th>
      </tr>
      </thead>
      <tbody>
      <!-- Filled by JS -->
      </tbody>
    </table>
  </section>

  <!-- Per-coin charts -->
  <section class="card" style="margin-top:20px;">
    <div class="card-header">
      <h2>Coin Tracks – Synthetic 90-Day Paths</h2>
      <span>Price fiction for the 10 core coins used in the script</span>
    </div>
    <p class="disclaimer">
      These charts are synthetic “what-if” paths generated client-side. Buy / sell markers show
      where Penguin Trader’s fictional swings occur for each asset along the 90-day window.
    </p>

    <div class="grid-charts" id="coinCharts">
      <!-- Mini charts injected via JS -->
    </div>

    <div class="subnote">
      The shapes are generated randomly with a slight upward drift to imitate a strong bull run
      across AI, infra, quantum-resistant and data-indexing ecosystems.
    </div>
  </section>

  <p class="footer-note">
    This entire dashboard is a storytelling tool. It mixes real-time pricing from CoinGecko with
    completely imagined future performance to show how aggressive compounding
    <em>would</em> look on a chart. In real markets, even professional traders rarely achieve
    anything close to this while surviving drawdowns and risk-of-ruin.
  </p>
</div>

<script>
  // -----------------------------
  // CONFIG: Coins & CoinGecko IDs
  // -----------------------------
  const COINS = [
    { symbol: "BTC", id: "bitcoin", name: "Bitcoin" },
    { symbol: "ETH", id: "ethereum", name: "Ethereum" },
    { symbol: "SOL", id: "solana", name: "Solana" },
    { symbol: "RNDR", id: "render-token", name: "Render" },
    { symbol: "FET", id: "fetch-ai", name: "Fetch.ai" },
    { symbol: "AGIX", id: "singularitynet", name: "SingularityNET" },
    { symbol: "ONDO", id: "ondo-finance", name: "Ondo" },
    { symbol: "GRT", id: "the-graph", name: "The Graph" },
    { symbol: "QRL", id: "the-quantum-resistant-ledger", name: "QRL" },
    { symbol: "CQT", id: "covalent", name: "Covalent" }
  ];

  // -----------------------------
  // Fictional trade path: 100 ➜ 1,001,175
  // -----------------------------
  const trades = [
    {trade:1,  buyDay:0,  sellDay:3,  coin:"BTC",  returnPct:46.1,  equityBefore:100.00,      equityAfter:146.12},
    {trade:2,  buyDay:5,  sellDay:7,  coin:"ETH",  returnPct:131.7, equityBefore:146.12,     equityAfter:338.56},
    {trade:3,  buyDay:8,  sellDay:10, coin:"SOL",  returnPct:121.7, equityBefore:338.56,     equityAfter:750.42},
    {trade:4,  buyDay:11, sellDay:16, coin:"RNDR", returnPct:-17.6, equityBefore:750.42,     equityAfter:618.24},
    {trade:5,  buyDay:17, sellDay:22, coin:"FET",  returnPct:83.9,  equityBefore:618.24,     equityAfter:1137.19},
    {trade:6,  buyDay:22, sellDay:24, coin:"AGIX", returnPct:108.2, equityBefore:1137.19,    equityAfter:2367.52},
    {trade:7,  buyDay:25, sellDay:27, coin:"ONDO", returnPct:124.6, equityBefore:2367.52,    equityAfter:5318.56},
    {trade:8,  buyDay:28, sellDay:33, coin:"GRT",  returnPct:41.3,  equityBefore:5318.56,    equityAfter:7513.17},
    {trade:9,  buyDay:35, sellDay:37, coin:"QRL",  returnPct:-9.1,  equityBefore:7513.17,    equityAfter:6829.03},
    {trade:10, buyDay:39, sellDay:44, coin:"CQT",  returnPct:81.9,  equityBefore:6829.03,    equityAfter:12424.19},
    {trade:11, buyDay:45, sellDay:48, coin:"BTC",  returnPct:121.5, equityBefore:12424.19,   equityAfter:27516.31},
    {trade:12, buyDay:50, sellDay:52, coin:"ETH",  returnPct:30.3,  equityBefore:27516.31,   equityAfter:35840.74},
    {trade:13, buyDay:53, sellDay:55, coin:"SOL",  returnPct:83.4,  equityBefore:35840.74,   equityAfter:65748.58},
    {trade:14, buyDay:55, sellDay:57, coin:"RNDR", returnPct:116.6, equityBefore:65748.58,   equityAfter:142401.43},
    {trade:15, buyDay:59, sellDay:65, coin:"FET",  returnPct:-6.4,  equityBefore:142401.43,  equityAfter:133332.97},
    {trade:16, buyDay:65, sellDay:70, coin:"AGIX", returnPct:138.2, equityBefore:133332.97,  equityAfter:317560.86},
    {trade:17, buyDay:72, sellDay:75, coin:"ONDO", returnPct:33.7,  equityBefore:317560.86,  equityAfter:424486.14},
    {trade:18, buyDay:76, sellDay:78, coin:"GRT",  returnPct:33.1,  equityBefore:424486.14,  equityAfter:564793.68},
    {trade:19, buyDay:80, sellDay:83, coin:"QRL",  returnPct:95.0,  equityBefore:564793.68,  equityAfter:1101175.40}
  ];

  // -----------------------------
  // Render trade table
  // -----------------------------
  function renderTradeTable() {
    const tbody = document.querySelector("#tradeTable tbody");
    tbody.innerHTML = "";

    trades.forEach(t => {
      const tr = document.createElement("tr");

      const isWin = t.returnPct > 0;
      const isLoss = t.returnPct < 0;

      const comment = (() => {
        if (t.returnPct > 100) return "Caught a narrative breakout & rotated to stables.";
        if (t.returnPct > 60)  return "Strong trend leg with tight stop, no overstay.";
        if (t.returnPct > 20)  return "Rode momentum, scaled out near prior high.";
        if (t.returnPct > 0)   return "Quick scalp on local liquidity pocket.";
        if (t.returnPct < -15) return "Whipsaw during volatility; hard stop preserved stack.";
        if (t.returnPct < -5)  return "Trend fakeout & fast cut to stable.";
        return "Flat-ish leg; protected capital.";
      })();

      tr.innerHTML = `
        <td>${t.trade}</td>
        <td class="text-muted">Day ${t.buyDay} → ${t.sellDay}</td>
        <td>${t.coin}</td>
        <td>
          <span class="pill ${isWin ? "pill--sell" : isLoss ? "pill--sell" : "pill--stable"}">
            ${isLoss ? "Stopped Out → USDC" : "Buy → Sell → USDC"}
          </span>
        </td>
        <td class="${isWin ? "text-green" : isLoss ? "text-red" : ""}">
          ${t.returnPct.toFixed(1)}%
        </td>
        <td>$${t.equityBefore.toLocaleString(undefined,{maximumFractionDigits:2})}</td>
        <td><strong>$${t.equityAfter.toLocaleString(undefined,{maximumFractionDigits:2})}</strong></td>
        <td class="text-muted">${comment}</td>
      `;
      tbody.appendChild(tr);
    });
  }

  // -----------------------------
  // Equity curve chart
  // -----------------------------
  function buildEquityChart() {
    const ctx = document.getElementById("equityChart").getContext("2d");
    const labels = trades.map(t => `T${t.trade} · D${t.buyDay}→${t.sellDay}`);
    const data = trades.map(t => t.equityAfter);

    new Chart(ctx, {
      type: "line",
      data: {
        labels,
        datasets: [
          {
            label: "Equity After Trade",
            data,
            borderColor: "#48d5ff",
            backgroundColor: "rgba(72,213,255,0.08)",
            borderWidth: 2,
            pointRadius: 3,
            pointHoverRadius: 5,
            tension: 0.26
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: {
            display: false
          },
          tooltip: {
            mode: "index",
            intersect: false,
            callbacks: {
              label: (ctx) => {
                const value = ctx.parsed.y;
                return `Equity: $${value.toLocaleString(undefined, {maximumFractionDigits: 2})}`;
              }
            }
          }
        },
        scales: {
          x: {
            ticks: {
              color: "#9ca3c7",
              maxRotation: 0,
              autoSkip: true,
              autoSkipPadding: 16
            },
            grid: {
              color: "rgba(55,65,95,0.6)"
            }
          },
          y: {
            ticks: {
              color: "#9ca3c7",
              callback: (value) => "$" + value.toLocaleString()
            },
            grid: {
              color: "rgba(34,43,75,0.9)"
            }
          }
        }
      }
    });
  }

  // -----------------------------
  // Synthetic coin charts with buy/sell markers
  // -----------------------------
  function generateSyntheticSeries(days, basePrice, volatility = 0.06, drift = 0.002) {
    const series = [];
    let price = basePrice;
    for (let d = 0; d <= days; d++) {
      const rand = (Math.random() - 0.5) * volatility;
      const seasonal = Math.sin((d / days) * Math.PI * 2) * volatility * 0.35;
      price = price * (1 + drift + rand + seasonal);
      if (price < basePrice * 0.25) price = basePrice * 0.25;
      series.push({ day: d, price: Number(price.toFixed(3)) });
    }
    return series;
  }

  function buildCoinCharts() {
    const container = document.getElementById("coinCharts");
    const days = 90;

    COINS.forEach((coin, idx) => {
      const card = document.createElement("div");
      card.className = "mini-chart-card";

      const header = document.createElement("div");
      header.className = "mini-chart-header";
      header.innerHTML = `
        <div>
          <span class="symbol">${coin.symbol}</span>
          <span class="name"> · ${coin.name}</span>
        </div>
        <span class="note">Synthetic 90-day path</span>
      `;
      card.appendChild(header);

      const canvas = document.createElement("canvas");
      const canvasId = `mini_${coin.symbol}`;
      canvas.id = canvasId;
      card.appendChild(canvas);

      container.appendChild(card);

      // Generate synthetic prices
      const basePrice = 0.5 + idx * 0.8;
      const series = generateSyntheticSeries(days, basePrice);

      // Map trades onto this coin
      const buyMarkers = [];
      const sellMarkers = [];
      trades
        .filter(t => t.coin === coin.symbol)
        .forEach(t => {
          const buyPoint = series.find(p => p.day === t.buyDay) || series[0];
          const sellPoint = series.find(p => p.day === t.sellDay) || series[series.length - 1];
          buyMarkers.push({ x: buyPoint.day, y: buyPoint.price });
          sellMarkers.push({ x: sellPoint.day, y: sellPoint.price });
        });

      const ctx = canvas.getContext("2d");
      new Chart(ctx, {
        type: "line",
        data: {
          labels: series.map(p => p.day),
          datasets: [
            {
              label: `${coin.symbol} Synthetic`,
              data: series.map(p => p.price),
              borderColor: "#48d5ff",
              backgroundColor: "rgba(72,213,255,0.12)",
              borderWidth: 1.4,
              pointRadius: 0,
              tension: 0.25
            },
            {
              type: "scatter",
              label: "Buys",
              data: buyMarkers,
              pointBackgroundColor: "#00d68f",
              pointBorderColor: "#00d68f",
              pointRadius: 4,
              pointHoverRadius: 5
            },
            {
              type: "scatter",
              label: "Sells",
              data: sellMarkers,
              pointBackgroundColor: "#ff4b5c",
              pointBorderColor: "#ff4b5c",
              pointRadius: 4,
              pointHoverRadius: 5
            }
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: {
              callbacks: {
                label: (ctx) => {
                  if (ctx.datasetIndex === 0) {
                    return `${coin.symbol} $${ctx.parsed.y.toFixed(3)}`;
                  }
                  const kind = ctx.datasetIndex === 1 ? "Buy" : "Sell";
                  return `${kind} · Day ${ctx.parsed.x} · $${ctx.parsed.y.toFixed(3)}`;
                }
              }
            }
          },
          scales: {
            x: {
              ticks: {
                display: false
              },
              grid: { display: false }
            },
            y: {
              ticks: {
                display: false
              },
              grid: { display: false }
            }
          }
        }
      });
    });
  }

  // -----------------------------
  // Live CoinGecko price fetcher
  // -----------------------------
  const COINGECKO_URL =
    "https://api.coingecko.com/api/v3/simple/price"; // Free/demo endpoint. See docs for pro-api & keys.

  async function fetchLivePrices() {
    const tbody = document.querySelector("#livePriceTable tbody");
    try {
      const ids = COINS.map(c => c.id).join(",");
      const params = new URLSearchParams({
        ids,
        vs_currencies: "usd",
        include_24hr_change: "true"
      }).toString();

      const res = await fetch(`${COINGECKO_URL}?${params}`);
      if (!res.ok) throw new Error("HTTP " + res.status);
      const data = await res.json();

      tbody.innerHTML = "";

      const now = new Date();
      const timeStr = now.toLocaleTimeString(undefined, { hour12: false });

      COINS.forEach(c => {
        const row = document.createElement("tr");
        const entry = data[c.id];

        if (!entry) {
          row.innerHTML = `
            <td>${c.name}</td>
            <td>${c.symbol}</td>
            <td colspan="3" class="text-muted">No data (rate limit or unsupported)</td>
          `;
        } else {
          const price = entry.usd;
          const chg = entry.usd_24h_change ?? 0;
          const chgClass = chg > 0 ? "text-green" : chg < 0 ? "text-red" : "text-muted";

          row.innerHTML = `
            <td>${c.name}</td>
            <td>${c.symbol}</td>
            <td>$${price.toLocaleString(undefined, {maximumFractionDigits: 6})}</td>
            <td class="${chgClass}">${chg.toFixed(2)}%</td>
            <td class="text-muted">${timeStr}</td>
          `;
        }
        tbody.appendChild(row);
      });
    } catch (err) {
      tbody.innerHTML = `
        <tr>
          <td colspan="5" class="text-red" style="text-align:center;padding:14px;">
            Error fetching prices from CoinGecko: ${err.message}
          </td>
        </tr>
      `;
    }
  }

  // Initial render
  renderTradeTable();
  buildEquityChart();
  buildCoinCharts();
  fetchLivePrices();
  setInterval(fetchLivePrices, 30_000); // refresh prices every 30 seconds
</script>
</body>
</html>