feat(dashboard): lista trades TP01 (entry/exit dal segnale causale)

Nuova sezione "Trades TP01" nella dashboard: eventi ENTRY long / EXIT flat dedotti da
target_series sui dati certificati (data, asset, transizione di posizione, prezzo). In
src/live/shadow.tp01_trades(): account-independent (gira anche offline nel container),
ricalcolata a ogni render -> storico + forward. Empty-state se TP01 non ha mai mosso.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-06-20 14:18:46 +00:00
parent bec2fb2089
commit 715f197cf2
2 changed files with 47 additions and 2 deletions
+30
View File
@@ -7,6 +7,7 @@ from __future__ import annotations
import json
from pathlib import Path
import numpy as np
import pandas as pd
from src.backtest.harness import load
@@ -20,6 +21,35 @@ FALLBACK_CAPITAL = 2000.0
PAPER_STATE = PROJECT_ROOT / "data" / "paper_trend" / "state.json"
def tp01_trades(limit: int = 15) -> list[dict]:
"""Lista dei TRADE di TP01 = cambi di posizione (ENTRY long / EXIT flat) dedotti dal segnale
causale `target_series` sui dati certificati. Account-independent (gira anche offline nel
container). Si ricalcola a ogni render -> include sia lo storico sia i trade forward man mano
che arrivano. Ritorna gli ultimi `limit` (piu' recenti primi)."""
tp = TrendPortfolio(**CANONICAL)
out: list[dict] = []
for a in ASSETS:
df = resample_1d(load(a, "1h"))
c = df["close"].to_numpy(dtype=float)
dt = pd.to_datetime(df["datetime"]).to_numpy()
tgt = tp.target_series(df)
prev = 0.0
for i in range(len(tgt)):
if np.sign(tgt[i]) != np.sign(prev):
out.append(dict(
ts=int(pd.Timestamp(dt[i]).value // 10**6),
date=str(pd.Timestamp(dt[i]).date()),
asset=a,
action="ENTRY" if tgt[i] != 0 else "EXIT",
from_pos=round(float(prev), 3),
to_pos=round(float(tgt[i]), 3),
price=round(float(c[i]), 1),
))
prev = tgt[i]
out.sort(key=lambda r: r["ts"], reverse=True)
return out[:limit]
def _safe_client() -> DeribitRead | None:
try:
return DeribitRead()