Why NablaTensor exists
Monte-Carlo books recompute the same valuation millions of times. We record it once as a flat trace and replay it — one forward sweep for the price, one reverse sweep for every Greek.
Pricing a structured note by Monte-Carlo is not one calculation. It is the same calculation run across a few million scenario paths, then run again for every risk perturbation: bump a rate, revalue the whole book; bump a vol, revalue it again. A desk that wants a full first-order risk ladder can spend more compute on the bumps than on the price itself.
Adjoint algorithmic differentiation removes the bumps. If you record the valuation as a sequence of primitive operations — a tape — you can walk that tape backwards once and read off the sensitivity to every input at the same time. The cost of all first-order Greeks together drops to a small constant multiple of a single valuation, independent of how many inputs you have.
What NablaTensor actually does
- Record once. A valuation is captured as a flat, contiguous trace of scalar operations — no graph pointers, no boxed nodes on the heap.
- Replay wide. The same trace is evaluated across millions of scenarios using plain arrays, SIMD lanes, or a GPU kernel, depending on the backend.
- Sweep back once. A single reverse pass over the trace produces the price and every first-order Greek.
This blog is the engineering log for that runtime: how the tape is laid out, why it stays cache-resident, where the JVM helps and where it fights back, and what the measurements look like on real books.
The project is Apache-2.0 and lives at github.com/nablatensor-dev/nablatensor. New notes land here once or twice a week.