Per-strategy equity curves + $100K paper capital
Paper trader now tracks individual equity history per strategy (strategy_equity dict with deque per strategy). Metrics file exports per-strategy data for dashboard rendering. Dashboard paper chart upgraded to 7 overlaid area series: - Each strategy gets its own colored curve (green, blue, purple, etc.) - 300px height for better visibility of multiple lines - Color palette distinguishes strategies at a glance $100K total capital: $10K per strategy × 7 + $30K reserve. Exeria Charts evaluated: excellent library (Benzinga award winner, Canvas/WebGL, exchange connectors) but requires npm+bundler — not suitable for single-file dashboard. Lightweight-charts remains the right choice for our architecture.
This commit is contained in:
@@ -100,7 +100,7 @@ footer{text-align:center;padding:20px;font-size:10px;color:#3f3f46}footer a{colo
|
||||
<!-- PAPER -->
|
||||
<div class="panel" id="pnl-paper">
|
||||
<div class="stats" id="paper-stats"></div>
|
||||
<div class="card"><h3>Equity Curve <span class="desc">real-time · Hyperliquid Mainnet (simulated fills)</span></h3><div class="chart-wrap" id="paper-chart"></div></div>
|
||||
<div class="card"><h3>Equity Curve <span class="desc">per-strategy · Hyperliquid Mainnet (simulated)</span></h3><div class="chart-wrap" id="paper-chart" style="height:300px"></div></div>
|
||||
<div class="grid" id="paper-grid"></div>
|
||||
<div class="card"><h3>Trade Log</h3><div class="tbl-scroll"><table><thead><tr><th>Time</th><th>Strategy</th><th>Side</th><th>Size</th><th>Price</th><th>Fee</th><th>PnL</th></tr></thead><tbody id="paper-tb"></tbody></table></div></div>
|
||||
</div>
|
||||
@@ -117,7 +117,20 @@ footer{text-align:center;padding:20px;font-size:10px;color:#3f3f46}footer a{colo
|
||||
var tab='live',lastData=null,lastPaper=null;
|
||||
function mkChart(el,w,h){var c=LightweightCharts.createChart(el,{layout:{background:{color:'transparent'},textColor:'#8b8b96'},grid:{vertLines:{color:'rgba(255,255,255,0.03)'},horzLines:{color:'rgba(255,255,255,0.03)'}},rightPriceScale:{borderColor:'rgba(255,255,255,0.06)'},timeScale:{borderColor:'rgba(255,255,255,0.06)',timeVisible:true},crosshair:{mode:0},width:w,height:h});return c}
|
||||
var eqChart=mkChart(document.getElementById('eq-chart'),0,0);var eqSer=eqChart.addAreaSeries({lineColor:'#3b82f6',topColor:'rgba(59,130,246,0.15)',bottomColor:'rgba(59,130,246,0.02)',lineWidth:2});
|
||||
var paperChart=mkChart(document.getElementById('paper-chart'),0,0);var paperSer=paperChart.addAreaSeries({lineColor:'#a855f7',topColor:'rgba(168,85,247,0.12)',bottomColor:'rgba(168,85,247,0.02)',lineWidth:2});
|
||||
var paperChart=mkChart(document.getElementById('paper-chart'),0,0);
|
||||
// Per-strategy equity series (7 strategies, 7 colors)
|
||||
var STRAT_COLORS = ['#22c55e','#3b82f6','#a855f7','#f59e0b','#ef4444','#06b6d4','#ec4899'];
|
||||
var paperStrataSeries = {};
|
||||
function getStratSeries(name){
|
||||
if(!paperStrataSeries[name]){
|
||||
var idx = Object.keys(paperStrataSeries).length;
|
||||
var color = STRAT_COLORS[idx % STRAT_COLORS.length];
|
||||
paperStrataSeries[name] = paperChart.addAreaSeries({
|
||||
lineColor: color, topColor: color+'26', bottomColor: color+'05', lineWidth: 1.5
|
||||
});
|
||||
}
|
||||
return paperStrataSeries[name];
|
||||
}
|
||||
var btChart=mkChart(document.getElementById('bt-chart'),0,0);var btSer=btChart.addAreaSeries({lineColor:'#a855f7',topColor:'rgba(168,85,247,0.12)',bottomColor:'rgba(168,85,247,0.02)',lineWidth:2});
|
||||
|
||||
function fitCharts(){
|
||||
@@ -196,8 +209,19 @@ function renLive(d){
|
||||
function renPaper(d){
|
||||
if(!d)return;
|
||||
var pnl=d.total_pnl||0;document.getElementById('stpnl').textContent=(pnl>=0?'+':'')+'$'+Math.abs(pnl).toFixed(2);document.getElementById('stpnl').className='pnl '+(pnl>=0?'up':'dn');
|
||||
document.getElementById('stpct').textContent='Mainnet Paper · Equity: $'+((d.total_equity||5000)).toFixed(2)+' · BTC: $'+(d.btc_price||0).toLocaleString('en-US',{maximumFractionDigits:0});
|
||||
renGrid('paper-grid',d.strategies||{},d.base_equity||5000,d.reserve||1000,'paper-stats','paper-tb',paperChart,paperSer,d.equity_history||[],d.trades||[]);
|
||||
document.getElementById('stpct').textContent='Mainnet Paper · Equity: $'+(d.total_equity||100000).toFixed(0)+' · BTC: $'+(d.btc_price||0).toLocaleString('en-US',{maximumFractionDigits:0});
|
||||
renGrid('paper-grid',d.strategies||{},d.base_equity||100000,d.reserve||30000,'paper-stats','paper-tb',paperChart,null,d.equity_history||[],d.trades||[]);
|
||||
// Per-strategy equity curves
|
||||
var seq = d.strategy_equity || {};
|
||||
var keyz = Object.keys(seq);
|
||||
for(var i=0;i<keyz.length;i++){
|
||||
var name=keyz[i],pts=seq[name],ser=getStratSeries(name);
|
||||
if(pts&&pts.length>0){
|
||||
var arr=[];for(var j=0;j<pts.length;j++) if(pts[j]&&pts[j].t) arr.push({time:pts[j].t,value:pts[j].v});
|
||||
ser.setData(arr);
|
||||
}
|
||||
}
|
||||
paperChart.timeScale().fitContent();
|
||||
}
|
||||
|
||||
function toggleStrat(sid){var el=document.getElementById('strat-'+sid);if(!el)return;el.classList.toggle('open');setTimeout(fitCharts,200)}
|
||||
|
||||
Reference in New Issue
Block a user