Go · REST + WebSocket · NinjaTrader 8

Go NinjaTrader 8 API examples

High-performance NinjaTrader 8 trading bots in Go. net/http for REST, gorilla/websocket for streaming with native goroutine concurrency.

Why Go

Using Go against the CrossTrade NinjaTrader API

Go is the right choice when you need concurrency, low latency, and zero-dependency deployment. CrossTrade's REST API works with the stdlib net/http. For WebSocket, gorilla/websocket is the established library and handles reconnect cleanly.

REST net/http (stdlib)
WebSocket github.com/gorilla/websocket
REST · animated

Watch the request get written

A pseudo-developer types out a real GET GetOrders call against your NinjaTrader 8 account. The animation runs on a loop; the static snippet below is yours to copy.

getorders.go
Copy this

Complete Go GetOrders example

package main

import (
  "encoding/json"
  "fmt"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET",
    "https://app.crosstrade.io/v1/api/accounts/Sim101/orders", nil)
  req.Header.Set("Authorization", "Bearer YOUR_TOKEN")

  res, err := http.DefaultClient.Do(req)
  if err != nil { panic(err) }
  defer res.Body.Close()

  var body struct {
    Orders  []map[string]any `json:"orders"`
    Success bool             `json:"success"`
  }
  json.NewDecoder(res.Body).Decode(&body)
  fmt.Printf("%d orders\n", len(body.Orders))
}
WebSocket · animated

Streaming data with github.com/gorilla/websocket

Same flow on a persistent connection: open the socket, send a subscribe message, receive market data or P&L pushes in real time. CrossTrade's WebSocket is at wss://app.crosstrade.io/ws/stream with the same Bearer token in the request header.

stream.go
Copy this

Complete Go WebSocket example

package main

import (
  "log"
  "net/http"
  "time"
  "github.com/gorilla/websocket"
)

func main() {
  headers := http.Header{}
  headers.Set("Authorization", "Bearer YOUR_TOKEN")

  for {
    ws, _, err := websocket.DefaultDialer.Dial(
      "wss://app.crosstrade.io/ws/stream", headers)
    if err != nil {
      log.Println("dial:", err, "— retrying in 5s")
      time.Sleep(5 * time.Second)
      continue
    }

    ws.WriteJSON(map[string]any{
      "action":      "subscribe",
      "instruments": []string{"ES 12-25"},
    })

    for {
      var msg map[string]any
      if err := ws.ReadJSON(&msg); err != nil {
        log.Println("read:", err)
        break
      }
      log.Println(msg)
    }

    ws.Close()
    time.Sleep(time.Second)
  }
}

The full Go-compatible API surface

Every endpoint documented with request/response schemas, error codes, rate-limit notes, and language-specific code samples.

FAQ

Common questions

Is Go a good language for algo trading bots?

Yes. Go shines when you need predictable latency, easy concurrency (one goroutine per instrument), and zero-dependency single-binary deployment. CrossTrade's WebSocket + REST API maps cleanly onto Go's net/http and gorilla/websocket patterns.

Which WebSocket library: gorilla/websocket or nhooyr.io/websocket?

Both work great. gorilla/websocket is the longest-running standard with the largest ecosystem (the example uses it). nhooyr.io/websocket is more modern (context-first API, automatic compression). Pick based on your team's familiarity — CrossTrade is agnostic.

How do I handle the "one WebSocket per account" limit?

CrossTrade closes the older connection if a second one opens on the same account. The Go example shows a clean reconnect loop with a 5-second backoff that handles unexpected closures (server restart, network blip, session takeover). For multi-account use, open one WebSocket per account and dispatch incoming messages to per-account goroutines.

Goroutines for multiple instrument subscriptions?

Yes — but on ONE WebSocket. Send multiple subscribe messages on the same connection (instruments accumulate). Then fan out incoming marketData messages to per-instrument goroutines via a channel for processing. The one-connection-per-account limit means you don't open one socket per instrument.

How big is a compiled Go trading bot binary?

Typically 8-15MB statically linked. CGO disabled keeps it pure-Go (good for containers). Cross-compile with GOOS=linux GOARCH=amd64 for VPS deployment, or GOOS=windows for a Windows trading host.

Error-handling pattern for trading code?

Wrap every API call in a small helper that returns (T, error) and check at every step. For mcp:trade flows, never panic — always return an error and bubble up to a top-level handler that decides whether to flatten + halt or retry. Use errors.Is to distinguish rate-limit errors from auth errors.

Go vs Rust for trading: which one?

Both are excellent. Go for faster development, easier deployment, and "good enough" performance — fits 95% of trading-bot use cases. Rust when you need zero-allocation hot paths or interop with C/C++ libraries. Both produce small static binaries; Rust gives stricter memory guarantees at the cost of compile time.

Performance vs Python or Java?

Go is roughly comparable to Java and 10-50x faster than Python on CPU-bound work. For network-bound CrossTrade calls (~50ms round-trip), all three are equivalent in practice. Go wins on memory footprint and startup time, which matters for containerized deployments.

JSON-binding library?

encoding/json (stdlib) is fine for CrossTrade responses. For very high-throughput parsing, look at json-iterator/go or goccy/go-json — both drop-in faster than stdlib. Most trading code doesn't need them.

Build your first NinjaTrader 8 trading bot in Go

One bearer token, one URL, every NinjaTrader endpoint. Ship to Sim101 first.