"""AN4.2 (DC Analyst 4, 7 Oct 2026): operator float share at entry for every trade of the SW live book and FW mc5 (lab.py trades).
Read only: /opt/sw/harness/gold (idx.json, p/<pool>.pkl), /opt/sw/crew_wallets.json, ffund_snap.db, crew.db. Writes /opt/tw/an4/an42/float.csv."""
import json, csv, pickle, sqlite3, datetime, os, collections
G = "/opt/sw/harness/gold"; OUT = "/opt/tw/an4/an42"; os.makedirs(OUT, exist_ok=True)
DISP = {"0x84157d3d24630c297849c84d49ae7f1805c1b60f", "0x03802649e469ed5680c58dff9e65425e22d21cc5"}
ROUTER = {"0xcaf681a66d020601342297493863e78c959e5cb2"}
BKK = datetime.timezone(datetime.timedelta(hours=7))
BOOKS = {"sw_live": "/root/fwa3/lab/out/sw_accept/live_book_trades.csv", "fw_mc5": "/root/fwa3/lab/out/sw/fw_mc5_trades.csv"}
IDX = json.load(open(G + "/idx.json"))
CW = json.load(open("/opt/sw/crew_wallets.json"))
FF = sqlite3.connect("file:/opt/pricepredict-data/ffund_snap.db?mode=ro", uri=True)
CR = sqlite3.connect("file:/opt/pricepredict-data/crew.db?mode=ro", uri=True)
def funders(addrs):
    out = {}
    addrs = list(addrs)
    for i in range(0, len(addrs), 500):
        ch = addrs[i:i + 500]; q = ",".join("?" * len(ch))
        for a, f, v in CR.execute("SELECT addr, funder, via FROM wallet WHERE addr IN (%s)" % q, ch): out[a] = ((f or "").lower(), (v or "").lower())
        for a, f, v in FF.execute("SELECT addr, funder, via FROM ff WHERE addr IN (%s)" % q, ch): out[a] = ((f or "").lower(), (v or "").lower())
    return out
def ent(s):
    return datetime.datetime.strptime("2026 " + s, "%Y %d %b %H:%M").replace(tzinfo=BKK).timestamp()
rows = []
for book, fn in BOOKS.items():
    for r in csv.DictReader(open(fn)):
        pool = r["pool"].lower(); m = IDX.get(pool, {})
        d = pickle.load(open(G + "/p/%s.pkl" % pool, "rb")); c = d["c"]
        te = ent(r["entry_bkk"]); creator = (m.get("creator") or "").lower()
        net = collections.defaultdict(float); first_b = None; early = set()
        for t, b, k, buy, tok, rcp in zip(c["t"], c["b"], c["k"], c["buy"], c["tok"], c["rcp"]):
            if k != 0: continue
            if t >= te: break
            rcp = (rcp or "").lower()
            if first_b is None: first_b = b
            if buy and b < first_b + 30: early.add(rcp)
            net[rcp] += abs(tok) if buy else -abs(tok)
        hold = {a: v for a, v in net.items() if v > 0 and a not in ROUTER}
        tot = sum(hold.values())
        crew = set()
        cw = CW.get(creator, {})
        for key in ("creators", "creator_funders", "distributors", "army"): crew |= {x.lower() for x in cw.get(key, [])}
        fu = funders(hold.keys())
        opf = {a for a in hold if a == creator or a in crew or (a in fu and (fu[a][1] in DISP or fu[a][0] in DISP or (creator and fu[a][0] == creator)))}
        opb = {a for a in hold if a == creator or a in early}
        rows.append(dict(book=book, tok=r["tok"], pool=pool, kit=r["kit"], half=r["half"], entry_bkk=r["entry_bkk"], why=r["why"], x=float(r["x"]),
                         creator=creator, crew_known=int(bool(cw)), holders=len(hold), fund_cov=round(len(fu) / len(hold), 3) if hold else 0,
                         n_opf=len(opf), opf_share=round(sum(hold[a] for a in opf) / tot, 4) if tot else 0, n_opb=len(opb),
                         opb_share=round(sum(hold[a] for a in opb) / tot, 4) if tot else 0, top1=round(max(hold.values()) / tot, 4) if tot else 0))
with open(OUT + "/float.csv", "w") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0])); w.writeheader(); w.writerows(rows)
print("rows", len(rows), {b: sum(1 for r in rows if r["book"] == b) for b in BOOKS})
