501696cSelf-audit — no external client
ASSAY Karat
One karat for every checkable claim that survives its attack. It does not measure future returns and it certifies nothing: it measures how much of what the strategy claims is still standing after scrutiny.
All 21 karats were contested: the engine's seven attacks ran against the record and the configuration, coverage 7 of 7. Nine survive. That full coverage is not a merit of the record: it is a consequence of H-07. A record with observed exit prices does not allow all seven attacks to run — one of them abstains in the face of real execution, and rightly so — so the ceiling for an honest record is 6 of 7 and 18 karats. WILL 4.0 reaches 7 of 7 because its exits are computed. Measured on 20 August 2026, after this report was issued. The ceiling is 21 and not 24 because the board defines eight roles and the engine covers five: the remaining three require mechanism and pre-registration this material does not contain, and they are not scored as failures — they leave the denominator.
A high karat count without coverage means nothing — it is obtained by not attacking. That is why both figures are always published together. Formula fixed in writing in QUILATES.md before being applied.
With the exit defect corrected, the strategy produces a profit factor below 1 in 12 of 14 pair-window combinations and −489.59 USD aggregated over 353 trades. And the record behind those figures does not describe execution: the exit prices are derived, not observed. Of the 21 karats contested, 9 survive — the figures are reproducible from the files and the declared geometry is internally coherent. Nothing else survives.
The 14 result sets were generated on 2 Aug 2026 between 09:28 and 09:29, two minutes after the exit_logic.py fix was saved. They are not the original run: they are the counterfactual.
Before reading the findings
Everything marked PROVEN ON DISK rests on a file that exists and a command that regenerates it. Everything marked REPORTED comes from the manager's own account and has not been verified in this audit; it appears because it gives context, not because it is demonstrated.
Seven of the auditor's own hypotheses died against the disk during this session, and they are worth writing down because they are the argument for the method:
1. "32 directories in projects/ are 32 research threads with a high cumulative trial count" → false. The weight sits in four directories; the rest are barely used.
2. "The four config_4_0.yaml.bak_* and three exit_logic.py.bak_* files are a parameter sweep" → false. Three backups are byte-for-byte identical; there was a single real change.
3. "The trades.csv header is offset from the rows" → false. 12 fields in both.
4. "The rows with a well-formed date are the signature of the H-01 global stop" → false. All seven are part_a, none part_b.
5. "Grouping by (entry_date, pair) yields the real trades" → false. It returns 398 because it uses the column with no entry data. The correct count is 353.
6. "The bar index reconstructs the date from the same origin in both windows" → false. It gets 410 of 410 right in 2023–2025 and 241 of 241 wrong in 2021–2022, which has a different origin per pair.
7. "The cross-pair correlation of results will resemble the 0.665 of prices and multiply the adjustment by ~2.2" → false. It is 0.043 and 0.088; the adjustment multiplies by 1.12 and 1.24. The attack assumed to be the strongest turned out to be the weakest against this strategy.
And two arithmetic corrections, published rather than buried: the count of rows with the wrong type was first given as 593 and is 651; and it was claimed that H-05 invalidated the counterfactual table, which proved false when measured. A report that does not publish its own errors cannot be audited.
Reconstructed from timestamps · the project uses no version control
The bot directory is not a git repository. Even so, the full working session can be reconstructed from the file system, which is where the real trace survives in most small quantitative projects.
| Time | Artefact | Reading |
|---|---|---|
| 08:55 | config_4_0.yaml.bak_fees | copy taken before touching fees |
| 09:09 | config_4_0.yaml.bak_bt | second configuration copy |
| 09:13 | exit_logic.py.bak_stop | copy before the single real logic change |
| 09:15 | exit_logic.py.bak_sweep | defensive copy — identical to the final file |
| 09:21 | exit_logic.py.bak_rr | defensive copy — identical to the final file |
| 09:27 | exit_logic.py | global stop relocated |
| 09:28–09:29 | 14 × metrics.json + trades.csv | full re-run |
| 09:29 | config_4_0.yaml | final configuration |
ls -l projects/will/core/. Timestamps verified directly for the BTC results in both windows; the rest are assumed to belong to the same batch by proximity of generation and remain to be confirmed file by file.Ten findings · nine proven on disk, one reported
If part_b_active was false, the function returned before evaluating the hard stop. A trade with trend strength below the minimum that never reached target_a had no way to close: it stayed open indefinitely. And since the results record only counts trades with an exit, those never appeared in any computation. The patch's own comment puts the impact at −169 R.
$ diff exit_logic.py.bak_stop exit_logic.py 70,73d69 < # PART B — dynamic stop < if not part_b_active: < return exits if exits else None, position 77a74,85 > # STOP GLOBAL — aplica aunque Part B no esté activa. > # Sin esto, un trade con trend_strength < min y sin tocar target_a > # queda abierto indefinidamente (bug forced_exit -169R). > if not part_a_closed and bar_low <= hard_stop: > exits.append(("part_a", hard_stop)) > exits.append(("part_b", hard_stop)) > return exits, None
projects/will/core/exit_logic.py.bak_stop (09:13).The entry_date column does not hold the entry time: it holds the exit bar index, duplicating the adjacent column. Checked across both windows without a single exception — 410 of 410 rows in 2023–2025 with origin 1 Jan 2023 at 00:00 UTC, and 241 of 241 in 2021–2022 with a single origin per pair, matching each asset's first available bar. In total, 651 of 701 rows have no entry data.
# solve for the implicit origin: origin = exit - index x 1h 2023_2025 origen 2023-01-01 00:00 match=410 fail=0 2021_2022/BTC n= 27 origins=1 → 2021-01-01 06:00 2021_2022/AVAX n= 40 origins=1 → 2021-03-05 10:00 # listing start 2021_2022/SOL n= 4 origins=1 → 2021-08-04 10:00 # listing start
A consequence beyond formatting. Without an entry time, trade duration cannot be computed; without duration there is no time exposure, no real turnover, and no correct funding cost on perpetuals. The execution cost floor depends on annual turnover: on these files, that figure cannot be computed. The data is only recoverable if the original price panel has been kept.
With the H-01 defect already corrected, the strategy loses money in 12 of the 14 pair-window combinations. The two cases above unity support no conclusion: BNB gives 1.008 — indistinguishable from zero — and SOL gives 1.326 over 18 trades, with no statistical power to claim anything.
metrics.json files.The bot directory is not a git repository, so there is no record of how many configurations were tried or in what order. The trace survives indirectly: five major versions in versions/, and 12 oos_trades files in an auxiliary directory with subversions reaching v10 on the same asset and the same out-of-sample window.
This is a crude lower bound on the trial count, not the count. A script may have run once or two hundred times, and an overwritten file leaves no trace. Without that number, the multiple-testing-corrected statistic cannot be computed rigorously — and that, not the sign of the result, is the underlying methodological problem.
$ git log --oneline fatal: not a git repository $ ls versions/ 2_8 3_0 3_3 4_0 will_2_8 $ ls ChatGPT/ | grep -c oos_trades 12 # subversions up to v10, same asset, same sample
Each trade is recorded in two rows, one per position leg (part_a and part_b), and the metrics computation treats every row as an independent trade. Across the 14 files, total_trades equals the row count and never the trade count. The real trades are 353, not the 701 reported.
The two legs of one trade are not independent observations: they share entry, direction and instrument, and the second is the continuation of the first. It is the effective sample size problem applied inside the unit of analysis.
$ for f in */*/trades.csv; do a=$(awk -F, 'NR>1 && $5=="part_a"' "$f" | wc -l) t=$(tail -n +2 "$f" | wc -l) echo "$f part_a=$a rows=$t" done 2023_2025/BTC/trades.csv part_a=52 rows=103 reports=103 2023_2025/ETH/trades.csv part_a=41 rows=81 reports=81 2021_2022/AVAX/trades.csv part_a=21 rows=42 reports=42 ... 14 of 14 report rows, none reports trades
Scope of the effect, measured and not assumed. The profit factor turns out to be insensitive to this aggregation, being a ratio of sums that do not change when grouped: BTC 2023–2025 moves from 0.489 to 0.482 and six of the fourteen do not move at all. The counterfactual table holds. What is inflated is anything that scales with sample size — the t statistic, the Sharpe ratio and any significance test.
Measured factor, adding cross-pair dependence. Rebuilding the daily result series per pair from the exit column, the mean cross-pair result correlation across the seven pairs is 0.043 in 2021–2022 and 0.088 in 2023–2025 — far below the price correlation, because each pair enters and exits at different moments. The resulting design factor is 1.26 and 1.53. Combined with the double counting of legs, the total inflation of the significance statistics is 1.59 in the first window and 1.75 in the second.
part=part_a. Grouping by (entry_date, pair) returns 398 and is wrong, because that column is the one H-02 documents as having no entry data.The r_multiple column takes four values across the whole sample: the design's three exit levels plus the second leg's target. Solving for the risk unit R from each leg of the same trade, 293 of 293 pairs give a 0.0000 % discrepancy. Two exits hours apart cannot give the same R to the last decimal if the prices were real fills.
# solve for R from each leg and compare within the trade r_multiple distinct values: 4 → -0.7 -0.42 +1.2 +2.0 comparable pairs: 293 max discrepancy: 0.0000%
Consequence. The degradation from slippage, rounding and fees is not small: it is unobservable with this record. The manager cannot measure what costs him most, and does not know that he cannot. Any break-even computed from these figures is understated by construction.
Measuring dispersion inside the dominant cluster instead of over a fixed window that mixed two design levels: 5 of 5 clusters with 0.0000 % dispersion across 393 trades, in both files. Eleven independent clusters, each with a single distinct value.
# observed clusters and their cardinality 2021-22: -0.7(88) -0.42(5) +1.2(30) +1.6(8) +2.0(12) 2023-25: -0.7(152) -0.42(11) +1.2(55) +1.6(9) +2.0(22) # a real execution record produces dispersion: tick, rounding, fees
The mean gross effect is −0.4258 against a cost floor of 0.5842 per trade. The observed ratio is 0.73: fees take 137.2 % of the gross. There is no effect from which to deduct costs.
# gross measured from prices and size, not reconstructed mean gross -0.425841 cost floor 0.584161 ratio 0.73
Comparing config_4_0.yaml against the levels the record produces: 65.0 % of trades (93 of 143) end at a level the configuration neither declares nor allows to be derived. The targets match exactly; the entire loss geometry sits outside the config.
# declared config against observed record declares part_a_target_r +1.2 part_b_target_r +2.0 part_b_stop_loss_r -0.5 part_b_be_buffer_r +0.3 observes +1.2(30) +2.0(12) declared -0.7(88) -0.42(5) orphans: neither declared nor derivable
part_b_stop_loss_r and part_b_be_buffer_r are declared and never executed; and the assumed cost went from 0.002 to 0.0005 between config_3_0 and config_4_0 — divided by four. That is not a change of strategy: it is a change to what the strategy has to clear in order to look viable.The manager documents a six-hour offset in the ETH series relative to the rest of the panel. This audit has not checked it. What does appear on disk is four scripts dedicated to the problem — check_eth_align.py, diag_eth.py, fix_eth_data.py, refix_eth.py — all dated 31 July, which is consistent with the account but does not prove it. Verifying it requires running the cross-correlation over the original panel.
14 pair-window combinations · result with H-01 corrected
| Window | Pair | Real trades | Profit factor | Sharpe | Result USD |
|---|---|---|---|---|---|
| 2021–2022 | AVAX | 21 | 0.649 | −1.178 | −20.92 |
| 2021–2022 | BNB | 18 | 1.008 | +0.044 | +0.34 |
| 2021–2022 | BTC | 15 | 0.415 | −1.990 | −29.40 |
| 2021–2022 | ETH | 30 | 0.552 | −1.928 | −39.67 |
| 2021–2022 | LINK | 23 | 0.573 | −1.590 | −27.37 |
| 2021–2022 | SOL | 2 | 0.000 | −1.979 | −8.02 |
| 2021–2022 | XRP | 21 | 0.631 | −1.199 | −21.42 |
| 2023–2025 | AVAX | 34 | 0.356 | −2.740 | −69.12 |
| 2023–2025 | BNB | 32 | 0.366 | −2.587 | −66.54 |
| 2023–2025 | BTC | 52 | 0.489 | −2.548 | −86.72 |
| 2023–2025 | ETH | 41 | 0.689 | −1.210 | −38.38 |
| 2023–2025 | LINK | 24 | 0.644 | −1.094 | −24.49 |
| 2023–2025 | SOL | 9 | 1.326 | +0.471 | +6.38 |
| 2023–2025 | XRP | 31 | 0.369 | −2.574 | −64.26 |
| 14 combinations | 353 | 12 of 14 < 1 | 12 of 14 < 0 | −489.59 | |
Three engine failures, each with its commit
The seven hypotheses in the opening section are the auditor's errors while reasoning. These three are the engine's errors while measuring, and they are published for the same reason: a method that only shows its hits cannot be checked. Each has the commit that corrects it.
The engine accused WILL 4.0, at terminal severity, of not reaching its own break-even. It counted each leg as an independent trade, and splitting every winner across two different levels while both losing legs exit at the same one sinks the hit rate. All of the bias ran in the same direction.
# the same sample, two units of count legs (2021-22) n=258 hit rate 28.3% break-even 32.8% FIRES R per trade n=143 hit rate 35.0% break-even 32.0% does not fire legs (2023-25) n=443 hit rate 27.3% break-even 32.9% FIRES R per trade n=250 hit rate 34.8% break-even 32.2% does not fire
63aedc1. Rule derived: currency is extensive and adds up; the risk multiple is intensive and must be weighted by leg size. Adding R gave −1.4R on a −0.7R stop, a level the design does not contemplate.100 % of trades were flagged by the noise of execution itself, not by the configuration: the attack could not tell a dishonest record from a merely executed one. We checked whether adjusting the criterion resolved it, and no adjustment separated the defect from the noise.
e942303: the attack abstains and says so on records it cannot judge fairly, instead of scoring them. The criterion that does separate the two cases is not published: a published threshold tells a dishonest seller exactly how far to move a record to clear it.The distribution analysis took the 90th percentile in money while the rest of the attack measured in risk multiples. In money, the tails are the biggest bets, not the best trades.
# tails identified by unit in currency 15 tails in risk multiples 20 tails overlap 8 # and in the right unit the 90th percentile falls on +2.0R, a design level # the "tails" would be every trade that reached the larger target
501696c. The code already had the guard written for this case and it could never fire, because in currency no continuous value repeats. With the unit corrected the attack abstains: an intended outcome is not a tail.Investment committee
It does not say there is no strategy there. It says that the results the code itself produces, once the exit defect is removed, are negative in 12 of 14 cases, and that the trial count cannot be reconstructed from the available information — so no significance statistic on this strategy can be rigorously corrected for multiple testing.
Three of the four artefacts the manager documents have not been verified in this audit and are reported as claims, not findings. Verifying them requires running the pipeline over the original panel, work that has not been done.
ASSAY finds problems; it does not certify that a strategy works and it issues no return forecasts. A report that finds nothing is an honest result and is delivered all the same.
Verifiable appendices
All ten findings rest on files that exist and commands that regenerate them. The last four — H-07 to H-10 — are produced by the ASSAY engine, and their full output lives in a generated report.
The three reports that used to accompany this document — A-0041, A-0042 and A-0041-EN — were withdrawn from circulation on 20 August 2026. The current WILL 4.0 report is informe_A-0047-EN.html, generated with the engine of that date: same verdict and the same nine karats, 120 commits later.
Every report states the engine commit it was produced with. A report that does not state which version generated it is not reproducible, and reproducibility is exactly what ASSAY sells. This document is written by hand — the engine cannot produce the seven dead hypotheses or the three retractions — and its figures were verified against that same commit.