BL-IN-002: Gross, Not Net
BIJECTIVE LABS
BL-IN-002: Gross, Not Net
Status: RELEASED
Classification: PUBLIC
Revision: 1
Date: 2026-09-07
Incident date: 2026-06-07 Class: K1, a cost term absent from the measurement path Rule produced: R-01
1. What was believed
By early June the programme had produced a series of verdicts. One of them read: T1.5, marginal pass, expected value +1.38 basis points per trade at a 7 basis point fee.
That figure had been used to justify continuing a line of work. The strategies looked marginal rather than broken, which supported the prevailing theory that the problem was either signal quality or instrument selection, and that better work on either would eventually push a strategy into positive territory.
Nobody suspected the measurement.
2. The trigger
The question came from outside the engineering track, and it was the right question:
Is it our strategy that cannot beat costs, or is there a gap in our code that makes every strategy fail?
That is a question about the measurement rather than about the market, and it had not been asked before.
3. The investigation
Six steps, one day.
Grep the shadow-tracking code for any fee, cost, or spread term. Zero matches.
Read the realised profit and loss function directly.
Recompute the historical T1.5 verdict with the missing terms restored.
Pull the stored shadow trades and re-tabulate them layer by layer.
Check the universe selector for a spread gate. There was none.
Confirm the data source was live mainnet rather than a demo feed, so that the spread figures being used were real.
4. The finding
The realised return function computed this:
realized_bps = (exit_mid - entry_mid) / entry_mid * 10000 * directionMid price at exit, minus mid price at entry, expressed in basis points. No fee. No spread. No slippage. No funding.
Every strategy verdict the programme had issued was a gross number wearing the label of a net one.
Restoring the terms to the T1.5 verdict:
| Term | Value |
|---|---|
| Fee assumed in the original verdict | 7.0 bps |
| Actual taker round trip, 0.055 pct per side | 11.0 bps |
| Fee understatement | 4.0 bps |
| Spread, unmodelled entirely | approximately 3.0 bps |
| Reported expected value | +1.38 bps |
| Corrected expected value | -5.6 bps |
The strategy was not marginal. It was negative by a wide margin, and had been the whole time.
A layer-by-layer tabulation of 28 stored shadow trades shows the shape of the error. The sample is too small to carry a verdict and is reproduced here only because it demonstrates the method:
| Layer | Mean realised |
|---|---|
| Gross, as the shadow tracker reported it | +24.76 bps |
| Less fee at 11.0 bps | +13.76 bps |
| Less fee and full spread at 2.99 bps | +10.77 bps |
Fourteen basis points of the reported figure were costs that had never been subtracted.
5. Why it survived review
Three things kept it invisible.
The variable was named realized_bps. Realised, in trading, means after the
fact and after costs. The name asserted a property the code did not implement,
and every reader downstream inherited the assertion.
The number was plausible. A gross mid-to-mid return on a short-horizon microstructure strategy produces figures in the same range a net return would occupy if the strategy were working. Nothing looked absurd.
The failure was uniform. Because every strategy was measured the same way, the comparisons between them were internally consistent. The programme could rank strategies correctly against each other while being wrong about all of them in the same direction.
That third property is the one worth carrying away. A systematic measurement error does not present as noise. It presents as a coherent world in which everything is slightly disappointing.
6. What it cost
Not quantified in the archive, and the honest answer is that it cannot be.
Every verdict issued before 2026-06-07 was computed gross. That does not mean every verdict was wrong; most of the strategies were negative enough that costs would not have saved them. It means no verdict from that period can be trusted without recomputation, and the programme treated them accordingly.
No capital was at risk. Everything in that window was shadow.
7. The fix
The strategy logic itself was independently re-verified and found correct. The take-profit, stop, confluence, and cooldown paths all did what they claimed. The defect was entirely in measurement.
Five actions came out of it, in the order they were ranked:
- Build a net analyser for shadow trades, and convert every existing verdict from gross to net.
- Add a maximum spread gate to universe selection.
- Reduce the universe rotation interval from 24 hours to four to six.
- Only after net expectation is shown at or above breakeven, revisit the frequency caps and measure net expectation multiplied by frequency.
- Remain in shadow against live mainnet data until net expectation is positive on at least 500 trades.
Item four is worth noting for what it declines to do. There was an argument on the table that if per-trade edge were genuinely positive, the frequency caps should be removed rather than tightened, which is correct as arithmetic. The response was to make that action conditional on the net measurement landing first. Sequencing a correct argument behind a measurement it depends on is the discipline this incident produced.
8. The rule
What was wrong is that we judged viability from the gross number. From now on every verdict must be net.
This became R-01, the first rule in the register, and the cost identity in
BL-D-011 section 4 is its formal statement. Every figure in this record is net
of fee, spread, slippage, and funding accrual where the position spans a
settlement, and every gross figure is labelled as gross.
9. What the source does not settle
The decision record cites the defective function at lines 100 to 103 of the strategy source. In the current repository the same computation sits at lines 106 to 110, unchanged in logic. The file has shifted since the record was written, and no commit hash is given, so the exact change that introduced the omission cannot be pinned from the document alone.
The 28-trade tabulation is explicitly labelled as too small for a verdict, and no later document confirms whether the 500-trade net-positive threshold in action five was ever reached. On the evidence of the Kill Ledger, it was not.
10. Cross-references
BL-D-011 section 4, the cost identity. BL-D-004 section 2.1. BL-D-009
rule R-01. BL-D-010 section 2.4. Ledger rows T1.5, DA-B, PS-A.
Copyright (c) 2026 Bijective Labs. All rights reserved.