Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 6 additions & 133 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ rustls = { version = "0.23", default-features = false, features = ["ring"] }
serde_json = "1"
futures = "0.3"
serde = { version = "1", features = ["derive"] }
simulator-api = { git = "https://github.com/nitro-svm/nitro-stream", rev = "d157f1b9" }
simulator-client = { git = "https://github.com/nitro-svm/nitro-stream", rev = "d157f1b9" }
simulator-api = "0.18.0"
simulator-client = "0.18.0"
solana-account = "4.1.0"
solana-account-decoder = "4.1.0"
solana-address = "2.6.0"
Expand Down
45 changes: 25 additions & 20 deletions src/bin/counterfactual_flow/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ per-hop `ammKey`s in any baseline run's `routePlan`.
## What we measured

The 10,000-slot range above, against **BisonFi** (`8FnX3xo2yYw3EUE6w3nQA4GfXGS9wpK6oj3veJpbFzLo`),
a SOL/USDC prop AMM. The pair carries **14,513** re-quotable swap legs in that window — every
SOL↔USDC swap a supported router placed, not just the ones this venue won.
a SOL/USDC prop AMM. The pair carries **13,615** re-quotable swap legs in that window — every
SOL↔USDC swap an admitted router placed, not just the ones this venue won.

**Fresh, the venue won 1,516 of them. Ten slots slower, it won 2.**
**Fresh, the venue won 1,341 of them. Ten slots slower, it won none.**

| | legs won |
|---|---|
| the venue as it really ran | 1,516 |
| the same venue, 4s slower | 2 |
| the venue as it really ran | 1,341 |
| the same venue, 4s slower | 0 |

Ten slots of staleness costs this venue **99.9%** of the flow it captures. That is one run per
Ten slots of staleness costs this venue **all** of the flow it captures. That is one run per
side; the router is not deterministic, so see [below](#reading-the-output-and-what-not-to-claim)
for how many runs a smaller difference would need.

Expand All @@ -110,26 +110,31 @@ books:

| | legs |
|---|---|
| SOL/USDC legs re-quoted | 14,513 |
| **…that routed through the venue on chain** | **2,595** |
| re-quoted fresh → router picks the venue | 1,516 |
| re-quoted 10 slots stale → router picks the venue | 2 |
| SOL/USDC legs re-quoted | 13,615 |
| **…that routed through the venue on chain** | **2,595** † |
| re-quoted fresh → router picks the venue | 1,341 |
| re-quoted 10 slots stale → router picks the venue | 0 |

† The on-chain figure is carried over from an earlier measurement. The run JSONL records only the
route Metis chose, never the one the original took, so this row cannot be re-derived from the
output of the runs above.

Two things to read here, and the first one bounds what any of this can say.

**This only sees aggregator flow.** Swaps are detected by decoding router instructions — Jupiter,
OKX, Titan and DFlow. A taker hitting your pool directly, through an unsupported aggregator, or via
private flow never enters the sample at all, so the totals here are a slice of your book, not your
book.
OKX, Titan and DFlow — and of those, only the venues the run admits are re-quoted, which is Jupiter
alone unless `--reroute-venues` names more. A taker hitting your pool directly, through an
unsupported aggregator, or via private flow never enters the sample at all, so the totals here are a
slice of your book, not your book.

**The baseline is close to history, but it is not a replay of it.** The venue held 2,595 legs on
chain and the fresh re-quote gives it 1,516 — 58%. It is not the same 58%, either: it keeps 660 of
the legs it really won and takes 856 it did not, because the re-quote runs against a different
router than the one that originally placed each swap, with its own market coverage and quote timing.
Read the baseline as *"what this router would do"*, not *"what happened"*.
**The baseline is close to history, but it is not a replay of it.** The fresh re-quote gives the
venue 1,341 legs against the 2,595 it held on chain — and they are not the same legs, because the
re-quote runs against a different router than the one that originally placed each swap, with its own
market coverage and quote timing. Read the baseline as *"what this router would do"*, not *"what
happened"*.

**Which is why the comparison is baseline-vs-modified, never modified-vs-L1.** Both arms run through
the same router with the same disagreements, so those cancel; what remains is your change. 1,5162
the same router with the same disagreements, so those cancel; what remains is your change. 1,3410
is not a haircut, it is elimination.

## What it means for a maker
Expand Down Expand Up @@ -175,7 +180,7 @@ Rows 1–5 are exact: every way of splitting ten runs into two disjoint arms of
are estimated by resampling, since two disjoint arms of six would need twelve runs.

So a single run is not a precise measurement of *how much* flow moved, even though the example above
separates so far — 1,516 against 2 — that one run per side already carries the direction. If you ever
separates so far — 1,341 against 0 — that one run per side already carries the direction. If you ever
see a minor difference between the baseline and the override, run both sides several times to take
run-to-run variance out of the answer.

Expand Down
Loading