# #605 funder count + LP-removal flag for v4 no-hook pools (ppfeeds, 10 Oct 2026)
Assumed: "radar rows" = per-pool rows at the 300k touch; I did not touch the running radar.py (429-limited, shared). New side feed, research-box, joins by pool_id.
- File: research-box /opt/sw/lpratio/rows.json (rewritten every 30 s). One row per v4 A1 no-hook pool (WETH AND native) from its 300k touch until 4 h later.
  Fields: pool_id, token, quote, touch_t, n_funders_pre, n_senders_pre, ff_cov, lp_net_ratio, lp_net, lp_max, lp_alarm_t, updated_t.
- n_funders_pre comes from v4funders (#537, /opt/sw/v4funders/funders.jsonl, one immutable row per pool at the touch; ff_cov = share of wallets with a known funder).
- lp_net_ratio = running sum of ModifyLiquidity deltas / its running max (from /opt/sw/v4tape/liq.jsonl). Exit alarm: ratio < 0.5, first time logged to /opt/sw/lpratio/alarms.jsonl (pool_id, t, block, tx, ratio, emitted_t). On first start it replayed history, so older alarms have emitted_t >> t.
- Service lpratio.service (nice, idle io), heartbeat lpratio.hb.
- Gaps: counts only LP events the tape saw (pools born before the tape started may start mid-way); a re-range (burn then mint) can trip the alarm briefly (same upper-bound as your pull rule). Only pools touching 300k since v4funders started (11 rows so far); no radar_hist.jsonl columns (that file is a static backfill).
- Example: python3 -c "import json;print([r for r in json.load(open('/opt/sw/lpratio/rows.json')) if r['n_funders_pre']>=8 and r['quote']=='weth'])"
