Skip to content

docs(readme): lead with the fee-reality benchmark, rendered from the ledger (#646, partial) - #679

Merged
eaitbrahim merged 1 commit into
mainfrom
feat-646-fee-reality
Sep 1, 2026
Merged

docs(readme): lead with the fee-reality benchmark, rendered from the ledger (#646, partial)#679
eaitbrahim merged 1 commit into
mainfrom
feat-646-fee-reality

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

Partial. #646 also asks for a ~10-second terminal capture of a real run with committed generation tooling. That is unbuilt and the issue stays open for it. This is the numbers half — and the half a GIF would have to agree with.

The README already stated the honest result in prose. #646 asks for it as numbers: the same rule priced twice, before the feature list.

asset trades PF at 0% fee PF at 1.2% taker break-even fee, measured
BTC 123 1.090 0.333 0.068%
ETH 121 1.458 0.556 0.433%
SOL 92 1.533 0.801 0.751%
ZEC 50 2.713 1.303 1.741%

Four of four profitable with the fee removed. Zero of four survive the fee actually charged. Break-even spans 0.068% to 1.741% — a factor of ~26 across four assets running the same rule on the same clock over the same window.

Rendered, never typed

That is the issue's binding constraint, not a nicety. Every figure is read out of docs/experiments/trials-ledger.jsonl — the hash-chained record of what was actually run — by scripts/render_fee_reality.py and reformatted. A hand-typed benchmark would be a marketing claim wearing a measurement's clothes, in the one block whose entire argument is the difference between those two.

tests/test_fee_reality_block.py fails if the README and the renderer disagree, and separately asserts that every number in the block appears in the ledger row — stronger than "the renderer produced it", because a renderer with a literal baked in would satisfy the drift pin with both sides carrying the same invention.

The caveats travel with the numbers

Pinned by a test, because dropping them would make the block a stronger claim than the measurement supports:

  • Every configuration is the argmax of its asset's 144-cell slice, selected on the same data it is re-priced on. Maxima of 144 draws, not edge estimates — the ledger's selection_bias field says so at full strength.
  • The bias runs against the finding, which is why the comparison survives it: it inflates the arm that wins with the fee removed, and that arm still dies when the fee is charged.
  • Slippage is held at 0.0005 in every cell, so the zero column is zero fee, not zero cost.

Parsing prose is deliberate

The ledger stores the curve as a recorded sentence, because that row was written by the experiment that produced it, and rewriting history to suit a renderer would be the tail wagging the dog. So the parser is strict and every recognition failure is fatal — a parse that silently produced three of four assets would be the quiet half-truth this block exists to refuse.

Two bugs the tests found in the renderer's own output:

Verification

9 mutants, 9 killed — and the last took three attempts to write. The column-count guard sat behind the missing-break-even guard, so every input meant to reach it tripped the earlier one instead, and the mutation survived while the test looked like it pinned something.

Full suite 5135 passed / 3 skipped; ruff and mypy clean.

…ledger (#646, partial)

The README already stated the honest result in prose -- "no shipped rule family is
net-positive at the taker fee actually paid". #646 asks for it as NUMBERS: the
same rule priced twice, fee-blind and then honestly, before the feature list.

RENDERED, NEVER TYPED, and that is the issue's binding constraint rather than a
nicety. Every figure is read out of `docs/experiments/trials-ledger.jsonl` -- the
hash-chained record of what was actually run -- by `scripts/render_fee_reality.py`
and reformatted. A hand-typed benchmark would be a marketing claim wearing a
measurement's clothes, in the one block whose entire argument is the difference
between those two.

The result, from the fee-curve row of `fee-curve-and-rsi-meanrev-2026-08-12`:
four of four assets profitable with the fee removed, ZERO of four surviving the
1.2% taker actually charged, and break-even fees spanning 0.068% (BTC) to 1.741%
(ZEC) -- a factor of ~26 across four assets running the same rule on the same
clock over the same window.

THE CAVEATS TRAVEL WITH THE NUMBERS, and a test pins that they do. Every
configuration is the argmax of its asset's 144-cell slice, selected on the same
data it is re-priced on -- maxima of 144 draws, not edge estimates, and the
ledger's `selection_bias` field says so at full strength. Quoting them as an
asset's expected profit factor is exactly what the experiment record forbids.
The bias runs AGAINST the finding, which is why the comparison survives it: it
inflates the arm that wins with the fee removed, and that arm still dies when the
fee is charged. Slippage is held at 0.0005 in every cell, so the zero column is
zero FEE and not zero cost.

PARSING PROSE IS DELIBERATE. The ledger stores the curve as a recorded sentence,
because that row was written by the experiment that produced it and rewriting
history to suit a renderer would be the tail wagging the dog. So the parser is
strict and every recognition failure is fatal -- a parse that silently produced
three of four assets would be the quiet half-truth this block exists to refuse.

Two bugs the tests found in the renderer's own output, both worth recording:
`[\d.]+` is greedy enough to swallow the SENTENCE'S full stop into the last
asset's profit factor, and "1.303." is still readable, still wrong, and would
have shipped inside a table. And the fee columns rendered as raw fractions
("PF at 0.012") -- making the reader perform the conversion that produced #247's
costing error in the first place.

9 mutants, 9 killed, and the last took three attempts to write. The column-count
guard sat behind the missing-break-even guard, so every input meant to reach it
tripped the earlier one instead and the mutation survived while looking pinned.

NOT DONE: the terminal capture. #646 also asks for a ~10-second GIF of a real
run with committed generation tooling; that is unbuilt and the issue stays open
for it. What is here is the numbers half, and the half a GIF would have to agree
with.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL
@eaitbrahim eaitbrahim self-assigned this Sep 1, 2026
@eaitbrahim
eaitbrahim merged commit c010985 into main Sep 1, 2026
4 checks passed
@eaitbrahim
eaitbrahim deleted the feat-646-fee-reality branch September 1, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant