Spaces:
Sleeping
Sleeping
feat: SPX crash risk monitor
Browse files- spx-crash-risk-monitor.html +901 -0
spx-crash-risk-monitor.html
ADDED
|
@@ -0,0 +1,901 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>SPX Directional Index β Crash Risk Monitor | Krupp Capital</title>
|
| 7 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
| 8 |
+
<style>
|
| 9 |
+
:root {
|
| 10 |
+
--bg: #07090f; --bg2: #0d1117; --border: #1e2a38;
|
| 11 |
+
--blue: #3b7bff; --red: #ef4444; --green: #22c55e;
|
| 12 |
+
--amber: #f59e0b; --text: #e2e8f0; --muted: #64748b; --subtle: #334155;
|
| 13 |
+
}
|
| 14 |
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 15 |
+
body { background: var(--bg); color: var(--text); font-family: 'SF Mono','Fira Code',monospace; font-size: 12px; min-height: 100vh; }
|
| 16 |
+
|
| 17 |
+
.header { display:flex; align-items:center; justify-content:space-between; padding:10px 18px; background:var(--bg2); border-bottom:1px solid var(--border); }
|
| 18 |
+
.header-left { display:flex; align-items:center; gap:14px; }
|
| 19 |
+
.logo-badge { background:var(--blue); color:#fff; font-size:9px; font-weight:700; letter-spacing:.08em; padding:3px 7px; border-radius:3px; }
|
| 20 |
+
.header-title { font-size:14px; font-weight:600; letter-spacing:.05em; }
|
| 21 |
+
.header-sub { font-size:10px; color:var(--muted); }
|
| 22 |
+
.live-badge { display:flex; align-items:center; gap:5px; font-size:10px; color:var(--green); }
|
| 23 |
+
.live-dot { width:6px; height:6px; border-radius:50%; background:var(--green); animation:pulse 2s infinite; }
|
| 24 |
+
@keyframes pulse { 0%,100%{opacity:1}50%{opacity:.4} }
|
| 25 |
+
|
| 26 |
+
.metric-strip { display:flex; border-bottom:1px solid var(--border); background:var(--bg2); overflow-x:auto; }
|
| 27 |
+
.metric-item { flex:1; min-width:110px; padding:8px 14px; border-right:1px solid var(--border); }
|
| 28 |
+
.metric-item:last-child { border-right:none; }
|
| 29 |
+
.metric-label { font-size:9px; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; margin-bottom:3px; }
|
| 30 |
+
.metric-val { font-size:14px; font-weight:700; }
|
| 31 |
+
.metric-sub { font-size:9px; color:var(--muted); margin-top:1px; }
|
| 32 |
+
.pos { color:var(--blue); } .neg { color:var(--red); } .warn { color:var(--amber); }
|
| 33 |
+
|
| 34 |
+
.tab-bar { display:flex; border-bottom:1px solid var(--border); background:var(--bg2); padding:0 18px; }
|
| 35 |
+
.tab-btn { padding:10px 20px; font-size:11px; font-weight:600; letter-spacing:.06em; color:var(--muted); cursor:pointer; border-bottom:2px solid transparent; background:none; border-top:none; border-left:none; border-right:none; transition:all .2s; }
|
| 36 |
+
.tab-btn:hover { color:var(--text); }
|
| 37 |
+
.tab-btn.active { color:var(--blue); border-bottom-color:var(--blue); }
|
| 38 |
+
.tab-content { display:none; padding:16px 18px; }
|
| 39 |
+
.tab-content.active { display:block; }
|
| 40 |
+
|
| 41 |
+
.two-col { display:grid; grid-template-columns:1fr 320px; gap:14px; }
|
| 42 |
+
.three-col { display:grid; grid-template-columns:1fr 1fr 1fr; gap:14px; }
|
| 43 |
+
.panel { background:var(--bg2); border:1px solid var(--border); border-radius:4px; padding:14px; }
|
| 44 |
+
.panel-title { font-size:10px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.1em; margin-bottom:10px; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:4px; }
|
| 45 |
+
.pbadge { font-size:9px; padding:2px 6px; border-radius:3px; }
|
| 46 |
+
.b-blue { background:rgba(59,123,255,.15); color:var(--blue); }
|
| 47 |
+
.b-amber { background:rgba(245,158,11,.15); color:var(--amber); }
|
| 48 |
+
|
| 49 |
+
#heatmapCanvas { display:block; }
|
| 50 |
+
#overlayCanvas { position:absolute; top:0; left:0; cursor:crosshair; }
|
| 51 |
+
.hm-wrap { position:relative; }
|
| 52 |
+
.hm-outer { padding-left:44px; position:relative; }
|
| 53 |
+
.x-axis { display:flex; justify-content:space-between; padding:4px 0 0; font-size:9px; color:var(--muted); }
|
| 54 |
+
.y-axis { position:absolute; left:-42px; top:0; height:100%; display:flex; flex-direction:column; justify-content:space-between; font-size:9px; color:var(--muted); text-align:right; pointer-events:none; }
|
| 55 |
+
.legend-bar { height:10px; border-radius:2px; margin:6px 0 2px; background:linear-gradient(to right,#7f1d1d,#ef4444,#f97316,#fbbf24,#f1f5f9,#93c5fd,#3b7bff,#1e3a6e,#0a1628); }
|
| 56 |
+
.legend-labels { display:flex; justify-content:space-between; font-size:9px; color:var(--muted); }
|
| 57 |
+
|
| 58 |
+
table { width:100%; border-collapse:collapse; font-size:11px; }
|
| 59 |
+
th { text-align:left; color:var(--muted); font-size:9px; text-transform:uppercase; letter-spacing:.08em; padding:3px 6px; border-bottom:1px solid var(--border); }
|
| 60 |
+
td { padding:5px 6px; border-bottom:1px solid rgba(30,42,56,.6); }
|
| 61 |
+
tr:last-child td { border-bottom:none; }
|
| 62 |
+
tr:hover td { background:rgba(59,123,255,.04); }
|
| 63 |
+
|
| 64 |
+
.chart-box { height:200px; position:relative; }
|
| 65 |
+
.chart-box-lg { height:260px; position:relative; }
|
| 66 |
+
|
| 67 |
+
.risk-meter { height:8px; border-radius:4px; background:linear-gradient(to right,var(--green),#84cc16,var(--amber),#f97316,var(--red)); position:relative; margin:8px 0 4px; }
|
| 68 |
+
.risk-needle { position:absolute; top:-4px; width:2px; height:16px; background:#fff; border-radius:1px; transform:translateX(-50%); box-shadow:0 0 4px rgba(255,255,255,.6); }
|
| 69 |
+
.risk-labels { display:flex; justify-content:space-between; font-size:9px; color:var(--muted); }
|
| 70 |
+
|
| 71 |
+
.row { display:flex; gap:14px; margin-bottom:14px; }
|
| 72 |
+
.col-half { flex:1; min-width:0; }
|
| 73 |
+
.mb { margin-bottom:14px; }
|
| 74 |
+
|
| 75 |
+
.fc-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:14px; }
|
| 76 |
+
.sc-card { padding:12px; border-radius:4px; }
|
| 77 |
+
.sc-row { display:flex; justify-content:space-between; padding:3px 0; border-bottom:1px solid rgba(255,255,255,.04); font-size:11px; }
|
| 78 |
+
.sc-row:last-child { border-bottom:none; }
|
| 79 |
+
.sc-title { font-size:11px; font-weight:700; margin-bottom:7px; }
|
| 80 |
+
|
| 81 |
+
#hmTooltip { position:fixed; background:rgba(7,9,15,.97); border:1px solid var(--border); border-radius:4px; padding:8px 12px; font-size:11px; pointer-events:none; display:none; z-index:9999; line-height:1.8; min-width:180px; }
|
| 82 |
+
.tip-hdr { font-size:9px; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; margin-bottom:4px; }
|
| 83 |
+
|
| 84 |
+
::-webkit-scrollbar { width:5px; height:5px; }
|
| 85 |
+
::-webkit-scrollbar-track { background:var(--bg); }
|
| 86 |
+
::-webkit-scrollbar-thumb { background:var(--subtle); border-radius:3px; }
|
| 87 |
+
</style>
|
| 88 |
+
</head>
|
| 89 |
+
<body>
|
| 90 |
+
|
| 91 |
+
<!-- Header -->
|
| 92 |
+
<div class="header">
|
| 93 |
+
<div class="header-left">
|
| 94 |
+
<div class="logo-badge">KRUPP CAPITAL</div>
|
| 95 |
+
<div>
|
| 96 |
+
<div class="header-title">SPX DIRECTIONAL INDEX β CRASH RISK MONITOR</div>
|
| 97 |
+
<div class="header-sub">Quantitative Research Β· GEX+ Risk Surface Β· Options Flow Intelligence</div>
|
| 98 |
+
</div>
|
| 99 |
+
</div>
|
| 100 |
+
<div class="live-badge"><div class="live-dot"></div><span>CBOE DATA Β· Apr 19 2026 Β· SPX 7,126</span></div>
|
| 101 |
+
</div>
|
| 102 |
+
|
| 103 |
+
<!-- Metric Strip -->
|
| 104 |
+
<div class="metric-strip">
|
| 105 |
+
<div class="metric-item"><div class="metric-label">SPX Spot</div><div class="metric-val pos">7,126</div><div class="metric-sub">β0.85% session</div></div>
|
| 106 |
+
<div class="metric-item"><div class="metric-label">Net GEX</div><div class="metric-val pos">+$1.195B</div><div class="metric-sub">Dealer Long Ξ</div></div>
|
| 107 |
+
<div class="metric-item"><div class="metric-label">Zero-Gamma</div><div class="metric-val warn">6,184</div><div class="metric-sub">β13.2% from spot</div></div>
|
| 108 |
+
<div class="metric-item"><div class="metric-label">HVL</div><div class="metric-val">6,860</div><div class="metric-sub">Regime transition</div></div>
|
| 109 |
+
<div class="metric-item"><div class="metric-label">Call Wall</div><div class="metric-val pos">7,100</div><div class="metric-sub">$1.178B gamma</div></div>
|
| 110 |
+
<div class="metric-item"><div class="metric-label">Put Wall</div><div class="metric-val neg">6,900</div><div class="metric-sub">Gamma support</div></div>
|
| 111 |
+
<div class="metric-item"><div class="metric-label">VGR</div><div class="metric-val warn">1,086Γ</div><div class="metric-sub">Vanna dominance</div></div>
|
| 112 |
+
<div class="metric-item"><div class="metric-label">Crash Risk</div><div class="metric-val neg">42</div><div class="metric-sub">ModerateβHigh</div></div>
|
| 113 |
+
</div>
|
| 114 |
+
|
| 115 |
+
<!-- Tab Bar -->
|
| 116 |
+
<div class="tab-bar">
|
| 117 |
+
<button class="tab-btn active" onclick="switchTab('heatmap',this)">HEATMAP</button>
|
| 118 |
+
<button class="tab-btn" onclick="switchTab('risk',this)">RISK ANALYSIS</button>
|
| 119 |
+
<button class="tab-btn" onclick="switchTab('crash',this)">CRASH RISK</button>
|
| 120 |
+
<button class="tab-btn" onclick="switchTab('forecast',this)">FORECAST</button>
|
| 121 |
+
</div>
|
| 122 |
+
|
| 123 |
+
<!-- βββ TAB 1: HEATMAP βββ -->
|
| 124 |
+
<div id="tab-heatmap" class="tab-content active">
|
| 125 |
+
<div class="two-col">
|
| 126 |
+
<div class="panel">
|
| 127 |
+
<div class="panel-title">
|
| 128 |
+
<span>GEX+ RISK SURFACE β Spot Move Γ IV Shock</span>
|
| 129 |
+
<div style="display:flex;gap:6px">
|
| 130 |
+
<span class="pbadge b-blue">CBOE OI</span>
|
| 131 |
+
<span class="pbadge b-amber">BS Gamma</span>
|
| 132 |
+
</div>
|
| 133 |
+
</div>
|
| 134 |
+
<div class="hm-outer" id="hmOuter">
|
| 135 |
+
<div class="y-axis">
|
| 136 |
+
<span>+60%</span><span>+45%</span><span>+30%</span><span>+15%</span><span>0%</span>
|
| 137 |
+
</div>
|
| 138 |
+
<div class="hm-wrap" id="hmWrap">
|
| 139 |
+
<canvas id="heatmapCanvas"></canvas>
|
| 140 |
+
<canvas id="overlayCanvas"></canvas>
|
| 141 |
+
</div>
|
| 142 |
+
<div class="x-axis">
|
| 143 |
+
<span>β20%</span><span>β15%</span><span>β10%</span><span>β5%</span><span>0%</span><span>+5%</span><span>+10%</span>
|
| 144 |
+
</div>
|
| 145 |
+
</div>
|
| 146 |
+
<div class="legend-bar"></div>
|
| 147 |
+
<div class="legend-labels">
|
| 148 |
+
<span>Amplifying (Cascade)</span>
|
| 149 |
+
<span>Neutral</span>
|
| 150 |
+
<span>Dampening (Safe)</span>
|
| 151 |
+
</div>
|
| 152 |
+
<div style="font-size:10px;color:var(--muted);margin-top:6px">
|
| 153 |
+
β IV Shock (0β+60%) Β· β Spot Move (β20%β+10%) Β· Hover for live values
|
| 154 |
+
</div>
|
| 155 |
+
</div>
|
| 156 |
+
|
| 157 |
+
<div style="display:flex;flex-direction:column;gap:12px">
|
| 158 |
+
<div class="panel">
|
| 159 |
+
<div class="panel-title">CURRENT POSITION</div>
|
| 160 |
+
<table>
|
| 161 |
+
<tbody>
|
| 162 |
+
<tr><td style="color:var(--muted)">Spot</td><td class="pos">7,126</td></tr>
|
| 163 |
+
<tr><td style="color:var(--muted)">Spot Move</td><td>0.00%</td></tr>
|
| 164 |
+
<tr><td style="color:var(--muted)">IV Shock</td><td>+0%</td></tr>
|
| 165 |
+
<tr><td style="color:var(--muted)">Net GEX+</td><td class="pos">+$1.195B</td></tr>
|
| 166 |
+
<tr><td style="color:var(--muted)">Regime</td><td class="pos">Dampening</td></tr>
|
| 167 |
+
<tr><td style="color:var(--muted)">Zero-Ξ Level</td><td class="warn">6,184</td></tr>
|
| 168 |
+
</tbody>
|
| 169 |
+
</table>
|
| 170 |
+
</div>
|
| 171 |
+
<div class="panel">
|
| 172 |
+
<div class="panel-title">GEX+ AT DRAWDOWN LEVELS</div>
|
| 173 |
+
<table>
|
| 174 |
+
<thead><tr><th>Drawdown</th><th>Spot</th><th>GEX+</th><th>Regime</th></tr></thead>
|
| 175 |
+
<tbody id="drawdownTable"></tbody>
|
| 176 |
+
</table>
|
| 177 |
+
</div>
|
| 178 |
+
<div class="panel">
|
| 179 |
+
<div class="panel-title">IV SKEW (CBOE)</div>
|
| 180 |
+
<table>
|
| 181 |
+
<thead><tr><th>Expiry</th><th>Call</th><th>Put</th><th>Skew</th></tr></thead>
|
| 182 |
+
<tbody id="skewTable"></tbody>
|
| 183 |
+
</table>
|
| 184 |
+
</div>
|
| 185 |
+
</div>
|
| 186 |
+
</div>
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<!-- βββ TAB 2: RISK ANALYSIS βββ -->
|
| 190 |
+
<div id="tab-risk" class="tab-content">
|
| 191 |
+
<div class="row mb">
|
| 192 |
+
<div class="col-half panel">
|
| 193 |
+
<div class="panel-title">DEALER GAMMA EXPOSURE BY STRIKE</div>
|
| 194 |
+
<div class="chart-box"><canvas id="gexChart"></canvas></div>
|
| 195 |
+
</div>
|
| 196 |
+
<div class="col-half panel">
|
| 197 |
+
<div class="panel-title">IV SKEW TERM STRUCTURE</div>
|
| 198 |
+
<div class="chart-box"><canvas id="skewChart"></canvas></div>
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
<div class="row mb">
|
| 202 |
+
<div class="col-half panel">
|
| 203 |
+
<div class="panel-title">NET GEX SENSITIVITY vs SPOT</div>
|
| 204 |
+
<div class="chart-box"><canvas id="sensitivityChart"></canvas></div>
|
| 205 |
+
</div>
|
| 206 |
+
<div class="col-half panel">
|
| 207 |
+
<div class="panel-title">VANNA EXPOSURE (IV-DRIVEN DELTA)</div>
|
| 208 |
+
<div class="chart-box"><canvas id="vannaChart"></canvas></div>
|
| 209 |
+
</div>
|
| 210 |
+
</div>
|
| 211 |
+
<div class="three-col">
|
| 212 |
+
<div class="panel">
|
| 213 |
+
<div class="panel-title">KEY LEVELS</div>
|
| 214 |
+
<table>
|
| 215 |
+
<thead><tr><th>Level</th><th>Price</th><th>Note</th></tr></thead>
|
| 216 |
+
<tbody id="keyLevelsTable"></tbody>
|
| 217 |
+
</table>
|
| 218 |
+
</div>
|
| 219 |
+
<div class="panel">
|
| 220 |
+
<div class="panel-title">FLOW METRICS</div>
|
| 221 |
+
<table>
|
| 222 |
+
<thead><tr><th>Metric</th><th>Value</th><th>Pctile</th></tr></thead>
|
| 223 |
+
<tbody id="flowMetricsTable"></tbody>
|
| 224 |
+
</table>
|
| 225 |
+
</div>
|
| 226 |
+
<div class="panel">
|
| 227 |
+
<div class="panel-title">REGIME SIGNALS</div>
|
| 228 |
+
<table>
|
| 229 |
+
<thead><tr><th>Signal</th><th>Status</th></tr></thead>
|
| 230 |
+
<tbody id="regimeTable"></tbody>
|
| 231 |
+
</table>
|
| 232 |
+
</div>
|
| 233 |
+
</div>
|
| 234 |
+
</div>
|
| 235 |
+
|
| 236 |
+
<!-- βββ TAB 3: CRASH RISK βββ -->
|
| 237 |
+
<div id="tab-crash" class="tab-content">
|
| 238 |
+
<div class="two-col">
|
| 239 |
+
<div>
|
| 240 |
+
<div class="panel mb">
|
| 241 |
+
<div class="panel-title">COMPOSITE CRASH RISK INDEX</div>
|
| 242 |
+
<div style="display:flex;align-items:center;gap:16px;margin-bottom:8px">
|
| 243 |
+
<div style="font-size:48px;font-weight:800;color:var(--amber);line-height:1">42</div>
|
| 244 |
+
<div>
|
| 245 |
+
<div style="font-size:13px;font-weight:700;color:var(--amber)">MODERATEβHIGH RISK</div>
|
| 246 |
+
<div style="font-size:10px;color:var(--muted);margin-top:2px">Elevated put skew Β· VIX 28 Β· Below HVL zone</div>
|
| 247 |
+
</div>
|
| 248 |
+
</div>
|
| 249 |
+
<div class="risk-meter"><div class="risk-needle" style="left:42%"></div></div>
|
| 250 |
+
<div class="risk-labels">
|
| 251 |
+
<span>LOW (0)</span><span>MODERATE (40)</span><span>HIGH (70)</span><span>EXTREME (100)</span>
|
| 252 |
+
</div>
|
| 253 |
+
</div>
|
| 254 |
+
<div class="panel mb">
|
| 255 |
+
<div class="panel-title">IMPLIED PROBABILITY DISTRIBUTION (Breeden-Litzenberger)</div>
|
| 256 |
+
<div class="chart-box-lg"><canvas id="probChart"></canvas></div>
|
| 257 |
+
</div>
|
| 258 |
+
<div class="panel">
|
| 259 |
+
<div class="panel-title">CRASH SCENARIO ANALYSIS</div>
|
| 260 |
+
<table>
|
| 261 |
+
<thead><tr><th>Scenario</th><th>Target</th><th>Move</th><th>GEX Regime</th><th>Prob</th></tr></thead>
|
| 262 |
+
<tbody id="scenarioTable"></tbody>
|
| 263 |
+
</table>
|
| 264 |
+
</div>
|
| 265 |
+
</div>
|
| 266 |
+
<div style="display:flex;flex-direction:column;gap:12px">
|
| 267 |
+
<div class="panel">
|
| 268 |
+
<div class="panel-title">RISK FACTOR DECOMPOSITION</div>
|
| 269 |
+
<table>
|
| 270 |
+
<thead><tr><th>Factor</th><th>Score</th><th>Wt</th><th>Contrib</th></tr></thead>
|
| 271 |
+
<tbody id="riskFactors"></tbody>
|
| 272 |
+
</table>
|
| 273 |
+
</div>
|
| 274 |
+
<div class="panel">
|
| 275 |
+
<div class="panel-title">GAMMA CLIFF</div>
|
| 276 |
+
<div class="chart-box"><canvas id="cliffChart"></canvas></div>
|
| 277 |
+
</div>
|
| 278 |
+
<div class="panel">
|
| 279 |
+
<div class="panel-title">GEX+ vs SPOT MOVE</div>
|
| 280 |
+
<table>
|
| 281 |
+
<thead><tr><th>Spot</th><th>Move</th><th>GEX+</th><th>Status</th></tr></thead>
|
| 282 |
+
<tbody id="gexLevelsTable"></tbody>
|
| 283 |
+
</table>
|
| 284 |
+
</div>
|
| 285 |
+
</div>
|
| 286 |
+
</div>
|
| 287 |
+
</div>
|
| 288 |
+
|
| 289 |
+
<!-- βββ TAB 4: FORECAST βββ -->
|
| 290 |
+
<div id="tab-forecast" class="tab-content">
|
| 291 |
+
<div class="row mb">
|
| 292 |
+
<div class="col-half panel">
|
| 293 |
+
<div class="panel-title">SPX 5-DAY SCENARIO FAN</div>
|
| 294 |
+
<div class="chart-box-lg"><canvas id="forecastChart"></canvas></div>
|
| 295 |
+
</div>
|
| 296 |
+
<div class="col-half panel">
|
| 297 |
+
<div class="panel-title">5-DAY EXPECTED MOVE DISTRIBUTION</div>
|
| 298 |
+
<div class="chart-box-lg"><canvas id="emChart"></canvas></div>
|
| 299 |
+
</div>
|
| 300 |
+
</div>
|
| 301 |
+
<div class="fc-grid" id="scenarioCards"></div>
|
| 302 |
+
<div class="row">
|
| 303 |
+
<div class="col-half panel">
|
| 304 |
+
<div class="panel-title">PROBABILITY FORECAST TABLE</div>
|
| 305 |
+
<table>
|
| 306 |
+
<thead><tr><th>Horizon</th><th>Bull Target</th><th>Bear Target</th><th>P(Up)</th><th>P(Down)</th></tr></thead>
|
| 307 |
+
<tbody id="probForecastTable"></tbody>
|
| 308 |
+
</table>
|
| 309 |
+
</div>
|
| 310 |
+
<div class="col-half panel">
|
| 311 |
+
<div class="panel-title">EXPECTED MOVE SUMMARY</div>
|
| 312 |
+
<table>
|
| 313 |
+
<thead><tr><th>Window</th><th>+1Ο</th><th>β1Ο</th><th>Range</th><th>IV</th></tr></thead>
|
| 314 |
+
<tbody id="emTable"></tbody>
|
| 315 |
+
</table>
|
| 316 |
+
</div>
|
| 317 |
+
</div>
|
| 318 |
+
</div>
|
| 319 |
+
|
| 320 |
+
<div id="hmTooltip">
|
| 321 |
+
<div class="tip-hdr" id="tipHdr">GEX+ Surface</div>
|
| 322 |
+
<div id="tipSpot"></div>
|
| 323 |
+
<div id="tipIV"></div>
|
| 324 |
+
<div id="tipGex"></div>
|
| 325 |
+
<div id="tipRegime"></div>
|
| 326 |
+
</div>
|
| 327 |
+
|
| 328 |
+
<script>
|
| 329 |
+
// βββ Tab switching βββββββββββββββββββββββββββββββββββββββ
|
| 330 |
+
function switchTab(id, btn) {
|
| 331 |
+
document.querySelectorAll('.tab-content').forEach(function(t){ t.classList.remove('active'); });
|
| 332 |
+
document.querySelectorAll('.tab-btn').forEach(function(b){ b.classList.remove('active'); });
|
| 333 |
+
document.getElementById('tab-' + id).classList.add('active');
|
| 334 |
+
btn.classList.add('active');
|
| 335 |
+
if (id === 'risk') initRiskCharts();
|
| 336 |
+
if (id === 'crash') initCrashCharts();
|
| 337 |
+
if (id === 'forecast') initForecastCharts();
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
// βββ Real CBOE OI data (Apr 19 2026) ββββββββββββββββββββ
|
| 341 |
+
var SPOT = 7126;
|
| 342 |
+
var CALLS_OI = {
|
| 343 |
+
6850:1053, 6900:1123, 6950:2635, 7000:3197, 7010:1779,
|
| 344 |
+
7025:746, 7030:1342, 7045:1166, 7050:4243, 7070:687,
|
| 345 |
+
7075:1255, 7100:4071, 7110:2185, 7120:607, 7125:1406,
|
| 346 |
+
7140:799, 7150:1663, 7175:1011, 7200:1707, 7240:842, 7250:1263
|
| 347 |
+
};
|
| 348 |
+
var PUTS_OI = {
|
| 349 |
+
6800:2170, 6825:660, 6850:4165, 6875:1355, 6890:765,
|
| 350 |
+
6900:4306, 6915:726, 6925:1302, 6935:714, 6950:1634,
|
| 351 |
+
7000:1344, 7050:834
|
| 352 |
+
};
|
| 353 |
+
|
| 354 |
+
// βββ Black-Scholes helpers βββββββββββββββββββββββββββββββ
|
| 355 |
+
function normalPDF(x) { return Math.exp(-0.5*x*x) / Math.sqrt(2*Math.PI); }
|
| 356 |
+
function bsGamma(S, K, sigma, T) {
|
| 357 |
+
if (T <= 0 || sigma <= 0 || S <= 0) return 0;
|
| 358 |
+
var sqrtT = Math.sqrt(T);
|
| 359 |
+
var d1 = (Math.log(S/K) + 0.5*sigma*sigma*T) / (sigma*sqrtT);
|
| 360 |
+
return normalPDF(d1) / (S * sigma * sqrtT);
|
| 361 |
+
}
|
| 362 |
+
// Returns net GEX in $B
|
| 363 |
+
function computeNetGex(spotPct, ivMult) {
|
| 364 |
+
var S = SPOT * (1 + spotPct);
|
| 365 |
+
var sigma = 0.158 * (1 + ivMult);
|
| 366 |
+
var T = 7 / 365;
|
| 367 |
+
var callGex = 0, putGex = 0;
|
| 368 |
+
var k, oi;
|
| 369 |
+
for (k in CALLS_OI) {
|
| 370 |
+
oi = CALLS_OI[k];
|
| 371 |
+
callGex += oi * bsGamma(S, +k, sigma, T) * S * S * 100;
|
| 372 |
+
}
|
| 373 |
+
for (k in PUTS_OI) {
|
| 374 |
+
oi = PUTS_OI[k];
|
| 375 |
+
putGex += oi * bsGamma(S, +k, sigma, T) * S * S * 100;
|
| 376 |
+
}
|
| 377 |
+
return (callGex - putGex) / 1e9;
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
// βββ Heatmap setup βββββββββββββββββββββββββββββββββββββββ
|
| 381 |
+
var SPOT_STEPS = 140, IV_STEPS = 90;
|
| 382 |
+
var SPOT_MIN = -0.20, SPOT_MAX = 0.10;
|
| 383 |
+
var IV_MIN = 0.00, IV_MAX = 0.60;
|
| 384 |
+
|
| 385 |
+
var gexGrid = new Float32Array(IV_STEPS * SPOT_STEPS);
|
| 386 |
+
var gexMin = 1e9, gexMax = -1e9;
|
| 387 |
+
(function buildGrid() {
|
| 388 |
+
for (var j = 0; j < IV_STEPS; j++) {
|
| 389 |
+
var ivMult = IV_MIN + (j / (IV_STEPS - 1)) * (IV_MAX - IV_MIN);
|
| 390 |
+
for (var i = 0; i < SPOT_STEPS; i++) {
|
| 391 |
+
var sPct = SPOT_MIN + (i / (SPOT_STEPS - 1)) * (SPOT_MAX - SPOT_MIN);
|
| 392 |
+
var v = computeNetGex(sPct, ivMult);
|
| 393 |
+
gexGrid[j * SPOT_STEPS + i] = v;
|
| 394 |
+
if (v < gexMin) gexMin = v;
|
| 395 |
+
if (v > gexMax) gexMax = v;
|
| 396 |
+
}
|
| 397 |
+
}
|
| 398 |
+
})();
|
| 399 |
+
|
| 400 |
+
// Color scale: norm=0 β deep red (max negative), norm=1 β deep navy (max positive)
|
| 401 |
+
function gexColor(val) {
|
| 402 |
+
var n = Math.max(0, Math.min(1, (val - gexMin) / (gexMax - gexMin)));
|
| 403 |
+
var stops = [
|
| 404 |
+
[0.00, [100,10,20]], [0.12,[180,30,30]], [0.25,[220,70,40]],
|
| 405 |
+
[0.38,[245,158,11]], [0.50,[225,225,225]], [0.60,[160,190,255]],
|
| 406 |
+
[0.72,[59,123,255]], [0.85,[20,70,180]], [1.00,[5,18,75]]
|
| 407 |
+
];
|
| 408 |
+
for (var s = 0; s < stops.length - 1; s++) {
|
| 409 |
+
if (n >= stops[s][0] && n <= stops[s+1][0]) {
|
| 410 |
+
var t = (n - stops[s][0]) / (stops[s+1][0] - stops[s][0]);
|
| 411 |
+
return [
|
| 412 |
+
Math.round(stops[s][1][0] + t*(stops[s+1][1][0]-stops[s][1][0])),
|
| 413 |
+
Math.round(stops[s][1][1] + t*(stops[s+1][1][1]-stops[s][1][1])),
|
| 414 |
+
Math.round(stops[s][1][2] + t*(stops[s+1][1][2]-stops[s][1][2]))
|
| 415 |
+
];
|
| 416 |
+
}
|
| 417 |
+
}
|
| 418 |
+
return stops[stops.length-1][1];
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
function drawHeatmap() {
|
| 422 |
+
var wrap = document.getElementById('hmWrap');
|
| 423 |
+
var W = wrap.offsetWidth || 620;
|
| 424 |
+
var H = Math.round(W * 0.56);
|
| 425 |
+
var hc = document.getElementById('heatmapCanvas');
|
| 426 |
+
var oc = document.getElementById('overlayCanvas');
|
| 427 |
+
hc.width = SPOT_STEPS; hc.height = IV_STEPS;
|
| 428 |
+
hc.style.width = W + 'px'; hc.style.height = H + 'px';
|
| 429 |
+
oc.width = W; oc.height = H;
|
| 430 |
+
oc.style.width = W + 'px'; oc.style.height = H + 'px';
|
| 431 |
+
|
| 432 |
+
var ctx = hc.getContext('2d');
|
| 433 |
+
var img = ctx.createImageData(SPOT_STEPS, IV_STEPS);
|
| 434 |
+
var d = img.data;
|
| 435 |
+
for (var j = 0; j < IV_STEPS; j++) {
|
| 436 |
+
var row = IV_STEPS - 1 - j; // flip: high IV at top
|
| 437 |
+
for (var i = 0; i < SPOT_STEPS; i++) {
|
| 438 |
+
var v = gexGrid[j * SPOT_STEPS + i];
|
| 439 |
+
var rgb = gexColor(v);
|
| 440 |
+
var idx = (row * SPOT_STEPS + i) * 4;
|
| 441 |
+
d[idx] = rgb[0]; d[idx+1] = rgb[1]; d[idx+2] = rgb[2]; d[idx+3] = 255;
|
| 442 |
+
}
|
| 443 |
+
}
|
| 444 |
+
ctx.putImageData(img, 0, 0);
|
| 445 |
+
drawOverlay(oc, W, H);
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
function drawOverlay(oc, W, H) {
|
| 449 |
+
var ctx = oc.getContext('2d');
|
| 450 |
+
ctx.clearRect(0, 0, W, H);
|
| 451 |
+
|
| 452 |
+
function spotToX(pct) { return ((pct - SPOT_MIN) / (SPOT_MAX - SPOT_MIN)) * W; }
|
| 453 |
+
function ivToY(mult) { return H - ((mult - IV_MIN) / (IV_MAX - IV_MIN)) * H; }
|
| 454 |
+
|
| 455 |
+
// Zero-contour
|
| 456 |
+
ctx.beginPath();
|
| 457 |
+
ctx.strokeStyle = 'rgba(255,255,255,0.88)';
|
| 458 |
+
ctx.lineWidth = 1.8;
|
| 459 |
+
ctx.setLineDash([5,4]);
|
| 460 |
+
var started = false;
|
| 461 |
+
for (var j = 0; j < IV_STEPS; j++) {
|
| 462 |
+
var ivMult = IV_MIN + (j / (IV_STEPS-1)) * (IV_MAX-IV_MIN);
|
| 463 |
+
for (var i = 0; i < SPOT_STEPS-1; i++) {
|
| 464 |
+
var v0 = gexGrid[j*SPOT_STEPS+i], v1 = gexGrid[j*SPOT_STEPS+i+1];
|
| 465 |
+
if ((v0 <= 0 && v1 > 0) || (v0 > 0 && v1 <= 0)) {
|
| 466 |
+
var t = Math.abs(v0) / (Math.abs(v0) + Math.abs(v1) + 1e-10);
|
| 467 |
+
var sPct = SPOT_MIN + ((i+t) / SPOT_STEPS) * (SPOT_MAX-SPOT_MIN);
|
| 468 |
+
var px = spotToX(sPct), py = ivToY(ivMult);
|
| 469 |
+
if (!started) { ctx.moveTo(px, py); started = true; }
|
| 470 |
+
else ctx.lineTo(px, py);
|
| 471 |
+
break;
|
| 472 |
+
}
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
ctx.stroke(); ctx.setLineDash([]);
|
| 476 |
+
|
| 477 |
+
// HVL vertical
|
| 478 |
+
var hvlX = spotToX(6860/SPOT - 1);
|
| 479 |
+
ctx.strokeStyle = 'rgba(245,158,11,0.65)';
|
| 480 |
+
ctx.lineWidth = 1.2; ctx.setLineDash([3,4]);
|
| 481 |
+
ctx.beginPath(); ctx.moveTo(hvlX,0); ctx.lineTo(hvlX,H); ctx.stroke();
|
| 482 |
+
ctx.setLineDash([]);
|
| 483 |
+
ctx.fillStyle = 'rgba(245,158,11,.9)'; ctx.font = '9px monospace';
|
| 484 |
+
ctx.fillText('HVL 6860', hvlX+3, 12);
|
| 485 |
+
|
| 486 |
+
// Zero-gamma vertical
|
| 487 |
+
var zgX = spotToX(6184/SPOT - 1);
|
| 488 |
+
ctx.strokeStyle = 'rgba(239,68,68,0.65)';
|
| 489 |
+
ctx.lineWidth = 1.2; ctx.setLineDash([3,4]);
|
| 490 |
+
ctx.beginPath(); ctx.moveTo(zgX,0); ctx.lineTo(zgX,H); ctx.stroke();
|
| 491 |
+
ctx.setLineDash([]);
|
| 492 |
+
ctx.fillStyle = 'rgba(239,68,68,.9)';
|
| 493 |
+
ctx.fillText('Zero-\u03937 6184', zgX+3, 24);
|
| 494 |
+
|
| 495 |
+
// Current crosshair
|
| 496 |
+
var cx = spotToX(0), cy = ivToY(0);
|
| 497 |
+
ctx.strokeStyle = 'rgba(252,211,77,0.7)';
|
| 498 |
+
ctx.lineWidth = 1; ctx.setLineDash([3,3]);
|
| 499 |
+
ctx.beginPath(); ctx.moveTo(cx,0); ctx.lineTo(cx,H); ctx.stroke();
|
| 500 |
+
ctx.beginPath(); ctx.moveTo(0,cy); ctx.lineTo(W,cy); ctx.stroke();
|
| 501 |
+
ctx.setLineDash([]);
|
| 502 |
+
ctx.beginPath(); ctx.arc(cx, cy, 5, 0, 2*Math.PI);
|
| 503 |
+
ctx.fillStyle = '#facc15'; ctx.fill();
|
| 504 |
+
ctx.strokeStyle = '#fff'; ctx.lineWidth = 1.5; ctx.stroke();
|
| 505 |
+
ctx.fillStyle = 'rgba(252,211,77,.9)'; ctx.font = 'bold 9px monospace';
|
| 506 |
+
ctx.fillText('\u25CF SPX 7126', cx+8, cy-6);
|
| 507 |
+
|
| 508 |
+
// Zone labels
|
| 509 |
+
ctx.font = '10px monospace';
|
| 510 |
+
ctx.fillStyle = 'rgba(239,68,68,.7)';
|
| 511 |
+
ctx.fillText('\u2190 AMPLIFYING', 6, H-8);
|
| 512 |
+
ctx.textAlign = 'right'; ctx.fillStyle = 'rgba(59,123,255,.7)';
|
| 513 |
+
ctx.fillText('DAMPENING \u2192', W-6, H-8);
|
| 514 |
+
ctx.textAlign = 'left'; ctx.fillStyle = 'rgba(255,255,255,.55)';
|
| 515 |
+
ctx.fillText('\u2500\u2500 Zero-\u0393 contour', 6, 38);
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
// βββ Heatmap tooltip βββββββββββββββββββββββββββββββββββββ
|
| 519 |
+
document.getElementById('overlayCanvas').addEventListener('mousemove', function(e) {
|
| 520 |
+
var rect = this.getBoundingClientRect();
|
| 521 |
+
var px = (e.clientX - rect.left) / rect.width;
|
| 522 |
+
var py = 1 - (e.clientY - rect.top) / rect.height;
|
| 523 |
+
var spotPct = SPOT_MIN + px * (SPOT_MAX - SPOT_MIN);
|
| 524 |
+
var ivMult = IV_MIN + py * (IV_MAX - IV_MIN);
|
| 525 |
+
var spot = SPOT * (1 + spotPct);
|
| 526 |
+
var gex = computeNetGex(spotPct, ivMult);
|
| 527 |
+
var regime = gex > 0.2 ? 'Dampening' : gex > 0 ? 'Weak' : 'Amplifying';
|
| 528 |
+
var regimeColor = gex > 0.2 ? '#3b7bff' : gex > 0 ? '#f59e0b' : '#ef4444';
|
| 529 |
+
|
| 530 |
+
var tip = document.getElementById('hmTooltip');
|
| 531 |
+
tip.style.display = 'block';
|
| 532 |
+
tip.style.left = (e.clientX + 14) + 'px';
|
| 533 |
+
tip.style.top = (e.clientY - 10) + 'px';
|
| 534 |
+
|
| 535 |
+
var spotSign = spotPct >= 0 ? '+' : '';
|
| 536 |
+
document.getElementById('tipSpot').textContent =
|
| 537 |
+
'Spot: ' + spot.toFixed(0) + ' (' + spotSign + (spotPct*100).toFixed(1) + '%)';
|
| 538 |
+
document.getElementById('tipIV').textContent =
|
| 539 |
+
'IV Shock: +' + (ivMult*100).toFixed(0) + '%';
|
| 540 |
+
var gexSign = gex >= 0 ? '+' : '';
|
| 541 |
+
document.getElementById('tipGex').textContent =
|
| 542 |
+
'Net GEX+: ' + gexSign + gex.toFixed(3) + 'B';
|
| 543 |
+
var regimeEl = document.getElementById('tipRegime');
|
| 544 |
+
regimeEl.textContent = 'Regime: ' + regime;
|
| 545 |
+
regimeEl.style.color = regimeColor;
|
| 546 |
+
});
|
| 547 |
+
document.getElementById('overlayCanvas').addEventListener('mouseleave', function() {
|
| 548 |
+
document.getElementById('hmTooltip').style.display = 'none';
|
| 549 |
+
});
|
| 550 |
+
|
| 551 |
+
// βββ DOM table builders ββββββββββββοΏ½οΏ½βββββββββββββββββββββ
|
| 552 |
+
function mkTr(cells) {
|
| 553 |
+
// cells = [{text, cls}] β cls is optional className
|
| 554 |
+
var tr = document.createElement('tr');
|
| 555 |
+
cells.forEach(function(c) {
|
| 556 |
+
var td = document.createElement('td');
|
| 557 |
+
td.textContent = c.text;
|
| 558 |
+
if (c.cls) td.className = c.cls;
|
| 559 |
+
if (c.style) td.style.cssText = c.style;
|
| 560 |
+
tr.appendChild(td);
|
| 561 |
+
});
|
| 562 |
+
return tr;
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
function buildSkewTable() {
|
| 566 |
+
var data = [
|
| 567 |
+
{exp:'0DTE', call:'9.35%', put:'15.50%', skew:'6.15%'},
|
| 568 |
+
{exp:'1DTE', call:'11.12%', put:'16.46%', skew:'5.34%'},
|
| 569 |
+
{exp:'4DTE', call:'12.97%', put:'17.26%', skew:'4.29%'},
|
| 570 |
+
{exp:'44DTE', call:'15.15%', put:'17.47%', skew:'2.32%'},
|
| 571 |
+
{exp:'Dec31', call:'17.85%', put:'19.24%', skew:'1.39%'}
|
| 572 |
+
];
|
| 573 |
+
var tbody = document.getElementById('skewTable');
|
| 574 |
+
data.forEach(function(r) {
|
| 575 |
+
tbody.appendChild(mkTr([{text:r.exp},{text:r.call},{text:r.put},{text:r.skew,cls:'neg'}]));
|
| 576 |
+
});
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
function buildDrawdownTable() {
|
| 580 |
+
var levels = [
|
| 581 |
+
{dd:'0%',pct:0},{dd:'-3%',pct:-0.03},{dd:'-5%',pct:-0.05},
|
| 582 |
+
{dd:'-7%',pct:-0.07},{dd:'-10%',pct:-0.10},
|
| 583 |
+
{dd:'-13.2%',pct:-0.132},{dd:'-15%',pct:-0.15},{dd:'-20%',pct:-0.20}
|
| 584 |
+
];
|
| 585 |
+
var tbody = document.getElementById('drawdownTable');
|
| 586 |
+
levels.forEach(function(lv) {
|
| 587 |
+
var spot = (SPOT * (1 + lv.pct)).toFixed(0);
|
| 588 |
+
var gex = computeNetGex(lv.pct, 0.25);
|
| 589 |
+
var cls = gex > 0.3 ? 'pos' : gex > 0 ? 'warn' : 'neg';
|
| 590 |
+
var reg = gex > 0.3 ? 'Dampening' : gex > 0 ? 'Transitional' : 'Amplifying';
|
| 591 |
+
var gSign = gex >= 0 ? '+' : '';
|
| 592 |
+
tbody.appendChild(mkTr([
|
| 593 |
+
{text:lv.dd, cls:'neg'},
|
| 594 |
+
{text:spot},
|
| 595 |
+
{text:gSign + gex.toFixed(2) + 'B', cls:cls},
|
| 596 |
+
{text:reg, cls:cls}
|
| 597 |
+
]));
|
| 598 |
+
});
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
function buildStaticTables() {
|
| 602 |
+
var kl = document.getElementById('keyLevelsTable');
|
| 603 |
+
[{l:'Call Wall',p:'7,100',n:'Gamma cap',c:'pos'},
|
| 604 |
+
{l:'Put Wall',p:'6,900',n:'Gamma floor',c:'warn'},
|
| 605 |
+
{l:'HVL',p:'6,860',n:'Regime flip',c:''},
|
| 606 |
+
{l:'Zero-Gamma',p:'6,184',n:'Cascade start',c:'neg'},
|
| 607 |
+
{l:'Spot',p:'7,126',n:'Current',c:'',cs:'color:var(--muted)'}
|
| 608 |
+
].forEach(function(r) {
|
| 609 |
+
kl.appendChild(mkTr([{text:r.l,cls:r.c,style:r.cs||''},{text:r.p,cls:r.c},{text:r.n}]));
|
| 610 |
+
});
|
| 611 |
+
|
| 612 |
+
var fm = document.getElementById('flowMetricsTable');
|
| 613 |
+
[{m:'DEX',v:'$2.43T',p:'86th',c:'pos'},{m:'Net GEX',v:'$1.195B',p:'71st',c:'pos'},
|
| 614 |
+
{m:'Charm (3M)',v:'+3.3M \u0394/day',p:'\u2014',c:'pos'},{m:'VGR',v:'1,086\u00D7',p:'High',c:'warn'},
|
| 615 |
+
{m:'0DTE %',v:'34.2%',p:'Elevated',c:''}
|
| 616 |
+
].forEach(function(r) {
|
| 617 |
+
fm.appendChild(mkTr([{text:r.m},{text:r.v,cls:r.c},{text:r.p}]));
|
| 618 |
+
});
|
| 619 |
+
|
| 620 |
+
var rg = document.getElementById('regimeTable');
|
| 621 |
+
[{s:'Gamma Regime',st:'Long Gamma',c:'pos'},{s:'Vol Regime',st:'Elevated',c:'warn'},
|
| 622 |
+
{s:'Flow Bias',st:'Bullish',c:'pos'},{s:'Skew Trend',st:'Put premium',c:'neg'},
|
| 623 |
+
{s:'Charm Bias',st:'Upward drift',c:'pos'}
|
| 624 |
+
].forEach(function(r) {
|
| 625 |
+
rg.appendChild(mkTr([{text:r.s},{text:r.st,cls:r.c}]));
|
| 626 |
+
});
|
| 627 |
+
|
| 628 |
+
var sc = document.getElementById('scenarioTable');
|
| 629 |
+
[{sc:'HVL Break',t:'6,860',m:'-3.7%',g:'Transition',p:'28%',c:'warn'},
|
| 630 |
+
{sc:'Zero-Gamma',t:'6,184',m:'-13.2%',g:'Cascade',p:'12%',c:'neg'},
|
| 631 |
+
{sc:'Vol Cascade',t:'5,850',m:'-17.9%',g:'Amplifying',p:'7%',c:'neg'},
|
| 632 |
+
{sc:'Tail Event',t:'5,200',m:'-27.0%',g:'Maximum',p:'2%',c:'neg'}
|
| 633 |
+
].forEach(function(r) {
|
| 634 |
+
sc.appendChild(mkTr([{text:r.sc,cls:r.c},{text:r.t},{text:r.m,cls:'neg'},{text:r.g,cls:'neg'},{text:r.p}]));
|
| 635 |
+
});
|
| 636 |
+
|
| 637 |
+
var pt = document.getElementById('probForecastTable');
|
| 638 |
+
[{h:'1-Day',bu:'7,180',be:'7,060',pu:'52%',pd:'48%'},
|
| 639 |
+
{h:'3-Day',bu:'7,240',be:'6,980',pu:'49%',pd:'51%'},
|
| 640 |
+
{h:'5-Day',bu:'7,350',be:'6,860',pu:'42%',pd:'58%'},
|
| 641 |
+
{h:'10-Day',bu:'7,450',be:'6,700',pu:'38%',pd:'62%'},
|
| 642 |
+
{h:'21-Day',bu:'7,600',be:'6,400',pu:'34%',pd:'66%'}
|
| 643 |
+
].forEach(function(r) {
|
| 644 |
+
pt.appendChild(mkTr([{text:r.h},{text:r.bu,cls:'pos'},{text:r.be,cls:'neg'},{text:r.pu,cls:'pos'},{text:r.pd,cls:'neg'}]));
|
| 645 |
+
});
|
| 646 |
+
|
| 647 |
+
var et = document.getElementById('emTable');
|
| 648 |
+
[{w:'0DTE',p:'+67',m:'-67',r:'134 pts',iv:'12.4%'},
|
| 649 |
+
{w:'1-Day',p:'+89',m:'-89',r:'178 pts',iv:'14.1%'},
|
| 650 |
+
{w:'1-Week',p:'+199',m:'-199',r:'398 pts',iv:'15.8%'},
|
| 651 |
+
{w:'1-Month',p:'+412',m:'-412',r:'824 pts',iv:'16.5%'},
|
| 652 |
+
{w:'3-Month',p:'+714',m:'-714',r:'1,428 pts',iv:'17.2%'}
|
| 653 |
+
].forEach(function(r) {
|
| 654 |
+
et.appendChild(mkTr([{text:r.w},{text:r.p,cls:'pos'},{text:r.m,cls:'neg'},{text:r.r},{text:r.iv}]));
|
| 655 |
+
});
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
function buildScenarioCards() {
|
| 659 |
+
var grid = document.getElementById('scenarioCards');
|
| 660 |
+
var cards = [
|
| 661 |
+
{title:'BULL SCENARIO (42%)', cls:'pos', border:'var(--blue)', bg:'rgba(59,123,255,.06)',
|
| 662 |
+
rows:[['Target','7,350','pos'],['Move','+3.1%','pos'],['Trigger','7,100 call wall break',''],['Charm','+3.3M \u0394/day','pos'],['VIX Target','22\u201324','']]},
|
| 663 |
+
{title:'BEAR SCENARIO (28%)', cls:'neg', border:'var(--red)', bg:'rgba(239,68,68,.06)',
|
| 664 |
+
rows:[['Target','6,860','neg'],['Move','-3.7%','neg'],['Trigger','HVL 6,860 loss',''],['VIX Target','32\u201338','warn'],['GEX Regime','Amplifying','neg']]},
|
| 665 |
+
{title:'RANGE SCENARIO (30%)', cls:'muted', border:'var(--muted)', bg:'rgba(100,116,139,.06)',
|
| 666 |
+
rows:[['Range','6,900\u20137,200',''],['Pivot','7,050',''],['GEX Support','Pinning','pos'],['VIX Target','26\u201330',''],['Charm','Mild upward','pos']]},
|
| 667 |
+
{title:'TAIL SCENARIO (2%)', cls:'purple', border:'#7c3aed', bg:'rgba(124,58,237,.06)',
|
| 668 |
+
rows:[['Target','5,200\u20135,800','neg'],['Move','-19% to -27%','neg'],['Trigger','Zero-Gamma + macro',''],['VIX Target','50+','neg'],['GEX','Max Amplifying','neg']]}
|
| 669 |
+
];
|
| 670 |
+
var colorMap = {pos:'var(--blue)',neg:'var(--red)',warn:'var(--amber)',purple:'#a78bfa',muted:'var(--muted)','':`var(--text)`};
|
| 671 |
+
cards.forEach(function(card) {
|
| 672 |
+
var div = document.createElement('div');
|
| 673 |
+
div.className = 'sc-card';
|
| 674 |
+
div.style.borderLeft = '3px solid ' + card.border;
|
| 675 |
+
div.style.background = card.bg;
|
| 676 |
+
|
| 677 |
+
var title = document.createElement('div');
|
| 678 |
+
title.className = 'sc-title';
|
| 679 |
+
title.textContent = card.title;
|
| 680 |
+
title.style.color = colorMap[card.cls] || 'var(--text)';
|
| 681 |
+
div.appendChild(title);
|
| 682 |
+
|
| 683 |
+
card.rows.forEach(function(r) {
|
| 684 |
+
var row = document.createElement('div');
|
| 685 |
+
row.className = 'sc-row';
|
| 686 |
+
var label = document.createElement('span');
|
| 687 |
+
label.textContent = r[0];
|
| 688 |
+
var val = document.createElement('span');
|
| 689 |
+
val.textContent = r[1];
|
| 690 |
+
if (r[2]) val.className = r[2];
|
| 691 |
+
row.appendChild(label); row.appendChild(val);
|
| 692 |
+
div.appendChild(row);
|
| 693 |
+
});
|
| 694 |
+
grid.appendChild(div);
|
| 695 |
+
});
|
| 696 |
+
}
|
| 697 |
+
|
| 698 |
+
// βββ Chart.js defaults βββββββββββββββββββββββββββββββββββ
|
| 699 |
+
Chart.defaults.color = '#64748b';
|
| 700 |
+
Chart.defaults.borderColor = '#1e2a38';
|
| 701 |
+
Chart.defaults.font.family = "'SF Mono','Fira Code',monospace";
|
| 702 |
+
Chart.defaults.font.size = 10;
|
| 703 |
+
var rCI = false, crCI = false, fcCI = false;
|
| 704 |
+
|
| 705 |
+
function initRiskCharts() {
|
| 706 |
+
if (rCI) return; rCI = true;
|
| 707 |
+
|
| 708 |
+
// GEX by strike β stacked call/put
|
| 709 |
+
var strikes = Object.keys(CALLS_OI).map(Number)
|
| 710 |
+
.concat(Object.keys(PUTS_OI).map(Number))
|
| 711 |
+
.filter(function(v,i,a){return a.indexOf(v)===i;})
|
| 712 |
+
.sort(function(a,b){return a-b;});
|
| 713 |
+
var callGV = strikes.map(function(K){
|
| 714 |
+
var o = CALLS_OI[K]||0;
|
| 715 |
+
return o*bsGamma(SPOT,K,0.158,7/365)*SPOT*SPOT*100/1e6;
|
| 716 |
+
});
|
| 717 |
+
var putGV = strikes.map(function(K){
|
| 718 |
+
var o = PUTS_OI[K]||0;
|
| 719 |
+
return -(o*bsGamma(SPOT,K,0.158,7/365)*SPOT*SPOT*100/1e6);
|
| 720 |
+
});
|
| 721 |
+
new Chart(document.getElementById('gexChart').getContext('2d'), {
|
| 722 |
+
type:'bar',
|
| 723 |
+
data:{labels:strikes,datasets:[
|
| 724 |
+
{label:'Call GEX ($M)',data:callGV,backgroundColor:'rgba(59,123,255,.7)',borderWidth:0},
|
| 725 |
+
{label:'Put GEX ($M)', data:putGV, backgroundColor:'rgba(239,68,68,.7)', borderWidth:0}
|
| 726 |
+
]},
|
| 727 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 728 |
+
plugins:{legend:{position:'top'}},
|
| 729 |
+
scales:{x:{grid:{color:'#1e2a38'},stacked:true},y:{grid:{color:'#1e2a38'},stacked:true}}}
|
| 730 |
+
});
|
| 731 |
+
|
| 732 |
+
// IV Skew
|
| 733 |
+
new Chart(document.getElementById('skewChart').getContext('2d'), {
|
| 734 |
+
type:'line',
|
| 735 |
+
data:{labels:['0DTE','1DTE','4DTE','44DTE','Dec31'],datasets:[
|
| 736 |
+
{label:'Put IV', data:[15.50,16.46,17.26,17.47,19.24],borderColor:'#ef4444',backgroundColor:'rgba(239,68,68,.1)',fill:true,tension:.4},
|
| 737 |
+
{label:'Call IV',data:[9.35,11.12,12.97,15.15,17.85],borderColor:'#3b7bff',backgroundColor:'rgba(59,123,255,.1)',fill:true,tension:.4},
|
| 738 |
+
{label:'Skew', data:[6.15,5.34,4.29,2.32,1.39], borderColor:'#f59e0b',borderDash:[4,3],tension:.4}
|
| 739 |
+
]},
|
| 740 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 741 |
+
plugins:{legend:{position:'top'}},
|
| 742 |
+
scales:{x:{grid:{color:'#1e2a38'}},y:{grid:{color:'#1e2a38'},ticks:{callback:function(v){return v+'%';}}}}}
|
| 743 |
+
});
|
| 744 |
+
|
| 745 |
+
// Net GEX sensitivity
|
| 746 |
+
var sL=[], sV=[];
|
| 747 |
+
for(var i=-20;i<=10;i++){sL.push(i+'%');sV.push(computeNetGex(i/100,0));}
|
| 748 |
+
new Chart(document.getElementById('sensitivityChart').getContext('2d'), {
|
| 749 |
+
type:'line',
|
| 750 |
+
data:{labels:sL,datasets:[{label:'Net GEX ($B)',data:sV,
|
| 751 |
+
segment:{borderColor:function(ctx){return ctx.p0.parsed.y>=0?'#3b7bff':'#ef4444';}},
|
| 752 |
+
backgroundColor:'transparent',tension:.3,pointRadius:0,borderWidth:2}]},
|
| 753 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 754 |
+
plugins:{legend:{display:false}},
|
| 755 |
+
scales:{x:{grid:{color:'#1e2a38'},ticks:{maxTicksLimit:7}},
|
| 756 |
+
y:{grid:{color:'#1e2a38'},ticks:{callback:function(v){return v.toFixed(1)+'B';}}}}}
|
| 757 |
+
});
|
| 758 |
+
|
| 759 |
+
// Vanna
|
| 760 |
+
var vS=[6800,6850,6900,6950,7000,7050,7100,7150,7200];
|
| 761 |
+
var vV=vS.map(function(K){
|
| 762 |
+
var co=CALLS_OI[K]||0, po=PUTS_OI[K]||0;
|
| 763 |
+
var T=7/365,sig=0.158,sqT=Math.sqrt(T);
|
| 764 |
+
var d1=(Math.log(SPOT/K)+.5*sig*sig*T)/(sig*sqT);
|
| 765 |
+
return (co-po)*(-normalPDF(d1)*d1/sig)*SPOT/1e6;
|
| 766 |
+
});
|
| 767 |
+
new Chart(document.getElementById('vannaChart').getContext('2d'), {
|
| 768 |
+
type:'bar',
|
| 769 |
+
data:{labels:vS,datasets:[{label:'Vanna ($M)',data:vV,
|
| 770 |
+
backgroundColor:vV.map(function(v){return v>=0?'rgba(59,123,255,.7)':'rgba(239,68,68,.7)';}),borderWidth:0}]},
|
| 771 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 772 |
+
plugins:{legend:{display:false}},
|
| 773 |
+
scales:{x:{grid:{color:'#1e2a38'}},y:{grid:{color:'#1e2a38'}}}}
|
| 774 |
+
});
|
| 775 |
+
}
|
| 776 |
+
|
| 777 |
+
function initCrashCharts() {
|
| 778 |
+
if (crCI) return; crCI = true;
|
| 779 |
+
|
| 780 |
+
// Risk factor table
|
| 781 |
+
var rfT = document.getElementById('riskFactors');
|
| 782 |
+
var factors=[
|
| 783 |
+
{n:'Put Skew Elevation',s:72,w:25,c:18.0},
|
| 784 |
+
{n:'VIX Term Structure', s:58,w:20,c:11.6},
|
| 785 |
+
{n:'GEX vs Zero-Gamma', s:23,w:20,c:4.6},
|
| 786 |
+
{n:'Macro Regime', s:55,w:15,c:8.25},
|
| 787 |
+
{n:'0DTE Volume', s:44,w:10,c:4.4},
|
| 788 |
+
{n:'Vol-of-Vol', s:38,w:10,c:3.8}
|
| 789 |
+
];
|
| 790 |
+
factors.forEach(function(f){
|
| 791 |
+
var cls = f.s>60?'neg':f.s>40?'warn':'pos';
|
| 792 |
+
rfT.appendChild(mkTr([{text:f.n},{text:String(f.s),cls:cls},{text:f.w+'%'},{text:f.c.toFixed(1),cls:cls}]));
|
| 793 |
+
});
|
| 794 |
+
|
| 795 |
+
// GEX levels table
|
| 796 |
+
var glT = document.getElementById('gexLevelsTable');
|
| 797 |
+
[-0.15,-0.10,-0.07,-0.05,-0.03,0,0.03,0.05,0.07].forEach(function(pct){
|
| 798 |
+
var spot = (SPOT*(1+pct)).toFixed(0);
|
| 799 |
+
var gex = computeNetGex(pct, 0.20);
|
| 800 |
+
var cls = gex>0.3?'pos':gex>0?'warn':'neg';
|
| 801 |
+
var st = gex>0.3?'\u25B2 Dampening':gex>0?'\u25C6 Weak':'\u25BC Amplifying';
|
| 802 |
+
var gSign = gex>=0?'+':'';
|
| 803 |
+
glT.appendChild(mkTr([{text:spot},{text:(pct*100).toFixed(0)+'%'},{text:gSign+gex.toFixed(2)+'B',cls:cls},{text:st,cls:cls}]));
|
| 804 |
+
});
|
| 805 |
+
|
| 806 |
+
// Probability distribution
|
| 807 |
+
var pS=[], pV=[];
|
| 808 |
+
var mu=Math.log(SPOT)+(0-.5*.158*.158)*21/365, sig=.158*Math.sqrt(21/365);
|
| 809 |
+
for(var K=5500;K<=8200;K+=40){
|
| 810 |
+
pS.push(K);
|
| 811 |
+
var x=(Math.log(K)-mu)/sig;
|
| 812 |
+
pV.push(normalPDF(x)/(K*sig)*40);
|
| 813 |
+
}
|
| 814 |
+
new Chart(document.getElementById('probChart').getContext('2d'),{
|
| 815 |
+
type:'line',
|
| 816 |
+
data:{labels:pS,datasets:[{label:'Implied PDF',data:pV,
|
| 817 |
+
borderColor:'#3b7bff',
|
| 818 |
+
backgroundColor:function(ctx){
|
| 819 |
+
var ch=ctx.chart,ca=ch.chartArea;
|
| 820 |
+
if(!ca)return'rgba(59,123,255,.2)';
|
| 821 |
+
var gr=ch.ctx.createLinearGradient(ca.left,0,ca.right,0);
|
| 822 |
+
gr.addColorStop(0,'rgba(239,68,68,.3)');
|
| 823 |
+
gr.addColorStop(.45,'rgba(245,158,11,.2)');
|
| 824 |
+
gr.addColorStop(.7,'rgba(59,123,255,.3)');
|
| 825 |
+
gr.addColorStop(1,'rgba(34,197,94,.2)');
|
| 826 |
+
return gr;
|
| 827 |
+
},
|
| 828 |
+
fill:true,tension:.4,borderWidth:2,pointRadius:0}]},
|
| 829 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 830 |
+
plugins:{legend:{display:false}},
|
| 831 |
+
scales:{x:{grid:{color:'#1e2a38'},ticks:{maxTicksLimit:9}},y:{display:false}}}
|
| 832 |
+
});
|
| 833 |
+
|
| 834 |
+
// Gamma cliff
|
| 835 |
+
var cL=[], cV=[];
|
| 836 |
+
for(var i2=-18;i2<=8;i2+=0.5){cL.push((SPOT*(1+i2/100)).toFixed(0));cV.push(computeNetGex(i2/100,.15));}
|
| 837 |
+
new Chart(document.getElementById('cliffChart').getContext('2d'),{
|
| 838 |
+
type:'line',
|
| 839 |
+
data:{labels:cL.filter(function(_,i){return i%4===0;}),
|
| 840 |
+
datasets:[{label:'Net GEX ($B)',data:cV.filter(function(_,i){return i%4===0;}),
|
| 841 |
+
segment:{
|
| 842 |
+
borderColor:function(ctx){return ctx.p0.parsed.y>=0?'#3b7bff':'#ef4444';},
|
| 843 |
+
backgroundColor:function(ctx){return ctx.p0.parsed.y>=0?'rgba(59,123,255,.12)':'rgba(239,68,68,.12)';}
|
| 844 |
+
},
|
| 845 |
+
fill:true,tension:.3,borderWidth:2,pointRadius:0}]},
|
| 846 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 847 |
+
plugins:{legend:{display:false}},
|
| 848 |
+
scales:{x:{grid:{color:'#1e2a38'},ticks:{maxTicksLimit:6}},
|
| 849 |
+
y:{grid:{color:'#1e2a38'},ticks:{callback:function(v){return v.toFixed(1)+'B';}}}}}
|
| 850 |
+
});
|
| 851 |
+
}
|
| 852 |
+
|
| 853 |
+
function initForecastCharts() {
|
| 854 |
+
if (fcCI) return; fcCI = true;
|
| 855 |
+
|
| 856 |
+
new Chart(document.getElementById('forecastChart').getContext('2d'),{
|
| 857 |
+
type:'line',
|
| 858 |
+
data:{labels:['Now','Day 1','Day 2','Day 3','Day 4','Day 5'],datasets:[
|
| 859 |
+
{label:'Bull (42%)',data:[SPOT,7180,7220,7270,7310,7350],borderColor:'#22c55e',backgroundColor:'rgba(34,197,94,.08)',fill:'+2',tension:.35},
|
| 860 |
+
{label:'Base (30%)',data:[SPOT,7126,7100,7090,7070,7040],borderColor:'#94a3b8',backgroundColor:'transparent',tension:.35,borderDash:[4,3]},
|
| 861 |
+
{label:'Bear (28%)',data:[SPOT,7060,7010,6960,6910,6860],borderColor:'#ef4444',backgroundColor:'rgba(239,68,68,.08)',fill:'-2',tension:.35}
|
| 862 |
+
]},
|
| 863 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 864 |
+
plugins:{legend:{position:'top'}},
|
| 865 |
+
scales:{x:{grid:{color:'#1e2a38'}},y:{grid:{color:'#1e2a38'},ticks:{callback:function(v){return v.toLocaleString();}}}}}
|
| 866 |
+
});
|
| 867 |
+
|
| 868 |
+
var emL=[], emV=[], emSig=.158*Math.sqrt(5/365);
|
| 869 |
+
for(var K=6400;K<=7900;K+=25){emL.push(K);emV.push(normalPDF((K-SPOT)/(SPOT*emSig)));}
|
| 870 |
+
new Chart(document.getElementById('emChart').getContext('2d'),{
|
| 871 |
+
type:'line',
|
| 872 |
+
data:{labels:emL,datasets:[{label:'5-Day EM',data:emV,
|
| 873 |
+
borderColor:'#3b7bff',
|
| 874 |
+
backgroundColor:function(ctx){
|
| 875 |
+
var ch=ctx.chart,ca=ch.chartArea;
|
| 876 |
+
if(!ca)return'rgba(59,123,255,.2)';
|
| 877 |
+
var gr=ch.ctx.createLinearGradient(ca.left,0,ca.right,0);
|
| 878 |
+
gr.addColorStop(0,'rgba(239,68,68,.25)');
|
| 879 |
+
gr.addColorStop(.5,'rgba(59,123,255,.25)');
|
| 880 |
+
gr.addColorStop(1,'rgba(34,197,94,.25)');
|
| 881 |
+
return gr;
|
| 882 |
+
},
|
| 883 |
+
fill:true,tension:.4,borderWidth:2,pointRadius:0}]},
|
| 884 |
+
options:{responsive:true,maintainAspectRatio:false,
|
| 885 |
+
plugins:{legend:{display:false}},
|
| 886 |
+
scales:{x:{grid:{color:'#1e2a38'},ticks:{maxTicksLimit:8}},y:{display:false}}}
|
| 887 |
+
});
|
| 888 |
+
}
|
| 889 |
+
|
| 890 |
+
// βββ Bootstrap βββββββββββββββββββββββββββββββββββββββββββ
|
| 891 |
+
window.addEventListener('DOMContentLoaded', function() {
|
| 892 |
+
drawHeatmap();
|
| 893 |
+
buildSkewTable();
|
| 894 |
+
buildDrawdownTable();
|
| 895 |
+
buildStaticTables();
|
| 896 |
+
buildScenarioCards();
|
| 897 |
+
window.addEventListener('resize', function() { drawHeatmap(); });
|
| 898 |
+
});
|
| 899 |
+
</script>
|
| 900 |
+
</body>
|
| 901 |
+
</html>
|