diff --git a/src/live/dashboard.py b/src/live/dashboard.py index f24a1a9..7f4c42e 100644 --- a/src/live/dashboard.py +++ b/src/live/dashboard.py @@ -211,13 +211,22 @@ def build_state() -> dict: if st.get("in_position") and not paper_only: is_pair = "entry_a" in st asset = wid.split("__")[1] - entry = st.get("entry_price") or st.get("entry_a") or 0.0 + # entry REALE se eseguito (il mark live è il prezzo reale USDC: confrontare + # con l'entry SIM mischierebbe le basi — il feed di decisione testnet inverse + # è dislocato dal lineare, vedi xex_divergence_research). Fallback al sim. + executed = st.get("real_in_position") + if is_pair: + real_e, sim_e = (st.get("real_entry_a") if executed else None), st.get("entry_a") or 0.0 + else: + real_e, sim_e = (st.get("real_entry_price") if executed else None), st.get("entry_price") or 0.0 + entry = real_e or sim_e if not is_pair: open_assets.add(asset) active.append({ "id": _short(wid), "family": _family_of(wid), "dir": "LONG" if st.get("direction", 0) > 0 else "SHORT", - "entry": entry, "bars": st.get("bars_held", 0), + "entry": round(entry, 4), "sim_entry": round(sim_e, 4), + "bars": st.get("bars_held", 0), "max_bars": st.get("max_bars", 0), "tp": st.get("tp", 0.0), "sl": st.get("sl", 0.0), "age_min": round(_age_min(sp), 1), @@ -588,8 +597,10 @@ function renderActive(a){const wrap=document.getElementById('active');wrap.inner a.forEach(p=>{const tr=E('tr'); const side=`${p.dir}`; const ue=p.unreal_eur!=null?`${eur(p.unreal_eur)} (${p.unreal_pct}%)`:(p.pair?'pairs (z)':''); + const gap=p.sim_entry&&Math.abs(p.sim_entry-p.entry)>0.01; + const ecell=gap?`${p.entry} ⚠sim ${p.sim_entry}`:`${p.entry}`; tr.innerHTML=`${p.id}${p.real?'':' sim'}${side} - ${p.entry}${p.mark||'—'}${ue} + ${ecell}${p.mark||'—'}${ue} ${p.bars}/${p.max_bars||'∞'}${p.to_tp_pct!=null?p.to_tp_pct:'—'} ${p.age_min}m${p.stale?' ⚠':''}`; t.append(tr);});wrap.append(t);}