Download tests/test_custom_pools.py from bryceweiner/fly-trader: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/bryceweiner/fly-trader/resolve/main/tests/test_custom_pools.py
- Command line
-
hf download hf://bryceweiner/fly-trader/tests/test_custom_pools.py
-
curl -L -o test_custom_pools.py https://huggingface.co/bryceweiner/fly-trader/resolve/main/tests/test_custom_pools.py
12.1 kB
| """Directly created (custom) PumpSwap pools are excluded from the universe: live stream, training aggregates, archive backfill.""" | |
| from datetime import date, datetime, timezone | |
| import pyarrow as pa | |
| import pyarrow.parquet as pq | |
| from fly_trader import config | |
| from fly_trader.ingest import pumpstream | |
| from fly_trader.train import corpus_meta, mature | |
| WSOL = pumpstream.WSOL | |
| def _leg(mint, ts_ms, price, pool_id, action="buy"): | |
| return {"action": action, "pool": "pump-amm", "mint": mint, "timestamp": ts_ms, "price": price, "quoteMint": WSOL, "quoteInPool": 80.0, | |
| "txSigner": "t", "breakdown": [{"action": action, "trader": "t", "quoteAmount": 1.0, "tokenAmount": 1.0}], "poolId": pool_id} | |
| def _create_pool(mint, ts_ms, pool_id, by="custom"): | |
| e = {"action": "createPool", "pool": "pump-amm", "mint": mint, "timestamp": ts_ms, "poolId": pool_id, "quoteMint": WSOL} | |
| if by is not None: | |
| e["poolCreatedBy"] = by | |
| return e | |
| def test_stream_drops_custom_pool_legs(db_conn): | |
| agg = pumpstream.Aggregator(); m = 1_800_000_000 | |
| agg.ingest(_leg("Apump", (m + 1) * 1000, 1.0, "MIGRATED")) # a migrated pool (no createPool here): kept | |
| agg.ingest(_create_pool("Bpump", (m + 2) * 1000, "CUSTOM_T1")) | |
| agg.ingest(_create_pool("Cpump", (m + 2) * 1000, "CUSTOM_T2", by=None)) # missing poolCreatedBy counts as custom | |
| agg.ingest(_create_pool("Dpump", (m + 2) * 1000, "MIGR_T3", by="pump")) # created by a pump.fun migration: not blocked | |
| for pid, mint in (("CUSTOM_T1", "Bpump"), ("CUSTOM_T2", "Cpump"), ("MIGR_T3", "Dpump"), ("MIGRATED", "Apump")): | |
| agg.ingest(_leg(mint, (m + 5) * 1000, 1.0, pid)); agg.ingest(_leg(mint, (m + 6) * 1000, 1.0, pid, "sell")) | |
| assert agg.blocked == {"CUSTOM_T1", "CUSTOM_T2"} and agg.stats["dropped_custom_pool"] == 4 | |
| assert set(agg.minutes[m]) == {"Apump", "Dpump"} and agg.row(m, "Apump").nb == 2 | |
| try: | |
| assert agg.write_pools() == 2 and agg.pending_pools == [] | |
| rows = db_conn.execute("SELECT pool_id, mint, created_by, source, ts FROM pump_pools WHERE pool_id LIKE 'CUSTOM_T%' ORDER BY 1").fetchall() | |
| assert [(r["pool_id"], r["mint"], r["created_by"], r["source"]) for r in rows] == [("CUSTOM_T1", "Bpump", "custom", "stream"), ("CUSTOM_T2", "Cpump", None, "stream")] | |
| assert rows[0]["ts"] == datetime.fromtimestamp(m + 2, timezone.utc) | |
| finally: | |
| db_conn.execute("DELETE FROM pump_pools WHERE pool_id LIKE 'CUSTOM_T%'"); db_conn.commit() | |
| def test_stream_loads_blocked_set(db_conn): | |
| db_conn.execute("INSERT INTO pump_pools (pool_id, mint, created_by, source) VALUES ('LOAD_T1', 'Lpump', 'custom', 'archive'), ('LOAD_T2', 'Lother', 'custom', 'archive') " | |
| "ON CONFLICT DO NOTHING"); db_conn.commit() | |
| try: | |
| agg = pumpstream.Aggregator(); pumpstream._load_blocked(agg) | |
| assert "LOAD_T1" in agg.blocked and "LOAD_T2" not in agg.blocked # a mint that is not pump.fun's never reaches the pool check | |
| agg.ingest(_leg("Lpump", 1_800_000_001_000, 1.0, "LOAD_T1")) | |
| assert agg.stats["dropped_custom_pool"] == 1 and not agg.minutes | |
| finally: | |
| db_conn.execute("DELETE FROM pump_pools WHERE pool_id LIKE 'LOAD_T%'"); db_conn.commit() | |
| def test_aggregate_day_excludes_custom_pools(db_conn, tmp_path, monkeypatch): | |
| d = date(2031, 1, 1); t0 = datetime(2031, 1, 1, tzinfo=timezone.utc).timestamp() | |
| rows = [] | |
| for k in range(3): # GOOD: minutes 0..2; AGG_BAD (custom) minutes 5..7 for the same mint, and a mint only in AGG_BAD | |
| rows.append(("Xpump", t0 + 60 * k + 1, "GOOD", 1.0)); rows.append(("Xpump", t0 + 60 * (5 + k) + 1, "AGG_BAD", 1.5)); rows.append(("Ypump", t0 + 60 * k + 1, "AGG_BAD", 2.0)) | |
| tab = pa.table({"ts": pa.array([datetime.fromtimestamp(r[1], timezone.utc) for r in rows], pa.timestamp("ms", tz="UTC")), "slot": pa.array(range(len(rows)), pa.int64()), | |
| "pool": ["pump-amm"] * len(rows), "mint": [r[0] for r in rows], "trader": ["t"] * len(rows), "side": pa.array([1] * len(rows), pa.int8()), | |
| "sol": [1.0] * len(rows), "price": [r[3] for r in rows], "quote_in_pool": [80.0] * len(rows), "quote_mint": [WSOL] * len(rows), | |
| "pool_id": [r[2] for r in rows]}) | |
| (tmp_path / "replay" / d.isoformat()).mkdir(parents=True) | |
| pq.write_table(tab, tmp_path / "replay" / d.isoformat() / "00_trades.parquet") | |
| monkeypatch.setattr(config, "REPLAY_DIR", tmp_path / "replay"); monkeypatch.setattr(mature, "MATURE_DIR", tmp_path / "mature") | |
| db_conn.execute("INSERT INTO pump_pools (pool_id, mint, created_by, source) VALUES ('AGG_BAD', 'Ypump', 'custom', 'archive') ON CONFLICT DO NOTHING"); db_conn.commit() | |
| try: | |
| assert mature.aggregate_day(d) == 3 | |
| out = pq.read_table(tmp_path / "mature" / f"{d.isoformat()}.parquet").to_pandas() | |
| assert set(out["mint"]) == {"Xpump"} and (out["close"] == 1.0).all() and len(out) == 3 | |
| assert mature.part_version(tmp_path / "mature" / f"{d.isoformat()}.parquet") == mature.AGG_VERSION == 5 | |
| finally: | |
| db_conn.execute("DELETE FROM pump_pools WHERE pool_id = 'AGG_BAD'"); db_conn.execute("DELETE FROM mature_days WHERE day = %s", (d,)); db_conn.commit() | |
| def test_archive_backfill_idempotent(db_conn, tmp_path, monkeypatch): | |
| day = tmp_path / "replay" / "2031-01-02"; day.mkdir(parents=True) | |
| t = lambda s: datetime(2031, 1, 2, 0, 0, s, tzinfo=timezone.utc) | |
| ev = pa.table({"ts": pa.array([t(5), t(1), t(2), t(3), t(4)], pa.timestamp("ms", tz="UTC")), "sig": ["s1", "s2", "s3", "s4", "s5"], | |
| "action": ["createPool", "createPool", "createPool", "migrate", "createPool"], "pool": ["pump-amm", "pump-amm", "pump-amm", "pump-amm", "raydium-cpmm"], | |
| "mint": ["Apump", "Apump", "Bpump", "Cpump", "Dpump"], "pool_id": ["BF_C1", "BF_C1", "BF_C2", "BF_M1", "BF_R1"], | |
| "pool_created_by": ["custom", "custom", None, "pump", "custom"]}) | |
| pq.write_table(ev, day / "00_events.parquet") | |
| monkeypatch.setattr(config, "REPLAY_DIR", tmp_path / "replay") | |
| db_conn.execute("DELETE FROM ui_settings WHERE key = 'pump_pools_backfill'"); db_conn.execute("DELETE FROM pump_pools WHERE pool_id LIKE 'BF_%'"); db_conn.commit() | |
| try: | |
| assert corpus_meta.backfill_pump_pools() == 2 | |
| assert corpus_meta.backfill_pump_pools() == 0 # re-run: nothing new | |
| rows = db_conn.execute("SELECT pool_id, mint, created_by, ts, source FROM pump_pools WHERE pool_id LIKE 'BF_%' ORDER BY 1").fetchall() | |
| assert [(r["pool_id"], r["mint"], r["created_by"], r["source"]) for r in rows] == [("BF_C1", "Apump", "custom", "archive"), ("BF_C2", "Bpump", None, "archive")] | |
| assert rows[0]["ts"] == t(1) # the pool's first createPool | |
| assert "BF_C1" in corpus_meta.blocked_pool_ids(db_conn) | |
| finally: | |
| db_conn.execute("DELETE FROM ui_settings WHERE key = 'pump_pools_backfill'"); db_conn.execute("DELETE FROM pump_pools WHERE pool_id LIKE 'BF_%'"); db_conn.commit() | |
| def test_stream_keeps_pumpfun_graduates_without_the_suffix(monkeypatch): | |
| """A pump.fun graduate whose mint lacks the "pump" suffix is a universe coin once its migration is seen; any other | |
| mint without the suffix is not.""" | |
| agg = pumpstream.Aggregator(); m = 1_800_000_000 | |
| monkeypatch.setattr(agg, "write_creates", lambda: 0); monkeypatch.setattr(agg, "_graduation", lambda e: None) | |
| agg.ingest({"action": "migrate", "pool": "pump-amm", "mint": "GradNoSuffix", "timestamp": (m + 1) * 1000, "poolId": "GRAD_POOL", "signature": "g1"}) | |
| assert agg.pumpfun("GradNoSuffix") and agg.pumpfun("Apump") and not agg.pumpfun("OtherNoSuffix") | |
| for mint, pid in (("GradNoSuffix", "GRAD_POOL"), ("OtherNoSuffix", "OTHER_POOL")): | |
| agg.ingest(_leg(mint, (m + 5) * 1000, 1.0, pid)) | |
| assert set(agg.minutes[m]) == {"GradNoSuffix"} | |
| def test_stream_loads_graduates_without_the_suffix(db_conn): | |
| db_conn.execute("INSERT INTO corpus_meta (mint, graduated_at) VALUES ('GradLoadNoSuffix', now()) ON CONFLICT DO NOTHING") | |
| db_conn.execute("INSERT INTO pump_pools (pool_id, mint, created_by, source) VALUES ('LOAD_G1', 'GradLoadNoSuffix', 'custom', 'archive') ON CONFLICT DO NOTHING") | |
| db_conn.commit() | |
| try: | |
| agg = pumpstream.Aggregator(); pumpstream._load_blocked(agg) | |
| assert "GradLoadNoSuffix" in agg.grads and "LOAD_G1" in agg.blocked # its custom pools are blocked like any universe coin's | |
| agg.ingest(_leg("GradLoadNoSuffix", 1_800_000_001_000, 1.0, "LOAD_G1")) | |
| assert agg.stats["dropped_custom_pool"] == 1 and not agg.minutes | |
| finally: | |
| db_conn.execute("DELETE FROM pump_pools WHERE pool_id = 'LOAD_G1'"); db_conn.execute("DELETE FROM corpus_meta WHERE mint = 'GradLoadNoSuffix'") | |
| db_conn.commit() | |
| def test_aggregate_day_includes_pumpfun_graduates_without_the_suffix(db_conn, tmp_path, monkeypatch): | |
| d = date(2031, 1, 3); t0 = datetime(2031, 1, 3, tzinfo=timezone.utc).timestamp() | |
| rows = [(mint, t0 + 60 * k + 1, pid) for k in range(3) for mint, pid in (("Xpump", "P_X"), ("GradAggNoSuffix", "P_G"), ("OtherAggNoSuffix", "P_O"))] | |
| tab = pa.table({"ts": pa.array([datetime.fromtimestamp(r[1], timezone.utc) for r in rows], pa.timestamp("ms", tz="UTC")), "slot": pa.array(range(len(rows)), pa.int64()), | |
| "pool": ["pump-amm"] * len(rows), "mint": [r[0] for r in rows], "trader": ["t"] * len(rows), "side": pa.array([1] * len(rows), pa.int8()), | |
| "sol": [1.0] * len(rows), "price": [1.0] * len(rows), "quote_in_pool": [80.0] * len(rows), "quote_mint": [WSOL] * len(rows), | |
| "pool_id": [r[2] for r in rows]}) | |
| (tmp_path / "replay" / d.isoformat()).mkdir(parents=True) | |
| pq.write_table(tab, tmp_path / "replay" / d.isoformat() / "00_trades.parquet") | |
| monkeypatch.setattr(config, "REPLAY_DIR", tmp_path / "replay"); monkeypatch.setattr(mature, "MATURE_DIR", tmp_path / "mature") | |
| db_conn.execute("INSERT INTO corpus_meta (mint, graduated_at) VALUES ('GradAggNoSuffix', now()) ON CONFLICT DO NOTHING"); db_conn.commit() | |
| try: | |
| assert mature.aggregate_day(d) == 6 | |
| out = pq.read_table(tmp_path / "mature" / f"{d.isoformat()}.parquet").to_pandas() | |
| assert set(out["mint"]) == {"Xpump", "GradAggNoSuffix"} # a mint pump.fun never graduated stays out | |
| finally: | |
| db_conn.execute("DELETE FROM corpus_meta WHERE mint = 'GradAggNoSuffix'"); db_conn.execute("DELETE FROM mature_days WHERE day = %s", (d,)); db_conn.commit() | |
| def test_corpus_versions_never_retire_a_model(): | |
| """The corpus build versions say when the files are rebuilt, not what a model means: a selector, fly or replay verdict | |
| that still carries them (every one trained before 2026-10-23 does) stays current, so a rebuild retires nothing; a | |
| changed, missing or extra definition still does (fly #251's ``distil`` must not make it the live fly).""" | |
| from fly_trader.train import fly_replay, fly_selector, selector | |
| assert "agg" not in selector.DATA_VERSION and "rh_agg" not in selector.DATA_VERSION | |
| old = {**selector.DATA_VERSION, "agg": 4, "rh_agg": 1} | |
| assert selector.is_current({"data": old}) and not selector.is_current({"data": {**old, "features": -1}}) | |
| assert fly_selector.is_current({"data": {**fly_selector.FLY_VERSION, "agg": 4, "rh_agg": 1}}) | |
| assert not fly_selector.is_current({"data": {k: v for k, v in fly_selector.FLY_VERSION.items() if k != "fly"}}) | |
| assert not fly_selector.is_current({"data": {**fly_selector.FLY_VERSION, "agg": 4, "distil": "x"}}) # any other extra key still retires a fly | |
| row = {"value": {"data": {**fly_selector.verdict_version(), "agg": 4, "rh_agg": 1}, "chains": {"rh": {"passed": True}}}} | |
| merged = fly_replay.merge_chains(row, {"data": fly_selector.verdict_version(), "chains": {"sol": {"passed": True}}, "S": "x"}, ("sol",)) | |
| assert set(merged["chains"]) == {"rh", "sol"} and merged["passed"] # the stored verdict's other chain is kept | |