Skip to content
Merged
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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ The point of this project is the enforcement machinery and the honest measuremen
runs through it, not a claim of alpha. A visitor who finds that out themselves feels misled;
one who is told upfront can read it as rigour.

<!-- fee-reality-capture:begin -- generated by scripts/render_fee_reality_cast.py; do not edit -->
<p align="center">
<img src="docs/assets/fee-reality.svg" alt="A terminal running scripts/render_fee_reality.py: the fee-reality benchmark, rendered from keel's hash-chained trials ledger — four assets profitable with the fee removed, none of them profitable at the 1.2% taker fee actually charged." width="800">
</p>

<sub>A real run of `python scripts/render_fee_reality.py`, captured by
`scripts/render_fee_reality_cast.py` and regenerated whenever the measurement moves. Every figure
in it is read from [`docs/experiments/trials-ledger.jsonl`](docs/experiments/trials-ledger.jsonl),
the hash-chained record of what was actually run — none is typed by hand. The pacing is composed;
the output is not.</sub>
<!-- fee-reality-capture:end -->

<!-- fee-reality:begin -- generated by scripts/render_fee_reality.py; do not edit -->

### The benchmark: the same rule, priced twice
Expand Down
109 changes: 109 additions & 0 deletions docs/assets/fee-reality.cast
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{"env": {"TERM": "xterm-256color"}, "height": 34, "title": "keel \u00b7 fee-reality benchmark \u00b7 Coinbase taker 1.2% \u00b7 rendered from the trials ledger", "version": 2, "width": 92}
[0.0, "o", "\u001b[90m# keel \u00b7 fee-reality benchmark \u00b7 Coinbase taker 1.2% \u00b7 rendered from the trials ledger\u001b[0m\r\n"]
[0.35, "o", "$ "]
[0.5, "o", "p"]
[0.555, "o", "y"]
[0.61, "o", "t"]
[0.665, "o", "h"]
[0.72, "o", "o"]
[0.775, "o", "n"]
[0.83, "o", " "]
[0.885, "o", "s"]
[0.94, "o", "c"]
[0.995, "o", "r"]
[1.05, "o", "i"]
[1.105, "o", "p"]
[1.16, "o", "t"]
[1.215, "o", "s"]
[1.27, "o", "/"]
[1.325, "o", "r"]
[1.38, "o", "e"]
[1.435, "o", "n"]
[1.49, "o", "d"]
[1.545, "o", "e"]
[1.6, "o", "r"]
[1.655, "o", "_"]
[1.71, "o", "f"]
[1.765, "o", "e"]
[1.82, "o", "e"]
[1.875, "o", "_"]
[1.93, "o", "r"]
[1.985, "o", "e"]
[2.04, "o", "a"]
[2.095, "o", "l"]
[2.15, "o", "i"]
[2.205, "o", "t"]
[2.26, "o", "y"]
[2.315, "o", "."]
[2.37, "o", "p"]
[2.425, "o", "y"]
[2.48, "o", "\r\n"]
[2.93, "o", "<!-- fee-reality:begin -- generated by scripts/render_fee_reality.py; do not edit -->\r\n"]
[2.99, "o", "\r\n"]
[3.05, "o", "### The benchmark: the same rule, priced twice\r\n"]
[3.11, "o", "\r\n"]
[3.17, "o", "`turtle_breakout` on hourly bars, at each asset's best-swept configuration. The left column is\r\n"]
[3.23, "o", "the number a fee-blind backtest reports. The right is the same run priced at the taker\r\n"]
[3.29, "o", "fee this account actually pays. Nothing else changes between them.\r\n"]
[3.35, "o", "\r\n"]
[3.41, "o", "| asset | trades | PF at 0% fee | PF at 1.2% taker | break-even fee, measured |\r\n"]
[3.47, "o", "| :-- | ---: | ---: | ---: | ---: |\r\n"]
[3.53, "o", "| BTC | 123 | 1.090 | 0.333 | 0.068% |\r\n"]
[3.59, "o", "| ETH | 121 | 1.458 | 0.556 | 0.433% |\r\n"]
[3.65, "o", "| SOL | 92 | 1.533 | 0.801 | 0.751% |\r\n"]
[3.71, "o", "| ZEC | 50 | 2.713 | 1.303 | 1.741% |\r\n"]
[3.77, "o", "\r\n"]
[3.83, "o", "Four of four are profitable with the fee removed. **Zero of four survive the fee that is\r\n"]
[3.89, "o", "actually charged**, and the break-even rate varies by a factor of ~26 across assets\r\n"]
[3.95, "o", "running the same rule on the same clock over the same window \u2014 the asset is a far larger\r\n"]
[4.01, "o", "lever than any parameter in an 864-trial sweep.\r\n"]
[4.07, "o", "\r\n"]
[4.13, "o", "**Read these as a comparison, never as edge estimates.** Every configuration above is the\r\n"]
[4.19, "o", "argmax of that asset's 144-cell slice, selected on the same data it is re-priced on \u2014 a\r\n"]
[4.25, "o", "maximum of 144 draws, not an expectation. The bias runs *against* the finding, which is\r\n"]
[4.31, "o", "why the comparison survives it: it inflates the arm that wins with the fee removed, and\r\n"]
[4.37, "o", "that arm still dies when the fee is charged. Break-even fees were bracketed by real\r\n"]
[4.43, "o", "cells,not interpolated. Slippage is held at 0.0005 in every cell, so the zero column is\r\n"]
[4.49, "o", "zero *fee*, not zero cost.\r\n"]
[4.55, "o", "\r\n"]
[4.61, "o", "Source: [`docs/experiments/2026-08-12-fee-curve-and-rsi-meanrev.md`](docs/experiments/2026-08-12-fee-curve-and-rsi-meanrev.md), rendered from the hash-chained trials ledger by\r\n"]
[4.67, "o", "`scripts/render_fee_reality.py`.\r\n"]
[4.73, "o", "\r\n"]
[4.79, "o", "<!-- fee-reality:end -->\r\n"]
[4.85, "o", "\r\n"]
[4.91, "o", "<!-- cost-distortion:begin -- generated by scripts/render_fee_reality.py; do not edit -->\r\n"]
[4.97, "o", "\r\n"]
[5.03, "o", "### We mis-priced our own execution by more than any strategy change we ever made\r\n"]
[5.09, "o", "\r\n"]
[5.15, "o", "Every backtest in this repository used to price fills at the **floor** of its own slippage model\r\n"]
[5.21, "o", "\u2014 the best case the model can produce, reached only at a $500M/day anchor. Measured against the\r\n"]
[5.27, "o", "24 assets keel actually holds candles for, **0 of 24 reach it**: the range runs from 1.1\u00d7 the\r\n"]
[5.33, "o", "floor at the most liquid to 36.8\u00d7 at the thinnest.\r\n"]
[5.39, "o", "\r\n"]
[5.45, "o", "Re-pricing every rule per product \u2014 5 rules, 24 assets, 240 trials \u2014 moved the median profit\r\n"]
[5.51, "o", "factor across 120 cells from **0.309** to **0.219**. The one cell that had cleared 1.0 no longer\r\n"]
[5.57, "o", "does.\r\n"]
[5.63, "o", "\r\n"]
[5.69, "o", "| | profit factor |\r\n"]
[5.75, "o", "| :-- | --: |\r\n"]
[5.81, "o", "| the cost-model correction | **-0.090** |\r\n"]
[5.87, "o", "| the best strategy improvement we have measured | **+0.033** |\r\n"]
[5.93, "o", "\r\n"]
[5.99, "o", "The error in how we priced execution was **2.7\u00d7 larger** than the largest genuine gain any\r\n"]
[6.05, "o", "change to the strategy itself produced \u2014 a better exit, measured against the same entry on the\r\n"]
[6.11, "o", "same universe. For as long as that was true, comparing strategies meant comparing them through a\r\n"]
[6.17, "o", "lens distorted by more than the differences being compared.\r\n"]
[6.23, "o", "\r\n"]
[6.29, "o", "**What this is and is not.** It is keel mis-pricing keel, on one venue, over one universe of\r\n"]
[6.35, "o", "cached candles \u2014 found, corrected and published. It is not a claim about any other framework's\r\n"]
[6.41, "o", "assumptions: we have not measured those, and an unsourced claim about someone else would be the\r\n"]
[6.47, "o", "exact failure this section exists to avoid making about ourselves.\r\n"]
[6.53, "o", "\r\n"]
[6.59, "o", "**Where the friction actually is.** Two taker legs cost 2.4% of notional before a basis point of\r\n"]
[6.65, "o", "slippage is counted, so on the most liquid asset the fee is the overwhelming majority of the\r\n"]
[6.71, "o", "round trip and only at the thin end does slippage overtake it. A cheaper venue matters more than\r\n"]
[6.77, "o", "a better model of the book \u2014 and an honest model of the book is what tells you that.\r\n"]
[6.83, "o", "\r\n"]
[6.89, "o", "Source: [`docs/experiments/2026-09-01-per-product-slippage-restatement.md`](docs/experiments/2026-09-01-per-product-slippage-restatement.md), rendered from the hash-chained trials ledger by `scripts/render_fee_reality.py`.\r\n"]
[6.95, "o", "\r\n"]
[7.01, "o", "<!-- cost-distortion:end -->\r\n"]
Loading
Loading