"""mc5wallet.py: wallet needed per ticket for mc5 live (4 h stop, max 3 open, dust guard), both fill models. Replays the 201 trades in time order with the live max-open cap, realised PnL path in $, max drawdown and worst day.""" exec(open("/opt/fw2/mc5v15.py").read().split("rows = []")[0]) def trade3(P, V, tstop, own): t = P.t; eu = t["eu"]; gas = 0.05 / eu; x = V / eu; te = 300 i = P.at(te) if i < 0: return None # dust guard (A1.20): a 0.001+ WETH swap before +5 min and 0.1+ WETH in the pool at +5 min pre = [e for e in P.ev if e[1] == "s" and e[0] < te] if not pre or max(e[2][3] for e in pre) < 0.001: return "dust" xin = max(0.0, (x * 0.99 - gas) * (1 - P.pf)) * 1e18 q = swap(P.S[i], xin, not P.is0, 0.0); pull = P.pull def net(k): g = gross_back(P, k, xin, q) if own else swap(P.S[k], q, P.is0, 0.0) return max(0.0, g / 1e18 * (1 - P.pf) * 0.99 - gas) / x for k in range(i + 1, len(P.S)): sec, kind, sp, L, tk, nt, tks, we = P.S[k] if sec > tstop: break if kind != "s" or we < 0.01 or sec <= te: continue m = net(k) if m <= 0.5: if pull is not None and pull <= sec + 3: return 0.0, pull j = max(k, P.at(sec + 3)); return net(j), sec + 3 if pull is not None and pull <= tstop: return 0.0, pull return net(P.at(tstop)), tstop for own, lab in ((True, "main"), (False, "lower")): for V in (100, 500, 1000): ev = [] nd = 0 for P in PS: r = trade3(P, V, 14400, own) if r == "dust": nd += 1; continue if r: ev.append((P.t["t"] + 300, P.t["t"] + r[1], r[0], P.t)) ev.sort(key=lambda e: e[0]) open_ = []; cum = 0.0; peak = 0.0; dd = 0.0; taken = 0; skipped = 0; maxopen = 0 byd = collections.defaultdict(float); closes = [] for tin, tout, xx, t in ev: closes = [c for c in open_ if c[0] <= tin] for c in closes: cum += c[1]; peak = max(peak, cum); dd = min(dd, cum - peak); open_.remove(c) if len(open_) >= 3: skipped += 1; continue open_.append((tout, (xx - 1) * V)); taken += 1; maxopen = max(maxopen, len(open_)); byd[day(t["t"])] += (xx - 1) * V for c in sorted(open_): cum += c[1]; peak = max(peak, cum); dd = min(dd, cum - peak) print("%s $%d: dust skipped %d, taken %d, skipped by max 3 open %d, total $%+.0f, max drawdown $%.0f (%.1f tickets), worst day $%.0f (%.1f tickets)" % ( lab, V, nd, taken, skipped, cum, dd, -dd / V, min(byd.values()), -min(byd.values()) / V), flush=True)