"""Audit check 2: the front's 40-pip / one-account pick and the second-account cell.

Rebuilds the notebook's section 26 cell arithmetic (cost26, pace26, chain26, G) for the
stops that matter and asks what moves the ordering of 34.8 against 40 pips: the swap
scaled by Wald's l^2 against the broker's measured pace, a 5% error in the pace at 40
pips, and the funded pick held fixed. Then the wallet at one and two accounts, 5,000
paths, three seeds, through spread.family and hedge.shared_wallet as the notebook does.

    cd /root/Projects/trading-framework && python3 /tmp/arena-prime-audit/candidate-2/c2_front.py
"""
import json
import sys
import time

import numpy as np

sys.path.insert(0, "/root/Projects/trading-framework")
from src.notebooks.reports.topics.prime_academy.modules import prime as PA  # noqa: E402
from src.notebooks.reports.topics.prime_academy.modules import spread as SP  # noqa: E402
from src.notebooks.reports.topics.prime_academy.modules import hedge as HG  # noqa: E402

OUT = "/tmp/arena-prime-audit/candidate-2/c2_front.json"
P = "/root/Projects/trading-framework/src/notebooks/reports/topics/prime_academy/paper/"
DEC = json.load(open(P + "decision.json")); BMJ = json.load(open(P + "broker_map.json")); FRJ = json.load(open(P + "front.json"))
SPLIT, B, FEE, W0, HON = 0.70, 3000.0, 38.0, 1000.0, 0.8
T3 = PA.Tier(B, FEE, 51.0)
STOP0 = DEC["stop"]
SWAP_COIN = DEC["side_share"]["coin"]
RR = [0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 2.5, 3.0]
X26 = np.array(RR); D26 = np.array([BMJ["pace"][str(r)] for r in RR])
FLOOR = 1.4
RHO_STAG = SP.rho_normal(0.26)
res = {}


def pace26(l):
    x = (l / STOP0) ** 2
    if x < X26[0]:
        slope = (D26[1] - D26[0]) / (X26[1] - X26[0])
        return max(FLOOR, float(D26[0] + slope * (x - X26[0])))
    return float(np.interp(x, X26, D26))


def cost26(l, scen, swap_scaling="wald"):
    g = PA.cost_share(l, s=0.0) if scen == "commission only" else PA.cost_share(l)
    if scen.startswith("random side"):
        if swap_scaling == "wald":
            g += SWAP_COIN * l / STOP0                       # nights ~ l^2, pips per night fixed, over l
        else:                                                # nights ~ measured pace, over l
            g += SWAP_COIN * (pace26(l) / pace26(STOP0)) * STOP0 / l
    if scen.endswith("asides"):
        g += 1.33 * PA.cost_share(l) * (l / STOP0) ** 2
    return g


def chain26(l, scen, g=None, d=None, rf=None):
    g = cost26(l, scen) if g is None else g
    d = pace26(l) if d is None else d
    wt = max(PA.MIN_DAYS, int(round(PA.WAIT / d)))
    e = PA.eval_chain(0.03, g * 0.03, rr=1.0, clip_up=True, clip_dn=True)
    if rf is None:
        rows = PA.funded_line_search(g, lo=0.006, hi=0.020, step=0.00025, wait=wt)
        rf = min(PA.plateau(rows), key=lambda r: (r["med_first_pay"], -r["e_W"]))["risk"]
    f = PA.funded_chain(rf, g * rf, PA.payout_threshold(rf, 1.0, B, SPLIT), rr=1.0, clip_dn=True, wait=wt)
    cash = SPLIT * B * e["p_pass"] * f["e_W"]
    days = d * (e["e_trades"] + e["p_pass"] * f["e_life"])
    return dict(stop=l, scen=scen, cost=g, pace=d, wait=wt, rf=rf, p_pass=e["p_pass"], p_any=f["p_any"], e_W=f["e_W"],
                cash_fee=cash / FEE, G1=(HON * cash - FEE) * 365 / days)


t0 = time.time()
SC = "random side, swap charged"
def _pub(scen):
    """front.json cells keyed by (stop, N); the deployed stop is stored at JSON precision, so match by closeness."""
    d = {}
    for c in FRJ["cells"]:
        if c["scenario"] == scen:
            key = STOP0 if abs(c["stop"] - STOP0) < 1e-6 else c["stop"]
            d[(key, c["N"])] = c
    return d


pub = _pub(SC)
print("[1] reproduce G at one account, swap scenario (published G from front.json):")
base = {}
for l in [30.0, STOP0, 40.0, 45.0]:
    c = chain26(l, SC); base[l] = c
    pb = pub.get((l, 1), {})
    print(f"    stop {l:5.1f}: cost {c['cost']:.4f} pace {c['pace']:.2f} wait {c['wait']} rf {c['rf']:.5f} p_any {c['p_any']:.4f} "
          f"G {c['G1']:+.1f} $/yr (published {pb.get('G', float('nan')):+.1f}, log_se {pb.get('log_se', float('nan')):.4f}, log_g {pb.get('log_g', float('nan')):+.3f})")
res["reproduce"] = base

print("[2] what moves the 34.8 against 40 ordering in G:")
alt = {}
for name, kw in (("swap scaled by measured pace, not Wald", dict(mode="pace")),
                 ("pace at 40 pips 5% slower", dict(dpace=1.05)),
                 ("pace at 40 pips 5% faster", dict(dpace=0.95)),
                 ("funded pick held at 1.575% at both", dict(rf=0.01575)),
                 ("funded pick held at 1.5% at both", dict(rf=0.015))):
    row = {}
    for l in [STOP0, 40.0]:
        g = cost26(l, SC, "pace") if kw.get("mode") == "pace" else None
        d = pace26(l) * kw["dpace"] if "dpace" in kw and l == 40.0 else None
        c = chain26(l, SC, g=g, d=d, rf=kw.get("rf"))
        row[l] = c
    alt[name] = row
    print(f"    {name:42}: 34.8 -> G {row[STOP0]['G1']:+.1f} (cost {row[STOP0]['cost']:.4f}, rf {row[STOP0]['rf']:.5f}) | "
          f"40 -> G {row[40.0]['G1']:+.1f} (cost {row[40.0]['cost']:.4f}, rf {row[40.0]['rf']:.5f}) | 40 richer: {row[40.0]['G1'] > row[STOP0]['G1']}")
res["alternatives"] = alt

# the pace at 40 at which G(40) = G(34.8)
g40 = base[40.0]; g348 = base[STOP0]
# G1 = (HON*cash - FEE)*365/(d*(trades)) is proportional to 1/d at fixed chains (wait fixed at 6)
d_eq = g40["pace"] * g40["G1"] / g348["G1"]
print(f"    G(40) equals G(34.8) when the 40-pip pace is {d_eq:.2f} days a trade against the mapped {g40['pace']:.2f} "
      f"({100 * (d_eq / g40['pace'] - 1):+.1f}%)")
res["pace_equal"] = d_eq

# ---- 3. the wallet at N = 1 for 34.8 and 40, three seeds, 5,000 paths, copula coin as the notebook --------
print("[3] wallet at one account, swap scenario, 5,000 paths x 3 seeds (T days, D p90 year one, ruin, log growth 3y):")
N, YEARS = 5000, 3


def wallet(c, rho, k_max, seed):
    H, H1 = int(round(YEARS * 365 / c["pace"])), int(round(365 / c["pace"]))
    out = []
    for k, F, G in SP.family(T3, rho, 0.03, c["cost"] * 0.03, SPLIT, 1.0, H, N, seed, k_max=k_max,
                             p_paid=HON, funded_risk=c["rf"], funded_cost=c["cost"] * c["rf"],
                             clip_up=True, clip_dn=True, wait=c["wait"]):
        w = HG.shared_wallet(F, W0, G, paths=True); p = w.pop("paths")
        dd1 = HG.shared_wallet(F[:, :H1], W0, G[:, :H1], paths=True)["paths"]["maxdd"]
        t = np.where(np.isnan(p["first_cash"]), np.inf, p["first_cash"] + 1) * c["pace"]
        out.append(dict(N=k, T=float(np.median(t)), D=float(np.percentile(dd1, 90)), ruin=w["p_ruin"], log_g=w["e_log_growth"],
                        log_se=float(p["log_g"].std(ddof=1) / np.sqrt(N)), p_any_cash=w["p_any_cash"]))
    return out


w1 = {}
for l in [STOP0, 40.0]:
    rows = [wallet(base[l], RHO_STAG, 1, s)[0] for s in (13, 14, 15)]
    w1[l] = rows
    lg = [r["log_g"] for r in rows]
    print(f"    stop {l:5.1f}: T {[round(r['T']) for r in rows]}  D {[round(r['D']) for r in rows]}  ruin {[r['ruin'] for r in rows]}  "
          f"log_g {[round(x, 4) for x in lg]} mean {np.mean(lg):+.4f} sd {np.std(lg, ddof=1):.4f} (within-run se {rows[0]['log_se']:.4f}); "
          f"published T {pub[(l, 1)]['T']:.0f} D {pub[(l, 1)]['D']:.0f} log_g {pub[(l, 1)]['log_g']:+.3f}")
res["wallet_N1"] = {str(k): v for k, v in w1.items()}

# ---- 4. the second account at 40 pips with commission and spread: correlation flips ---------------------------
SC2 = "commission and spread"
pub2 = _pub(SC2)
c40 = chain26(40.0, SC2)
print(f"[4] two accounts at 40 pips, commission and spread (cost {c40['cost']:.4f}, rf {c40['rf']:.5f}); published N=2: "
      f"ruin {pub2[(40.0, 2)]['ruin']:.3f} log_g {pub2[(40.0, 2)]['log_g']:+.3f} T {pub2[(40.0, 2)]['T']:.0f} D {pub2[(40.0, 2)]['D']:.0f}")
w2 = {}
for rho_name, rho in (("independent", 0.0), ("staggered 0.26 -> 0.40", RHO_STAG), ("0.70", 0.70), ("copies", 1.0)):
    rows = [wallet(c40, rho, 2, s)[1] for s in (13, 14)]
    w2[rho_name] = rows
    print(f"    rho {rho_name:24}: ruin {[r['ruin'] for r in rows]} log_g {[round(r['log_g'], 3) for r in rows]} "
          f"T {[round(r['T']) for r in rows]} D {[round(r['D']) for r in rows]}")
res["wallet_N2_40"] = w2
# and at 34.8 pips N=2 which the paper says fails (ruin 5.1%)
c348 = chain26(STOP0, SC2)
rows = [wallet(c348, RHO_STAG, 2, s)[1] for s in (13, 14)]
print(f"    34.8 pips N=2 staggered: ruin {[r['ruin'] for r in rows]} log_g {[round(r['log_g'], 3) for r in rows]} "
      f"(published ruin {pub2[(STOP0, 2)]['ruin']:.3f}, log_g {pub2[(STOP0, 2)]['log_g']:+.3f})")
res["wallet_N2_348"] = rows

json.dump(res, open(OUT, "w"), indent=1, default=float)
print(f"done in {time.time() - t0:.0f} s -> {OUT}")
