#!/usr/bin/env python3
import json
from pathlib import Path
from datetime import datetime, timezone
from decimal import Decimal
from collections import Counter, defaultdict
ROOT=Path('/home/agent/projects/CryptoTradingBot/Crypto_Agent')
START=datetime.fromisoformat('2026-07-04T23:10:00+02:00').astimezone(timezone.utc)
SPLIT=datetime.fromisoformat('2026-07-05T07:01:18+02:00').astimezone(timezone.utc)
STRATS=['candidate_v76_strict_live_candidate','candidate_v76_research_probe','candidate_v76_fee_aware_anti_chase','candidate_swing_trend_retest_research']
def D(x):
    try: return Decimal(str(x))
    except: return Decimal(0)
def T(s):
    try: return datetime.fromisoformat(str(s).replace('Z','+00:00')).astimezone(timezone.utc)
    except: return None
def jl(p):
    if not p.exists(): return []
    out=[]
    for line in p.read_text(errors='ignore').splitlines():
        if line.strip():
            try: out.append(json.loads(line))
            except: pass
    return out
def top(c,n=8): return dict(c.most_common(n))
for sid in STRATS:
    base=ROOT/'runtime/experiments'/sid
    rows=jl(base/'trade_journal.jsonl')
    fifo=defaultdict(list); closed=[]
    for r in rows:
        t=T(r.get('timestamp'))
        if r.get('event')=='entry': fifo[r.get('coin')].append(r)
        elif r.get('event')=='exit':
            e=fifo[r.get('coin')].pop(0) if fifo[r.get('coin')] else {}
            if t and t>=START:
                pnl=D(r.get('realized_pnl_usd',r.get('net_pnl_usd',0)))
                risk=abs(D(e.get('entry_price',r.get('entry_price',0)))-D(e.get('stop_loss',r.get('stop_loss',0))))*D(r.get('size',e.get('size',0)))
                closed.append((r,pnl,pnl/risk if risk else Decimal(0)))
    sig=[r for r in jl(base/'signal_journal.jsonl') if T(r.get('timestamp')) and T(r.get('timestamp'))>=START]
    blocks=Counter(); decisions=Counter(); trends=Counter()
    for r in sig:
        decisions[r.get('final_decision') or r.get('decision') or '?']+=1
        br=r.get('block_reason') or []
        if isinstance(br,str): br=[br]
        br+=((r.get('risk_gate_result') or {}).get('reasons') or [])
        for b in br: blocks[str(b)]+=1
        if r.get('trend_state'): trends[str(r['trend_state'])]+=1
    wins=[x for x in closed if x[1]>0]; losses=[x for x in closed if x[1]<0]
    gw=sum((x[1] for x in wins),Decimal(0)); gl=-sum((x[1] for x in losses),Decimal(0))
    st=json.loads((base/'state.json').read_text()) if (base/'state.json').exists() else {}
    print('\n',sid)
    print('closed',len(closed),'wins',len(wins),'losses',len(losses),'pnl',round(sum((x[1] for x in closed),Decimal(0)),6),'R',round(sum((x[2] for x in closed),Decimal(0)),3),'WR',round(len(wins)/len(closed)*100,1) if closed else 0,'PF',round(float(gw/gl),2) if gl else 0)
    print('avg_win',round(gw/len(wins),6) if wins else 0,'avg_loss',round(-gl/len(losses),6) if losses else 0,'reasons',top(Counter(x[0].get('exit_reason') for x in closed)),'coins',top(Counter(x[0].get('coin') for x in closed)))
    print('open',len(st.get('open_positions') or st.get('positions') or {}),'signals',len(sig),'blocks',top(blocks,10),'trends',top(trends,4),'decisions_top',top(decisions,5))
# desk
base=ROOT/'runtime/experiments/trader_desk_shadow'
decs=[r for r in jl(base/'decision_journal.jsonl') if T(r.get('timestamp')) and T(r.get('timestamp'))>=START]
outs=[r for r in jl(base/'outcome_journal.jsonl') if T(r.get('timestamp')) and T(r.get('timestamp'))>=START]
cl=[r for r in outs if r.get('event')=='shadow_close']; op=[r for r in outs if r.get('event')=='shadow_open']
rvals=[D(r.get('r_multiple')) for r in cl]; w=[x for x in rvals if x>0]; l=[x for x in rvals if x<0]
dir=Counter(r.get('direction') for r in decs); block=Counter();
for r in decs:
    for b in r.get('blockers') or []: block[str(b)]+=1
print('\ntrader_desk_shadow')
print('decisions',len(decs),'opens',len(op),'closed',len(cl),'wins',len(w),'losses',len(l),'R',round(sum(rvals),4),'WR',round(len(w)/len(cl)*100,1) if cl else 0,'PF',round(float(sum(w,Decimal(0))/-sum(l,Decimal(0))),2) if l else 0,'short_share',round(dir.get('short',0)/len(decs)*100,1) if decs else 0)
print('dirs',dict(dir),'coins',top(Counter(r.get('coin') for r in decs)),'blockers',top(block),'reasons',top(Counter(r.get('reason') for r in cl)),'open_state',len((json.loads((base/'state.json').read_text())).get('positions') or {}))
# split
rows=jl(ROOT/'runtime/experiments/candidate_v76_fee_aware_anti_chase/trade_journal.jsonl')
for name,a,b in [('pre',START,SPLIT),('post',SPLIT,datetime.max.replace(tzinfo=timezone.utc))]:
    ex=[r for r in rows if r.get('event')=='exit' and T(r.get('timestamp')) and a<=T(r.get('timestamp'))<b]
    stops=[r for r in ex if r.get('exit_reason')=='stop_loss']
    print('anti_chase_'+name,'exits',len(ex),'stops',len(stops),'SOL/LINK/ETH',dict(Counter(r.get('coin') for r in stops if r.get('coin') in ['SOL','LINK','ETH'])),'all',dict(Counter(r.get('coin') for r in stops)))
