Docs / nablatensor-core / com.nablatensor.engine
final class
Nabla
The client-facing entry point: record a valuation once, then value it under as many market states and scenario counts as you like.
try (Nabla.Pricer pricer = Nabla.model(rec -> {
SDouble spot = rec.input("S0", 100.0);
SDouble vol = rec.input("sigma", 0.2);
...
rec.output(payoff);
})
.fp32()
.greeks()
.fastest()
.build()) {
Nabla.Valuation v = pricer.value()
.with("S0", 110.0)
.scenarios(10_000_000)
.run();
System.out.println(v.price() + " delta " + v.greek("S0"));
}
The split between Model and Pricer is the split between what is expensive and what is not. Building a pricer records the tape and generates a kernel for it; valuing costs a launch. Everything you pass to with is a kernel argument, so moving the market never rebuilds anything — which is why a pricer is worth holding onto rather than creating per valuation.
Methods
Records a valuation written against ADouble into a reusable model.
Records a valuation whose inputs are the components of a market record.
The record supplies both the input names and their initial values, so no risk factor is ever named with a string: the valuation reads inputs through accessor references, and greeks() hands back the gradient as a record of the same type.
record EquityMarket(double spot, double vol, double rate) {}
var market = new EquityMarket(100.0, 0.28, 0.03);
try (var pricer = Nabla.model(market, (rec, in) -> {
SDouble spot = in.of(EquityMarket::spot);
...
rec.output(payoff);
}).fp32().greeks().fastest().build()) {
EquityMarket greeks = pricer.value().with(market).run().greeks();
hedge(greeks.spot()); // delta, checked by the compiler
}