Go SDK¶
The Go package calls the Rust core through cgo. Import it with an explicit name:
itofin is the package name; go is only the final directory in the module path.
The Go API reference
provides the exported types and methods.
Install in an application¶
Use Go 1.27.1, a C compiler, and the native package from the same release as
the Go module. go get downloads Go source; it does not install native headers
or libraries. Published native packages support Linux amd64 and arm64 (Ubuntu
24.04, glibc 2.39 or compatible newer systems), macOS arm64 (macOS 14 or newer),
and macOS amd64 (Intel, macOS 15 or newer).
The Linux arm64 and macOS amd64 packages are published from the release after
v0.27.0; earlier releases ship only Linux amd64 and macOS arm64.
The following commands pin the v0.24.0 release. With the GitHub CLI
installed, run them in your application's module directory. For a new project,
first run go mod init example.com/pricing.
Download, verify, and extract the native package:
gh release download "v$version" --repo bitbrew-dev/libitofin \
--pattern "itofin-native-$version-$platform.tar.gz*"
shasum -a 256 -c "itofin-native-$version-$platform.tar.gz.sha256"
tar -xzf "itofin-native-$version-$platform.tar.gz"
export ITOFIN_NATIVE="$PWD/itofin-native-$version-$platform"
(cd "$ITOFIN_NATIVE" && shasum -a 256 -c SHA256SUMS)
export CGO_ENABLED=1
export CGO_CFLAGS="\"-I$ITOFIN_NATIVE/include\""
export CGO_LDFLAGS="\"-L$ITOFIN_NATIVE/lib\" -litofin_ffi \"-Wl,-rpath,$ITOFIN_NATIVE/lib\""
go get "github.com/bitbrew-dev/libitofin/sdk/go@v$version"
Save this as main.go:
package main
import (
"fmt"
"log"
itofin "github.com/bitbrew-dev/libitofin/sdk/go"
)
func main() {
session, err := itofin.NewSession()
if err != nil {
log.Fatal(err)
}
defer session.Close()
fmt.Println("Native version:", itofin.Version())
}
Use itofin_external for every build, run, test, and vet of an external consumer:
go run -tags itofin_external .
go test -tags itofin_external ./...
go vet -tags itofin_external ./...
go build -tags itofin_external .
The linker configuration embeds the absolute native-library directory. If you move that directory, rebuild with its new path. Keep the header and library together. For relocatable bundles and source-built native packages, see the native distribution guide.
Run examples from a source checkout¶
From the repository root, build the native library using the pinned Rust toolchain. These examples use the matching Go source in the checkout and do not need the external build tag.
Set the runtime library path in the same shell:
Then run:
The European option walkthrough
uses the same inputs as Python and returns NPV 2.1333684449.
Finite-difference vanilla options¶
Current source builds can price European, American and Bermudan vanilla options
with a Black-Scholes process. Once session, process and option belong to
the same session, construct an engine and price in one operation:
timeSteps, priceNodes := uint(200), uint(200)
engine, err := session.NewFdBlackScholesVanillaEngine(process, itofin.FdConfig{
TGrid: &timeSteps, XGrid: &priceNodes,
})
if err != nil { return err }
value, err := option.PriceFd(engine)
if err != nil { return err }
delta, err := option.Delta()
if err != nil { return err }
gamma, err := option.Gamma()
if err != nil { return err }
theta, err := option.Theta()
if err != nil { return err }
fmt.Println(value, delta, gamma, theta)
FdConfig{} selects a 100 by 100 grid, zero damping steps and Douglas
rollback. FdImplicitEuler is the other supported scheme; set it through
Scheme: &scheme. Grid and damping values are optional pointers, so an explicit
zero time grid or undersized equity grid is rejected instead of silently
becoming a default. The engine retains its process, and the option retains an
attached engine. Cash dividends, quanto and local-volatility settings are not
part of this binding.
Portfolio simulation¶
This runnable example simulates two correlated assets with synthetic initial allocations of 6,000 and 4,000 over one year. It sums their terminal values without applying allocation weights a second time. The fixed seed makes the run reproducible; its stream is not promised to match NumPy.
// This example uses synthetic allocations; no service-specific code or data.
package main
import (
"fmt"
"log"
itofin "github.com/bitbrew-dev/libitofin/sdk/go"
)
func main() {
result, err := itofin.SimulateGBM(itofin.GBMConfig{
Initial: []float64{6000, 4000},
Drift: []float64{0.06, 0.03},
Volatility: []float64{0.20, 0.10},
Correlation: []float64{1, 0.3, 0.3, 1},
Horizon: 1, Steps: 252, Paths: 1000, Seed: 42, TerminalOnly: true,
})
if err != nil {
log.Fatal(err)
}
var mean float64
for path := range result.Paths {
var total float64
for asset := range result.Assets {
total += result.Values[path*result.Assets+asset]
}
mean += total / float64(result.Paths)
}
fmt.Printf("native %s; %d paths; mean terminal portfolio %.2f\n", itofin.Version(), result.Paths, mean)
}
With v0.24.0, it prints native 0.24.0; 1000 paths; mean terminal portfolio 10525.33.
Sessions and errors¶
A session owns the native object graph and runs its calls on one OS thread.
Defer session.Close() after successful creation; no finalizer releases the
session for you. Closing a session releases all its objects. You may also
close individual handles earlier; dependent native objects retain what they
need. Do not mix objects from different sessions or copy session values.
Calls from multiple goroutines are serialized within a session. Use separate
sessions for independent graphs. Calls into the same session during a
bootstrap callback return ErrCallbackReentry, including Close; close the
session after the callback returns.
Check returned errors before using results. Native errors expose a code and
message through *itofin.Error, accessible with errors.As. See the
SDK guide
for ownership, simulation layout, and validation details.