Premchan369 commited on
Commit
bb84d61
Β·
verified Β·
1 Parent(s): 998ec17

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +154 -0
index.html ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>AlphaForge Pro</title>
7
+ <script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>
8
+ <style>
9
+ :root{--bg:#0a0e17;--card:#111827;--accent:#38bdf8;--green:#10b981;--red:#ef4444;--yellow:#f59e0b;--text:#94a3b8;--bright:#e2e8f0;--border:#1e293b}
10
+ *{margin:0;padding:0;box-sizing:border-box}
11
+ body{background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,sans-serif}
12
+ .header{background:var(--card);padding:12px 24px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--border)}
13
+ .header h1{color:var(--accent);font-size:20px;font-weight:800}
14
+ .header .badge{color:var(--text);font-size:10px;padding:2px 8px;background:rgba(30,41,59,0.8);border-radius:4px}
15
+ .header .live{color:var(--green);font-size:10px}
16
+ .kpi-row{display:flex;gap:10px;flex-wrap:wrap;padding:16px 24px}
17
+ .kpi{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 18px;text-align:center;flex:1;min-width:100px}
18
+ .kpi-val{font-size:20px;font-weight:700}
19
+ .kpi-lbl{color:var(--text);font-size:10px;text-transform:uppercase;margin-top:4px;letter-spacing:.5px}
20
+ .main-grid{display:grid;grid-template-columns:280px 1fr;gap:16px;padding:0 24px 40px}
21
+ .panel{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px;margin-bottom:16px}
22
+ .panel-title{color:var(--bright);font-weight:600;font-size:13px;margin-bottom:12px}
23
+ .pill{display:inline-block;padding:6px 12px;margin:3px;border:1px solid var(--border);border-radius:8px;font-size:12px}
24
+ .pill .sym{color:var(--accent);font-weight:700;margin-right:6px}
25
+ .alert-row{padding:8px 12px;margin:4px 0;border-left:3px solid var(--accent);border-radius:4px;font-size:11px}
26
+ .alert-row b{font-size:11px}
27
+ .tabs{display:flex;gap:4px;margin-bottom:12px}
28
+ .tab{padding:6px 16px;border-radius:6px;cursor:pointer;font-size:12px;background:transparent;color:var(--text);border:1px solid transparent}
29
+ .tab.active{background:var(--card);color:var(--accent);border-color:var(--border)}
30
+ .tab-content{display:none}
31
+ .tab-content.active{display:block}
32
+ .chart{min-height:300px}
33
+ @media(max-width:900px){.main-grid{grid-template-columns:1fr}}
34
+ </style>
35
+ </head>
36
+ <body>
37
+ <div class="header">
38
+ <div style="display:flex;align-items:center;gap:12px"><h1>AlphaForge Pro</h1><span class="badge">v2.0</span></div>
39
+ <div style="display:flex;align-items:center;gap:16px">
40
+ <span class="live">● LIVE</span>
41
+ <span style="color:var(--text);font-size:12px" id="clock"></span>
42
+ </div>
43
+ </div>
44
+
45
+ <div class="kpi-row" id="kpis"></div>
46
+
47
+ <div class="main-grid">
48
+ <div>
49
+ <div class="panel"><div class="panel-title">Positions</div><div id="positions"></div></div>
50
+ <div class="panel"><div class="panel-title">Market Regime</div><div class="chart" id="regime"></div></div>
51
+ <div class="panel"><div class="panel-title">Sentiment</div><div class="chart" id="sentiment"></div></div>
52
+ <div class="panel"><div class="panel-title">Alerts</div><div id="alerts"></div></div>
53
+ </div>
54
+ <div>
55
+ <div class="tabs">
56
+ <div class="tab active" onclick="switchTab('pnl')">PnL & Drawdown</div>
57
+ <div class="tab" onclick="switchTab('risk')">Risk Metrics</div>
58
+ <div class="tab" onclick="switchTab('weights')">Portfolio Weights</div>
59
+ </div>
60
+ <div class="tab-content active" id="tab-pnl"><div class="chart" id="chart-pnl"></div></div>
61
+ <div class="tab-content" id="tab-risk"><div class="chart" id="chart-risk"></div></div>
62
+ <div class="tab-content" id="tab-weights"><div class="chart" id="chart-weights"></div></div>
63
+ </div>
64
+ </div>
65
+
66
+ <script>
67
+ // ─── Data ──────────────────────────────────────────────────────
68
+ const sharpe=1.82,sortino=2.14,maxDD=-4.3,var95=18340,calmar=4.2;
69
+ const positions={SPY:0.18,QQQ:0.15,AAPL:0.10,MSFT:0.12,GOOGL:0.08,AMZN:0.07,META:0.06,NVDA:0.14,TSLA:0.05,JPM:0.05};
70
+ const sentiment={AAPL:0.72,MSFT:0.65,NVDA:0.88,TSLA:-0.34,SPY:0.15};
71
+ const alertList=[{t:"10:23",lv:"info",ti:"Backtest Complete",tx:"Sharpe: 1.82, Max DD: -4.3%"},{t:"10:24",lv:"warn",ti:"Volatility Spike",tx:"VIX at 28.5, reducing exposure"},{t:"10:25",lv:"info",ti:"Regime Change",tx:"Switched to bull - increasing equity"}];
72
+ const ac={"info":"#38bdf8","warn":"#f59e0b","error":"#ef4444"};
73
+
74
+ // Generate returns and PnL
75
+ let rng=Math.seedrandom?(()=>{let s=42;return ()=>((s=(s*16807)%2147483647)/2147483647)})():Math.random;
76
+ let rets=[],pnl=0,pnls=[],dd=0,mx=0,dds=[];
77
+ for(let i=0;i<252;i++){
78
+ let r=0.0008+rng()*0.012-(i>100&&i<140?0.003:0);
79
+ if(i>140&&i<180)r=0.0025+rng()*0.012;
80
+ rets.push(r);pnl+=r*1e6;pnls.push(pnl);
81
+ }
82
+ let cum=1;rets.forEach(r=>{cum*=(1+r);mx=Math.max(mx,cum);dds.push(((cum-mx)/mx)*100);});
83
+
84
+ // Rolling metrics
85
+ let rollingSharpe=[],rollingVol=[];
86
+ for(let i=0;i<rets.length;i++){
87
+ if(i<21){rollingSharpe.push(sharpe);rollingVol.push(20);continue}
88
+ let w=rets.slice(i-21,i+1),m=w.reduce((a,b)=>a+b)/w.length;
89
+ let s=Math.sqrt(w.reduce((a,b)=>a+b*b,0)/w.length-m*m);
90
+ rollingSharpe.push(s>0?m/s*Math.sqrt(252):sharpe);
91
+ rollingVol.push(s*Math.sqrt(252)*100);
92
+ }
93
+
94
+ let dates=[];let d=new Date(2024,0,1);
95
+ for(let i=0;i<252;i++){dates.push(d.toISOString().slice(0,10));d.setDate(d.getDate()+1);if(d.getDay()===6)d.setDate(d.getDate()+2);if(d.getDay()===0)d.setDate(d.getDate()+1)}
96
+
97
+ // ─── KPIs ──────────────────────────────────────────────────────
98
+ document.getElementById("kpis").innerHTML=[
99
+ {v:"$"+pnls[pnls.length-1].toLocaleString("en-US",{maximumFractionDigits:0}),l:"Cumulative PnL",c:"var(--accent)"},
100
+ {v:sharpe.toFixed(2),l:"Sharpe",c:sharpe>=1?"var(--green)":"var(--yellow)"},
101
+ {v:sortino.toFixed(2),l:"Sortino",c:"var(--accent)"},
102
+ {v:maxDD.toFixed(1)+"%",l:"Max Drawdown",c:"var(--red)"},
103
+ {v:"$"+var95.toLocaleString(),l:"VaR 95%",c:"var(--yellow)"},
104
+ {v:calmar.toFixed(2),l:"Calmar",c:"var(--accent)"},
105
+ {v:"+12.1%",l:"Alpha",c:"var(--green)"},
106
+ {v:"0.95",l:"Beta",c:"var(--accent)"}
107
+ ].map(k=>'<div class="kpi"><div class="kpi-val" style="color:'+k.c+'">'+k.v+'</div><div class="kpi-lbl">'+k.l+'</div></div>').join("");
108
+
109
+ // ─── Positions ─────────────────────────────────────────────────
110
+ document.getElementById("positions").innerHTML=Object.entries(positions).sort((a,b)=>b[1]-a[1]).map(([s,w])=>'<span class="pill"><span class="sym">'+s+'</span>'+(w*100).toFixed(1)+'%</span>').join("");
111
+
112
+ // ─── Alerts ────────────────────────────────────────────────────
113
+ document.getElementById("alerts").innerHTML=alertList.map(a=>'<div class="alert-row" style="border-left-color:'+ac[a.lv]+'"><b style="color:'+ac[a.lv]+'">['+a.t+'] '+a.ti+'</b> '+a.tx+'</div>').join("");
114
+
115
+ // ─── Charts ────────────────────────────────────────────────────
116
+ const lo={template:"plotly_dark",paper_bgcolor:"#0a0e17",plot_bgcolor:"#0a0e17",font:{color:"#94a3b8",size:11},showlegend:false,margin:{l:8,r:24,t:28,b:8}};
117
+
118
+ // PnL & Drawdown
119
+ Plotly.newPlot("chart-pnl",[
120
+ {type:"scatter",x:dates,y:pnls,line:{color:"#38bdf8",width:2},fill:"tozeroy",fillcolor:"rgba(56,189,248,0.08)",name:"PnL"},
121
+ {type:"scatter",x:dates,y:dds,line:{color:"#ef4444",width:1.5},fill:"tozeroy",fillcolor:"rgba(239,68,68,0.08)",name:"Drawdown %",yaxis:"y2"}
122
+ ],{...lo,height:400,yaxis:{tickprefix:"$",tickformat:",.0f",title:"PnL $"},yaxis2:{ticksuffix:"%",title:"Drawdown %",overlaying:"y",side:"right"}});
123
+
124
+ // Risk
125
+ Plotly.newPlot("chart-risk",[
126
+ {type:"scatter",x:dates,y:rollingSharpe,line:{color:"#38bdf8",width:2},name:"Rolling Sharpe"},
127
+ {type:"scatter",x:dates,y:Array(dates.length).fill(sharpe),line:{color:"rgba(239,68,68,0.5)",dash:"dot",width:1},name:"Average"},
128
+ {type:"scatter",x:dates,y:rollingVol,line:{color:"#f59e0b",width:2},name:"Volatility %",yaxis:"y2"}
129
+ ],{...lo,height:400,yaxis:{title:"Sharpe"},yaxis2:{title:"Vol %",ticksuffix:"%",overlaying:"y",side:"right"}});
130
+
131
+ // Weights
132
+ let wp=Object.entries(positions).sort((a,b)=>b[1]-a[1]);
133
+ Plotly.newPlot("chart-weights",[{type:"bar",x:wp.map(e=>e[0]),y:wp.map(e=>e[1]*100),marker:{color:["#38bdf8","#38bdf8","#38bdf8","#6366f1","#6366f1","#6366f1","#10b981","#10b981","#8b5cf6","#8b5cf6"]}}],{...lo,height:340,yaxis:{title:"Weight %",ticksuffix:"%"}});
134
+
135
+ // Regime
136
+ Plotly.newPlot("regime",[{type:"pie",labels:["Bull","Bear","High Vol","Neutral"],values:[0.45,0.12,0.28,0.15],hole:0.55,marker:{colors:["#10b981","#ef4444","#f59e0b","#64748b"]},textinfo:"label+percent",textfont:{color:"#e2e8f0",size:11}}],{...lo,height:240});
137
+
138
+ // Sentiment
139
+ Plotly.newPlot("sentiment",[{type:"bar",x:Object.keys(sentiment),y:Object.values(sentiment),marker:{color:Object.values(sentiment).map(v=>v>0?"#10b981":"#ef4444")}}],{...lo,height:240,yaxis:{title:"Score",range:[-1.1,1.1]}});
140
+
141
+ // ─── Tabs ──────────────────────────────────────────────────────
142
+ function switchTab(t){
143
+ document.querySelectorAll(".tab").forEach(e=>e.classList.remove("active"));
144
+ document.querySelectorAll(".tab-content").forEach(e=>e.classList.remove("active"));
145
+ event.target.classList.add("active");
146
+ document.getElementById("tab-"+t).classList.add("active");
147
+ }
148
+
149
+ // ─── Clock ─────────────────────────────────────────────────────
150
+ setInterval(()=>{document.getElementById("clock").textContent=new Date().toLocaleString();},1000);
151
+ document.getElementById("clock").textContent=new Date().toLocaleString();
152
+ </script>
153
+ </body>
154
+ </html>