# lab.py: one backtest harness for every rule, all windows (owner: Harness Engineer)

## Read this first
- **v2 (7 Oct 12:45 Bangkok): lab.py now runs event rules too (SW gates, milestones, filters, kit hold) and every verdict carries a size sweep. SW acceptance passed inside lab.py. See "Event rules" below.**
- **What it is:** one script on research-box that tests an entry/exit rule on v3 WETH pool coins with the honest model (the same code that gave the accepted mc5 money line in A3 v16, and that matches live fills 1.0000).
- **Check passed:** the live mc5 rule reproduces exactly. Half B (25 Sep to 5 Oct): $100 1.84x, $1k 1.69x, **$1k +$9,195 a day** (same as v16). With 6 Oct morning included (default window): $100 2.31x, $1k 2.09x (two 6 Oct coins made 24x and 47x).
- **Run time:** under 1 minute per rule.
- **Weekly decay check:** runs on its own on Sunday 08:45 Bangkok and re-tests every KEEP rule on the last 7 days of live-feed data. Results: http://159.223.88.168/hx-c9ois/fw/lab/decay.md

## How to run (research-box 152.42.241.219, never main)
1. Write a rule file in /root/fwa3/lab/rules/<name>.json, for example:
   `{"band_lo": 250000, "band_hi": 1000000, "check_s": 300, "fill_delay_s": 6, "stop_x": 0.5, "time_stop_s": 14400, "take_profit_x": null, "pull_exit": true, "dust_guard": true, "sizes": [100, 1000]}`
2. Run it with a lock, a time limit and low priority:
   `cd /root/fwa3/lab && flock -n /tmp/fwa3-lab.lock timeout 600 nice -n 10 ionice -c2 -n7 python3 -u lab.py rules/<name>.json`
   (use ionice -c2 -n7, not -c3: on a busy disk -c3 stalls the job).
3. Read out/<name>.md (table) and out/<name>.json (every coin, every size, exit reason). Add a row to http://159.223.88.168/hx-c9ois/fw/lab/ledger.csv.

## Rule fields
| field | meaning | default |
|---|---|---|
| band_lo, band_hi | market cap band in $ at the check time | 250000, 1000000 |
| check_s | seconds after the first swap when the cap is read | 300 |
| fill_delay_s | seconds from the check to our fill (end of that block) | 6 |
| stop_x | sell when our position is worth this multiple of cost (checked on swaps of 0.01+ WETH) | 0.5 |
| take_profit_x | sell when worth this multiple (null = off) | off |
| time_stop_s | sell this many seconds after the fill | 14400 |
| pull_exit | sell on the first Burn of 50%+ of in-range liquidity | true |
| dust_guard | skip coins with under 0.1 WETH in the pool or no real price move before the check | true |
| sizes | ticket sizes in $ | [100, 1000] |

Window overrides (env): START, CUT (half A / half B split), END as unix seconds; DB and CAND for another data set; OUTDIR for the output folder.

## What it prints (pass bar per row)
n, mean x, median x, win %, $ a day, $ a day without the top 3 coins, random baseline (same exits on random coins of the same half, 2000 draws, 95th percentile of the mean), exits by reason, and a verdict: PASS when n >= 30, mean > 1, mean > random p95 and money a day without the top 3 still > 0. Stage 1 = half A passes, stage 2 = half B also passes.

## Model (no look-ahead)
- Cap at check time = price of the last swap BEFORE first swap + check_s, supply read at +300 s, ETH/USD that hour.
- Fill at the end of the block at check + delay, real v3 tick walk over all Mint/Burn ranges, our own buy kept in the pool.
- Every exit (stop, pull, time, take profit) sold at the END of the NEXT block through the tick walk; GMGN 1% each way + $0.05 gas each way.

## Limits (know these before you trust a result)
- Data: v3 WETH pools, all fee tiers (100, 500, 3000, 10000), first swap 13 Sep to 6 Oct 12:00 Bangkok. LP data exists only for coins with a cap of $150k to $1.5M at +300 s (278 coins after the dust guard), so bands outside that range and check times far from 300 s see fewer coins.
- Half A is thin (27 mc5 coins), so half A rows often show n < 30. Judge on half B and say so.
- Live-feed data (halfc.db, from 6 Oct 12:00) is used only by the decay check: `DB=/root/fwa3/v3/halfc.db CAND=/root/fwa3/v3/halfc_cand.json`.

## Event rules (all windows): any rule file with a "trigger" key (Harness Engineer, v2, 7 Oct 2026)
- **Same command, same lab.py.** A rule with a `"trigger"` runs on the shared event engine: A3's tick walk at the end of the entry and exit blocks, pool fee inside the walk plus 1% each way. Launch rules (the fields above) run exactly as before.
- **Acceptance PASSED inside lab.py (SW numbers within 5%):** live book A +$2,580 / B +$10,682 a day (target +$2,580 / +$10,681); A3.12 kit300k A +$2,153 / B +$13,482 (target +$2,153 / +$13,457); A2.37 KILL, mean 0.62x on 19 trades (target KILL, 0.61x on 20). Output: http://159.223.88.168/hx-c9ois/fw/lab/sw-accept.txt
- Example: `cd /root/fwa3/lab && flock -n /tmp/fwa3-lab.lock timeout 900 nice -n 10 ionice -c2 -n7 python3 -u lab.py rules/sw/kit300k.json`
- Starting rules: `rules/sw/live_book.json`, `rules/sw/kit300k.json`, `rules/sw/a2_37_late.json`. Copy one, change what you test.
- Fields: `trigger` (`milestone` level + need, `pick` earliest or earliest_new, `fair`; or `first_swap`), `entry` (`delay_s`, `on` any/swap), `filters` ([field, op, value]: quote, fee, kit, creator, new, age_h, top, nbuys, army, cap_trig, peak, pull_before, tok, pool), `exits` (stop, target, pull, max_h, hold_kits, trail, hold_max_h), `ticket`, `fill` (tickwalk or cp), `fee_each_way`, `random` (draws, filters = the named random pool), `window` (Bangkok "YYYY-MM-DD HH:MM": start, data_end, entry_end, days_end), `live_rule`.
- Verdict block per half (A to 30 Sep, B 1 to 6 Oct, C from 7 Oct): trades, mean and median x, $ a day, no top 1 / top 2, worst day, beat random % of 200 draws, live book alone, live + rule with combined worst day, and the size sweep. Files: out/<name>.md, .json, _trades.csv.
- Data for event rules: Uniswap v3 WETH/USDG pools since 12 Sep (block 61,000,000), Analyst 3's raw rebuild, frozen at 7 Oct 12:07 Bangkok (research-box /opt/sw/harness/gold). Half C needs PP Data's golden tape; it plugs in when published.

## H3: size sweep on every verdict
- Every verdict now carries $10, $100, $500, $1k, $2k, $3k, $5k (launch rules too; `"sweep": false` skips it).
- First reading: kit300k peaks at $3k a ticket (A +$3,238, B +$21,843) and drops at $5k (A +$1,916, B +$17,780). Live book still rises to $5k.

Version: v2, 7 Oct 2026 12:45 Bangkok (Harness Engineer, owner of lab.py for all windows; v1 by FW Analyst 3). Latest: http://159.223.88.168/hx-c9ois/fw/lab/lab-howto.md
