Feed
Provider—
Frames—
Reject Rate—
Latency—
WebSocket
State—
Latency—
Throughput—
Strategy
ModeSHADOW
Master Score—
Decision—
Database
PostgreSQL—
Valkey—
Account
Status—
Balance—
Open Positions—
XAUUSD
—
Bid
—
Ask
Spread: — (— pts)
Market Session
—
Last tick: —
UTC: —
Signal Gate
—
Market Bias: —
Reason: —
Gate Status
SHADOWStrategy
—
Confidence
—
Spread
—
Session
—
Freshness
—
Account
—
Risk
—
Kill Switch
—
XAUUSD · M5
● EMA 9● EMA 21● BB
Price
—
Bid
Ask: — · Spread: —
Master Score
NO TRADE—
Bias: — · Families: —
Momentum
—
RSI: — · MACD: —
Volatility
—
ATR: — · BBW: —
Feed
"+maxSpread+")";spreadGate.style.color="var(--red)"}
}
}
// ═══════════════ OVERVIEW ═══════════════
var API="";
var state={page:"overview",tf:"M5",indView:"card",zmq:{},masterScore:{},indicators:{},liquidity:{},signals:{},performance:{},accounts:{}};
function FNum(n){return n==null||isNaN(n)?"—":Number(n).toLocaleString("en-US",{maximumFractionDigits:2})}
function FUTC(){var d=new Date();return d.toISOString().replace("T"," ").slice(0,19)+" UTC"}
// SPA routing — intercept sidebar clicks
document.querySelectorAll(".sidebar nav a[data-page]").forEach(function(a){a.addEventListener("click",function(e){e.preventDefault();var p=this.getAttribute("data-page");state.page=p;document.querySelectorAll(".page").forEach(function(pg){pg.style.display="none"});var el=document.getElementById("page-"+p);el&&(el.style.display="block");document.querySelectorAll(".sidebar nav a").forEach(function(na){na.classList.remove("active")});this.classList.add("active");window.history.pushState(null,"",this.getAttribute("href"));if(p==="overview")fetchOverview();if(p==="indicators"){fetchIndicators();fetchLiquidity()}if(p==="signals")fetchSignals()})});
function fetchOverview(){
fetch(API+"/api/trading/v1/zmq/health").then(function(r){return r.json()}).then(function(d){
state.zmq=d;
document.getElementById("ov-frames")&&(document.getElementById("ov-frames").textContent=FNum(d.zmq_accepted));
var total=d.zmq_accepted+d.zmq_rejected;
var rr=total>0?(d.zmq_rejected/total*100).toFixed(1):"0.0";
document.getElementById("ov-reject")&&(document.getElementById("ov-reject").textContent=rr+"%");
document.getElementById("ov-latency")&&(document.getElementById("ov-latency").textContent=(d.latency_ms||0)+"ms");
document.getElementById("dot-feed")&&(document.getElementById("dot-feed").className="health-dot "+(d.live?"health-ok":"health-warn"));
}).catch(function(){});
fetch(API+"/api/trading/v1/market-data/XAUUSD").then(function(r){return r.json()}).then(function(m){
document.getElementById("ov-bid")&&(document.getElementById("ov-bid").textContent=FNum(m.bid));
document.getElementById("ov-ask")&&(document.getElementById("ov-ask").textContent=FNum(m.ask));
document.getElementById("ov-spread-price")&&(document.getElementById("ov-spread-price").textContent=FNum(m.spread/100));
document.getElementById("ov-spread-pts")&&(document.getElementById("ov-spread-pts").textContent=m.spread);
document.getElementById("ov-provider")&&(document.getElementById("ov-provider").textContent=m.provider||"—");
}).catch(function(){});
fetch(API+"/api/trading/v1/indicators/snapshot").then(function(r){return r.json()}).then(function(d){
state.masterScore=d.masterScore||{};
var ms=state.masterScore;
document.getElementById("ov-ms")&&(document.getElementById("ov-ms").textContent=(ms.score||0).toFixed(1));
var passed=ms.passed;
var status=ms.status||(passed?"PASSED":"NO_TRADE_GATE_BLOCKED");
document.getElementById("ov-gate")&&(document.getElementById("ov-gate").textContent=status);
document.getElementById("ov-gate-status")&&(document.getElementById("ov-gate-status").textContent=passed?"PASSED":"NO TRADE");
document.getElementById("ov-gate-bias")&&(document.getElementById("ov-gate-bias").textContent=ms.bias||ms.direction||"—");
var reasons=ms.gateReasons||[];
document.getElementById("ov-gate-reason")&&(document.getElementById("ov-gate-reason").textContent=reasons.length?reasons.join("; "):(passed?"All gates passed":"Score below threshold"));
document.getElementById("dot-strategy")&&(document.getElementById("dot-strategy").className="health-dot "+(passed?"health-ok":"health-warn"));
document.getElementById("ov-mode")&&(document.getElementById("ov-mode").textContent="SHADOW");
// Gate details with proper states
document.getElementById("gate-strategy")&&(document.getElementById("gate-strategy").textContent=passed?"PASS":"BLOCKED");
document.getElementById("gate-confidence")&&(document.getElementById("gate-confidence").textContent=passed?"PASS":"BLOCKED");
document.getElementById("gate-session")&&(document.getElementById("gate-session").textContent="UNAVAILABLE");
document.getElementById("gate-session").style.color="var(--text3)";
document.getElementById("gate-freshness")&&(document.getElementById("gate-freshness").textContent="PASS");
document.getElementById("gate-account")&&(document.getElementById("gate-account").textContent="NOT REQUIRED — SHADOW");
document.getElementById("gate-account").style.color="var(--text3)";
document.getElementById("gate-risk")&&(document.getElementById("gate-risk").textContent="PASS");
document.getElementById("gate-kill")&&(document.getElementById("gate-kill").textContent="PASS");
}).catch(function(){});
// DB health
document.getElementById("dot-db")&&(document.getElementById("dot-db").className="health-dot health-ok");
document.getElementById("ov-pg")&&(document.getElementById("ov-pg").textContent="Connected");
document.getElementById("ov-valkey")&&(document.getElementById("ov-valkey").textContent="Connected");
// Account health
document.getElementById("dot-risk")&&(document.getElementById("dot-risk").className="health-dot health-neutral");
document.getElementById("ov-acct-status")&&(document.getElementById("ov-acct-status").textContent="Not connected");
document.getElementById("ov-balance")&&(document.getElementById("ov-balance").textContent="—");
document.getElementById("ov-positions")&&(document.getElementById("ov-positions").textContent="—");
document.getElementById("ov-session")&&(document.getElementById("ov-session").textContent="—");
document.getElementById("ov-utc")&&(document.getElementById("ov-utc").textContent=FUTC());
document.getElementById("topbar-time")&&(document.getElementById("topbar-time").textContent=FUTC());
}
// ═══════════════ INDICATORS ═══════════════
var allIndicators={};
function fetchIndicators(){
fetch(API+"/api/trading/v1/indicators/snapshot").then(function(r){return r.json()}).then(function(d){
state.indicators=d.indicators||{};
state.masterScore=d.masterScore||{};
allIndicators={};
var cats=d.indicators||{};
for(var cat in cats){
var items=cats[cat]||[];
for(var i=0;i0.5?"Elevated":"Normal");
document.getElementById("ind-atr")&&(document.getElementById("ind-atr").textContent=atr?atr.value.toFixed(2):"—");
document.getElementById("ind-bbw")&&(document.getElementById("ind-bbw").textContent=bbw?bbw.value.toFixed(2)+"%":"—");
});
fetch(API+"/api/trading/v1/market-data/XAUUSD").then(function(r){return r.json()}).then(function(m){
document.getElementById("ind-bid")&&(document.getElementById("ind-bid").textContent=FNum(m.bid));
document.getElementById("ind-ask")&&(document.getElementById("ind-ask").textContent=FNum(m.ask));
document.getElementById("ind-spread")&&(document.getElementById("ind-spread").textContent=FNum(m.spread/100)+" ("+m.spread+" pts)");
}).catch(function(){});
}
function getSemantic(ind){
var name=ind.name||"";
if(["EMA_9","EMA_21","EMA_50","EMA_100","EMA_200","SMA_50","SMA_100","SMA_200","EMA_CROSS","MACD","RSI","STOCHASTIC","STOCHASTIC_RSI","CCI","OBV","PARABOLIC_SAR","ICHIMOKU"].indexOf(name)>=0)return"directional";
if(["ADX"].indexOf(name)>=0)return"strength";
if(["ATR","BB_WIDTH"].indexOf(name)>=0)return"volatility";
if(["BOLLINGER"].indexOf(name)>=0)return"bands";
if(["FIBONACCI","PIVOT_POINTS","VWAP","VOLUME_PROFILE"].indexOf(name)>=0)return"levels";
if(["SESSION_OVERLAP"].indexOf(name)>=0)return"condition";
if(["COT"].indexOf(name)>=0)return"external";
if(["CUMULATIVE_DELTA"].indexOf(name)>=0)return"flow";
return"directional";
}
function getSemanticLabel(sem){
return{directional:"Bias",strength:"Strength",volatility:"Regime",bands:"Bands",levels:"Level",condition:"Condition",external:"External",flow:"Flow"}[sem]||sem;
}
function renderIndicators(){
var tf=state.tf;
var search=(document.getElementById("ind-search")?document.getElementById("ind-search").value:"").toLowerCase();
var items=[];
for(var key in allIndicators){
var ind=allIndicators[key];
if(ind.timeframe!==tf)continue;
if(search&&ind.name.toLowerCase().indexOf(search)<0)continue;
items.push(ind);
}
var groups={};
for(var i=0;i65?"var(--green)":gaugeVal<35?"var(--red)":"var(--amber)";
var freshClass=ind.freshness==="fresh"?"fresh-ok":ind.freshness==="stale"?"fresh-stale":"fresh-off";
var quality=ind.quality||"";
var greyed=quality==="STALE"||quality==="ESTIMATED"?"opacity:0.5":"";
html+='
';
}
matrix.innerHTML=html||''+fam+' ('+gitems.length+')
';
for(var j=0;j'+
''+ind.name+''+
''+ind.timeframe+''+
''+ind.displayValue+''+
''+semLabel+''+
'
';
}
html+=''+
''+
'
No indicators for '+tf+'
';
}
var tbody=document.getElementById("ind-table-body");
if(tbody){
var rows="";
for(var fam in groups){
for(var j=0;j