"""Generate the complete pink e2e test file.""" import sys sys.path.insert(0, '/mnt/dolphinng5_predict') fpath = '/mnt/dolphinng5_predict/prod/tests/test_pink_bingx_dita_live_e2e.py' lines = [] def emit(s=""): lines.append(s) # ---- IMPORTS ---- emit('#!/usr/bin/env python3') emit('"""PINK DITAv2 Live BingX Testnet E2E — conceptual gap coverage."""') emit('from __future__ import annotations') emit('import asyncio, json, os, socket, time, urllib.request') emit('import urllib.parse') emit('from dataclasses import dataclass') emit('from typing import Any, Optional') emit('import pytest') emit('from prod.bingx.http import BingxHttpClient') emit('from prod.bingx.config import BingxExecClientConfig, BingxEnvironment') emit('from prod.clean_arch.dita_v2.launcher import build_launcher_bundle') emit('from prod.clean_arch.dita_v2.contracts import (') emit(' KernelCommandType as KC, KernelIntent as KI, TradeSide as TS,') emit(' VenueEvent, VenueEventStatus, KernelEventKind,') emit(' TradeStage, KernelDiagnosticCode, KernelSeverity,') emit(' KernelOutcome, KernelTransition, TradeSlot, VenueOrder,') emit(')') emit('from prod.clean_arch.ports.data_feed import MarketSnapshot') emit('E = KC') emit('') emit('# Force IPv4') emit('_orig_gai = socket.getaddrinfo') emit('def _ipv4_gai(host, port, family=0, type=0, proto=0, flags=0):') emit(' return _orig_gai(host, port, socket.AF_INET, type, proto, flags)') emit('socket.getaddrinfo = _ipv4_gai') emit('') emit('_last_finish: float = 0.0') emit('def _throttle(min_gap: float = 3.0) -> None:') emit(' global _last_finish') emit(' now = __import__("time").time()') emit(' elapsed = now - _last_finish') emit(' if elapsed < min_gap:') emit(' __import__("time").sleep(min_gap - elapsed)') emit(' _last_finish = __import__("time").time()') emit('') # ---- HELPERS ---- emit('class VR:') emit(' def __init__(self, symbol, positions_flat, error):') emit(' self.symbol = symbol; self.positions_flat = positions_flat; self.error = error') emit('') emit('class RB:') emit(' def __init__(self, runtime=None, config=None):') emit(' self.runtime = runtime; self.config = config') emit('') emit('def _build_config(ic: float = 25000.0) -> BingxExecClientConfig:') emit(' return BingxExecClientConfig(environment=BingxEnvironment.TESTNET,') emit(' api_key=os.environ["BINGX_API_KEY"], secret_key=os.environ["BINGX_SECRET_KEY"],') emit(' testnet=True, recv_window_ms=5000, default_leverage=1, initial_capital_usdt=ic)') emit('') emit('def _build_rb(ic: float = 25000.0, max_slots: int = 1) -> RB:') emit(' cfg = _build_config(ic)') emit(' b = build_launcher_bundle(venue_mode="BINGX", max_slots=max_slots, bingx_config=cfg)') emit(' k = b.kernel; k.account.snapshot.capital = ic') emit(' k.account.snapshot.peak_capital = ic; k.account.snapshot.equity = ic') emit(' class Shim:') emit(' def __init__(self, k): self.kernel = k') emit(' async def connect(self, initial_capital=0): self.kernel.venue.connect()') emit(' async def disconnect(self):') emit(' try: self.kernel.venue.disconnect()') emit(' except: pass') emit(' return RB(runtime=Shim(k), config=cfg)') emit('') emit('def _inspect_outcome(r, label):') emit(' return dict(accepted=r.accepted, state=r.state.value if r.state else "",') emit(' diagnostic=r.diagnostic_code.value if r.diagnostic_code else "",') emit(' severity=r.severity.value if r.severity else "",') emit(' transitions=[(t.prev_state.value, t.next_state.value) for t in (r.transitions or ())],') emit(' event_kinds=[e.kind.value for e in (r.emitted_events or ())],') emit(' details=dict(r.details or {}))') emit('') emit('def _assert_accepted(r, label):') emit(' info = _inspect_outcome(r, label)') emit(' assert r.accepted, f"{label}: intent rejected diag={info[chr(34)+chr(34)]diagnostic[chr(34)+chr(34)]} state={info[chr(34)+chr(34)]state[chr(34)+chr(34)]} detail={info[chr(34)+chr(34)]details[chr(34)+chr(34)]}"') emit('') emit('def _assert_rejected(r, expected_diag, label):') emit(' info = _inspect_outcome(r, label)') emit(' assert not r.accepted, f"{label}: expected rejection but got accepted state={info[chr(34)+chr(34)]state[chr(34)+chr(34)]}"') emit(' assert info["diagnostic"] == expected_diag, f"{label}: expected {expected_diag} got {info[chr(34)+chr(34)]diagnostic[chr(34)+chr(34)]}"') emit('') emit('def _check_slot_accounting(k, label):') emit(' sc = getattr(k, "_start_cap", None)') emit(' if sc is None: return') emit(' trp = sum(k.slot(i).realized_pnl for i in range(k.max_slots))') emit(' tup = sum(k.slot(i).unrealized_pnl for i in range(k.max_slots))') emit(' expected = sc + trp + tup') emit(' actual = k.account.snapshot.capital') emit(' assert abs(actual - expected) < 0.01, f"{label}: acct mismatch cap={actual} exp={expected} rp={trp} upnl={tup}"') emit('') emit('def _check_open_orders(c, vs):') emit(' import asyncio') emit(' r = asyncio.run(c._request_json("GET", "/openApi/swap/v2/trade/openOrders", {"symbol": vs}, signed=True))') emit(' data = r if isinstance(r, list) else (r.get("data") or r.get("orders") or [])') emit(' return [o for o in data if isinstance(o, dict)]') emit('') emit('def _build_fresh_kernel_from_slot(slot_data, ic=25000.0):') emit(' from prod.clean_arch.dita_v2.rust_backend import _slot_from_payload') emit(' cfg = _build_config(ic)') emit(' b = build_launcher_bundle(venue_mode="BINGX", max_slots=1, bingx_config=cfg)') emit(' k = b.kernel; k.account.snapshot.capital = ic') emit(' k.account.snapshot.peak_capital = ic; k.account.snapshot.equity = ic') emit(' restored = _slot_from_payload(slot_data)') emit(' k.reconcile_from_slots([restored])') emit(' class Shim:') emit(' def __init__(self, k): self.kernel = k') emit(' async def connect(self, ic=0): self.kernel.venue.connect()') emit(' async def disconnect(self):') emit(' try: self.kernel.venue.disconnect()') emit(' except: pass') emit(' return RB(runtime=Shim(k), config=cfg)') emit('') # ---- EXISTING HELPERS ---- emit('async def _contract_rows(c):') emit(' r = await c._request_json("GET", "/openApi/swap/v2/user/positions", {}, signed=True)') emit(' return r if isinstance(r, list) else (r.get("data") or r.get("positions") or [])') emit('') emit('async def _pick_sym(k, c):') emit(' rs = await _contract_rows(c)') emit(' oss = {str(r.get("symbol","")).replace("-","").upper() for r in rs}') emit(' return next((x for x in ["TRXUSDT","XRPUSDT","ADAUSDT","DOGEUSDT"] if x not in oss), "TRXUSDT")') emit('') emit('async def _snap(c, sym):') emit(' pr = await c._request_json("GET", "/openApi/swap/v2/quote/price", {"symbol": sym}, signed=False)') emit(' d = pr.get("data") or pr; rp = float(d.get("price") or d.get("lastPrice") or 0)') emit(' return MarketSnapshot(timestamp=__import__("datetime").datetime.now(__import__("datetime").timezone.utc),') emit(' symbol=sym, price=rp, bid=rp*0.9995, ask=rp*1.0005), sym') emit('') emit('async def _verify(c, vs):') emit(' rs = await _contract_rows(c)') emit(' tr = [r for r in rs if str(r.get("symbol","")).upper().replace("-","") == vs.replace("-","").upper()]') emit(' ts = sum(abs(float(r.get("positionAmt",r.get("positionQty",0)) or 0)) for r in tr)') emit(' flat = ts < 1e-8') emit(' oos = _check_open_orders(c, vs)') emit(' no_orders = len(oos) == 0') emit(' err = ""') emit(' if not flat: err += f"pos_open: {tr} "') emit(' if not no_orders: err += f"open_orders: {oos} "') emit(' return VR(symbol=vs, positions_flat=flat and no_orders, error=err.strip())') emit('') emit('def _si(k, act, tid, asset, side_str, price, size, **kw):') emit(' ds = TS.SHORT if side_str.upper() == "SHORT" else TS.LONG') emit(' slot_id = kw.pop("slot_id", 0)') emit(' return k.process_intent(KI(timestamp=__import__("datetime").datetime.now(__import__("datetime").timezone.utc),') emit(' intent_id=tid, trade_id=tid, slot_id=slot_id, asset=asset, side=ds, action=act,') emit(' reference_price=price, target_size=size, leverage=kw.pop("leverage",1.0),') emit(' exit_leg_ratios=kw.pop("exit_leg_ratios",(1.0,)),') emit(' reason=kw.pop("reason",f"auto_{act.value.lower()}"), metadata=kw))') emit('') emit('def _flatten(k, sym, price, label, slot_id=0):') emit(' if k.slot(slot_id).is_free(): return') emit(' ts = int(time.time()*1000)') emit(' _si(k, E.EXIT, f"fl{label}-{ts}", sym, "SHORT", price, 0.001, slot_id=slot_id)') emit(' if not k.slot(slot_id).is_free():') emit(' _si(k, E.EXIT, f"fl{label}b-{ts}", sym, "LONG", price, 0.001, slot_id=slot_id)') emit('') emit('async def _run(bundle, client, body_fn, label, ic):') emit(' k = bundle.runtime.kernel') emit(' sym = await _pick_sym(k, client)') emit(' snap, vsym = await _snap(client, sym)') emit(' await bundle.runtime.connect(initial_capital=ic)') emit(' p = float(snap.price)') emit(' try:') emit(' for si in range(k.max_slots):') emit(' if not k.slot(si).is_free():') emit(' _flatten(k, sym, p*0.99 if si == 0 else p*1.005, f"{label}-pre-{si}")') emit(' await asyncio.sleep(0.3)') emit(' k._start_cap = k.account.snapshot.capital') emit(' cb = k.account.snapshot.capital') emit(' await body_fn(k, sym, p)') emit(' ca = k.account.snapshot.capital') emit(' assert ca > 0, f"Capital zero: {ca}"') emit(' max_change = max(1.0, cb * 0.10)') emit(' assert cb - ca < max_change, f"Capital shrunk beyond tolerance: {cb} -> {ca} (limit={max_change})"') emit(' total_rp = sum(k.slot(i).realized_pnl for i in range(k.max_slots))') emit(' if abs(total_rp) > 0.0001:') emit(' assert abs(total_rp) < abs(cb - ca) + 0.01, f"{label}: rp={total_rp} != cap_change={cb-ca}"') emit(' for si in range(k.max_slots):') emit(' if not k.slot(si).is_free():') emit(' _flatten(k, sym, p*0.99 if si == 0 else p*1.005, f"{label}-post-{si}")') emit(' await asyncio.sleep(1.0)') emit(' _throttle(3.0)') emit(' return await _verify(client, vsym)') emit(' finally:') emit(' await bundle.runtime.disconnect()') emit('') # ---- BODY TEMPLATES ---- # I'll build the body functions from a structured list bodies = {} # name -> list of code lines def B(name, lines): bodies[name] = lines B("simple_entry_exit", [ 'tid = f"ss-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', ]) B("multi_leg_exit", [ 'tid = f"ml-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(1)', ]) B("cancel_entry_order", [ 'tid = f"ce-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', ]) B("entry_hold_exit", [ 'tid = f"eh-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(3)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', ]) B("entry_exit_at_loss", [ 'tid = f"el-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*1.005, 0.001); await asyncio.sleep(1)', ]) B("two_sequential_cycles", [ 't1 = f"sq1-{int(time.time()*1000)}"; t2 = f"sq2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', '_si(k, E.ENTER, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, t2, symbol, "SHORT", p*0.99, 0.001); await asyncio.sleep(1)', ]) B("entry_then_recover", [ 'tid = f"r-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', ]) B("long_entry_exit", [ 'tid = f"l-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(1)', ]) B("cancel_idempotent", [ 'tid = f"ci-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', ]) B("double_cancel", [ 'tid = f"dc-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', ]) B("cancel_then_exit", [ 'tid = f"ctx-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', ]) B("exit_then_cancel_exit", [ 'tid = f"ecx-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', ]) B("exit_then_reentry", [ 't1 = f"er1-{int(time.time()*1000)}"; t2 = f"er2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', '_si(k, E.ENTER, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(1)', '_si(k, E.EXIT, t2, symbol, "SHORT", p*0.99, 0.001); await asyncio.sleep(1)', ]) B("limit_cancel", [ 'tid = f"lc-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p*0.9, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p*0.9, 0.001); await asyncio.sleep(1)', ]) B("x4_partial_hold_exit", [ 'tid = f"x4ph-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.3,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.0006, exit_leg_ratios=(0.3,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.0014, exit_leg_ratios=(0.3,1.0)); await asyncio.sleep(1)', ]) B("x4_three_leg", [ 'tid = f"x4tl-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.003, exit_leg_ratios=(0.25,0.25,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.00075, exit_leg_ratios=(0.25,0.25,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.0015, exit_leg_ratios=(0.25,0.25,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.991, 0.00075, exit_leg_ratios=(0.25,0.25,1.0)); await asyncio.sleep(1)', ]) B("x4_cancel_fill_partial", [ 'tid = f"x4cf-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', ]) B("x4_rapid_three", [ "for j in range(3):", ' tid = f"x4r{j}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, tid, symbol, "SHORT", p*(1-j*0.003), 0.001); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995*(1-j*0.003), 0.001); await asyncio.sleep(0.5)', ]) B("x4_diff_symbol", [ "ts = int(time.time()*1000)", '_si(k, E.ENTER, f"x4ds1-{ts}", symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', '_si(k, E.EXIT, f"x4ds1-{ts}", "ZZZUSDT", "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("x4_alternating", [ "ts = int(time.time()*1000)", '_si(k, E.ENTER, f"x4a1-{ts}", symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', '_si(k, E.EXIT, f"x4a1-{ts}", symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', '_si(k, E.ENTER, f"x4a2-{ts}", symbol, "LONG", p*0.995, 0.001); await asyncio.sleep(0.5)', '_si(k, E.EXIT, f"x4a2-{ts}", symbol, "LONG", p*1.002, 0.001); await asyncio.sleep(0.5)', ]) B("x4_multi_flatten", [ 'tid = f"x4mf-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "while not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', ]) B("x4_three_leg_25_50_25", [ 'tid = f"x4t3-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.25,0.5,1.0)); await asyncio.sleep(1)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.0005, exit_leg_ratios=(0.25,0.5,1.0)); await asyncio.sleep(0.7)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.25,0.5,1.0)); await asyncio.sleep(0.7)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.991, 0.0005, exit_leg_ratios=(0.25,0.5,1.0)); await asyncio.sleep(1)', ]) B("x4_enter_exit_hold_twice", [ "for j in range(3):", ' tid = f"x4ht{j}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, tid, symbol, "SHORT", p*(1-j*0.002), 0.001); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995*(1-j*0.002), 0.001); await asyncio.sleep(0.5)', ]) B("x4_cancel_then_double_exit", [ 'tid = f"x4cd-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', ]) def make_profit_loss_bodies(): for side, side_label in [("SHORT", "short"), ("LONG", "long")]: for pl, pl_label, price_factor in [("profit", "profit", ("0.997" if side == "SHORT" else "1.003")), ("loss", "loss", ("1.003" if side == "SHORT" else "0.997"))]: for pattern, pat_label in [("basic", "basic"), ("partial", "partial"), ("cancel", "cancel"), ("double_exit", "double_exit")]: name = f"{pat_label}_{side_label}_{pl}" lines = [] tid_expr = f'f"{name[:3]}-{{int(time.time()*1000)}}"' lines.append(f'tid = {tid_expr}') if pattern == "basic": exit_price = f"p*{price_factor}" lines.append(f'_si(k, E.ENTER, tid, symbol, "{side}", p, 0.001); await asyncio.sleep(0.8)') lines.append(f'_si(k, E.EXIT, tid, symbol, "{side}", {exit_price}, 0.001); await asyncio.sleep(0.5)') elif pattern == "partial": exit1 = f"p*{float(price_factor) ** 1}" if "*" not in str(price_factor) else f"p*{price_factor}" # Use different prices for two legs if pl == "profit": p1, p2 = ("p*0.995", "p*0.993") if side == "SHORT" else ("p*1.005", "p*1.007") else: p1, p2 = ("p*1.003", "p*1.005") if side == "SHORT" else ("p*0.997", "p*0.995") lines.append('_si(k, E.ENTER, tid, symbol, "' + side + '", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.8)') lines.append(f'_si(k, E.EXIT, tid, symbol, "{side}", {p1}, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)') lines.append(f'_si(k, E.EXIT, tid, symbol, "{side}", {p2}, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)') elif pattern == "cancel": lines.append(f'_si(k, E.ENTER, tid, symbol, "{side}", p, 0.001); await asyncio.sleep(0.5)') lines.append(f'_si(k, E.CANCEL, tid, symbol, "{side}", p, 0.001); await asyncio.sleep(0.3)') lines.append("if not k.slot(0).is_free():") ef = f"p*{price_factor}" lines.append(f' _si(k, E.EXIT, tid, symbol, "{side}", {ef}, 0.001); await asyncio.sleep(0.5)') elif pattern == "double_exit": if side == "SHORT": p1, p2 = ("p*0.995", "p*0.993") if pl == "profit" else ("p*1.003", "p*1.005") else: p1, p2 = ("p*1.005", "p*1.007") if pl == "profit" else ("p*0.997", "p*0.995") lines.append('_si(k, E.ENTER, tid, symbol, "' + side + '", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.8)') lines.append(f'_si(k, E.EXIT, tid, symbol, "{side}", {p1}, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)') lines.append(f'_si(k, E.EXIT, tid, symbol, "{side}", {p2}, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)') B(name, lines) make_profit_loss_bodies() # Triple seq for i in range(4): name = f"triple_seq_{i}" B(name, [ "for j in range(3):", f' tid = f"ts{i}_{{j}}-{{int(time.time()*1000)}}"', ' _si(k, E.ENTER, tid, symbol, "SHORT", p*(1-j*0.003), 0.001); await asyncio.sleep(0.8)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995*(1-j*0.003), 0.001); await asyncio.sleep(0.5)', ]) for i in range(4): name = f"triple_seq_long_{i}" B(name, [ "for j in range(3):", f' tid = f"tsl{i}_{{j}}-{{int(time.time()*1000)}}"', ' _si(k, E.ENTER, tid, symbol, "LONG", p*(1+j*0.003), 0.001); await asyncio.sleep(0.8)', ' _si(k, E.EXIT, tid, symbol, "LONG", p*1.005*(1+j*0.003), 0.001); await asyncio.sleep(0.5)', ]) # Cancel reenter for i in range(4): name = f"cancel_reenter_{i}" better = ["p*0.997", "p*0.994", "p*0.991", "p*0.988"][i] B(name, [ 't1 = f"cr{}a-{}".format(' + str(i) + ', int(time.time()*1000))', 't2 = f"cr{}b-{}".format(' + str(i) + ', int(time.time()*1000))', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', f'_si(k, E.ENTER, t2, symbol, "SHORT", {better}, 0.001); await asyncio.sleep(0.8)', f'_si(k, E.EXIT, t2, symbol, "SHORT", p*{0.995 + 0.001*i:.3f}, 0.001); await asyncio.sleep(0.5)', ]) for i in range(4): name = f"cancel_reenter_long_{i}" better = ["p*1.003", "p*1.006", "p*1.009", "p*1.012"][i] B(name, [ 't1 = f"crl{}a-{}".format(' + str(i) + ', int(time.time()*1000))', 't2 = f"crl{}b-{}".format(' + str(i) + ', int(time.time()*1000))', '_si(k, E.ENTER, t1, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t1, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.3)', f'_si(k, E.ENTER, t2, symbol, "LONG", {better}, 0.001); await asyncio.sleep(0.8)', f'_si(k, E.EXIT, t2, symbol, "LONG", p*{1.005 + 0.003*(i+1):.3f}, 0.001); await asyncio.sleep(0.5)', ]) # Leg ratio variants ratios_data = [ ("leg_ratio_0", [(0.1,1.0)], 0.002, [0.0002, 0.0018]), ("leg_ratio_1", [(0.33,0.33,1.0)], 0.003, [0.001, 0.001, 0.001]), ("leg_ratio_2", [(0.5,0.5,1.0)], 0.002, [0.001, 0.001]), ("leg_ratio_3", [(0.75,1.0)], 0.002, [0.0015, 0.0005]), ("leg_ratio_4", [(0.2,0.3,0.5,1.0)], 0.004, [0.0008, 0.0012, 0.002]), ("leg_ratio_5", [(0.4,0.6,1.0)], 0.002, [0.0008, 0.0012]), ("leg_ratio_6", [(0.15,0.85,1.0)], 0.002, [0.0003, 0.0017]), ("leg_ratio_7", [(0.25,0.25,0.5,1.0)], 0.002, [0.0005, 0.0005, 0.001]), ] for lr_name, ratios, total_sz, sizes in ratios_data: lines = [f'tid = f"{lr_name[:4]}-{{int(time.time()*1000)}}"'] lines.append(f'_si(k, E.ENTER, tid, symbol, "SHORT", p, {total_sz}, exit_leg_ratios={ratios[0]}); await asyncio.sleep(0.8)') prices = [0.995, 0.993, 0.991, 0.989][:len(sizes)] for i, (sz, pr) in enumerate(zip(sizes, prices)): lines.append(f'_si(k, E.EXIT, tid, symbol, "SHORT", p*{pr}, {sz}, exit_leg_ratios={ratios[0]}); await asyncio.sleep(0.5)') B(lr_name, lines) # Breakeven for i in range(4): B(f"breakeven_{i}", [ f'tid = f"be{i}-{{int(time.time()*1000)}}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', ]) # Price-level variants price_variants = [ ("short_exit_one_pct_profit", "SHORT", "p*0.99"), ("short_exit_third_pct_profit", "SHORT", "p*0.997"), ("short_exit_third_pct_loss", "SHORT", "p*1.003"), ("short_exit_one_pct_loss", "SHORT", "p*1.01"), ("long_exit_one_pct_profit", "LONG", "p*1.01"), ("long_exit_third_pct_profit", "LONG", "p*1.003"), ("long_exit_third_pct_loss", "LONG", "p*0.997"), ("long_exit_one_pct_loss", "LONG", "p*0.99"), ] for pn, ps, pe in price_variants: B(pn, [ f'tid = f"{pn[:4]}-{{int(time.time()*1000)}}"', f'_si(k, E.ENTER, tid, symbol, "{ps}", p, 0.001); await asyncio.sleep(0.8)', f'_si(k, E.EXIT, tid, symbol, "{ps}", {pe}, 0.001); await asyncio.sleep(0.5)', ]) # Leverage lev = [ ("entry_exit_short_2x_profit", "SHORT", 2, "p*0.995"), ("entry_exit_long_2x_profit", "LONG", 2, "p*1.005"), ("entry_exit_short_3x_profit", "SHORT", 3, "p*0.995"), ("entry_exit_long_3x_profit", "LONG", 3, "p*1.005"), ("entry_exit_short_2x_loss", "SHORT", 2, "p*1.005"), ("entry_exit_long_2x_loss", "LONG", 2, "p*0.995"), ("entry_exit_short_3x_loss", "SHORT", 3, "p*1.005"), ("entry_exit_long_3x_loss", "LONG", 3, "p*0.995"), ] for pn, ps, lv, pe in lev: B(pn, [ f'tid = f"{pn[:4]}-{{int(time.time()*1000)}}"', f'_si(k, E.ENTER, tid, symbol, "{ps}", p, 0.001, leverage={lv}); await asyncio.sleep(0.8)', f'_si(k, E.EXIT, tid, symbol, "{ps}", {pe}, 0.001, leverage={lv}); await asyncio.sleep(0.5)', ]) # Size sz = [ ("entry_exit_short_2x_size", "SHORT", 0.002), ("entry_exit_long_2x_size", "LONG", 0.002), ("entry_exit_short_3x_size", "SHORT", 0.003), ("entry_exit_long_3x_size", "LONG", 0.003), ("entry_exit_short_4x_size", "SHORT", 0.004), ("entry_exit_long_4x_size", "LONG", 0.004), ("entry_exit_short_5x_size", "SHORT", 0.005), ("entry_exit_long_5x_size", "LONG", 0.005), ] for pn, ps, s in sz: B(pn, [ f'tid = f"{pn[:4]}-{{int(time.time()*1000)}}"', f'_si(k, E.ENTER, tid, symbol, "{ps}", p, {s}); await asyncio.sleep(0.8)', f'_si(k, E.EXIT, tid, symbol, "{ps}", p*0.995 if "{ps}" == "SHORT" else p*1.005, {s}); await asyncio.sleep(0.5)', ]) # Cycles B("three_cycle_short", [ "for j in range(3):", ' tid = f"tcs{j}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, tid, symbol, "SHORT", p*(1-j*0.003), 0.001); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.997*(1-j*0.003), 0.001); await asyncio.sleep(0.5)', ]) B("three_cycle_long", [ "for j in range(3):", ' tid = f"tcl{j}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, tid, symbol, "LONG", p*(1+j*0.003), 0.001); await asyncio.sleep(0.5)', ' _si(k, E.EXIT, tid, symbol, "LONG", p*1.003*(1+j*0.003), 0.001); await asyncio.sleep(0.5)', ]) # Partial ratio prs = [ ("partial_ratio_0_short", "SHORT", (0.5,0.5,1.0), 0.002, ["p*0.995","p*0.993"], [0.001, 0.001]), ("partial_ratio_0_long", "LONG", (0.5,0.5,1.0), 0.002, ["p*1.005","p*1.007"], [0.001, 0.001]), ("partial_ratio_1_short", "SHORT", (0.33,0.33,1.0), 0.003, ["p*0.995","p*0.993","p*0.991"], [0.001, 0.001, 0.001]), ("partial_ratio_1_long", "LONG", (0.33,0.33,1.0), 0.003, ["p*1.005","p*1.007","p*1.009"], [0.001, 0.001, 0.001]), ("partial_ratio_2_short", "SHORT", (0.1,0.9,1.0), 0.002, ["p*0.995","p*0.993"], [0.0002, 0.0018]), ("partial_ratio_2_long", "LONG", (0.1,0.9,1.0), 0.002, ["p*1.005","p*1.007"], [0.0002, 0.0018]), ("partial_ratio_3_short", "SHORT", (0.25,0.25,0.5,1.0), 0.004, ["p*0.995","p*0.993","p*0.991"], [0.001, 0.001, 0.002]), ("partial_ratio_3_long", "LONG", (0.25,0.25,0.5,1.0), 0.004, ["p*1.005","p*1.007","p*1.009"], [0.001, 0.001, 0.002]), ] for pn, ps, rat, tsz, exits, szs in prs: lines = [f'tid = f"{pn[:4]}-{{int(time.time()*1000)}}"'] lines.append(f'_si(k, E.ENTER, tid, symbol, "{ps}", p, {tsz}, exit_leg_ratios={rat}); await asyncio.sleep(0.8)') for xp, xs in zip(exits, szs): lines.append(f'_si(k, E.EXIT, tid, symbol, "{ps}", {xp}, {xs}, exit_leg_ratios={rat}); await asyncio.sleep(0.5)') B(pn, lines) # Other groups B("cross_asset_short", [ 'tid = f"cas-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("cross_asset_long", [ 'tid = f"cal-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.5)', ]) B("cancel_on_fill_short", [ 'tid = f"cfs-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("cancel_on_fill_long", [ 'tid = f"cfl-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.5)', ]) B("entry_quick_exit_short", [ 'tid = f"eqs-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("entry_quick_exit_long", [ 'tid = f"eql-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.5)', ]) B("triple_leg_exit_short", [ 'tid = f"tls-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.003, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.991, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', ]) B("triple_leg_exit_long", [ 'tid = f"tll-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "LONG", p, 0.003, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.005, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.007, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', '_si(k, E.EXIT, tid, symbol, "LONG", p*1.009, 0.001, exit_leg_ratios=(0.33,0.33,1.0)); await asyncio.sleep(0.5)', ]) B("cancel_reenter_exit_short", [ 't1 = f"cres-{int(time.time()*1000)}"; t2 = f"cres2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', '_si(k, E.ENTER, t2, symbol, "SHORT", p*0.997, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("cancel_reenter_exit_long", [ 't1 = f"crel-{int(time.time()*1000)}"; t2 = f"crel2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t1, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.3)', '_si(k, E.ENTER, t2, symbol, "LONG", p*1.003, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, t2, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.5)', ]) B("zero_capital_safety", [ 'tid = f"zcs-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', "if not k.slot(0).is_free():", ' _si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("position_survives_exit", [ 'tid = f"pse-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("double_entry_prevention", [ 't1 = f"dep1-{int(time.time()*1000)}"; t2 = f"dep2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.ENTER, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("negative_capital_check", [ 'tid = f"nec-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', ]) # RECONCILE B("reconcile_empty", [ "k.reconcile_from_slots([]); await asyncio.sleep(0.3)", ]) B("reconcile_after_entry", [ 'tid = f"re-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reconcile_after_exit", [ 'tid = f"rx-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", ]) B("reconcile_after_cancel", [ 'tid = f"rcn-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', "if not k.slot(0).is_free():", ' _si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reconcile_twice", [ 'tid = f"rtw-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reconcile_then_cancel", [ 'tid = f"rtc-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', "k.reconcile_from_slots([k.slot(0)]); await asyncio.sleep(0.3)", "if not k.slot(0).is_free():", ' _si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # CHAOS B("concurrent_enter_cancel", [ 'tid = f"cc-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("rapid_alternating", [ 't1 = f"ras-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.2)', '_si(k, E.CANCEL, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.2)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', 't2 = f"ral-{int(time.time()*1000)}"', '_si(k, E.ENTER, t2, symbol, "LONG", p, 0.001); await asyncio.sleep(0.2)', '_si(k, E.CANCEL, t2, symbol, "LONG", p, 0.001); await asyncio.sleep(0.2)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t2, symbol, "LONG", p*1.005, 0.001); await asyncio.sleep(0.3)', ]) B("duplicate_trade_id", [ 'tid = f"dt-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.ENTER, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("slot_busy_double_entry", [ 't1 = f"sb1-{int(time.time()*1000)}"; t2 = f"sb2-{int(time.time()*1000)}"', '_si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', '_si(k, E.ENTER, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("exit_on_idle_slot", [ '_si(k, E.EXIT, f"exidle-{int(time.time()*1000)}", symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', 'tid = f"eoi-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("cancel_on_idle_slot", [ '_si(k, E.CANCEL, f"coi-{int(time.time()*1000)}", symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', 'tid = f"cis-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("rapid_ten_cycle", [ "for i in range(10):", ' tid = f"rc10-{i}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, tid, symbol, "SHORT", p*(1-i*0.001), 0.001); await asyncio.sleep(0.4)', " if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995*(1-i*0.001), 0.001); await asyncio.sleep(0.4)', " else:", " break", ]) B("cancel_after_exit_fill", [ 'tid = f"caf-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # MULTI-SLOT B("multi_slot_enter_exit", [ 't0 = f"ms0-{int(time.time()*1000)}"; t1 = f"ms1-{int(time.time()*1000)}"', '_si(k, E.ENTER, t0, symbol, "SHORT", p, 0.001, slot_id=0); await asyncio.sleep(0.4)', '_si(k, E.ENTER, t1, symbol, "LONG", p, 0.001, slot_id=1); await asyncio.sleep(0.4)', '_si(k, E.EXIT, t0, symbol, "SHORT", p*0.995, 0.001, slot_id=0); await asyncio.sleep(0.4)', '_si(k, E.EXIT, t1, symbol, "LONG", p*1.005, 0.001, slot_id=1); await asyncio.sleep(0.4)', ]) B("multi_slot_cross_cancel", [ 't0 = f"msx0-{int(time.time()*1000)}"; t1 = f"msx1-{int(time.time()*1000)}"', '_si(k, E.ENTER, t0, symbol, "SHORT", p, 0.001, slot_id=0); await asyncio.sleep(0.3)', '_si(k, E.ENTER, t1, symbol, "LONG", p, 0.001, slot_id=1); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t0, symbol, "SHORT", p, 0.001, slot_id=0); await asyncio.sleep(0.3)', '_si(k, E.CANCEL, t1, symbol, "LONG", p, 0.001, slot_id=1); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t0, symbol, "SHORT", p*0.995, 0.001, slot_id=0); await asyncio.sleep(0.3)', "if not k.slot(1).is_free():", ' _si(k, E.EXIT, t1, symbol, "LONG", p*1.005, 0.001, slot_id=1); await asyncio.sleep(0.3)', ]) B("multi_slot_rapid_cycle", [ "for i in range(5):", ' t0 = f"msc0-{i}-{int(time.time()*1000)}"; t1 = f"msc1-{i}-{int(time.time()*1000)}"', ' _si(k, E.ENTER, t0, symbol, "SHORT", p*(1-i*0.002), 0.001, slot_id=0); await asyncio.sleep(0.3)', ' _si(k, E.ENTER, t1, symbol, "LONG", p*(1+i*0.002), 0.001, slot_id=1); await asyncio.sleep(0.3)', ' _si(k, E.EXIT, t0, symbol, "SHORT", p*0.995*(1-i*0.002), 0.001, slot_id=0); await asyncio.sleep(0.3)', ' _si(k, E.EXIT, t1, symbol, "LONG", p*1.005*(1+i*0.002), 0.001, slot_id=1); await asyncio.sleep(0.3)', ]) # REJECTION B("reject_wrong_symbol", [ 'tid = f"rs-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, "ZZZUSDT", "SHORT", 0.001, 0.001); await asyncio.sleep(0.5)', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reject_zero_size", [ 'tid = f"rz-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.0); await asyncio.sleep(0.3)', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reject_side_mismatch_cancel", [ 'tid = f"rsm-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.CANCEL, tid, symbol, "LONG", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("reject_negative_price", [ 'tid = f"rn-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", -1.0, 0.001); await asyncio.sleep(0.5)', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # SNAPSHOT B("snapshot_restore_empty", [ "s = k.snapshot(); await asyncio.sleep(0.1)", "j = json.dumps(s); _ = json.loads(j)", 'tid = f"sre-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("snapshot_restore_mid_trade", [ 'tid = f"srm-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "s = k.snapshot(); await asyncio.sleep(0.1)", "j = json.dumps(s); _ = json.loads(j)", '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("snapshot_restore_after_cancel", [ 'tid = f"src-{int(time.time()*1000)}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.5)', '_si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "s = k.snapshot(); await asyncio.sleep(0.1)", "j = json.dumps(s); _ = json.loads(j)", "if not k.slot(0).is_free():", ' _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # LIMIT B("limit_does_not_fill", [ 'tid = "l0-" + str(int(time.time()*1000))', "k.process_intent(KI(timestamp=__import__(\"datetime\").datetime.now(__import__(\"datetime\").timezone.utc),", " intent_id=tid, trade_id=tid, slot_id=0, asset=symbol, side=TS.SHORT, action=E.ENTER,", " reference_price=0.0, target_size=0.001, leverage=1.0, exit_leg_ratios=(1.0,),", ' reason="auto_zeroprice")); await asyncio.sleep(0.3)', 'tid2 = "l0r-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid2, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("limit_immediate_fill", [ 'tid = "ln-" + str(int(time.time()*1000))', "k.process_intent(KI(timestamp=__import__(\"datetime\").datetime.now(__import__(\"datetime\").timezone.utc),", " intent_id=tid, trade_id=tid, slot_id=0, asset=symbol, side=TS.SHORT, action=E.ENTER,", " reference_price=p, target_size=-0.001, leverage=1.0, exit_leg_ratios=(1.0,),", ' reason="auto_negsize")); await asyncio.sleep(0.3)', 'tid2 = "lnr-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid2, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # ===== FRESH KERNEL RECONCILE ===== B("fresh_kernel_reconcile_entry", [ 'tid = "fk-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "slot_data = k.slot(0).to_dict()", "cb = k.account.snapshot.capital", "fresh = _build_fresh_kernel_from_slot(slot_data, ic=cb)", "k2 = fresh.runtime.kernel", "s = k2.slot(0)", 'assert not s.is_free(), f"fresh kernel slot should not be free: {s.fsm_state}"', 'assert s.trade_id == tid, f"trade_id mismatch: {s.trade_id} vs {tid}"', '_si(k2, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', 'assert k2.slot(0).is_free(), "fresh kernel slot not free after exit"', 'assert abs(k2.account.snapshot.capital - cb) < 0.01, f"capital drift: {k2.account.snapshot.capital} vs {cb}"', ]) B("fresh_kernel_reconcile_after_cancel", [ 'tid = "fkc-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', 'r = _si(k, E.CANCEL, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "slot_data = k.slot(0).to_dict()", "cb = k.account.snapshot.capital", "fresh = _build_fresh_kernel_from_slot(slot_data, ic=cb)", "k2 = fresh.runtime.kernel", 'assert k2.slot(0).is_free(), f"cancelled slot not free: {k2.slot(0).fsm_state}"', ]) B("fresh_kernel_reconcile_after_exit", [ 'tid = "fkx-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', "slot_data = k.slot(0).to_dict()", "cb = k.account.snapshot.capital", "fresh = _build_fresh_kernel_from_slot(slot_data, ic=cb)", "k2 = fresh.runtime.kernel", 'assert k2.slot(0).is_free(), f"closed slot not free: {k2.slot(0).fsm_state}"', 'assert k2.slot(0).closed, "slot should be marked closed"', 'assert abs(k2.account.snapshot.capital - cb) < 0.01, f"capital drift: {k2.account.snapshot.capital} vs {cb}"', ]) B("fresh_kernel_reconcile_partial_exit", [ 'tid = "fkp-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.5)', "slot_data = k.slot(0).to_dict()", "cb = k.account.snapshot.capital", "fresh = _build_fresh_kernel_from_slot(slot_data, ic=cb)", "k2 = fresh.runtime.kernel", "s = k2.slot(0)", 'assert not s.is_free(), f"partial-exit slot not free: {s.fsm_state}"', 'assert s.realized_pnl != 0 or s.size > 0, "partial-exit slot should have remaining position or realized PnL"', '_si(k2, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(1.0,)); await asyncio.sleep(0.5)', 'assert k2.slot(0).is_free(), "slot not free after final exit on fresh kernel"', ]) # ===== CROSS-SLOT PORTFOLIO ===== B("cross_slot_portfolio_short_long", [ 't0 = "psl0-" + str(int(time.time()*1000))', 't1 = "psl1-" + str(int(time.time()*1000))', "cb = k.account.snapshot.capital", '_si(k, E.ENTER, t0, symbol, "SHORT", p, 0.001, slot_id=0); await asyncio.sleep(0.4)', '_si(k, E.ENTER, t1, symbol, "LONG", p, 0.001, slot_id=1); await asyncio.sleep(0.4)', 'assert not k.slot(0).is_free(), "slot 0 should be open"', 'assert not k.slot(1).is_free(), "slot 1 should be open"', "rp0 = k.slot(0).realized_pnl; up0 = k.slot(0).unrealized_pnl", "rp1 = k.slot(1).realized_pnl; up1 = k.slot(1).unrealized_pnl", "expected = cb + rp0 + up0 + rp1 + up1", "actual = k.account.snapshot.capital", 'assert abs(actual - expected) < 0.01, f"portfolio misalignment: cap={actual} exp={expected} rp0={rp0} up0={up0} rp1={rp1} up1={up1}"', '_si(k, E.EXIT, t0, symbol, "SHORT", p*0.995, 0.001, slot_id=0); await asyncio.sleep(0.4)', 'assert k.slot(0).is_free(), "slot 0 should be free after exit"', '_si(k, E.EXIT, t1, symbol, "LONG", p*1.005, 0.001, slot_id=1); await asyncio.sleep(0.4)', 'assert k.slot(1).is_free(), "slot 1 should be free after exit"', ]) # ===== KERNEL OUTCOME INSPECTION ===== B("outcome_inspect_entry", [ 'tid = "oi-" + str(int(time.time()*1000))', 'r = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "_assert_accepted(r, 'entry')", "info = _inspect_outcome(r, 'entry')", 'assert r.accepted, f"entry not accepted: {info}"', 'assert r.trade_id == tid, f"trade_id mismatch: {r.trade_id} vs {tid}"', 'assert r.slot_id == 0, f"slot_id: {r.slot_id}"', 'assert len(info["transitions"]) > 0, f"no transitions in outcome: {info}"', 'assert info["diagnostic"] == "OK", f"diagnostic not OK: {info}"', 'r2 = _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', "_assert_accepted(r2, 'exit')", 'info2 = _inspect_outcome(r2, "exit")', 'assert len(info2["transitions"]) > 0, f"no exit transitions: {info2}"', 'assert info2["diagnostic"] == "OK", f"exit diagnostic: {info2}"', ]) B("outcome_inspect_rejection", [ 'tid = "or-" + str(int(time.time()*1000))', 'tid2 = "or2-" + str(int(time.time()*1000))', 'r1 = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "_assert_accepted(r1, 'first entry')", 'r2 = _si(k, E.ENTER, tid2, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "_assert_rejected(r2, 'SLOT_BUSY', 'double entry')", "info = _inspect_outcome(r2, 'double entry')", 'assert not r2.accepted, f"second entry should be rejected: {info}"', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) B("outcome_inspect_exit_on_idle", [ 'tid = "oei-" + str(int(time.time()*1000))', 'r = _si(k, E.EXIT, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "_assert_rejected(r, 'INVALID_FSM_TRANSITION', 'exit on idle')", "info = _inspect_outcome(r, 'exit on idle')", 'assert not r.accepted, f"exit on idle should be rejected: {info}"', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # ===== EVENT DEDUP ===== B("dedup_duplicate_fill_event", [ 'tid = "dd-" + str(int(time.time()*1000))', 'r = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "_assert_accepted(r, 'entry')", "sl = k.slot(0)", "ao = sl.active_entry_order if sl.active_entry_order else sl.active_exit_order", "if ao:", " dup = VenueEvent(", " timestamp=__import__(\"datetime\").datetime.now(__import__(\"datetime\").timezone.utc),", ' event_id="dedup-test-99999",', " trade_id=tid, slot_id=0,", " kind=KernelEventKind.FULL_FILL,", " status=VenueEventStatus.FILLED,", " venue_order_id=ao.venue_order_id,", " venue_client_id=ao.venue_client_id,", " side=sl.side,", " asset=symbol,", " price=p,", " size=0.001, filled_size=0.001, remaining_size=0.0,", ' reason="dedup_test",', " )", " r2 = k.on_venue_event(dup)", " _assert_accepted(r2, 'dedup_fill')", '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # ===== FILL-PRICE DIVERGENCE ===== B("fill_price_divergence_1pct", [ 'tid = "fd-" + str(int(time.time()*1000))', '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "sl = k.slot(0)", "ao = sl.active_entry_order if sl.active_entry_order else sl.active_exit_order", "if ao and str(sl.fsm_state) not in ('IDLE', 'CLOSED'):", " divergent_price = p * 1.01", " div_event = VenueEvent(", " timestamp=__import__(\"datetime\").datetime.now(__import__(\"datetime\").timezone.utc),", ' event_id="divergence-test",', " trade_id=tid, slot_id=0,", " kind=KernelEventKind.FULL_FILL,", " status=VenueEventStatus.FILLED,", ' venue_order_id=ao.venue_order_id if ao else "",', ' venue_client_id=ao.venue_client_id if ao else "",', " side=sl.side,", " asset=symbol,", " price=divergent_price,", " size=0.001, filled_size=0.001, remaining_size=0.0,", ' reason="divergence_test",', " )", " k.on_venue_event(div_event); await asyncio.sleep(0.3)", '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # ===== NEGATIVE CAPITAL ===== B("neg_cap_entry_rejected", [ 'tid = "nc-" + str(int(time.time()*1000))', "k.account.snapshot.capital = 0.0", 'r = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "info = _inspect_outcome(r, 'neg_cap')", "k.account.snapshot.capital = 25000.0", '_si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', '_si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', ]) # ===== CROSS-SAMPLE: new patterns on old shapes ===== B("cross_sample_basic_entry_exit_outcome", [ 'tid = "cs-" + str(int(time.time()*1000))', "cb = k.account.snapshot.capital; k._start_cap = cb", 'r1 = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.8)', "_assert_accepted(r1, 'cs_entry')", "_check_slot_accounting(k, 'cs_after_entry')", 'r2 = _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', "_assert_accepted(r2, 'cs_exit')", "_check_slot_accounting(k, 'cs_after_exit')", "ca = k.account.snapshot.capital", "max_change = max(1.0, cb * 0.10)", 'assert cb - ca < max_change, f"cs: cap shrunk {cb} -> {ca}"', ]) B("cross_sample_cancel_reenter_outcome", [ 't1 = "csc-" + str(int(time.time()*1000))', 't2 = "csc2-" + str(int(time.time()*1000))', "cb = k.account.snapshot.capital; k._start_cap = cb", 'r1 = _si(k, E.ENTER, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "_assert_accepted(r1, 'cs_cancel_entry')", 'r2 = _si(k, E.CANCEL, t1, symbol, "SHORT", p, 0.001); await asyncio.sleep(0.3)', "if not k.slot(0).is_free():", ' _si(k, E.EXIT, t1, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.3)', "_check_slot_accounting(k, 'cs_after_cancel')", 'assert k.slot(0).is_free(), "slot should be free after cancel"', 'r3 = _si(k, E.ENTER, t2, symbol, "SHORT", p*0.997, 0.001); await asyncio.sleep(0.8)', "_assert_accepted(r3, 'cs_reenter')", "_check_slot_accounting(k, 'cs_after_reenter')", 'r4 = _si(k, E.EXIT, t2, symbol, "SHORT", p*0.995, 0.001); await asyncio.sleep(0.5)', "_assert_accepted(r4, 'cs_reenter_exit')", "_check_slot_accounting(k, 'cs_after_reenter_exit')", ]) B("cross_sample_multi_leg_outcome", [ 'tid = "csm-" + str(int(time.time()*1000))', "cb = k.account.snapshot.capital; k._start_cap = cb", 'r = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.002, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.8)', "_assert_accepted(r, 'cs_ml_entry')", 'r = _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.4)', "_assert_accepted(r, 'cs_ml_leg1')", "_check_slot_accounting(k, 'cs_ml_after_leg1')", 'r = _si(k, E.EXIT, tid, symbol, "SHORT", p*0.993, 0.001, exit_leg_ratios=(0.5,1.0)); await asyncio.sleep(0.4)', "_assert_accepted(r, 'cs_ml_leg2')", "_check_slot_accounting(k, 'cs_ml_after_leg2')", ]) B("cross_sample_leverage_tight_bounds", [ 'tid = "csl-" + str(int(time.time()*1000))', "cb = k.account.snapshot.capital; k._start_cap = cb", 'r_ent = _si(k, E.ENTER, tid, symbol, "SHORT", p, 0.001, leverage=2); await asyncio.sleep(0.8)', "_assert_accepted(r_ent, 'cs_lev_entry')", "_check_slot_accounting(k, 'cs_lev_after_entry')", 'r_ex = _si(k, E.EXIT, tid, symbol, "SHORT", p*0.995, 0.001, leverage=2); await asyncio.sleep(0.5)', "_assert_accepted(r_ex, 'cs_lev_exit')", "_check_slot_accounting(k, 'cs_lev_after_exit')", "ca = k.account.snapshot.capital", "max_change = max(1.0, cb * 0.10)", 'assert cb - ca < max_change, f"cs_lev: cap shrunk {cb} -> {ca}"', ]) # ---- BUILD SCENARIOS LIST ---- emit("# ============================================================") emit("# SCENARIOS") emit("# ============================================================") emit("SCENARIOS = [") for name in sorted(bodies.keys()): emit(f' pytest.param("{name}", _body_{name}, id="{name}"),') emit("]") emit("") # ---- FIXTURE + TEST ---- emit("@pytest.fixture(scope=\"session\")") emit("def _live_client():") emit(" return BingxHttpClient(_build_config())") emit("") emit("") emit("@pytest.mark.parametrize(\"name,body_fn\", SCENARIOS)") emit("def test_pink_ditav2(_live_client, name, body_fn) -> None:") emit(" bundle = _build_rb()") emit(" ic = bundle.runtime.kernel.account.snapshot.capital") emit(" r = asyncio.run(_run(bundle, _live_client, body_fn, name, ic))") emit(" assert r.positions_flat, f\"{name}: {r.error}\"") # ---- WRITE BODY FUNCTIONS ---- # Build the full file: header + helpers + body functions + scenarios + fixture/test header = "\n".join(lines) body_funcs = [] for name, blines in bodies.items(): body_funcs.append(f"async def _body_{name}(k, symbol, p):") for bl in blines: body_funcs.append(f" {bl}") body_funcs.append("") full = header + "\n".join(body_funcs) + "\n\n" + header[header.rindex("# =="):] # Actually let me just assemble properly # Split header at the body section comment body_section_header = "# ============================================================\n# SCENARIO BODIES\n# Each receives (k, symbol, p) and exercises a slice of the FSM.\n# ============================================================\n\n" all_body_text = "" for name, blines in bodies.items(): all_body_text += f"async def _body_{name}(k, symbol, p):\n" for bl in blines: if bl.startswith(" "): all_body_text += bl + "\n" else: all_body_text += " " + bl + "\n" all_body_text += "\n" # Find the pre-body section (imports + helpers) body_start_idx = header.index("# SCENARIO BODIES") pre_body = header full_text = pre_body + all_body_text + """ # ============================================================ # SCENARIOS # ============================================================ SCENARIOS = [ """ + "\n".join([f' pytest.param("{n}", _body_{n}, id="{n}"),' for n in sorted(bodies.keys())]) + """ ] @pytest.fixture(scope="session") def _live_client(): return BingxHttpClient(_build_config()) @pytest.mark.parametrize("name,body_fn", SCENARIOS) def test_pink_ditav2(_live_client, name, body_fn) -> None: bundle = _build_rb() ic = bundle.runtime.kernel.account.snapshot.capital r = asyncio.run(_run(bundle, _live_client, body_fn, name, ic)) assert r.positions_flat, f"{name}: {r.error}" """ with open(fpath, 'w') as f: f.write(full_text) import py_compile try: py_compile.compile(fpath, doraise=True) print(f"Compiles OK. {len(bodies)} scenarios") except py_compile.PyCompileError as e: print(f"Compile error: {e}") # Show the broken area import traceback traceback.print_exc()