In which the ruler turns out to be the wrong length, and every measurement taken with it comes into question.
Having bought real data in Part V, I assumed the measurement problem was solved. It was not.
Every result in this series rests on replaying that tape day by day. It is the instrument. And in August I discovered that even with genuine prices underneath it, the instrument had been lying - not wildly, not randomly, but consistently and in my favour.
The exchange altered how the closing price is determined. Where the close was previously derived from a weighted average over the final half-hour, it is now the uncross price of a closing auction - a separate session where the index freezes, an indicative price publishes, and the auction resolves a few minutes later.
Our backtest settled expiring positions at the 15:29 minute print. That was a defensible proxy for the old regime. Under the new one it is simply the wrong number.
The measured effect was a systematic ~6.5% understatement of results. Note the direction: the error made the strategy look worse than it was, which is the only reason it survived as long as it did undetected. An error that flatters you gets found the moment you go live and reality disagrees. An error that maligns you can sit there for months while you congratulate yourself on conservatism.
Correcting it opened three more problems in a fortnight.
The vendor's documentation was wrong. Zerodha's own article stated the auction fields were available in the web interface only, not the API. Taking that at face value would have closed the investigation. Sampling the live API payload 174 times at fifteen-second intervals showed the fields are there - indicative_close_price sits in the standard quote response. Only the index publishes one, no auction runs for the options themselves - which happens to be precisely the instrument the breach logic needs.
Our own correction had a bug. The guard built to detect auction-window dislocation compared a live-implied spot against a model. But the model assumed a 6.5% annualised cost of carry, and the live basis on that particular day annualised at 17.3%. The residual sat permanently above the alarm threshold, so the guard latched its override on for an entire live session, feeding a substituted price to a book trading real money.
And the correction changed a conclusion. With settlement priced properly, a previously settled question - whether to square off before expiry or hold to settlement - flipped. The answer we had been operating under was an artefact of the measurement error.
That is the genuinely unsettling part. Not the bug. The realisation that a conclusion I had banked and moved on from was downstream of it.
The thing that made recovery tractable was a discipline adopted early and never relaxed.
Every research study in this project runs the same engine with knobs. With all knobs off, the engine must reproduce ₹12,246,459 across 1,628 positions - exactly, to the rupee. Every study prints this reconciliation before reporting anything else. If it does not match, the study is void and nothing in it is discussed.
It sounds bureaucratic. It is the single most valuable convention in the codebase. When the settlement basis changed, that number changed too - and because every study self-checks against it, the blast radius was immediately visible. I knew precisely which conclusions had been drawn under the old basis and needed re-running, rather than guessing.
It also catches the mundane failure. Twice, a refactor that "obviously could not change behaviour" was caught changing behaviour, because the reconciliation moved by a few rupees.
Instrument your instruments. In any AI-accelerated programme you will generate conclusions far faster than you can validate the machinery producing them. The bottleneck moves from "can we test this?" to "can we trust the test?" - and nothing about a fast, confident, well-formatted result tells you which.
Two practices are cheap and disproportionately effective:
This series was written with Claude, the same tool it describes. I supplied the project, the judgement calls and the arguments; Claude supplied the drafting, and dug every figure out of the repository’s own commit history so I could not flatter myself from memory.
Declaring that seems the least I can do given the subject. It would be a peculiar hypocrisy to publish eight posts on harnessing AI while implying I typed them all by hand. If the writing is good, that is partly the tool. If the judgement is sound, that part is mine. Distinguishing between those two things is, as it happens, what the entire series is about.
By day I run product for data strategy and operations at Condé Nast, where the brief is customer identity: the unglamorous business of establishing that the person reading on a phone in Mumbai and the one subscribing on a laptop in London are the same human being. Essentially the ‘slow work’ of turning unknown into known, in various stages. The glamorous parts of my day: developing the single customer view, and harnessing that data to optimise for amplified engagement and revenue across multiple lines and brands.
Twenty-four years of it now, across product, data and technology - client side and agency side, in media and publishing, CPG, insurance, automotive, FMCG and telecom, across North America, Europe and Asia. Enough time in front of CXOs to have learned that a business case travels further than an architecture diagram, and enough time behind them to know the diagram still has to be right.
This project was my evenings. It brings together the triumvirate - my love for the world of finance and markets, my drive to build a production grade system using the latest AI toolset, and the itch to discover first hand what these tools are truly capable of. And the only honest way to find out what these tools can carry is to hand them something that can lose real money.
Questions, disagreements, war stories from your own build, or a conversation about senior product leadership and AI-delivery roles - all welcome.