topstepx

package module
v0.0.0-...-6729b5a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: GPL-3.0 Imports: 21 Imported by: 0

README

topstepx — Go SDK for the ProjectX Gateway API (TopstepX)

A Go client for the ProjectX Gateway API as deployed by TopstepX: all 21 REST operations, the SignalR user and market hubs, token lifecycle management, retries, client-side rate limiting and request validation.

This SDK implements the cross-SDK behavior contract in spec/SDK_BEHAVIOR.md; the Rust and Python SDKs implement the same behavior. Where this SDK deviates or decides something the contract leaves open, Deviations and Go-specific decisions says so.

  • Module: github.com/CurtisTechSolutions/TopstepX/go (package topstepx), realtime hubs in github.com/CurtisTechSolutions/TopstepX/go/realtime
  • Version 0.1.0, license GPL-3.0-only (see the repository LICENSE)
  • Go 1.22 or later. Runtime dependencies: github.com/shopspring/decimal and github.com/coder/websocket (v1.8.13, the last release that supports Go 1.22)

Orders are real. Orders.Place, Cancel, Modify and Positions.Close / PartialClose act on real accounts. Use a simulated account while developing.

Installation

go get github.com/CurtisTechSolutions/TopstepX/go
import (
	topstepx "github.com/CurtisTechSolutions/TopstepX/go"
	"github.com/CurtisTechSolutions/TopstepX/go/realtime"
)

Quick start

client, err := topstepx.NewClient(
	topstepx.WithCredentials(os.Getenv("TOPSTEPX_USERNAME"), os.Getenv("TOPSTEPX_API_KEY")),
)
if err != nil {
	log.Fatal(err)
}
ctx := context.Background()

accounts, err := client.Accounts.Search(ctx, true) // logs in lazily on first use
if err != nil {
	log.Fatal(err)
}
for _, a := range accounts {
	fmt.Println(a.ID, a.Name, a.Balance, a.Simulated)
}

contracts, _ := client.Contracts.Search(ctx, "ES", false)
bars, _ := client.History.RetrieveBars(ctx, topstepx.RetrieveBarRequest{
	ContractID: contracts[0].ID,
	StartTime:  time.Now().Add(-24 * time.Hour),
	EndTime:    time.Now(),
	Unit:       topstepx.AggregateBarUnitMinute,
	UnitNumber: 5,
	Limit:      100,
})

Every network method takes a context.Context first. A *Client is safe for concurrent use; create one per process (or per account) and share it.

Configuration
Option Default
WithBaseURL(url) https://api.topstepx.com
WithUserHubURL(url) / WithMarketHubURL(url) https://rtc.topstepx.com/hubs/user / .../hubs/market
WithCredentials(userName, apiKey) / WithToken(token) none
WithTimeout(d) 30 s per HTTP attempt (the default HTTP client also has a 10 s connect / TLS timeout)
WithMaxRetries(n) 3 (0 disables retries)
WithRetryBackoff(initial, max) 1 s, doubling, capped at 30 s, no jitter
WithRateLimits(limits) / WithoutRateLimiting() enabled: history 50 / 30 s, everything else 200 / 60 s
WithoutValidation() validation enabled
WithRefreshMargin(d) 1 h before expiry
WithUserAgent(ua) topstepx-go/0.1.0
WithHTTPClient(c) a dedicated client with connect/TLS timeouts
WithLogger(*slog.Logger) discard

Every URL is configurable because other firms run the same gateway on other hosts. The examples read TOPSTEPX_USERNAME and TOPSTEPX_API_KEY, plus the optional TOPSTEPX_API_URL, TOPSTEPX_USER_HUB_URL and TOPSTEPX_MARKET_HUB_URL.

Authentication and token lifecycle

Log in with your platform username and an API key (Auth_LoginKey). With WithCredentials, the client does this lazily before the first authenticated call. You can also start from an existing token with WithToken, alone or together with credentials.

Before every authenticated request the client runs ensure-token:

  1. No token: log in when credentials are configured, otherwise fail with ErrNotAuthenticated before any network I/O.
  2. Token expired (now >= exp): log in when credentials are configured; otherwise send the request with the current token and let the server decide (clock skew).
  3. Token inside the refresh margin (now >= exp - 1h): call Auth_Validate and store its newToken. If that fails, log in when credentials are configured, and otherwise keep using the current, still-valid token.
  4. Otherwise use the stored token.

Renewal cooldown: when a renewal fails and the client keeps using the current token (step 3 without credentials, or with credentials when the re-login fails too), it does not call Auth_Validate again for 60 seconds (topstepx.RenewalCooldown). It uses the token as-is until the cooldown ends or the token expires, so a failing validate is not repeated before every request during the last hour. Storing any new token clears the cooldown.

Expiry comes from the JWT exp claim (decoded, never verified); a token that is not a decodable JWT is assumed to last 24 hours. Refreshes are single-flight: concurrent callers wait for one login or validate instead of stampeding.

An HTTP 401 on an authenticated request triggers one re-login and retry when credentials are configured (or a retry with a token another caller stored meanwhile); a second 401 returns an error matching ErrUnauthorized. A 401 never consumes the retry budget.

token, err := client.Token(ctx)           // ensure-token; also the realtime token provider
token, err = client.Auth.LoginKey(ctx, user, apiKey)
token, err = client.Auth.Validate(ctx)    // sends the current token, stores newToken
err = client.Auth.Logout(ctx)             // calls the endpoint, then clears the token (no-op without one)
client.InvalidateToken(token)             // discard a token the gateway rejected, if still stored

client.InvalidateToken(token) discards token only if it is still the stored token (a stale report never discards a newer one). The next call then logs in again when credentials are configured and fails with ErrNotAuthenticated otherwise. The realtime hubs call it when the gateway rejects a token (see Rejected tokens).

Auth.LoginApp targets Auth_LoginApp, which appears only in Swagger: the current authentication guide does not support application login; use LoginKey.

The API key and tokens are secrets. Client, LoginAPIKeyRequest, LoginAppRequest, LoginResponse and ValidateResponse redact them for every fmt verb (%v, %+v, %#v, ...) and in slog output, error messages never contain them, and the SDK never logs them.

Endpoint groups

Each high-level method checks the business result (see Error handling) and returns the payload.

Group Method Operation
client.Accounts Search(ctx, onlyActiveAccounts) ([]TradingAccount, error) POST /api/Account/search
client.Auth LoginKey(ctx, userName, apiKey) (string, error) POST /api/Auth/loginKey
LoginApp(ctx, LoginAppRequest) (string, error) (Swagger only, unsupported by the guide) POST /api/Auth/loginApp
Validate(ctx) (string, error) POST /api/Auth/validate (empty body)
Logout(ctx) error (Swagger only) POST /api/Auth/logout (empty body)
client.Contracts Search(ctx, searchText, live) ([]Contract, error) POST /api/Contract/search
SearchByID(ctx, contractID) (*Contract, error) POST /api/Contract/searchById
Available(ctx, live) ([]Contract, error) POST /api/Contract/available
client.History RetrieveBars(ctx, RetrieveBarRequest) ([]AggregateBar, error) POST /api/History/retrieveBars
client.Orders Search(ctx, SearchOrderRequest) ([]Order, error) POST /api/Order/search
SearchByID(ctx, accountID, orderID) (*Order, error) (Swagger only) POST /api/Order/searchById
SearchOpen(ctx, accountID) ([]Order, error) POST /api/Order/searchOpen
Query(ctx, SearchOrdersQueryRequest) (*OrdersQueryResult, error) (Swagger only) POST /api/Order/v2/query
Place(ctx, PlaceOrderRequest) (int64, error) POST /api/Order/place
Cancel(ctx, accountID, orderID) error POST /api/Order/cancel
Modify(ctx, ModifyOrderRequest) error POST /api/Order/modify
client.Positions SearchOpen(ctx, accountID) ([]Position, error) POST /api/Position/searchOpen
Close(ctx, accountID, contractID) error POST /api/Position/closeContract
PartialClose(ctx, accountID, contractID, size) error POST /api/Position/partialCloseContract
client.Status Ping(ctx) (string, error) (Swagger only) GET /api/Status/ping
client.Trades Search(ctx, SearchTradeRequest) ([]HalfTrade, error) POST /api/Trade/search

The live flag of the contract and bar methods selects the live or simulated market-data subscription; it says nothing about whether an account is simulated.

Status.Ping returns "pong" whether the gateway answers text/plain or a JSON string. It attaches a bearer token when one is held or obtainable. If obtaining one fails for any reason other than cancellation, including a failed login, it pings anonymously (anonymous access is unverified either way).

Placing orders
req := topstepx.NewLimitOrder(accountID, contractID, topstepx.OrderSideBid, 1,
	decimal.RequireFromString("6000.25")).
	WithCustomTag("my-unique-tag").
	WithStopLossBracket(8, topstepx.OrderTypeStop).
	WithTakeProfitBracket(16, topstepx.OrderTypeLimit)
orderID, err := client.Orders.Place(ctx, req)

Constructors exist for every supported type: NewMarketOrder, NewLimitOrder, NewStopOrder, NewTrailingStopOrder, NewJoinBidOrder and NewJoinAskOrder. Brackets require the account's Auto OCO Brackets mode. customTag must be unique within the account.

Trailing stops: in requests (PlaceOrderRequest.TrailPrice, ModifyOrderRequest.TrailPrice) trailPrice is an absolute stop price aligned to the tick size. In responses (Order.TrailPrice) it is a price distance.

Optional fields are pointers; topstepx.Ptr fills them: ModifyOrderRequest{AccountID: 1, OrderID: 2, Size: topstepx.Ptr(int32(3))}. Nil fields are omitted from the request.

Low-level escape hatch

client.Do(ctx, op, req, resp) performs any operation and decodes the complete envelope, without turning a business failure into an error. HTTP, transport, decode and validation errors are still returned, and authentication, rate limiting and retries behave as for the high-level methods. Use it to read fields the high-level methods discard, such as the orderId of a rejected order:

var resp topstepx.PlaceOrderResponse
if err := client.Do(ctx, topstepx.OpOrderPlaceOrder, req, &resp); err != nil {
	return err // HTTP/transport/decode/validation error
}
if resp.IsBusinessFailure() {
	fmt.Println("rejected", resp.ErrorCode, resp.OrderID)
}

topstepx.Operations() describes all 21 operations (method, path, auth mode, rate bucket, retry class). Do does not change the stored session.

Realtime (SignalR)

The realtime package implements the ASP.NET Core SignalR JSON hub protocol v1 over WebSockets itself (no SignalR library): it skips negotiation, sends the token both as the URL-encoded access_token query parameter and as a bearer header, pings after 15 s of client silence, treats 30 s of server silence as a lost connection and times invocations out after 30 s.

hub := realtime.NewUserHubForClient(client) // token provider = client.Token
if err := hub.Connect(ctx); err != nil {
	return err
}
defer hub.Close()
if err := hub.SubscribeOrders(ctx, accountID); err != nil {
	return err
}
for ev := range hub.Events() {
	switch ev := ev.(type) {
	case *realtime.OrderEvent:
		fmt.Println(ev.Order.ID, ev.Order.Status)
	case *realtime.StateEvent:
		fmt.Println("state:", ev.State, ev.Attempt, ev.Err)
	case *realtime.UnknownEvent:
		fmt.Println("undecodable", ev.Target, ev.Err)
	}
}
Hub Methods (each with an Unsubscribe* counterpart) Events
UserHub SubscribeAccounts(ctx), SubscribeOrders(ctx, accountID), SubscribePositions(ctx, accountID), SubscribeTrades(ctx, accountID) *AccountEvent, *OrderEvent, *PositionEvent, *UserTradeEvent
MarketHub SubscribeContractQuotes(ctx, contractID), SubscribeContractTrades(ctx, contractID), SubscribeContractMarketDepth(ctx, contractID) *QuoteEvent, *MarketTradesEvent, *DepthEvent

Both hubs also deliver *StateEvent (connected, reconnecting with attempt and cause, reconnected, closed with cause), *SubscriptionErrorEvent (a failed replay after a reconnect) and *UnknownEvent (unknown targets and undecodable payloads) on the same channel. hub.Invoke(ctx, method, args...) calls any hub method.

  • Reconnect: after a lost connection or a server close with allowReconnect: true, the hub reconnects with delays of 0, 1, 2, 5 and 10 s and then every 30 s, without an attempt limit, fetching a fresh token for every attempt. Configure it with WithReconnectPolicy(realtime.ReconnectPolicy{...}) (MaxAttempts: 0 disables it) or WithoutReconnect(). A close without allowReconnect ends the connection.
  • Rejected tokens: when the WebSocket upgrade is rejected with HTTP 401, on the initial Connect or on any reconnect attempt, the hub reports the rejected token through WithTokenRejected(func(token string)) before the next attempt. NewUserHubForClient and NewMarketHubForClient wire this to client.InvalidateToken, so the next attempt logs in again instead of reusing the token until it expires. The attempt fails with a *realtime.DialError whose StatusCode is 401 and which matches realtime.ErrUnauthorized (the same value as topstepx.ErrUnauthorized); a failed Connect returns it, a reconnect attempt reports it as the cause of the next StateReconnecting event. With a plain TokenProvider and no hook the hub works as before and still reports the 401 distinctly.
  • Subscriptions that succeed are recorded (deduplicated by method and arguments; a successful unsubscribe removes them) and replayed in insertion order after every reconnect, before the StateReconnected event. Invocations while disconnected or reconnecting fail fast with ErrNotConnected; invocations pending when the connection drops fail with ErrConnectionLost.
  • Backpressure: delivery never blocks the connection. When the buffered channel (WithEventBuffer, default 1024) is full, the oldest event is dropped (WithOverflowPolicy(realtime.DropNewest) drops the incoming one instead); Dropped() counts losses and the logger reports them.
  • Close() stops reconnecting, sends a SignalR close message, closes the socket, fails pending invocations with ErrClosed, waits for the hub's goroutines and closes the event channel after a final StateClosed event. It is idempotent.
  • Timings are configurable (WithKeepAliveInterval, WithServerTimeout, WithHandshakeTimeout, WithInvocationTimeout), as are WithURL, WithHTTPClient, WithReadLimit and WithLogger.

Payload provenance and lenient decoding. The payload models (GatewayUserAccount, GatewayUserOrder, GatewayUserPosition, GatewayUserTrade, GatewayQuote, GatewayTrade, GatewayDepth, plus DomType and TradeLogType) follow the official realtime guide; they are not assumed to equal the REST models. Every field except identifiers is a pointer because updates may be partial (quotes often carry only the changed fields). User-hub payloads may arrive bare, wrapped as {"action": n, "data": {...}} (the undocumented action is exposed as Action), or as arrays of either: each element becomes one event. Market trades and depth arrive as one object or an array and are normalized to a list in one event per message. Volumes accept integers, integral floats such as 3.0 and numeric strings. A payload that cannot be decoded arrives as *UnknownEvent with the raw arguments and the error; the connection is unaffected. Every data event also carries the Raw JSON.

Error handling

Condition Error Match with
success == false or errorCode != 0 (arrives with HTTP 200, including invalid credentials, errorCode 3) *APIError: Operation, Code, CodeName (or Unrecognized(<n>)), Message (may be nil), OrderID (place only), Response (full envelope) errors.As
HTTP 401 after the single re-login *HTTPError (StatusCode 401, Err = re-login failure if any) errors.Is(err, topstepx.ErrUnauthorized)
HTTP 429 after the retries *RateLimitError (RetryAfter when sent) errors.Is(err, topstepx.ErrRateLimited)
HTTP 400 and other statuses *HTTPError with Body, and Problem (RFC 7807 ProblemDetails, extensions included) when the body is one errors.As
No token and no credentials ErrNotAuthenticated (before any I/O) errors.Is
Client-side validation *ValidationError (Field, Reason) errors.As
Undecodable body, or a successful response without its payload *DecodeError with Body errors.As
DNS, connection, TLS, timeout *TransportError wrapping the cause errors.As; errors.Is(err, context.DeadlineExceeded) works
Realtime realtime.ErrNotConnected, ErrConnectionLost, ErrClosed, ErrInvocationTimeout, *HubError (invocation error), *HandshakeError, *DialError (token-free message, StatusCode; an upgrade rejected with 401 matches realtime.ErrUnauthorized / topstepx.ErrUnauthorized), *ServerCloseError errors.Is / errors.As

A returned orderId does not establish acceptance: a rejected order is an *APIError whose OrderID may be set.

id, err := client.Orders.Place(ctx, req)
var apiErr *topstepx.APIError
switch {
case errors.As(err, &apiErr):
	log.Printf("rejected: %s (code %d) orderId=%v", apiErr.CodeName, apiErr.Code, apiErr.OrderID)
case errors.Is(err, topstepx.ErrRateLimited):
	// back off
case err != nil:
	log.Print(err)
}

Responses are parsed as JSON whatever the Content-Type (text/plain, application/json, text/json); unknown members are ignored, hasBusinessFailure defaults to false and enums tolerate unknown values (OrderStatus(42).String() is "Unrecognized(42)").

Retries and rate limits

  • HTTP 429: every operation is retried up to WithMaxRetries times (default 3), waiting for Retry-After (delta-seconds or HTTP-date) when present and otherwise for the backoff: 1 s, 2 s, 4 s, ... capped at 30 s, without jitter.
  • HTTP 502, 503, 504 and transport errors: only read operations are retried, with the same budget and backoff. Writes (login, validate, logout, place, cancel, modify, close, partial close) are never retried for these, because they may already have run.
  • HTTP 401 follows the re-login rule and does not consume the budget. Nothing else is retried.

Client-side rate limiting uses a sliding window per bucket: History_GetBars 50 requests per 30 s, every other operation 200 per 60 s. A slot is taken before every HTTP attempt, including retries and logins; when the window is full the call waits (honoring its context) until the oldest entry expires. The limiter is per Client instance: separate clients or processes do not share it, so share one client per account. Replace the limits with WithRateLimits or disable them with WithoutRateLimiting.

Validation

Validation runs before any network I/O, login included, and returns a *ValidationError. It reproduces the spec's rules and nothing more:

  1. PlaceOrderRequest.Type must be Limit, Market, Stop, TrailingStop, JoinBid or JoinAsk (StopLimit, Unknown and unrecognized values are rejected).
  2. A TrailingStop order needs a non-nil TrailPrice.
  3. Bracket types must come from the same six values.
  4. RetrieveBarRequest.Limit must not exceed 20,000 (topstepx.MaxBars).
  5. PartialCloseContractPositionRequest.Size must be at least 1.

The request types expose the rules as Validate() error. The server remains the final authority: WithoutValidation() disables client-side checks.

Decimals and timestamps

Prices and balances are github.com/shopspring/decimal values (*decimal.Decimal when optional). They are always sent as JSON numbers ("limitPrice":6000.25, never "6000.25") and decoded from numbers without losing printed digits: 6000.25 is exactly 6000.25. The SDK never touches the global decimal.MarshalJSONWithoutQuotes; the models have their own JSON methods.

Timestamps are time.Time values in UTC. They are sent as RFC 3339 with a Z suffix and decoded leniently: Z or any numeric offset, 0 to 9 fractional digits (.NET emits 7), and a missing offset, which is read as UTC.

Absent optional fields decode as nil pointers. Absent arrays decode as nil slices, which Go treats as empty (length 0, safe to range over).

Spec unknowns and deviations

  • Swagger-only operations: Auth_LoginApp (unsupported by the current guide; use LoginKey), Auth_Logout, Order_SearchOrderById, Order_SearchOrdersQuery and Status_Ping are listed only in the gateway's Swagger schema. They are implemented, but their runtime availability is unverified. The pagination defaults and bounds of Order_SearchOrdersQuery are not published and none are invented.
  • Realtime payloads come from the official realtime guide, not from the REST models, and are decoded leniently as described above.
  • Undocumented bar fields: AggregateBar.D (JSON d, a date in Swagger) and AggregateBar.K (JSON k, an integer) are exposed raw and optional; their semantics are not guessed.
  • Order.UpdateTimestamp is required by the spec but optional here, so a null update time does not fail decoding. HalfTrade.ProfitAndLoss is nil for a half-turn trade.
Deviations and Go-specific decisions

These are either Go idioms or decisions on points the contract leaves open:

  • Field names. Go initialisms apply to identifiers (AccountID, SearchContractByIDRequest, LoginErrorCodeAPIKeyAuthenticationDisabled); JSON names and String() names match the spec exactly. AggregateBar uses descriptive field names (Time, Open, High, Low, Close, Volume) for the JSON members t, o, h, l, c, v.
  • Missing arrays decode as nil slices rather than allocated empty slices.
  • Auth.Logout sends the stored token as-is (no renewal or login first, no re-login on 401). Auth.LoginKey stores the token but does not configure the credentials for automatic re-login.
  • Failed renewal. When validate fails inside the refresh margin and the follow-up login also fails while the current token has not expired, the client logs a warning and keeps using the current token instead of failing the request; the renewal cooldown then applies as in step 3 without credentials.
  • HTTP 401 without credentials: if another caller replaced the token meanwhile, the request is still retried once with the new token.
  • Supersets: ProblemDetails is parsed for every non-2xx status, not only 400; decimal fields also accept numeric strings; the timestamp parser also accepts a t or space separator and +hhmm / +hh offsets; a realtime envelope whose data is an array and a quote payload that is an array each yield one event per element.
  • Missing payloads: a successful Place, Orders.SearchByID or Contracts.SearchByID response without its orderId / order / contract is a *DecodeError.
  • Do never changes the stored session (a login or validate through Do does not store the token; a logout does not clear it).
  • Realtime: the first Connect is not retried automatically (reconnection applies after a connection has been established); Unsubscribe* while disconnected fails with ErrNotConnected and keeps the registry entry; payload identifiers (id, accountId, contractId, symbolId, orderId, symbol) are plain values while every other field is a pointer; a state event is always enqueued but, like any buffered event, can be evicted under DropOldest when the consumer falls far behind (the channel closing still signals the end).

Examples

Example What it does
examples/accounts lists active accounts (read-only)
examples/contracts searches contracts and prints recent bars (read-only)
examples/realtime-user streams account, order, position and trade updates (read-only)
examples/realtime-market streams quotes, trades and optionally depth (read-only)
examples/place-order places a limit order and cancels it; refuses to run unless TOPSTEPX_ALLOW_TRADING=1 and refuses non-simulated accounts without -allow-live
TOPSTEPX_USERNAME=... TOPSTEPX_API_KEY=... go run ./examples/accounts

Running the tests

cd go
go test -race ./...
go vet ./...

The tests need no network access and no credentials: HTTP behavior runs against net/http/httptest servers and the realtime tests against a local WebSocket server that speaks the SignalR protocol. They cover spec conformance (reading ../spec/projectx-openapi.json: all 21 operations, every request and response example, a synthesized full-object round trip of all 45 object schemas and the exact (value, name) pairs of all 24 enums), the five negative cases of ../spec/validation-report.json, the HTTP rules (lazy login, business failures, 401 re-login, 429 and Retry-After, no retries of writes on 503, ProblemDetails, ping, refresh through validate, logout, single-flight refresh, rate limiting, secret redaction) and the realtime rules (handshake, invocations, event forms, unknown targets, keepalive, server timeout, reconnect with a fresh token and replay, rejected tokens on connect and reconnect against a local REST login, close, backpressure and goroutine cleanup).

Documentation

Overview

Package topstepx is a Go client for the ProjectX Gateway API as deployed by TopstepX.

It implements the cross-SDK behavior contract in spec/SDK_BEHAVIOR.md: typed models for all 21 REST operations, token lifecycle management (lazy API-key login, refresh through validate, single-flight re-login on HTTP 401), business-failure detection, retries, client-side rate limiting and request validation. The realtime SignalR hubs live in the realtime subpackage.

Quick start

client, err := topstepx.NewClient(
	topstepx.WithCredentials(os.Getenv("TOPSTEPX_USERNAME"), os.Getenv("TOPSTEPX_API_KEY")),
)
if err != nil {
	log.Fatal(err)
}
accounts, err := client.Accounts.Search(ctx, true)

The first authenticated call logs in with the API key and stores the token. Every method takes a context.Context and the Client is safe for concurrent use.

Errors

A response with success == false or a non-zero errorCode becomes an *APIError, even though it arrives with HTTP 200. Other failures are reported as *HTTPError (ErrUnauthorized for 401), *RateLimitError, *ValidationError, *DecodeError or *TransportError. Use errors.Is and errors.As to inspect them.

Wire format

Decimal fields use github.com/shopspring/decimal and are always sent as JSON numbers. Timestamps are time.Time values in UTC; they are sent as RFC 3339 with a "Z" suffix and decoded leniently (any offset, a missing offset read as UTC, and 0 to 9 fractional digits). Optional and nullable fields are pointers; use Ptr to fill them. Arrays missing from a response decode as nil slices, which behave as empty slices.

Orders placed through this package are real. Use simulated accounts while developing.

Index

Examples

Constants

View Source
const (
	// DefaultBaseURL is the TopstepX REST gateway.
	DefaultBaseURL = "https://api.topstepx.com"
	// DefaultUserHubURL is the TopstepX SignalR user hub.
	DefaultUserHubURL = "https://rtc.topstepx.com/hubs/user"
	// DefaultMarketHubURL is the TopstepX SignalR market hub.
	DefaultMarketHubURL = "https://rtc.topstepx.com/hubs/market"
	// DefaultUserAgent is sent with every request unless WithUserAgent overrides it.
	DefaultUserAgent = "topstepx-go/" + Version
	// DefaultTimeout bounds each HTTP attempt.
	DefaultTimeout = 30 * time.Second
	// DefaultConnectTimeout bounds TCP connection setup and the TLS handshake
	// of the default HTTP client.
	DefaultConnectTimeout = 10 * time.Second
	// DefaultMaxRetries is the retry budget for throttled and failed attempts.
	DefaultMaxRetries = 3
	// DefaultRetryBackoff is the first retry delay; it doubles per retry.
	DefaultRetryBackoff = 1 * time.Second
	// DefaultMaxRetryBackoff caps the retry delay.
	DefaultMaxRetryBackoff = 30 * time.Second
	// DefaultRefreshMargin is how long before expiry a token is renewed.
	DefaultRefreshMargin = time.Hour
	// DefaultTokenLifetime is assumed for tokens without a decodable JWT exp claim.
	DefaultTokenLifetime = 24 * time.Hour
	// RenewalCooldown is how long the client waits before calling validate
	// again after a failed renewal left it using the current token.
	RenewalCooldown = 60 * time.Second
)

Default configuration values from the cross-SDK contract (section 2).

View Source
const MaxBars = 20000

MaxBars is the largest RetrieveBarRequest.Limit the gateway accepts.

View Source
const Version = "0.1.0" // x-release-please-version

Version is the SDK version, also sent in the default User-Agent.

Variables

View Source
var (
	// ErrUnauthorized matches the *HTTPError of an HTTP 401 response that
	// survived the single re-login attempt.
	ErrUnauthorized = errors.New("topstepx: unauthorized")

	// ErrNotAuthenticated is returned, before any network I/O, when an
	// authenticated operation runs with neither a token nor credentials.
	ErrNotAuthenticated = errors.New("topstepx: not authenticated: no token and no credentials configured")

	// ErrRateLimited matches every *RateLimitError.
	ErrRateLimited = errors.New("topstepx: rate limited")
)

Sentinel errors, for use with errors.Is.

Functions

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to a copy of v. It fills optional fields:

req.EndTimestamp = topstepx.Ptr(time.Now())

Types

type APIError

type APIError struct {
	// Operation is the failed operation.
	Operation OperationID
	// Code is the raw errorCode.
	Code int
	// CodeName is the errorCode's name in the operation's error-code enum, or
	// "Unrecognized(<n>)" for a value the enum lacks.
	CodeName string
	// Message is the errorMessage, which the gateway may leave null.
	Message *string
	// OrderID is the orderId returned by Order_PlaceOrder, if any. A returned
	// identifier does not mean the order was accepted.
	OrderID *int64
	// Response is the complete decoded envelope, such as *PlaceOrderResponse.
	Response any
}

APIError is a business failure: a response with success == false or a non-zero errorCode. The gateway reports these with HTTP 200, including invalid login credentials (LoginErrorCodeInvalidCredentials).

func (*APIError) Error

func (e *APIError) Error() string

Error describes the failure.

type AccountsService

type AccountsService struct {
	// contains filtered or unexported fields
}

AccountsService searches trading accounts. Obtain it from Client.Accounts.

func (*AccountsService) Search

func (s *AccountsService) Search(ctx context.Context, onlyActiveAccounts bool) ([]TradingAccount, error)

Search returns the trading accounts (Account_SearchAccounts). With onlyActiveAccounts set, only active accounts are returned.

type AggregateBar

type AggregateBar struct {
	// Time is the bar timestamp (JSON "t").
	Time time.Time `json:"t"`
	// Open is the opening price (JSON "o").
	Open decimal.Decimal `json:"o"`
	// High is the highest price (JSON "h").
	High decimal.Decimal `json:"h"`
	// Low is the lowest price (JSON "l").
	Low decimal.Decimal `json:"l"`
	// Close is the closing price (JSON "c").
	Close decimal.Decimal `json:"c"`
	// Volume is the traded volume (JSON "v").
	Volume int64 `json:"v"`
	// D is the undocumented "d" member (a date in Swagger), exposed raw. Its
	// semantics are not described by the guides.
	D *string `json:"d,omitempty"`
	// K is the undocumented "k" integer member, exposed raw. Its semantics are
	// not described by the guides.
	K *int64 `json:"k,omitempty"`
}

AggregateBar is one historical OHLCV bar (spec schema AggregateBarModel). The spec's single-letter members map to descriptive field names.

func (AggregateBar) MarshalJSON

func (m AggregateBar) MarshalJSON() ([]byte, error)

MarshalJSON encodes the bar with decimals as JSON numbers.

func (*AggregateBar) UnmarshalJSON

func (m *AggregateBar) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the bar, reading the timestamp leniently.

type AggregateBarUnit

type AggregateBarUnit int32

AggregateBarUnit is the aggregation unit of historical bars (spec schema AggregateBarUnit). The guide documents Second through Month; Unspecified and Tick appear only in Swagger and their acceptance is unverified.

const (
	AggregateBarUnitUnspecified AggregateBarUnit = 0
	AggregateBarUnitSecond      AggregateBarUnit = 1
	AggregateBarUnitMinute      AggregateBarUnit = 2
	AggregateBarUnitHour        AggregateBarUnit = 3
	AggregateBarUnitDay         AggregateBarUnit = 4
	AggregateBarUnitWeek        AggregateBarUnit = 5
	AggregateBarUnitMonth       AggregateBarUnit = 6
	AggregateBarUnitTick        AggregateBarUnit = 7
)

AggregateBarUnit values.

func (AggregateBarUnit) IsKnown

func (v AggregateBarUnit) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (AggregateBarUnit) String

func (v AggregateBarUnit) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type AuthMode

type AuthMode int

AuthMode says how an operation authenticates.

const (
	// AuthNone sends no Authorization header (the login operations).
	AuthNone AuthMode = iota
	// AuthBearer requires a bearer token, obtained and renewed automatically.
	AuthBearer
	// AuthBearerIfAvailable attaches a bearer token when one is held or
	// obtainable and otherwise sends the request anonymously (Status_Ping).
	AuthBearerIfAvailable
)

AuthMode values.

func (AuthMode) String

func (m AuthMode) String() string

String returns the mode's name.

type AuthService

type AuthService struct {
	// contains filtered or unexported fields
}

AuthService manages the session token. Obtain it from Client.Auth.

Most programs never call it directly: with WithCredentials the client logs in lazily, renews the token through Validate inside the refresh margin and logs in again after expiry or HTTP 401.

func (*AuthService) LoginApp deprecated

func (s *AuthService) LoginApp(ctx context.Context, req LoginAppRequest) (string, error)

LoginApp performs application login (Auth_LoginApp) and stores the returned token.

Deprecated: application login appears only in the gateway's Swagger schema; the current authentication guide does not support it and says API-key login is the only supported way to create a session. Use LoginKey.

func (*AuthService) LoginKey

func (s *AuthService) LoginKey(ctx context.Context, userName, apiKey string) (string, error)

LoginKey logs in with a platform username and API key (Auth_LoginKey) and stores the returned token, which it also returns. On a business failure, such as invalid credentials (errorCode 3, InvalidCredentials, delivered with HTTP 200), it returns an *APIError and stores nothing.

LoginKey does not configure the credentials for automatic re-login; use WithCredentials for that.

func (*AuthService) Logout

func (s *AuthService) Logout(ctx context.Context) error

Logout ends the session (Auth_Logout) and then clears the stored token, whatever the result; a business failure is still returned. It sends the stored token as-is, without renewing it first, and does nothing when no token is stored. A later authenticated call logs in again when credentials are configured.

func (*AuthService) Validate

func (s *AuthService) Validate(ctx context.Context) (string, error)

Validate renews the session (Auth_Validate): it sends the current token, stores the returned newToken and returns it. When the response carries no newToken, the current token stays in use and is returned.

type CancelOrderErrorCode

type CancelOrderErrorCode int32

CancelOrderErrorCode is the errorCode of Order_CancelOrder responses (spec schema CancelOrderErrorCode). Zero means success.

const (
	CancelOrderErrorCodeSuccess         CancelOrderErrorCode = 0
	CancelOrderErrorCodeAccountNotFound CancelOrderErrorCode = 1
	CancelOrderErrorCodeOrderNotFound   CancelOrderErrorCode = 2
	CancelOrderErrorCodeRejected        CancelOrderErrorCode = 3
	CancelOrderErrorCodePending         CancelOrderErrorCode = 4
	CancelOrderErrorCodeUnknownError    CancelOrderErrorCode = 5
	CancelOrderErrorCodeAccountRejected CancelOrderErrorCode = 6
)

CancelOrderErrorCode values.

func (CancelOrderErrorCode) IsKnown

func (v CancelOrderErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (CancelOrderErrorCode) String

func (v CancelOrderErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type CancelOrderRequest

type CancelOrderRequest struct {
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// OrderID is the order to cancel.
	OrderID int64 `json:"orderId"`
}

CancelOrderRequest is the Order_CancelOrder request.

type CancelOrderResponse

type CancelOrderResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode CancelOrderErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
}

CancelOrderResponse is the Order_CancelOrder response.

func (*CancelOrderResponse) IsBusinessFailure

func (r *CancelOrderResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type Client

type Client struct {
	// Auth manages the session: login, validate and logout.
	Auth *AuthService
	// Accounts searches trading accounts.
	Accounts *AccountsService
	// Contracts searches contracts.
	Contracts *ContractsService
	// History retrieves historical bars.
	History *HistoryService
	// Orders searches, places, cancels and modifies orders.
	Orders *OrdersService
	// Positions searches and closes positions.
	Positions *PositionsService
	// Trades searches trades.
	Trades *TradesService
	// Status checks API responsiveness.
	Status *StatusService
	// contains filtered or unexported fields
}

Client is a ProjectX Gateway API client. It is safe for concurrent use.

Endpoint groups are exposed as fields, for example client.Orders.Place. Client.Do is the low-level escape hatch for any operation.

func NewClient

func NewClient(opts ...Option) (*Client, error)

NewClient returns a client configured by opts. Without WithCredentials or WithToken, authenticated calls fail with ErrNotAuthenticated until Auth.LoginKey succeeds.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	topstepx "github.com/CurtisTechSolutions/TopstepX/go"
)

func main() {
	client, err := topstepx.NewClient(
		topstepx.WithCredentials(os.Getenv("TOPSTEPX_USERNAME"), os.Getenv("TOPSTEPX_API_KEY")),
	)
	if err != nil {
		log.Fatal(err)
	}
	accounts, err := client.Accounts.Search(context.Background(), true) // logs in lazily
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range accounts {
		fmt.Println(a.ID, a.Name, a.Balance)
	}
}

func (*Client) BaseURL

func (c *Client) BaseURL() string

BaseURL returns the REST base URL.

func (*Client) CloseIdleConnections

func (c *Client) CloseIdleConnections()

CloseIdleConnections closes idle keep-alive connections of the client's HTTP client. The Client stays usable.

func (*Client) Do

func (c *Client) Do(ctx context.Context, op OperationID, req, resp any) error

Do performs any operation and decodes the complete response envelope into resp, a pointer such as *PlaceOrderResponse (or any value accepted by json.Unmarshal, such as *json.RawMessage). For Status_Ping, pass a *string.

Unlike the high-level methods, Do does not turn a business failure into an error: inspect the envelope's Success and ErrorCode, for example to read the orderId of a rejected order. HTTP, transport, decode and validation errors are still returned, and authentication, rate limiting and retries work as for the high-level methods.

req is the request body (a value or pointer of the operation's request type) and is ignored for operations without one (Auth_Validate, Auth_Logout and Status_Ping). Do never changes the stored session: a token returned by a login or validate operation is not stored and Auth_Logout does not clear it. Use Client.Auth for session management.

Example
package main

import (
	"context"
	"fmt"
	"log"

	topstepx "github.com/CurtisTechSolutions/TopstepX/go"
)

func main() {
	client, _ := topstepx.NewClient(topstepx.WithToken("token"))
	var resp topstepx.PlaceOrderResponse
	err := client.Do(context.Background(), topstepx.OpOrderPlaceOrder,
		topstepx.NewMarketOrder(123, "CON.F.US.EP.U25", topstepx.OrderSideAsk, 1), &resp)
	if err != nil {
		log.Fatal(err) // HTTP, transport, decode or validation error
	}
	if resp.IsBusinessFailure() {
		fmt.Println("rejected with code", resp.ErrorCode, "orderId", resp.OrderID)
	}
}

func (Client) Format

func (c Client) Format(f fmt.State, _ rune)

Format implements fmt.Formatter so that no verb prints a secret, whether the client is formatted by value or by pointer.

func (Client) GoString

func (c Client) GoString() string

GoString describes the client without secrets.

func (*Client) InvalidateToken

func (c *Client) InvalidateToken(token string)

InvalidateToken discards token when it is still the stored token, for example because the gateway rejected it. The next authenticated call, or Token, then logs in again when credentials are configured and fails with ErrNotAuthenticated otherwise. A token that was already replaced is ignored, so a stale report never discards a newer token.

The realtime hubs call it when a WebSocket upgrade is rejected with HTTP 401 (see realtime.WithTokenRejected), so that the next connection attempt does not reuse the rejected token until it expires.

func (Client) LogValue

func (c Client) LogValue() slog.Value

LogValue implements slog.LogValuer without secrets.

func (*Client) Logger

func (c *Client) Logger() *slog.Logger

Logger returns the client's logger.

func (*Client) MarketHubURL

func (c *Client) MarketHubURL() string

MarketHubURL returns the configured SignalR market hub URL.

func (Client) String

func (c Client) String() string

String describes the client without secrets.

func (*Client) Token

func (c *Client) Token(ctx context.Context) (string, error)

Token returns a usable session token, logging in or renewing it first when needed (the contract's ensure_token). Its signature matches the realtime package's token provider, so client.Token can be passed to the hubs.

func (*Client) UserHubURL

func (c *Client) UserHubURL() string

UserHubURL returns the configured SignalR user hub URL.

type CloseContractPositionRequest

type CloseContractPositionRequest struct {
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract whose position is closed.
	ContractID string `json:"contractId"`
}

CloseContractPositionRequest is the Position_CloseContractPosition request.

type ClosePositionErrorCode

type ClosePositionErrorCode int32

ClosePositionErrorCode is the errorCode of Position_CloseContractPosition responses (spec schema ClosePositionErrorCode). Zero means success.

const (
	ClosePositionErrorCodeSuccess           ClosePositionErrorCode = 0
	ClosePositionErrorCodeAccountNotFound   ClosePositionErrorCode = 1
	ClosePositionErrorCodePositionNotFound  ClosePositionErrorCode = 2
	ClosePositionErrorCodeContractNotFound  ClosePositionErrorCode = 3
	ClosePositionErrorCodeContractNotActive ClosePositionErrorCode = 4
	ClosePositionErrorCodeOrderRejected     ClosePositionErrorCode = 5
	ClosePositionErrorCodeOrderPending      ClosePositionErrorCode = 6
	ClosePositionErrorCodeUnknownError      ClosePositionErrorCode = 7
	ClosePositionErrorCodeAccountRejected   ClosePositionErrorCode = 8
)

ClosePositionErrorCode values.

func (ClosePositionErrorCode) IsKnown

func (v ClosePositionErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (ClosePositionErrorCode) String

func (v ClosePositionErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type ClosePositionResponse

type ClosePositionResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode ClosePositionErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
}

ClosePositionResponse is the Position_CloseContractPosition response.

func (*ClosePositionResponse) IsBusinessFailure

func (r *ClosePositionResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type Contract

type Contract struct {
	// ID is the contract identifier, such as "CON.F.US.EP.U25".
	ID string `json:"id"`
	// Name is the contract name, such as "ESU5".
	Name string `json:"name"`
	// Description is a human-readable description.
	Description string `json:"description"`
	// TickSize is the minimum price increment.
	TickSize decimal.Decimal `json:"tickSize"`
	// TickValue is the monetary value of one tick.
	TickValue decimal.Decimal `json:"tickValue"`
	// ActiveContract reports whether this is the active contract.
	ActiveContract bool `json:"activeContract"`
	// SymbolID is the symbol identifier, such as "F.US.EP".
	SymbolID string `json:"symbolId"`
}

Contract describes a tradable contract (spec schema ContractModel).

func (Contract) MarshalJSON

func (m Contract) MarshalJSON() ([]byte, error)

MarshalJSON encodes the contract with decimals as JSON numbers.

func (*Contract) UnmarshalJSON

func (m *Contract) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the contract.

type ContractsService

type ContractsService struct {
	// contains filtered or unexported fields
}

ContractsService searches contracts. Obtain it from Client.Contracts.

The live flag of each method selects the live or simulated market-data subscription; it says nothing about whether an account is simulated.

func (*ContractsService) Available

func (s *ContractsService) Available(ctx context.Context, live bool) ([]Contract, error)

Available returns the contracts available for the selected data subscription (Contract_AvailableContracts).

func (*ContractsService) Search

func (s *ContractsService) Search(ctx context.Context, searchText string, live bool) ([]Contract, error)

Search returns up to 20 contracts whose names match searchText (Contract_SearchContracts).

func (*ContractsService) SearchByID

func (s *ContractsService) SearchByID(ctx context.Context, contractID string) (*Contract, error)

SearchByID returns the contract with the given identifier (Contract_SearchContractById). A successful response without a contract is reported as a *DecodeError.

type DecodeError

type DecodeError struct {
	// Operation is the operation whose response failed to decode.
	Operation OperationID
	// StatusCode is the HTTP status code of the response.
	StatusCode int
	// Body is the response body text. Token values in responses of
	// token-bearing operations are replaced with "[REDACTED]".
	Body string
	// Err is the underlying decode error.
	Err error
}

DecodeError is a response body that could not be decoded, or a successful response that lacks the payload the operation returns.

func (*DecodeError) Error

func (e *DecodeError) Error() string

Error describes the failure without echoing the body.

func (*DecodeError) Unwrap

func (e *DecodeError) Unwrap() error

Unwrap returns Err.

type GatewayOrderFilter

type GatewayOrderFilter struct {
	// AccountID is the account to search.
	AccountID int32 `json:"accountId"`
	// Statuses optionally restricts the order statuses.
	Statuses []OrderStatus `json:"statuses,omitempty"`
	// ContractID optionally restricts the contract.
	ContractID *string `json:"contractId,omitempty"`
	// CreatedAfter optionally bounds the creation time from below.
	CreatedAfter *time.Time `json:"createdAfter,omitempty"`
	// CreatedBefore optionally bounds the creation time from above.
	CreatedBefore *time.Time `json:"createdBefore,omitempty"`
}

GatewayOrderFilter is the filter of SearchOrdersQueryRequest.

func (GatewayOrderFilter) MarshalJSON

func (r GatewayOrderFilter) MarshalJSON() ([]byte, error)

MarshalJSON encodes the filter with RFC 3339 UTC timestamps.

func (*GatewayOrderFilter) UnmarshalJSON

func (r *GatewayOrderFilter) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the filter, reading timestamps leniently.

type HTTPError

type HTTPError struct {
	// Operation is the failed operation.
	Operation OperationID
	// StatusCode is the HTTP status code.
	StatusCode int
	// Header holds the response headers.
	Header http.Header
	// Body is the response body text.
	Body string
	// Problem is the parsed RFC 7807 body, including extension members, when
	// the body is ProblemDetails JSON (Order_SearchOrdersQuery documents this
	// for HTTP 400).
	Problem *ProblemDetails
	// Err is the error that prevented recovery, such as a failed re-login
	// after HTTP 401. It is nil otherwise.
	Err error
}

HTTPError is a non-2xx HTTP response other than an exhausted 429 (see RateLimitError). An HTTP 401 response matches ErrUnauthorized.

func (*HTTPError) Error

func (e *HTTPError) Error() string

Error describes the failure, including a short prefix of the body.

func (*HTTPError) Is

func (e *HTTPError) Is(target error) bool

Is reports whether target is ErrUnauthorized and the status is 401.

func (*HTTPError) Unwrap

func (e *HTTPError) Unwrap() error

Unwrap returns Err.

type HalfTrade

type HalfTrade struct {
	// ID is the trade identifier.
	ID int64 `json:"id"`
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract identifier.
	ContractID string `json:"contractId"`
	// CreationTimestamp is when the trade happened.
	CreationTimestamp time.Time `json:"creationTimestamp"`
	// Price is the execution price.
	Price decimal.Decimal `json:"price"`
	// ProfitAndLoss is the realized profit and loss. Nil marks a half-turn
	// trade.
	ProfitAndLoss *decimal.Decimal `json:"profitAndLoss"`
	// Fees are the trade fees.
	Fees decimal.Decimal `json:"fees"`
	// Commissions are the trade commissions, if provided.
	Commissions *decimal.Decimal `json:"commissions,omitempty"`
	// Side is the trade side.
	Side OrderSide `json:"side"`
	// Size is the traded quantity.
	Size int32 `json:"size"`
	// Voided reports whether the trade was voided.
	Voided bool `json:"voided"`
	// OrderID is the order that produced the trade.
	OrderID int64 `json:"orderId"`
}

HalfTrade is an account trade (spec schema HalfTradeModel).

func (HalfTrade) MarshalJSON

func (m HalfTrade) MarshalJSON() ([]byte, error)

MarshalJSON encodes the trade with decimals as JSON numbers.

func (*HalfTrade) UnmarshalJSON

func (m *HalfTrade) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the trade, reading timestamps leniently.

type HistoryService

type HistoryService struct {
	// contains filtered or unexported fields
}

HistoryService retrieves historical bars. Obtain it from Client.History.

func (*HistoryService) RetrieveBars

func (s *HistoryService) RetrieveBars(ctx context.Context, req RetrieveBarRequest) ([]AggregateBar, error)

RetrieveBars returns historical OHLCV bars (History_GetBars). At most MaxBars bars may be requested. The operation has its own rate limit of 50 requests per 30 seconds.

type ListAvailableContractErrorCode

type ListAvailableContractErrorCode int32

ListAvailableContractErrorCode is the errorCode of Contract_AvailableContracts responses (spec schema ListAvailableContractErrorCode). Zero means success.

const (
	ListAvailableContractErrorCodeSuccess ListAvailableContractErrorCode = 0
)

ListAvailableContractErrorCode values.

func (ListAvailableContractErrorCode) IsKnown

IsKnown reports whether the spec lists the value.

func (ListAvailableContractErrorCode) String

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type ListAvailableContractRequest

type ListAvailableContractRequest struct {
	// Live selects the live (true) or simulated (false) data subscription.
	Live bool `json:"live"`
}

ListAvailableContractRequest is the Contract_AvailableContracts request.

type ListAvailableContractResponse

type ListAvailableContractResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode ListAvailableContractErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Contracts are the available contracts.
	Contracts []Contract `json:"contracts,omitempty"`
}

ListAvailableContractResponse is the Contract_AvailableContracts response. Missing arrays decode as nil slices.

func (*ListAvailableContractResponse) IsBusinessFailure

func (r *ListAvailableContractResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type LoginAPIKeyRequest

type LoginAPIKeyRequest struct {
	// UserName is the platform sign-in username (case-insensitive; not an
	// email address or account label).
	UserName string `json:"userName"`
	// APIKey is the API key issued in the firm's trading platform. It is a
	// secret.
	APIKey string `json:"apiKey"`
}

LoginAPIKeyRequest is the Auth_LoginKey request (spec schema LoginApiKeyRequest). Printing it with fmt or slog redacts the API key.

func (LoginAPIKeyRequest) Format

func (r LoginAPIKeyRequest) Format(f fmt.State, verb rune)

Format implements fmt.Formatter so that no verb prints the API key.

func (LoginAPIKeyRequest) GoString

func (r LoginAPIKeyRequest) GoString() string

GoString returns a Go-syntax representation with the API key redacted.

func (LoginAPIKeyRequest) LogValue

func (r LoginAPIKeyRequest) LogValue() slog.Value

LogValue implements slog.LogValuer with the API key redacted.

func (LoginAPIKeyRequest) String

func (r LoginAPIKeyRequest) String() string

String returns a representation with the API key redacted.

type LoginAppRequest

type LoginAppRequest struct {
	// UserName is the platform username.
	UserName string `json:"userName"`
	// Password is the account password. It is a secret.
	Password string `json:"password"`
	// DeviceID identifies the device.
	DeviceID string `json:"deviceId"`
	// AppID identifies the application.
	AppID string `json:"appId"`
	// VerifyKey is the application verification key. It is a secret.
	VerifyKey string `json:"verifyKey"`
}

LoginAppRequest is the Auth_LoginApp request. The current authentication guide does not support application login; use LoginAPIKeyRequest. Printing it with fmt or slog redacts the password and verify key.

func (LoginAppRequest) Format

func (r LoginAppRequest) Format(f fmt.State, verb rune)

Format implements fmt.Formatter so that no verb prints a secret.

func (LoginAppRequest) GoString

func (r LoginAppRequest) GoString() string

GoString returns a Go-syntax representation with secrets redacted.

func (LoginAppRequest) LogValue

func (r LoginAppRequest) LogValue() slog.Value

LogValue implements slog.LogValuer with secrets redacted.

func (LoginAppRequest) String

func (r LoginAppRequest) String() string

String returns a representation with secrets redacted.

type LoginErrorCode

type LoginErrorCode int32

LoginErrorCode is the errorCode of Auth_LoginKey and Auth_LoginApp responses (spec schema LoginErrorCode). Zero means success.

const (
	LoginErrorCodeSuccess                      LoginErrorCode = 0
	LoginErrorCodeUserNotFound                 LoginErrorCode = 1
	LoginErrorCodePasswordVerificationFailed   LoginErrorCode = 2
	LoginErrorCodeInvalidCredentials           LoginErrorCode = 3
	LoginErrorCodeAppNotFound                  LoginErrorCode = 4
	LoginErrorCodeAppVerificationFailed        LoginErrorCode = 5
	LoginErrorCodeInvalidDevice                LoginErrorCode = 6
	LoginErrorCodeAgreementsNotSigned          LoginErrorCode = 7
	LoginErrorCodeUnknownError                 LoginErrorCode = 8
	LoginErrorCodeAPISubscriptionNotFound      LoginErrorCode = 9
	LoginErrorCodeAPIKeyAuthenticationDisabled LoginErrorCode = 10
)

LoginErrorCode values.

func (LoginErrorCode) IsKnown

func (v LoginErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (LoginErrorCode) String

func (v LoginErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type LoginResponse

type LoginResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode LoginErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Token is the session JWT, null on failure. It is a secret.
	Token *string `json:"token,omitempty"`
}

LoginResponse is the Auth_LoginKey and Auth_LoginApp response.

func (LoginResponse) Format

func (r LoginResponse) Format(f fmt.State, verb rune)

Format implements fmt.Formatter so that no verb prints the token.

func (LoginResponse) GoString

func (r LoginResponse) GoString() string

GoString returns a Go-syntax representation with the token redacted.

func (*LoginResponse) IsBusinessFailure

func (r *LoginResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

func (LoginResponse) LogValue

func (r LoginResponse) LogValue() slog.Value

LogValue implements slog.LogValuer with the token redacted.

func (LoginResponse) String

func (r LoginResponse) String() string

String returns a representation with the token redacted.

type LogoutErrorCode

type LogoutErrorCode int32

LogoutErrorCode is the errorCode of Auth_Logout responses (spec schema LogoutErrorCode). Zero means success.

const (
	LogoutErrorCodeSuccess        LogoutErrorCode = 0
	LogoutErrorCodeInvalidSession LogoutErrorCode = 1
	LogoutErrorCodeUnknownError   LogoutErrorCode = 2
)

LogoutErrorCode values.

func (LogoutErrorCode) IsKnown

func (v LogoutErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (LogoutErrorCode) String

func (v LogoutErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type LogoutResponse

type LogoutResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode LogoutErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
}

LogoutResponse is the Auth_Logout response.

func (*LogoutResponse) IsBusinessFailure

func (r *LogoutResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type ModifyOrderErrorCode

type ModifyOrderErrorCode int32

ModifyOrderErrorCode is the errorCode of Order_ModifyOrder responses (spec schema ModifyOrderErrorCode). Zero means success.

const (
	ModifyOrderErrorCodeSuccess          ModifyOrderErrorCode = 0
	ModifyOrderErrorCodeAccountNotFound  ModifyOrderErrorCode = 1
	ModifyOrderErrorCodeOrderNotFound    ModifyOrderErrorCode = 2
	ModifyOrderErrorCodeRejected         ModifyOrderErrorCode = 3
	ModifyOrderErrorCodePending          ModifyOrderErrorCode = 4
	ModifyOrderErrorCodeUnknownError     ModifyOrderErrorCode = 5
	ModifyOrderErrorCodeAccountRejected  ModifyOrderErrorCode = 6
	ModifyOrderErrorCodeContractNotFound ModifyOrderErrorCode = 7
)

ModifyOrderErrorCode values.

func (ModifyOrderErrorCode) IsKnown

func (v ModifyOrderErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (ModifyOrderErrorCode) String

func (v ModifyOrderErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type ModifyOrderRequest

type ModifyOrderRequest struct {
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// OrderID is the order to modify.
	OrderID int64 `json:"orderId"`
	// Size is the new quantity.
	Size *int32 `json:"size,omitempty"`
	// LimitPrice is the new limit price.
	LimitPrice *decimal.Decimal `json:"limitPrice,omitempty"`
	// StopPrice is the new stop price.
	StopPrice *decimal.Decimal `json:"stopPrice,omitempty"`
	// TrailPrice is the new ABSOLUTE trailing-stop level, not a distance. The
	// server recalculates the tick distance from its current last price.
	TrailPrice *decimal.Decimal `json:"trailPrice,omitempty"`
}

ModifyOrderRequest is the Order_ModifyOrder request. Nil fields are left unchanged and are omitted from the request. Prices are sent as JSON numbers.

func (ModifyOrderRequest) MarshalJSON

func (r ModifyOrderRequest) MarshalJSON() ([]byte, error)

MarshalJSON encodes the request with prices as JSON numbers.

func (*ModifyOrderRequest) UnmarshalJSON

func (r *ModifyOrderRequest) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the request.

type ModifyOrderResponse

type ModifyOrderResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode ModifyOrderErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
}

ModifyOrderResponse is the Order_ModifyOrder response.

func (*ModifyOrderResponse) IsBusinessFailure

func (r *ModifyOrderResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type OperationID

type OperationID string

OperationID is the spec operationId of a REST operation. Pass it to Client.Do.

const (
	OpAccountSearchAccounts                OperationID = "Account_SearchAccounts"
	OpAuthLoginApp                         OperationID = "Auth_LoginApp"
	OpAuthLoginKey                         OperationID = "Auth_LoginKey"
	OpAuthLogout                           OperationID = "Auth_Logout"
	OpAuthValidate                         OperationID = "Auth_Validate"
	OpContractSearchContracts              OperationID = "Contract_SearchContracts"
	OpContractSearchContractByID           OperationID = "Contract_SearchContractById"
	OpContractAvailableContracts           OperationID = "Contract_AvailableContracts"
	OpHistoryGetBars                       OperationID = "History_GetBars"
	OpOrderSearchOrders                    OperationID = "Order_SearchOrders"
	OpOrderSearchOrderByID                 OperationID = "Order_SearchOrderById"
	OpOrderSearchOpenOrders                OperationID = "Order_SearchOpenOrders"
	OpOrderSearchOrdersQuery               OperationID = "Order_SearchOrdersQuery"
	OpOrderPlaceOrder                      OperationID = "Order_PlaceOrder"
	OpOrderCancelOrder                     OperationID = "Order_CancelOrder"
	OpOrderModifyOrder                     OperationID = "Order_ModifyOrder"
	OpPositionSearchOpenPositions          OperationID = "Position_SearchOpenPositions"
	OpPositionCloseContractPosition        OperationID = "Position_CloseContractPosition"
	OpPositionPartialCloseContractPosition OperationID = "Position_PartialCloseContractPosition"
	OpStatusPing                           OperationID = "Status_Ping"
	OpTradeSearchHalfTurnTrades            OperationID = "Trade_SearchHalfTurnTrades"
)

The 21 REST operations of the ProjectX Gateway API.

func (OperationID) Info

func (id OperationID) Info() (OperationInfo, bool)

Info returns the description of the operation.

func (OperationID) String

func (id OperationID) String() string

String returns the operationId.

type OperationInfo

type OperationInfo struct {
	// ID is the spec operationId.
	ID OperationID
	// Method is the HTTP method.
	Method string
	// Path is the request path, relative to the base URL.
	Path string
	// Auth is the authentication mode.
	Auth AuthMode
	// RateBucket is the client-side rate-limit bucket.
	RateBucket RateBucket
	// RetryClass decides which failures are retried.
	RetryClass RetryClass
	// HasBody reports whether the operation sends a JSON request body.
	// Auth_Validate and Auth_Logout are POSTs with an empty body.
	HasBody bool
}

OperationInfo describes one REST operation.

func Operations

func Operations() []OperationInfo

Operations returns the descriptions of all 21 operations.

type Option

type Option func(*settings) error

Option configures a Client. Options are applied in order by NewClient.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL sets the REST base URL (default DefaultBaseURL). Other firms run the same gateway on other hosts.

func WithCredentials

func WithCredentials(userName, apiKey string) Option

WithCredentials configures the platform username and API key used to log in (lazily, on the first authenticated call) and to log in again when the token expires or the gateway answers HTTP 401. The API key is never printed or logged.

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient sets the HTTP client. The default client uses a 10 second connect and TLS-handshake timeout.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the logger for request, retry and session diagnostics. The default discards everything. Secrets are never logged.

func WithMarketHubURL

func WithMarketHubURL(hubURL string) Option

WithMarketHubURL sets the SignalR market hub URL reported by MarketHubURL (default DefaultMarketHubURL).

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the retry budget (default DefaultMaxRetries). Zero disables retries. HTTP 401 re-login does not consume the budget.

func WithRateLimits

func WithRateLimits(limits RateLimits) Option

WithRateLimits replaces the client-side rate limits (default DefaultRateLimits) and enables limiting.

func WithRefreshMargin

func WithRefreshMargin(d time.Duration) Option

WithRefreshMargin sets how long before expiry the token is renewed through Auth_Validate (default DefaultRefreshMargin). Zero renews only on expiry.

func WithRetryBackoff

func WithRetryBackoff(initial, maxDelay time.Duration) Option

WithRetryBackoff sets the first retry delay and its cap (defaults DefaultRetryBackoff and DefaultMaxRetryBackoff). The delay doubles per retry and has no jitter. A Retry-After header on HTTP 429 takes precedence.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout bounds each HTTP attempt (default DefaultTimeout). Zero disables the per-attempt timeout; the context still applies.

func WithToken

func WithToken(token string) Option

WithToken configures a pre-existing session token, used instead of or in addition to credentials. Its expiry is read from the JWT exp claim, or assumed to be 24 hours away.

func WithUserAgent

func WithUserAgent(userAgent string) Option

WithUserAgent sets the User-Agent header (default DefaultUserAgent).

func WithUserHubURL

func WithUserHubURL(hubURL string) Option

WithUserHubURL sets the SignalR user hub URL reported by UserHubURL (default DefaultUserHubURL).

func WithoutRateLimiting

func WithoutRateLimiting() Option

WithoutRateLimiting disables client-side rate limiting.

func WithoutValidation

func WithoutValidation() Option

WithoutValidation disables client-side request validation; the server remains the final authority.

type Order

type Order struct {
	// ID is the order identifier.
	ID int64 `json:"id"`
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract identifier.
	ContractID string `json:"contractId"`
	// SymbolID is the symbol identifier.
	SymbolID string `json:"symbolId"`
	// CreationTimestamp is when the order was created.
	CreationTimestamp time.Time `json:"creationTimestamp"`
	// UpdateTimestamp is when the order last changed. The spec requires it,
	// but it is optional here so that a null update time does not fail
	// decoding.
	UpdateTimestamp *time.Time `json:"updateTimestamp"`
	// Status is the order status.
	Status OrderStatus `json:"status"`
	// Type is the order type.
	Type OrderType `json:"type"`
	// Side is the order side.
	Side OrderSide `json:"side"`
	// Size is the order quantity.
	Size int32 `json:"size"`
	// LimitPrice is the limit price, if any.
	LimitPrice *decimal.Decimal `json:"limitPrice,omitempty"`
	// StopPrice is the stop price, if any.
	StopPrice *decimal.Decimal `json:"stopPrice,omitempty"`
	// FillVolume is the filled quantity.
	FillVolume int32 `json:"fillVolume"`
	// FilledPrice is the fill price, if any.
	FilledPrice *decimal.Decimal `json:"filledPrice,omitempty"`
	// CustomTag is the caller-supplied tag, if any.
	CustomTag *string `json:"customTag,omitempty"`
	// TrailDistance is the trailing distance in ticks, if any.
	TrailDistance *int32 `json:"trailDistance,omitempty"`
	// TrailPrice is, for a returned trailing stop, the price DISTANCE (ticks
	// multiplied by tickSize), not the absolute level submitted in
	// PlaceOrderRequest.TrailPrice.
	TrailPrice *decimal.Decimal `json:"trailPrice,omitempty"`
	// ParentOrderID links a bracket order to its parent, if any.
	ParentOrderID *int64 `json:"parentOrderId,omitempty"`
	// LinkedOrderID links an order to its OCO sibling, if any.
	LinkedOrderID *int64 `json:"linkedOrderId,omitempty"`
}

Order is an order (spec schema OrderModel).

func (Order) MarshalJSON

func (m Order) MarshalJSON() ([]byte, error)

MarshalJSON encodes the order with decimals as JSON numbers.

func (*Order) UnmarshalJSON

func (m *Order) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the order, reading timestamps leniently.

type OrderSide

type OrderSide int32

OrderSide is the side of an order or trade (spec schema OrderSide): Bid buys and Ask sells.

const (
	OrderSideBid OrderSide = 0
	OrderSideAsk OrderSide = 1
)

OrderSide values.

func (OrderSide) IsKnown

func (v OrderSide) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (OrderSide) String

func (v OrderSide) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type OrderSortField

type OrderSortField int32

OrderSortField selects the sort key of Order_SearchOrdersQuery (spec schema OrderSortField).

const (
	OrderSortFieldCreatedAt OrderSortField = 0
	OrderSortFieldID        OrderSortField = 1
)

OrderSortField values.

func (OrderSortField) IsKnown

func (v OrderSortField) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (OrderSortField) String

func (v OrderSortField) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type OrderStatus

type OrderStatus int32

OrderStatus is the lifecycle status of an order (spec schema OrderStatus).

const (
	OrderStatusNone                OrderStatus = 0
	OrderStatusOpen                OrderStatus = 1
	OrderStatusFilled              OrderStatus = 2
	OrderStatusCancelled           OrderStatus = 3
	OrderStatusExpired             OrderStatus = 4
	OrderStatusRejected            OrderStatus = 5
	OrderStatusPending             OrderStatus = 6
	OrderStatusPendingCancellation OrderStatus = 7
	OrderStatusSuspended           OrderStatus = 8
)

OrderStatus values.

func (OrderStatus) IsKnown

func (v OrderStatus) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (OrderStatus) String

func (v OrderStatus) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type OrderType

type OrderType int32

OrderType is the type of an order (spec schema OrderType). Placement and brackets accept Limit, Market, Stop, TrailingStop, JoinBid and JoinAsk; Unknown and StopLimit appear only in responses.

const (
	OrderTypeUnknown      OrderType = 0
	OrderTypeLimit        OrderType = 1
	OrderTypeMarket       OrderType = 2
	OrderTypeStopLimit    OrderType = 3
	OrderTypeStop         OrderType = 4
	OrderTypeTrailingStop OrderType = 5
	OrderTypeJoinBid      OrderType = 6
	OrderTypeJoinAsk      OrderType = 7
)

OrderType values.

func (OrderType) IsKnown

func (v OrderType) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (OrderType) String

func (v OrderType) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type OrdersQueryResult

type OrdersQueryResult struct {
	// Orders are the orders of the requested page.
	Orders []Order
	// TotalCount is the number of matching orders, present when requested
	// with IncludeTotalCount.
	TotalCount *int32
}

OrdersQueryResult is the payload of Orders.Query.

type OrdersService

type OrdersService struct {
	// contains filtered or unexported fields
}

OrdersService searches and manages orders. Obtain it from Client.Orders.

Orders are real. Use simulated accounts while developing.

func (*OrdersService) Cancel

func (s *OrdersService) Cancel(ctx context.Context, accountID int32, orderID int64) error

Cancel cancels an order (Order_CancelOrder). Cancellation is documented for simulated accounts that are not copy-trading followers.

func (*OrdersService) Modify

Modify changes an open order (Order_ModifyOrder). Nil fields of req are left unchanged; ModifyOrderRequest.TrailPrice is an absolute level.

func (*OrdersService) Place

func (s *OrdersService) Place(ctx context.Context, req PlaceOrderRequest) (int64, error)

Place submits an order (Order_PlaceOrder) and returns its identifier.

A rejected order is an *APIError whose OrderID holds the identifier the gateway may still return; that identifier does not mean the order was accepted. Place is never retried on HTTP 5xx or transport errors, since the order may already exist. Brackets need the account's Auto OCO Brackets mode, and PlaceOrderRequest.TrailPrice is an absolute price.

Example
package main

import (
	"context"
	"errors"
	"fmt"

	topstepx "github.com/CurtisTechSolutions/TopstepX/go"
	"github.com/shopspring/decimal"
)

func main() {
	client, _ := topstepx.NewClient(topstepx.WithCredentials("user", "api-key"))
	req := topstepx.NewLimitOrder(123, "CON.F.US.EP.U25", topstepx.OrderSideBid, 1, decimal.RequireFromString("6000.25")).
		WithStopLossBracket(8, topstepx.OrderTypeStop).
		WithTakeProfitBracket(16, topstepx.OrderTypeLimit)
	id, err := client.Orders.Place(context.Background(), req)
	var apiErr *topstepx.APIError
	if errors.As(err, &apiErr) {
		// A rejected order can still carry an identifier.
		fmt.Println("rejected:", apiErr.CodeName, apiErr.OrderID)
		return
	}
	fmt.Println("placed", id, err)
}

func (*OrdersService) Query

Query filters, sorts and pages the account's orders (Order_SearchOrdersQuery, listed only in Swagger). An HTTP 400 response carries a parsed ProblemDetails in the returned *HTTPError.

func (*OrdersService) Search

func (s *OrdersService) Search(ctx context.Context, req SearchOrderRequest) ([]Order, error)

Search returns the account's orders created in the requested range (Order_SearchOrders).

func (*OrdersService) SearchByID

func (s *OrdersService) SearchByID(ctx context.Context, accountID int32, orderID int64) (*Order, error)

SearchByID returns one order of the account (Order_SearchOrderById, listed only in Swagger). A successful response without an order is reported as a *DecodeError.

func (*OrdersService) SearchOpen

func (s *OrdersService) SearchOpen(ctx context.Context, accountID int32) ([]Order, error)

SearchOpen returns the account's open orders (Order_SearchOpenOrders).

type PartialCloseContractPositionRequest

type PartialCloseContractPositionRequest struct {
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract whose position is reduced.
	ContractID string `json:"contractId"`
	// Size is the quantity to close: at least 1 and no larger than the open
	// position.
	Size int32 `json:"size"`
}

PartialCloseContractPositionRequest is the Position_PartialCloseContractPosition request.

func (PartialCloseContractPositionRequest) Validate

Validate checks that Size is at least 1. It returns a *ValidationError.

type PartialClosePositionErrorCode

type PartialClosePositionErrorCode int32

PartialClosePositionErrorCode is the errorCode of Position_PartialCloseContractPosition responses (spec schema PartialClosePositionErrorCode). Zero means success.

const (
	PartialClosePositionErrorCodeSuccess           PartialClosePositionErrorCode = 0
	PartialClosePositionErrorCodeAccountNotFound   PartialClosePositionErrorCode = 1
	PartialClosePositionErrorCodePositionNotFound  PartialClosePositionErrorCode = 2
	PartialClosePositionErrorCodeContractNotFound  PartialClosePositionErrorCode = 3
	PartialClosePositionErrorCodeContractNotActive PartialClosePositionErrorCode = 4
	PartialClosePositionErrorCodeInvalidCloseSize  PartialClosePositionErrorCode = 5
	PartialClosePositionErrorCodeOrderRejected     PartialClosePositionErrorCode = 6
	PartialClosePositionErrorCodeOrderPending      PartialClosePositionErrorCode = 7
	PartialClosePositionErrorCodeUnknownError      PartialClosePositionErrorCode = 8
	PartialClosePositionErrorCodeAccountRejected   PartialClosePositionErrorCode = 9
)

PartialClosePositionErrorCode values.

func (PartialClosePositionErrorCode) IsKnown

func (v PartialClosePositionErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (PartialClosePositionErrorCode) String

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type PartialClosePositionResponse

type PartialClosePositionResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode PartialClosePositionErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
}

PartialClosePositionResponse is the Position_PartialCloseContractPosition response.

func (*PartialClosePositionResponse) IsBusinessFailure

func (r *PartialClosePositionResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type PlaceOrderBracket

type PlaceOrderBracket struct {
	// Ticks is the bracket distance in ticks.
	Ticks int32 `json:"ticks"`
	// Type must be Limit, Market, Stop, TrailingStop, JoinBid or JoinAsk.
	Type OrderType `json:"type"`
}

PlaceOrderBracket is a stop-loss or take-profit bracket, placed the given number of ticks from the fill.

type PlaceOrderErrorCode

type PlaceOrderErrorCode int32

PlaceOrderErrorCode is the errorCode of Order_PlaceOrder responses (spec schema PlaceOrderErrorCode). Zero means success.

const (
	PlaceOrderErrorCodeSuccess             PlaceOrderErrorCode = 0
	PlaceOrderErrorCodeAccountNotFound     PlaceOrderErrorCode = 1
	PlaceOrderErrorCodeOrderRejected       PlaceOrderErrorCode = 2
	PlaceOrderErrorCodeInsufficientFunds   PlaceOrderErrorCode = 3
	PlaceOrderErrorCodeAccountViolation    PlaceOrderErrorCode = 4
	PlaceOrderErrorCodeOutsideTradingHours PlaceOrderErrorCode = 5
	PlaceOrderErrorCodeOrderPending        PlaceOrderErrorCode = 6
	PlaceOrderErrorCodeUnknownError        PlaceOrderErrorCode = 7
	PlaceOrderErrorCodeContractNotFound    PlaceOrderErrorCode = 8
	PlaceOrderErrorCodeContractNotActive   PlaceOrderErrorCode = 9
	PlaceOrderErrorCodeAccountRejected     PlaceOrderErrorCode = 10
)

PlaceOrderErrorCode values.

func (PlaceOrderErrorCode) IsKnown

func (v PlaceOrderErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (PlaceOrderErrorCode) String

func (v PlaceOrderErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type PlaceOrderRequest

type PlaceOrderRequest struct {
	// AccountID is the account that places the order.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract to trade.
	ContractID string `json:"contractId"`
	// Type must be Limit, Market, Stop, TrailingStop, JoinBid or JoinAsk.
	Type OrderType `json:"type"`
	// Side is Bid (buy) or Ask (sell).
	Side OrderSide `json:"side"`
	// Size is the order quantity.
	Size int32 `json:"size"`
	// LimitPrice is the limit price for limit orders.
	LimitPrice *decimal.Decimal `json:"limitPrice,omitempty"`
	// StopPrice is the stop price for stop orders.
	StopPrice *decimal.Decimal `json:"stopPrice,omitempty"`
	// TrailPrice is required for TrailingStop orders. It is an ABSOLUTE stop
	// price aligned to the contract's tickSize, not a distance; the server
	// converts its gap from the last price into whole ticks and rejects
	// initial trails above 1,000 ticks. (Order.TrailPrice in responses is a
	// distance.)
	TrailPrice *decimal.Decimal `json:"trailPrice,omitempty"`
	// CustomTag is an optional tag that must be unique within the account.
	CustomTag *string `json:"customTag,omitempty"`
	// StopLossBracket attaches a stop-loss bracket. Brackets require the
	// account's Auto OCO Brackets mode.
	StopLossBracket *PlaceOrderBracket `json:"stopLossBracket,omitempty"`
	// TakeProfitBracket attaches a take-profit bracket. Brackets require the
	// account's Auto OCO Brackets mode.
	TakeProfitBracket *PlaceOrderBracket `json:"takeProfitBracket,omitempty"`
}

PlaceOrderRequest is the Order_PlaceOrder request. Build one with NewMarketOrder, NewLimitOrder, NewStopOrder, NewTrailingStopOrder, NewJoinBidOrder or NewJoinAskOrder and refine it with the With methods.

Prices are sent as JSON numbers. Orders are real: use simulated accounts while developing.

func NewJoinAskOrder

func NewJoinAskOrder(accountID int32, contractID string, side OrderSide, size int32) PlaceOrderRequest

NewJoinAskOrder returns a JoinAsk order request.

func NewJoinBidOrder

func NewJoinBidOrder(accountID int32, contractID string, side OrderSide, size int32) PlaceOrderRequest

NewJoinBidOrder returns a JoinBid order request.

func NewLimitOrder

func NewLimitOrder(accountID int32, contractID string, side OrderSide, size int32, limitPrice decimal.Decimal) PlaceOrderRequest

NewLimitOrder returns a limit order request at limitPrice.

func NewMarketOrder

func NewMarketOrder(accountID int32, contractID string, side OrderSide, size int32) PlaceOrderRequest

NewMarketOrder returns a market order request.

func NewStopOrder

func NewStopOrder(accountID int32, contractID string, side OrderSide, size int32, stopPrice decimal.Decimal) PlaceOrderRequest

NewStopOrder returns a stop order request triggered at stopPrice.

func NewTrailingStopOrder

func NewTrailingStopOrder(accountID int32, contractID string, side OrderSide, size int32, trailPrice decimal.Decimal) PlaceOrderRequest

NewTrailingStopOrder returns a trailing-stop order request. trailPrice is the ABSOLUTE initial stop price aligned to tickSize, not a distance.

func (PlaceOrderRequest) MarshalJSON

func (r PlaceOrderRequest) MarshalJSON() ([]byte, error)

MarshalJSON encodes the request with prices as JSON numbers.

func (*PlaceOrderRequest) UnmarshalJSON

func (r *PlaceOrderRequest) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the request.

func (PlaceOrderRequest) Validate

func (r PlaceOrderRequest) Validate() error

Validate checks the placement rules of the spec: the order type and both bracket types must be Limit, Market, Stop, TrailingStop, JoinBid or JoinAsk (StopLimit and Unknown are rejected), and a TrailingStop order needs a non-nil TrailPrice. It returns a *ValidationError.

func (PlaceOrderRequest) WithCustomTag

func (r PlaceOrderRequest) WithCustomTag(tag string) PlaceOrderRequest

WithCustomTag returns a copy of r with the custom tag set. The tag must be unique within the account.

func (PlaceOrderRequest) WithStopLossBracket

func (r PlaceOrderRequest) WithStopLossBracket(ticks int32, typ OrderType) PlaceOrderRequest

WithStopLossBracket returns a copy of r with a stop-loss bracket ticks away from the fill, placed as an order of type typ.

func (PlaceOrderRequest) WithTakeProfitBracket

func (r PlaceOrderRequest) WithTakeProfitBracket(ticks int32, typ OrderType) PlaceOrderRequest

WithTakeProfitBracket returns a copy of r with a take-profit bracket ticks away from the fill, placed as an order of type typ.

type PlaceOrderResponse

type PlaceOrderResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode PlaceOrderErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// OrderID is the order identifier. It can be present on a business
	// failure too; an identifier does not establish acceptance.
	OrderID *int64 `json:"orderId,omitempty"`
}

PlaceOrderResponse is the Order_PlaceOrder response.

func (*PlaceOrderResponse) IsBusinessFailure

func (r *PlaceOrderResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type Position

type Position struct {
	// ID is the position identifier.
	ID int32 `json:"id"`
	// AccountID is the owning account.
	AccountID int32 `json:"accountId"`
	// ContractID is the contract identifier.
	ContractID string `json:"contractId"`
	// ContractDisplayName is the contract's display name, if provided.
	ContractDisplayName *string `json:"contractDisplayName,omitempty"`
	// CreationTimestamp is when the position was opened.
	CreationTimestamp time.Time `json:"creationTimestamp"`
	// Type is the position direction.
	Type PositionType `json:"type"`
	// Size is the position quantity.
	Size int32 `json:"size"`
	// AveragePrice is the average entry price.
	AveragePrice decimal.Decimal `json:"averagePrice"`
}

Position is an open position (spec schema PositionModel).

func (Position) MarshalJSON

func (m Position) MarshalJSON() ([]byte, error)

MarshalJSON encodes the position with decimals as JSON numbers.

func (*Position) UnmarshalJSON

func (m *Position) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the position, reading timestamps leniently.

type PositionType

type PositionType int32

PositionType is the direction of a position (spec schema PositionType).

const (
	PositionTypeUndefined PositionType = 0
	PositionTypeLong      PositionType = 1
	PositionTypeShort     PositionType = 2
)

PositionType values.

func (PositionType) IsKnown

func (v PositionType) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (PositionType) String

func (v PositionType) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type PositionsService

type PositionsService struct {
	// contains filtered or unexported fields
}

PositionsService searches and closes positions. Obtain it from Client.Positions.

func (*PositionsService) Close

func (s *PositionsService) Close(ctx context.Context, accountID int32, contractID string) error

Close closes the account's position in the contract (Position_CloseContractPosition). It is never retried on HTTP 5xx or transport errors.

func (*PositionsService) PartialClose

func (s *PositionsService) PartialClose(ctx context.Context, accountID int32, contractID string, size int32) error

PartialClose reduces the account's position in the contract by size, which must be at least 1 (Position_PartialCloseContractPosition). It is never retried on HTTP 5xx or transport errors.

func (*PositionsService) SearchOpen

func (s *PositionsService) SearchOpen(ctx context.Context, accountID int32) ([]Position, error)

SearchOpen returns the account's open positions (Position_SearchOpenPositions).

type ProblemDetails

type ProblemDetails struct {
	// Type is a URI reference identifying the problem type.
	Type *string `json:"type,omitempty"`
	// Title is a short summary of the problem type.
	Title *string `json:"title,omitempty"`
	// Status is the HTTP status code.
	Status *int32 `json:"status,omitempty"`
	// Detail explains this occurrence of the problem.
	Detail *string `json:"detail,omitempty"`
	// Instance identifies this occurrence of the problem.
	Instance *string `json:"instance,omitempty"`
	// Extensions holds every other member, such as "traceId" or "errors",
	// as raw JSON.
	Extensions map[string]json.RawMessage `json:"-"`
}

ProblemDetails is an RFC 7807 error body (spec schema ProblemDetails). Members other than the five standard ones are kept in Extensions.

func (ProblemDetails) MarshalJSON

func (p ProblemDetails) MarshalJSON() ([]byte, error)

MarshalJSON encodes the standard members followed by the extensions in key order.

func (*ProblemDetails) UnmarshalJSON

func (p *ProblemDetails) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the standard members and collects the rest in Extensions.

type RateBucket

type RateBucket int

RateBucket is the client-side rate-limit bucket of an operation.

const (
	// RateBucketGeneral covers every operation except History_GetBars.
	RateBucketGeneral RateBucket = iota
	// RateBucketHistory covers History_GetBars.
	RateBucketHistory
)

RateBucket values.

func (RateBucket) String

func (b RateBucket) String() string

String returns the bucket's name.

type RateLimit

type RateLimit struct {
	// Requests is the number of attempts allowed per window.
	Requests int
	// Window is the length of the sliding window.
	Window time.Duration
}

RateLimit is a sliding-window limit: at most Requests HTTP attempts in any Window.

type RateLimitError

type RateLimitError struct {
	// Operation is the throttled operation.
	Operation OperationID
	// RetryAfter is the server's Retry-After value, nil when absent or
	// unparsable. HTTP-date values are converted to a duration.
	RetryAfter *time.Duration
	// Body is the response body text.
	Body string
}

RateLimitError is an HTTP 429 response that persisted after the retry budget was spent. It matches ErrRateLimited.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

Error describes the failure.

func (*RateLimitError) Is

func (e *RateLimitError) Is(target error) bool

Is reports whether target is ErrRateLimited.

type RateLimits

type RateLimits struct {
	// History applies to History_GetBars.
	History RateLimit
	// General applies to every other operation.
	General RateLimit
}

RateLimits holds the limit of each rate bucket.

func DefaultRateLimits

func DefaultRateLimits() RateLimits

DefaultRateLimits returns the documented gateway limits: 50 requests per 30 seconds for History_GetBars and 200 requests per 60 seconds for every other operation.

type RetrieveBarErrorCode

type RetrieveBarErrorCode int32

RetrieveBarErrorCode is the errorCode of History_GetBars responses (spec schema RetrieveBarErrorCode). Zero means success.

const (
	RetrieveBarErrorCodeSuccess           RetrieveBarErrorCode = 0
	RetrieveBarErrorCodeContractNotFound  RetrieveBarErrorCode = 1
	RetrieveBarErrorCodeUnitInvalid       RetrieveBarErrorCode = 2
	RetrieveBarErrorCodeUnitNumberInvalid RetrieveBarErrorCode = 3
	RetrieveBarErrorCodeLimitInvalid      RetrieveBarErrorCode = 4
)

RetrieveBarErrorCode values.

func (RetrieveBarErrorCode) IsKnown

func (v RetrieveBarErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (RetrieveBarErrorCode) String

func (v RetrieveBarErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type RetrieveBarRequest

type RetrieveBarRequest struct {
	// ContractID is the string contract identifier.
	ContractID string `json:"contractId"`
	// Live selects the live (true) or simulated (false) data subscription.
	Live bool `json:"live"`
	// StartTime is the start of the range.
	StartTime time.Time `json:"startTime"`
	// EndTime is the end of the range.
	EndTime time.Time `json:"endTime"`
	// Unit is the aggregation unit. The guide documents Second through Month.
	Unit AggregateBarUnit `json:"unit"`
	// UnitNumber is the number of units per bar.
	UnitNumber int32 `json:"unitNumber"`
	// Limit is the maximum number of bars, at most MaxBars.
	Limit int32 `json:"limit"`
	// IncludePartialBar includes the current, incomplete bar.
	IncludePartialBar bool `json:"includePartialBar"`
}

RetrieveBarRequest is the History_GetBars request. History_GetBars has its own rate limit of 50 requests per 30 seconds.

func (RetrieveBarRequest) MarshalJSON

func (r RetrieveBarRequest) MarshalJSON() ([]byte, error)

MarshalJSON encodes the request with RFC 3339 UTC timestamps.

func (*RetrieveBarRequest) UnmarshalJSON

func (r *RetrieveBarRequest) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the request, reading timestamps leniently.

func (RetrieveBarRequest) Validate

func (r RetrieveBarRequest) Validate() error

Validate checks that Limit does not exceed MaxBars. It returns a *ValidationError.

type RetrieveBarResponse

type RetrieveBarResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode RetrieveBarErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Bars are the requested bars.
	Bars []AggregateBar `json:"bars,omitempty"`
}

RetrieveBarResponse is the History_GetBars response. Missing arrays decode as nil slices.

func (*RetrieveBarResponse) IsBusinessFailure

func (r *RetrieveBarResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type RetryClass

type RetryClass int

RetryClass decides which failures an operation retries.

const (
	// RetryRead operations retry on HTTP 429, 502, 503, 504 and transport
	// errors.
	RetryRead RetryClass = iota
	// RetryWrite operations retry only on HTTP 429, because any other failure
	// may follow a request that already executed.
	RetryWrite
)

RetryClass values.

func (RetryClass) String

func (c RetryClass) String() string

String returns the class's name.

type SearchAccountErrorCode

type SearchAccountErrorCode int32

SearchAccountErrorCode is the errorCode of Account_SearchAccounts responses (spec schema SearchAccountErrorCode). Zero means success.

const (
	SearchAccountErrorCodeSuccess SearchAccountErrorCode = 0
)

SearchAccountErrorCode values.

func (SearchAccountErrorCode) IsKnown

func (v SearchAccountErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchAccountErrorCode) String

func (v SearchAccountErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchAccountRequest

type SearchAccountRequest struct {
	// OnlyActiveAccounts limits the result to active accounts.
	OnlyActiveAccounts bool `json:"onlyActiveAccounts"`
}

SearchAccountRequest is the Account_SearchAccounts request.

type SearchAccountResponse

type SearchAccountResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchAccountErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Accounts are the matching accounts.
	Accounts []TradingAccount `json:"accounts,omitempty"`
}

SearchAccountResponse is the Account_SearchAccounts response. Missing arrays decode as nil slices.

func (*SearchAccountResponse) IsBusinessFailure

func (r *SearchAccountResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchContractByIDErrorCode

type SearchContractByIDErrorCode int32

SearchContractByIDErrorCode is the errorCode of Contract_SearchContractById responses (spec schema SearchContractByIdErrorCode). Zero means success.

const (
	SearchContractByIDErrorCodeSuccess          SearchContractByIDErrorCode = 0
	SearchContractByIDErrorCodeContractNotFound SearchContractByIDErrorCode = 1
)

SearchContractByIDErrorCode values.

func (SearchContractByIDErrorCode) IsKnown

func (v SearchContractByIDErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchContractByIDErrorCode) String

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchContractByIDRequest

type SearchContractByIDRequest struct {
	// ContractID is the contract identifier.
	ContractID string `json:"contractId"`
}

SearchContractByIDRequest is the Contract_SearchContractById request (spec schema SearchContractByIdRequest).

type SearchContractByIDResponse

type SearchContractByIDResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchContractByIDErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Contract is the requested contract.
	Contract *Contract `json:"contract,omitempty"`
}

SearchContractByIDResponse is the Contract_SearchContractById response (spec schema SearchContractByIdResponse).

func (*SearchContractByIDResponse) IsBusinessFailure

func (r *SearchContractByIDResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchContractErrorCode

type SearchContractErrorCode int32

SearchContractErrorCode is the errorCode of Contract_SearchContracts responses (spec schema SearchContractErrorCode). Zero means success.

const (
	SearchContractErrorCodeSuccess SearchContractErrorCode = 0
)

SearchContractErrorCode values.

func (SearchContractErrorCode) IsKnown

func (v SearchContractErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchContractErrorCode) String

func (v SearchContractErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchContractRequest

type SearchContractRequest struct {
	// SearchText is matched against contract names; at most 20 contracts are
	// returned.
	SearchText string `json:"searchText"`
	// Live selects the live (true) or simulated (false) data subscription.
	// It does not describe the account type.
	Live bool `json:"live"`
}

SearchContractRequest is the Contract_SearchContracts request.

type SearchContractResponse

type SearchContractResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchContractErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Contracts are the matching contracts (at most 20).
	Contracts []Contract `json:"contracts,omitempty"`
}

SearchContractResponse is the Contract_SearchContracts response. Missing arrays decode as nil slices.

func (*SearchContractResponse) IsBusinessFailure

func (r *SearchContractResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchHalfTradeResponse

type SearchHalfTradeResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchTradeErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Trades are the matching trades. A nil ProfitAndLoss marks a half-turn.
	Trades []HalfTrade `json:"trades,omitempty"`
}

SearchHalfTradeResponse is the Trade_SearchHalfTurnTrades response. Missing arrays decode as nil slices.

func (*SearchHalfTradeResponse) IsBusinessFailure

func (r *SearchHalfTradeResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchOpenOrderRequest

type SearchOpenOrderRequest struct {
	// AccountID is the account to search.
	AccountID int32 `json:"accountId"`
}

SearchOpenOrderRequest is the Order_SearchOpenOrders request.

type SearchOrderByIDErrorCode

type SearchOrderByIDErrorCode int32

SearchOrderByIDErrorCode is the errorCode of Order_SearchOrderById responses (spec schema SearchOrderByIdErrorCode). Zero means success.

const (
	SearchOrderByIDErrorCodeSuccess       SearchOrderByIDErrorCode = 0
	SearchOrderByIDErrorCodeOrderNotFound SearchOrderByIDErrorCode = 1
)

SearchOrderByIDErrorCode values.

func (SearchOrderByIDErrorCode) IsKnown

func (v SearchOrderByIDErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchOrderByIDErrorCode) String

func (v SearchOrderByIDErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchOrderByIDRequest

type SearchOrderByIDRequest struct {
	// AccountID is the owning account; it must belong to the caller.
	AccountID int32 `json:"accountId"`
	// OrderID is the order identifier.
	OrderID int64 `json:"orderId"`
}

SearchOrderByIDRequest is the Order_SearchOrderById request (spec schema SearchOrderByIdRequest).

type SearchOrderByIDResponse

type SearchOrderByIDResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchOrderByIDErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Order is the requested order.
	Order *Order `json:"order,omitempty"`
}

SearchOrderByIDResponse is the Order_SearchOrderById response (spec schema SearchOrderByIdResponse).

func (*SearchOrderByIDResponse) IsBusinessFailure

func (r *SearchOrderByIDResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchOrderErrorCode

type SearchOrderErrorCode int32

SearchOrderErrorCode is the errorCode of Order_SearchOrders, Order_SearchOpenOrders and Order_SearchOrdersQuery responses (spec schema SearchOrderErrorCode). Zero means success.

const (
	SearchOrderErrorCodeSuccess         SearchOrderErrorCode = 0
	SearchOrderErrorCodeAccountNotFound SearchOrderErrorCode = 1
)

SearchOrderErrorCode values.

func (SearchOrderErrorCode) IsKnown

func (v SearchOrderErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchOrderErrorCode) String

func (v SearchOrderErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchOrderRequest

type SearchOrderRequest struct {
	// AccountID is the account to search.
	AccountID int32 `json:"accountId"`
	// StartTimestamp is the start of the creation-time range.
	StartTimestamp time.Time `json:"startTimestamp"`
	// EndTimestamp is the optional end of the creation-time range.
	EndTimestamp *time.Time `json:"endTimestamp,omitempty"`
}

SearchOrderRequest is the Order_SearchOrders request.

func (SearchOrderRequest) MarshalJSON

func (r SearchOrderRequest) MarshalJSON() ([]byte, error)

MarshalJSON encodes the request with RFC 3339 UTC timestamps.

func (*SearchOrderRequest) UnmarshalJSON

func (r *SearchOrderRequest) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the request, reading timestamps leniently.

type SearchOrderResponse

type SearchOrderResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchOrderErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Orders are the matching orders.
	Orders []Order `json:"orders,omitempty"`
}

SearchOrderResponse is the Order_SearchOrders and Order_SearchOpenOrders response. Missing arrays decode as nil slices.

func (*SearchOrderResponse) IsBusinessFailure

func (r *SearchOrderResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchOrdersQueryRequest

type SearchOrdersQueryRequest struct {
	// Filter selects the orders.
	Filter GatewayOrderFilter `json:"filter"`
	// PageSize is the optional page size.
	PageSize *int32 `json:"pageSize,omitempty"`
	// PageOffset is the optional page offset.
	PageOffset *int32 `json:"pageOffset,omitempty"`
	// SortBy is the optional sort key.
	SortBy *OrderSortField `json:"sortBy,omitempty"`
	// SortDirection is the optional sort order.
	SortDirection *SortDirection `json:"sortDirection,omitempty"`
	// IncludeTotalCount asks for totalCount in the response.
	IncludeTotalCount *bool `json:"includeTotalCount,omitempty"`
}

SearchOrdersQueryRequest is the Order_SearchOrdersQuery request. The gateway's pagination defaults and bounds are not published.

type SearchOrdersQueryResponse

type SearchOrdersQueryResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchOrderErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Orders are the orders of the requested page.
	Orders []Order `json:"orders,omitempty"`
	// TotalCount is the number of matching orders, when requested.
	TotalCount *int32 `json:"totalCount,omitempty"`
}

SearchOrdersQueryResponse is the Order_SearchOrdersQuery response. Missing arrays decode as nil slices.

func (*SearchOrdersQueryResponse) IsBusinessFailure

func (r *SearchOrdersQueryResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchPositionErrorCode

type SearchPositionErrorCode int32

SearchPositionErrorCode is the errorCode of Position_SearchOpenPositions responses (spec schema SearchPositionErrorCode). Zero means success.

const (
	SearchPositionErrorCodeSuccess         SearchPositionErrorCode = 0
	SearchPositionErrorCodeAccountNotFound SearchPositionErrorCode = 1
)

SearchPositionErrorCode values.

func (SearchPositionErrorCode) IsKnown

func (v SearchPositionErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchPositionErrorCode) String

func (v SearchPositionErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchPositionRequest

type SearchPositionRequest struct {
	// AccountID is the account to search.
	AccountID int32 `json:"accountId"`
}

SearchPositionRequest is the Position_SearchOpenPositions request.

type SearchPositionResponse

type SearchPositionResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode SearchPositionErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// Positions are the open positions.
	Positions []Position `json:"positions,omitempty"`
}

SearchPositionResponse is the Position_SearchOpenPositions response. Missing arrays decode as nil slices.

func (*SearchPositionResponse) IsBusinessFailure

func (r *SearchPositionResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

type SearchTradeErrorCode

type SearchTradeErrorCode int32

SearchTradeErrorCode is the errorCode of Trade_SearchHalfTurnTrades responses (spec schema SearchTradeErrorCode). Zero means success.

const (
	SearchTradeErrorCodeSuccess         SearchTradeErrorCode = 0
	SearchTradeErrorCodeAccountNotFound SearchTradeErrorCode = 1
)

SearchTradeErrorCode values.

func (SearchTradeErrorCode) IsKnown

func (v SearchTradeErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SearchTradeErrorCode) String

func (v SearchTradeErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type SearchTradeRequest

type SearchTradeRequest struct {
	// AccountID is the account to search.
	AccountID int32 `json:"accountId"`
	// StartTimestamp is the start of the range.
	StartTimestamp time.Time `json:"startTimestamp"`
	// EndTimestamp is the optional end of the range.
	EndTimestamp *time.Time `json:"endTimestamp,omitempty"`
}

SearchTradeRequest is the Trade_SearchHalfTurnTrades request. StartTimestamp is required, following the guide (Swagger requires only accountId).

func (SearchTradeRequest) MarshalJSON

func (r SearchTradeRequest) MarshalJSON() ([]byte, error)

MarshalJSON encodes the request with RFC 3339 UTC timestamps.

func (*SearchTradeRequest) UnmarshalJSON

func (r *SearchTradeRequest) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the request, reading timestamps leniently.

type SortDirection

type SortDirection int32

SortDirection selects the sort order of Order_SearchOrdersQuery (spec schema SortDirection).

const (
	SortDirectionAsc  SortDirection = 0
	SortDirectionDesc SortDirection = 1
)

SortDirection values.

func (SortDirection) IsKnown

func (v SortDirection) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (SortDirection) String

func (v SortDirection) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type StatusService

type StatusService struct {
	// contains filtered or unexported fields
}

StatusService checks API responsiveness. Obtain it from Client.Status.

func (*StatusService) Ping

func (s *StatusService) Ping(ctx context.Context) (string, error)

Ping calls Status_Ping (listed only in Swagger) and returns its text, normally "pong", whether the gateway answers with text/plain or a JSON string. A bearer token is attached when one is held or obtainable; otherwise the ping is sent anonymously.

type TradesService

type TradesService struct {
	// contains filtered or unexported fields
}

TradesService searches trades. Obtain it from Client.Trades.

func (*TradesService) Search

Search returns the account's trades in the requested range (Trade_SearchHalfTurnTrades). A nil ProfitAndLoss marks a half-turn trade.

type TradingAccount

type TradingAccount struct {
	// ID is the account identifier used by every account-scoped operation.
	ID int32 `json:"id"`
	// Name is the account name.
	Name string `json:"name"`
	// Balance is the account balance.
	Balance decimal.Decimal `json:"balance"`
	// CanTrade reports whether the account may trade.
	CanTrade bool `json:"canTrade"`
	// IsVisible reports whether the account is visible.
	IsVisible bool `json:"isVisible"`
	// Simulated reports whether the account is simulated. Some guide
	// examples omit it; it then decodes as false.
	Simulated bool `json:"simulated"`
}

TradingAccount is a trading account (spec schema TradingAccountModel).

func (TradingAccount) MarshalJSON

func (m TradingAccount) MarshalJSON() ([]byte, error)

MarshalJSON encodes the account with its balance as a JSON number.

func (*TradingAccount) UnmarshalJSON

func (m *TradingAccount) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the account.

type TransportError

type TransportError struct {
	// Operation is the operation that failed.
	Operation OperationID
	// Err is the underlying error.
	Err error
}

TransportError is a failure below HTTP: DNS, connection, TLS, timeout or a body that could not be read. Err keeps the cause, so errors.Is works with context.DeadlineExceeded and context.Canceled.

func (*TransportError) Error

func (e *TransportError) Error() string

Error describes the failure.

func (*TransportError) Unwrap

func (e *TransportError) Unwrap() error

Unwrap returns Err.

type ValidateErrorCode

type ValidateErrorCode int32

ValidateErrorCode is the errorCode of Auth_Validate responses (spec schema ValidateErrorCode). Zero means success.

const (
	ValidateErrorCodeSuccess         ValidateErrorCode = 0
	ValidateErrorCodeInvalidSession  ValidateErrorCode = 1
	ValidateErrorCodeSessionNotFound ValidateErrorCode = 2
	ValidateErrorCodeExpiredToken    ValidateErrorCode = 3
	ValidateErrorCodeUnknownError    ValidateErrorCode = 4
)

ValidateErrorCode values.

func (ValidateErrorCode) IsKnown

func (v ValidateErrorCode) IsKnown() bool

IsKnown reports whether the spec lists the value.

func (ValidateErrorCode) String

func (v ValidateErrorCode) String() string

String returns the spec name of the value, or "Unrecognized(<n>)" for a value the spec does not list.

type ValidateResponse

type ValidateResponse struct {
	// Success is false for a business failure.
	Success bool `json:"success"`
	// ErrorCode is zero on success.
	ErrorCode ValidateErrorCode `json:"errorCode"`
	// ErrorMessage describes a failure; the gateway may leave it null.
	ErrorMessage *string `json:"errorMessage,omitempty"`
	// HasBusinessFailure is the gateway's own failure flag; it decodes as
	// false when absent. Failures are detected from Success and ErrorCode.
	HasBusinessFailure bool `json:"hasBusinessFailure"`
	// NewToken is the renewed session JWT. It is a secret.
	NewToken *string `json:"newToken,omitempty"`
}

ValidateResponse is the Auth_Validate response.

func (ValidateResponse) Format

func (r ValidateResponse) Format(f fmt.State, verb rune)

Format implements fmt.Formatter so that no verb prints the token.

func (ValidateResponse) GoString

func (r ValidateResponse) GoString() string

GoString returns a Go-syntax representation with the token redacted.

func (*ValidateResponse) IsBusinessFailure

func (r *ValidateResponse) IsBusinessFailure() bool

IsBusinessFailure reports whether success is false or errorCode is non-zero.

func (ValidateResponse) LogValue

func (r ValidateResponse) LogValue() slog.Value

LogValue implements slog.LogValuer with the token redacted.

func (ValidateResponse) String

func (r ValidateResponse) String() string

String returns a representation with the token redacted.

type ValidationError

type ValidationError struct {
	// Operation is the rejected operation; it is empty when the error comes
	// from calling a request's Validate method directly.
	Operation OperationID
	// Field is the JSON path of the offending field, such as "trailPrice" or
	// "stopLossBracket.type".
	Field string
	// Reason explains the rule that failed.
	Reason string
}

ValidationError is a client-side validation failure (contract section 9). It is returned before any network I/O, login included.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Error describes the failure.

Directories

Path Synopsis
examples
accounts command
Command accounts lists the active trading accounts.
Command accounts lists the active trading accounts.
contracts command
Command contracts searches contracts and prints recent bars of the first match.
Command contracts searches contracts and prints recent bars of the first match.
place-order command
Command place-order places a limit order and cancels it again.
Command place-order places a limit order and cancels it again.
realtime-market command
Command realtime-market streams quotes, market trades and market depth for a contract until interrupted.
Command realtime-market streams quotes, market trades and market depth for a contract until interrupted.
realtime-user command
Command realtime-user streams account, order, position and trade updates from the user hub until interrupted.
Command realtime-user streams account, order, position and trade updates from the user hub until interrupted.
internal
jsonx
Package jsonx is the JSON codec shared by the SDK's data models.
Package jsonx is the JSON codec shared by the SDK's data models.
logx
Package logx provides the SDK's default logger, which discards every record.
Package logx provides the SDK's default logger, which discards every record.
Package realtime connects to the ProjectX Gateway SignalR hubs: the user hub (accounts, orders, positions, trades) and the market hub (quotes, market trades, market depth).
Package realtime connects to the ProjectX Gateway SignalR hubs: the user hub (accounts, orders, positions, trades) and the market hub (quotes, market trades, market depth).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL