---
title: "Een autoresearch-lab bouwen waar ik ook echt naar kan kijken"
date: 2026-08-15T10:31:00.000Z
updated: 2026-08-15T17:39:51.794Z
canonical: https://ninokroesen.nl/blog/een-autoresearch-lab-bouwen-waar-ik-ook-echt-naar-kan-kijken
lang: nl
author: "Nino Kroesen"
---

# Een autoresearch-lab bouwen waar ik ook echt naar kan kijken

De afgelopen zes weken heeft een machine die ik zelf gebouwd heb een deel van mijn quant-onderzoek voor me gedaan. Hij scant arXiv en het open web op mechanismen, stelt een hypothese op, schrijft de strategiecode zelf, backtest die over twaalf wekelijkse out-of-sample windows en vertelt me welke ideeën dood zijn. Hij heeft inmiddels zo rond de 700 experimenten gedraaid. Niets heeft de holdout overleefd.

Dat leest als een oordeel over autoresearch en dat is het niet. De eerlijke versie is smaller en nuttiger: wat ik gebouwd heb is een heel goed instrument om strategieën te *weerleggen* en een nog-niet-goed instrument om ze te *vinden*. Zes weken mislukkingen leverden me een redelijk precieze kaart op van waar een loop als deze tegen je liegt, en de fouten die me de meeste tijd gekost hebben waren nooit de strategieën.

Mijn eerste tests met een kant-en-klare autoresearch-pipeline op de automatische piloot leverden niets op dan een hoop mislukkingen, en de zes weken daarna zijn vooral bezig geweest met uitzoeken waarom. Het antwoord is dat autoresearch staat of valt met zijn harness. Het model stelt voor, het framework beoordeelt, en die twee moeten hard genoeg van elkaar gescheiden zijn dat het model zich geen weg kan reward-hacken naar een mooi getal. Dat deel is inmiddels redelijk bekend. Het stuk dat de meeste setups overslaan is het stuk waarvan ik nu denk dat het het zwaarst weegt: zichtbaarheid. Je kunt geen loop sturen die je niet kunt zien, en wekenlang kon ik de mijne niet zien.

## Wat het eigenlijk is

Mijn eerdere quant-onderzoek was veel te gevoelig voor overfitting: ik vond dan iets dat op een edge leek en zag het weer verdwijnen zodra ik er opnieuw naar keek. Het enige goede dat eruit voortkwam was de omgeving, een workflow die precies gebouwd is om snel op ideeën te itereren en ze robuust te testen. Dit is persoonlijk onderzoek dat ik in mijn eigen vrije tijd doe, buiten mijn vaste baan om, dus het tijdsbudget is wat er aan het eind van een week overblijft. Toen die omgeving er eenmaal was, was een onbemande pipeline de enige tijdsefficiënte manier om het onderzoek überhaupt levend te houden.

Het resultaat is een agent-loop van veertien fases breed. Een research-fase scant arXiv en het open web en schrijft briefingdocumenten waar de hypothesizer vervolgens letterlijk uit moet citeren. Een hypothesize-fase stelt een mechanisme voor en registreert zijn voorspelling *voordat* er iets geschreven wordt, welke pairs, welke kant op, verwachte trade-frequentie, verwachte Sharpe. Een codegen-fase schrijft de daadwerkelijke strategie, die een mechanische hindernisbaan moet doorstaan voordat er ook maar één dure run plaatsvindt: lint, smoke tests, look-ahead checks, determinisme, parametergebruik. Een adversarial review-fase probeert de code te weerleggen voordat de backtest überhaupt draait. Pas dan gaat de strategie door twaalf wekelijkse out-of-sample windows, walk-forward: fit in-sample, test out-of-sample, één window tegelijk en sorteert een deterministische evidence gate het resultaat in validated, refuted of inconclusive.

Alles wat de loop leert belandt in een append-only geheugen dat in elke toekomstige hypothese geïnjecteerd wordt, en wanneer een cycle als refuted sluit schrijft de loop nu zijn eigen seed voor de volgende en zet hij de lineage voort. De graph is de single source of truth voor dat alles, veertien nodes en hun conditionele edges, opnieuw afgespeeld tegen 1.674 echte cycles met nul overtredingen voordat ik hem iets liet aansturen.

Daarbovenop zit een live dashboard dat die graph tekent terwijl hij draait: welke fase er draait, wat die opgeleverd heeft, wat er misging. Ik bouw er nu een editor omheen zodat ik fases midden in een cycle kan inspecteren en bijstellen, één fase opnieuw kan draaien tegen echte artifacts, en de daadwerkelijke model-turns van elk eerder experiment kan teruglezen.

## De tradeoffs

![1.00](https://media.ninokroesen.com/uploads/2026/08/fb83b844f9e879f49d7c/_1280.jpeg)

### Valideer de validator voordat je hem gebruikt

Voordat ik de loop ook maar één hypothese liet genereren, heb ik de eerste dagen besteed aan het auditen van de backtester zelf. Die audit vond vier echte bugs, waaronder een datalek waarbij een nog vormende candle zijn eigen close kon zien voordat die bestond, en een column-index bug in de optimizer die stilletjes elke kandidaat afwees die hij binnenkreeg. Beide draaiden al in mijn productietooling. Had ik deze stap overgeslagen, dan was alles wat het lab daarna produceerde ruis geweest en had ik dat niet geweten. Het waardevolste eerste product van een autoresearch-setup bleek een audit van zijn eigen meting te zijn.

Twee weken later betaalde dezelfde truc zich uit vanuit de andere richting. Bij het overzetten van mijn productie-gating-logica naar het lab, zodat het lab kon testen wat productie daadwerkelijk doet, kwam er een bug in de productieversie boven water: een bootstrap die de verkeerde serielengte afsneed en daardoor elke positieve kandidaat doorliet die hij juist had moeten filteren. Diezelfde slice-bug zat in meerdere zusterstrategieën. Ik vond hem door het lab productie te laten nabootsen, niet door productie te testen.

### Het model stelt voor, het framework beoordeelt

De inner loop, het stuk waar het model op een kandidaat itereert, draait tegen een bevroren evaluator die hash-pinned is: het model mag hem zo vaak draaien als het wil en elk getal lezen dat hij afdrukt, maar het kan hem niet veranderen, en de pin breekt zodra er iets aan komt. Er is een sanity gate waarbij een vlak signaal zich moet onthouden, zodat een strategie niet kan winnen door simpelweg altijd te traden. Dit is de regel die ik iedereen zou meegeven die zoiets bouwt: het model stelt voor, het framework beoordeelt, en die twee raken elkaar nooit, want een model dat zijn eigen huiswerk mag nakijken, doet dat ook.

### Goedkoop model genereert, duur model weerlegt

Codegeneratie draait op een goedkoop worker-tier model (DeepSeek). Review draait op een duur frontier model (Opus). De invariant is bewust: het goedkope model schrijft, het dure model weerlegt. Het ving vanaf dag één echte defecten, een verkeerde deler in een nettowinstberekening die de self-check van de schrijver zelf had goedgekeurd, en een verkeerde parameter die stilletjes een experiment geruïneerd zou hebben. De prijs is dat review de duurste fase in de loop werd. Een weerlegging vóór de backtest is nog altijd de goedkoopste fout die het systeem kan maken.

### De strateeg ziet de holdouts nooit

Elke "validated" familie werd opnieuw getest door een mens, ik, op onaangeroerde data die de loop nooit gezien had, en de holdout-resultaten gingen nooit terug het geheugen van de loop in. Die firewall houdt de strateeg onbesmet. Hij creëerde ook een blinde vlek: niets kon de loop vertellen om te stoppen met het aanmaken van varianten van een familie die allang dood was, dus één nachtelijke run stapelde tientallen zusjes op in één enkele familie en produceerde zestien gecorreleerde "validations". Eén weddenschap, zestien keer geteld. Wat het erger maakt is dat de eigen research-fase van het lab de monocultuur eerder signaleerde dan ik; hij had er alleen geen enkel mechanisme voor om er iets mee te doen. De fix was mechanisch in plaats van op oordeel gebaseerd: experimenten worden geclusterd op wat ze daadwerkelijk traden, en een cluster heeft een cap.

In de eerste versie mocht het model ook zijn eigen assets kiezen, welke het er maar leuk uit vond zien. Dat is selectiebias per constructie, het model cherry-pickt de markt waar zijn idee toevallig op past. De fix is een vaste basis van achttien assets. Ik weet alleen niet helemaal zeker of achttien het juiste aantal is; het kan een beetje te breed zijn, terwijl het alternatief met één asset te weinig trades opleverde om iets statistisch significants te kunnen zeggen. Die tradeoff staat nog open.

### Eén taal was goedkoper geweest

De adaptieve experimenten fitten een signaal in Go en traden vervolgens de JavaScript-versie, omdat dat de vorm van mijn productiesysteem spiegelt. Elk gegenereerd paar moet door een parity gate die bewijst dat beide implementaties zich identiek gedragen, en die gate is de nummer één doodsoorzaak van codegen-runs. Een model vragen dezelfde logica twee keer te schrijven verdubbelt ruwweg het oppervlak waarop het fout kan gaan, en de gate vangt elk van die fouten ten koste van het hele experiment, tokens, tijd en nauwkeurigheid. Bij een rewrite is single-source, één taal, geen tweeling, de eerste structurele fix die ik zou maken.

## Wat de mislukkingen werkelijk waren

Er zijn ooit zo'n 45 experimenten als validated gemarkeerd. 44 van die 45 dateren van vóór het aanscherpen van de evidence-eisen dat ik half juli doorvoerde, en ze delen één profiel: een hoge Sharpe op twintig tot dertig trades. Zes families kwamen zo ver als een echte holdout, door mij gedraaid, met de hand, op een maand data die de loop nooit had aangeraakt. De holdout-score staat op 0 uit 6.

Ik was al sceptisch over de validated-oordelen voordat de holdouts draaiden; de samples waren klein en dat wist ik. De holdouts bevestigden dat met een consistentie die bijna grappig was. De in-sample ranking werd niet alleen zwakker, hij draaide om: de variant met de meeste filters erop gestapeld, de best geselecteerde van het stel, presteerde out-of-sample het slechtst.

| Wat er getest is                                        | In-sample                                            | Holdout                                           |
| :------------------------------------------------------ | :--------------------------------------------------- | :------------------------------------------------ |
| London-sessie familie, 4 varianten                      | alle vier "validated"                                | allemaal teruggezakt naar nul, ranking omgedraaid |
| Beste statistische profiel in de ledger                 | Sharpe 0,41, profit factor 1,91, 145 trades, p 0,003 | Sharpe 0,01, profit factor 1,01, p 0,48           |
| Eerste adaptieve experiment                             | Sharpe 0,65, profit factor 2,65, 52 trades, p 0,005  | Sharpe −0,24, profit factor 0,75, netto −47       |
| Vroeg "Sharpe 1,71"-signaal, opnieuw gedraaid op schaal | Sharpe 1,71 op één enkel window                      | Sharpe −0,13, p 0,80                              |

![1.00](https://media.ninokroesen.com/uploads/2026/08/de27eb212ae08e23d579/_1280.jpeg)

Het beste profiel in de ledger is degene waar ik steeds op terugkom. De hit rate hield vrijwel exact stand, wat instortte was de payoff. De edge had in de gemiddelde winst per trade gezeten, de meest gelukgevoelige component waar je een argument op kunt bouwen, en niets in de in-sample statistieken zou me dat ooit verteld hebben.

Niets hiervan was luiheid van de gate, wat me langer kostte om te accepteren dan zou moeten. Uiteindelijk heb ik de power-berekening gedaan, en die is meedogenloos. Met een minimum van 60 trades kan de gate alleen een Sharpe per trade van 0,212 of beter bevestigen. De gemeten mediaan van alles wat aan de positieve kant landt is 0,188, met een standaardfout van ongeveer 0,129. Het effect en de foutmarge zijn even groot. Die gelijkheid, niet slordigheid, is waarom 87 experimenten in één exposure cell, dezelfde kant en dezelfde pair set, 41 "validated"-oordelen opleverden en nul holdout-overlevenden. Het antwoord is geen strengere gate. Het is een tweede, goedkopere test van het *mechanisme* met een veel hogere n, conditionele forward returns over elke bar, geen optimizer, geen onthouding, los van de dure test van de strategie. Die staat nog op de lijst.

De subtielere variant van hetzelfde probleem is een kandidaat wiens "signaal" 94% van de tijd bleek samen te vallen met zijn eigen onvoorwaardelijke controle. Hij filterde helemaal niets; hij koos een instapuur. Dat generaliseert naar een gate die het lab nodig heeft en nog niet heeft: elke kandidaat wiens trade-aantal binnen zo'n 10% van zijn controle ligt, hertimet, hij signaleert niet.

Toen werkte de meetkant eindelijk goed en vertelde me de waarheid in één klap. De eerste run op volle schaal waarbij de evaluator elk window daadwerkelijk tradede kwam terug met 3.783 trades over twaalf windows, een nettoresultaat van −17.663, en nul positieve windows. Een eerlijk, ondubbelzinnig verlies, en de goedkope inner evaluator had dezelfde kant op gewezen als de echte engine, wat het enige echt goede nieuws op het hele scorebord is. Het kompas werkt. Er was alleen nog niets goeds om naar te wijzen.

Daarvoor waren er weken waarin het lab vrijwel niets produceerde. Zijn eigen geheugen bevat de diagnose die hij destijds stelde, de gate moet de trades onderdrukken, schreef hij, en die was fout. De echte oorzaak was een sizing-bug in mijn eigen eval kernel die posities op de exotische paren naar nul afrondde. De strategieën waren nooit het probleem; de meting wel. Er was ook een telbug die er bijna de eerste valse bevestiging doorheen kreeg: aangrenzende testwindows deelden een bar op de grens, dus een strategie die daarop triggerde kreeg dezelfde trade twee keer geteld, en het lab was één fix verwijderd van het uitbrengen van een "confirmed" strategie op basis van dubbelgetelde data. Dat was de week waarin het lab leerde dat zijn eigen meting de leugenaar kan zijn.

De reden dat die sizing-bug wekenlang overleefde is het punt van deze hele post. Ik had te weinig inzicht in mijn eigen harness, en de enige output van de loop was proza. Honderden regels model-verhaal lezen over wat er gedaan is, is een snelle manier om mentaal uitgeput te raken, en het laat je geen bug zien. Een graph wel.

Op dit moment is de bottleneck alweer verschoven, naar de generator. Na de laatste geslaagde close begin augustus volgden er 480 opeenvolgende error closes, vrijwel allemaal goedkope codegen-defecten op smoke-niveau, verkeerde parameterranges, gedeclareerde maar ongebruikte parameters, verwijzingen naar helpers die nooit gegenereerd zijn. Ergens onderweg begon het eigen geheugen van het lab zijn generator te vergiftigen: meer opgestapelde learnings betekende langere hypotheses vol constraints, waar de codegenerator (die die learnings nooit ziet) niet aan kon voldoen, waarna de review gate ze afwees. Een feedback loop die vanzelf alleen maar erger wordt.

## Eerlijke kanttekeningen

![1.00](https://media.ninokroesen.com/uploads/2026/08/35f21ef0ea3d4366ff50/_1280.jpeg)

Geen mens buiten mijn eigen setup heeft hier ooit naar gekeken, en dat was bewust. Ik heb de publieke autoresearch-projecten gelezen, die van Karpathy, de Claude Code-port van Driveline, en pi-autoresearch, en de inner eval loop leent zijn vorm openlijk van alle drie: single-file edit scope, een locked scorer, een metric contract dat tussen modelaanroepen door teruggelezen wordt, een noise floor afgeleid van multi-seed variantie, een sanity gate waarbij een vlak signaal zich moet onthouden. Verder heb ik niet veel gelezen, omdat mijn use case heel specifiek is en het toch met mijn eigen ecosysteem moest integreren. Ik denk dat het het beste is om gewoon zelf te proberen en te experimenteren, ook al kan dat snel oplopen tot dure lessen. Ik zou het niet zo goed begrijpen als nu wanneer ik dingen van andere mensen had overgenomen.

Ik moet ook duidelijk zijn over waar dit nooit voor bedoeld was. Ik heb nooit het vertrouwen in dit systeem gehad om iets dat het maakte in productie te zetten, het was altijd onderzoek om te zien hoe ver het model zou komen, en om te leren en op het systeem te itereren. Ik verkoop geen signalen en ik geef geen financieel advies, en het scorebord hierboven is het beste bewijs dat er hier niets te verkopen valt.

En de eerlijke staat van de harness zelf: het is nog steeds niet wat het hoort te zijn. De eval-omgeving moet gehard worden, en ik ben de code nog steeds een grondige duik schuldig in wat het model daadwerkelijk geproduceerd heeft. Ik denk erover om een compleet nieuwe iteratie vanaf de grond op te bouwen, omdat de eerdere experimenten verpest hebben wat ik voor ogen had, vooral aangekoekte rommel in de pipeline, plus het tweelingontwerp met twee talen. Het geheugen kwijtraken zit me niet dwars. Het was nooit een productiesysteem, het was een heel vroeg prototype waar sowieso op geïtereerd moest worden, en het hele geheugen weggooien kost me niets wat ik wil bewaren.

## Waar het nu staat en wat er nu komt

De loop en het dashboard draaien live, en het actieve werk is de fase-editor: het production design is goedgekeurd en de implementatie begint nu. Die maakt de pipeline bewerkbaar en inspecteerbaar, prompt templates per fase die live toegepast worden, knoppen voor model en temperature, sturen welke data een fase mag aanraken, één echte cycle draaien, één fase opnieuw draaien tegen echte artifacts, en per node de daadwerkelijke model-turns van elk eerder experiment doorbladeren. Hij kan ook zelf nieuwe fases genereren: beschrijf een fase, en hij produceert de prompt, de config en de graph-bedrading als een reviewbare draft, zodat ik nooit met de hand nodes hoef te bedraden.

Als ik herbouw en dat doe ik waarschijnlijk, gaan de isolatie en de mechanische gates mee, verder gehard. De aangekoekte rommel gaat eruit. De Go/JavaScript-tweeling ga ik nog eens goed tegen het licht houden, want hij laat de modellen te snel fouten maken, en elk van die fouten kost tokens, tijd en nauwkeurigheid. En de geparkeerde vraag blijft geparkeerd: als discovery ooit een holdout-overlever oplevert, is de lifecycle om er één live te draaien geschetst en klaar om gebouwd te worden, en geen moment eerder. De beslissing over de herbouw wacht zelf op die grondige duik in wat het model daadwerkelijk geschreven heeft.

## Wat ik eruit meeneem

![1.00](https://media.ninokroesen.com/uploads/2026/08/61bafb619ad0cd8f37c5/_1280.jpeg)

Niets hiervan gaat eigenlijk over traden. Geef een agent een loop, en twee dingen bepalen of die loop je de waarheid vertelt.

Het eerste is isolatie, en dat is degene waar iedereen het al over heeft. Het model mag de evaluator zo vaak draaien als het wil en mag hem nooit veranderen, want het alternatief is een systeem dat je scoringsfunctie optimaliseert in plaats van je probleem.

Het tweede komt veel minder ter sprake. Je moet het ding aan het werk kunnen zien. Elke dure fout in deze zes weken, de weken met lege output, de dubbelgetelde trades, het geheugen dat stilletjes zijn eigen generator wurgde, zat de hele tijd in de artifacts en was volledig onzichtbaar in het proza. Een muur van model-output vertelt je wat de loop dénkt dat hij gedaan heeft. Een graph vertelt je wat hij gedaan heeft. Het meeste werk in agentic coding gaat op dit moment naar het model slimmer maken; ik steek het mijne in het kunnen zien ervan, want de bug die je een maand kost is nooit de bug die in de samenvatting staat.
