Skip to content
Back to App

Enums & Types

This page documents all enum values, type constants, and data format conventions used across the TestMax API. Use this as a quick reference when building strategies or integrating with the API.

OrderType

The type of order to place. Used in the type field of Order/place.

ValueNameDescriptionRequired price fields
1LimitExecutes at the specified price or better. Rests in the book until filled or canceled.limitPrice
2MarketExecutes immediately at the current market price.None
3StopLimitBecomes a limit order when the stop price is triggered.stopPrice, limitPrice
4StopBecomes a market order when the stop price is triggered.stopPrice

When to use each type

  • Market (2): Fast entries and exits where execution certainty matters more than price. Used for scalping, emergency flatten, and momentum entries.
  • Limit (1): Entries at a specific price or better. Used for pullback entries, take-profit orders, and scaling into positions.
  • Stop (4): Breakout entries and stop-loss protection. Triggers when the market trades through the stop price.
  • StopLimit (3): Combines a stop trigger with a limit price to avoid slippage on breakout entries. The limit price controls the worst acceptable fill price.

OrderSide

The direction of the order. Used in the side field of Order/place.

ValueNameDescription
0BuyBuy to open a long position or close a short position
1SellSell to open a short position or close a long position

OrderStatus

The current state of an order. Returned in the status field of Order/search and Order/searchOpen.

ValueNameDescription
1PartialOrder is partially filled — some contracts executed, remaining are still working
2FilledOrder is completely filled — all contracts executed
3CanceledOrder was canceled before being fully filled
6PendingOrder is active and waiting to be filled (limit/stop orders resting in the book)

Status transitions

Pending (6) → Partial (1) → Filled (2)
Pending (6) → Filled (2) (fully filled immediately)
Pending (6) → Canceled (3) (manually canceled)
Partial (1) → Canceled (3) (canceled with partial fill)

PositionType

The direction of an open position. Returned in the type field of Position/searchOpen.

ValueNameDescription
1LongHolding a long position (bought contracts, profit when price rises)
2ShortHolding a short position (sold contracts, profit when price falls)

Usage in strategy code

positions = get_positions(ACCOUNT_ID)
for pos in positions:
if pos["type"] == 1:
print(f"LONG {pos['size']} @ {pos['averagePrice']}")
elif pos["type"] == 2:
print(f"SHORT {pos['size']} @ {pos['averagePrice']}")

AggregateBarUnit

The time unit for bar aggregation. Used in the unit field of History/retrieveBars.

ValueNameDescription
1SecondBars aggregated by seconds
2MinuteBars aggregated by minutes
3HourBars aggregated by hours
4DayBars aggregated by days

Combine unit with unitNumber to define the bar timeframe:

TimeframeunitunitNumber
1-second11
30-second130
1-minute21
5-minute25
15-minute215
30-minute230
1-hour31
4-hour34
Daily41

Contract ID format

Contract identifiers follow the gateway-schema convention:

CON.F.US.{symbol}.{monthYear}
ComponentDescriptionExample
CONFixed prefix (contract)CON
FAsset class (futures)F
USExchange/regionUS
{symbol}Internal instrument symbolENQ, EP, GC
{monthYear}Month code + 2-digit yearH25 (March 2025)

The simulator maps symbols as follows: NQENQ, ESEP, MNQMENQ, MESMEP, MCLMCL; CL, GC, YM, and RTY keep their own symbols. Generated IDs always carry the current front-month code (e.g. .N26 in July 2026), and the month/year segment is ignored when the simulator resolves an ID you send.

Full examples

Contract IDInstrumentExpiry
CON.F.US.ENQ.H25Nasdaq 100 E-miniMarch 2025
CON.F.US.EP.H25S&P 500 E-miniMarch 2025
CON.F.US.GC.J25Gold FuturesApril 2025
CON.F.US.CL.F25Crude Oil FuturesJanuary 2025

Month codes

CodeMonthCodeMonth
FJanuaryNJuly
GFebruaryQAugust
HMarchUSeptember
JAprilVOctober
KMayXNovember
MJuneZDecember

Standard response format

Every API endpoint returns a response with these three fields:

{
"success": true,
"errorCode": 0,
"errorMessage": null
}
FieldTypeDescription
successbooleantrue if the request succeeded
errorCodenumber0 for success, non-zero for errors
errorMessagestring or nullHuman-readable error message, or null on success

Additional data fields are included alongside these fields depending on the endpoint. For example:

{
"success": true,
"errorCode": 0,
"errorMessage": null,
"accounts": [...]
}

Error codes

Error codes are contextual — the same number can mean different things on different endpoints, so always read errorMessage. Rough taxonomy:

CodeTypical meaning
0Success
1Not found (account, contract) or invalid session on Auth/validate
2Invalid state or parameter (order/position not found, no active replay session, missing startDate, invalid unit or time range)
3Auth failure (invalid credentials/token), unsupported operation (Order/modify), or invalid amount/unit number
4Account violation (terminal challenge), withdrawal not eligible, or invalid limit
57Endpoint-specific: invalid close size, engine rejections, invalid order size/type
9Pro subscription required
99Internal server error
429Rate limited — arrives as a real HTTP 429 with a Retry-After header

The full per-endpoint list is in Error Codes. Note that simulator errors (other than 429) are returned with HTTP 200 and success: false.


Bar data format

OHLCV bars returned by Replay/step and History/retrieveBars use this format:

{
"t": "2025-01-15T14:30:00Z",
"o": 21500.25,
"h": 21505.50,
"l": 21498.75,
"c": 21503.00,
"v": 150
}
FieldTypeDescription
tstringISO 8601 UTC timestamp for the bar’s open time
onumberOpen price (first traded price in the bar period)
hnumberHigh price (highest traded price in the bar period)
lnumberLow price (lowest traded price in the bar period)
cnumberClose price (last traded price in the bar period)
vnumberVolume (total contracts traded in the bar period)

Timeframe strings

Timeframe strings are used in Replay/start and Playground API endpoints. A timeframe is a positive count followed by a unit letter:

^([1-9]\d{0,4})(s|m|h|d|w|M|y)$
UnitMeaningBucketing
ssecondsFixed width, bucketed on the epoch grid
mminutesFixed width, bucketed on the epoch grid
hhoursFixed width, bucketed on the epoch grid
ddaysFixed width, bucketed on the epoch grid
wweeksCalendar, ISO Monday weeks in UTC
MmonthsCalendar, UTC calendar months
yyearsCalendar, UTC calendar years

The grammar is the whole validation surface — leading zeros ("01m"), empty counts ("m"), unknown units ("1D", "5x") and anything else that fails the pattern is rejected with an Invalid timeframe error.

Free presets

These 12 timeframes are available on every plan:

StringDescription
"1s"1-second bars
"5s"5-second bars
"10s"10-second bars
"15s"15-second bars
"30s"30-second bars
"1m"1-minute bars
"5m"5-minute bars
"15m"15-minute bars
"30m"30-minute bars
"1h"1-hour bars
"4h"4-hour bars
"1d"Daily bars

Pro timeframes

Every other value the grammar accepts — "7m", "90m", "2h", "3d" — plus the calendar presets "1w", "1M", "3M" and "1y" is a custom timeframe.

On the platform surfaces — the replay WebSocket and the /api/data candle and volume-profile endpoints — a custom timeframe requires a Pro subscription: requests for one from a free account are refused with Timeframe "<label>" requires a Pro subscription. Custom timeframes on those surfaces are also behind a platform feature switch, and while it is off every non-preset value is refused with Custom timeframes are currently disabled, whatever the plan. The Playground endpoints require Pro before they look at the timeframe at all, so only the switch refusal reaches them.

The Simulator API applies neither check — a Pro plan is already required to hold a simulator token — so Replay/start and the bar endpoints validate only the grammar and the per-instrument availability rule below.

Admin and research endpoints accept any parseable timeframe without the subscription check.

Canonicalization

A timeframe is promoted to the largest unit that divides it evenly before it is used, echoed or cached, so "60m" and "1h" are the same request:

SentCanonical
"120s""2m"
"60m""1h"
"1440m""1d"
"48h""2d"
"90m""90m"
"12M""1y"
"24M""2y"

Promotion never crosses the fixed/calendar boundary: "7d" is not "1w", "30d" is not "1M", "365d" is not "1y". All 12 free presets are already canonical. Responses echo the canonical label, so read the timeframe back from the response rather than assuming the string you sent.

Bounds

Checked on the canonical form, so "24M" is accepted as "2y" while "13M" is rejected:

FamilyMaximum
s / m / h / d30 days
w52
M12
y5

Availability per instrument

Bars are aggregated up from each instrument’s stored resolution, so a timeframe is only available when it lines up with that resolution:

  • Fixed (s/m/h/d): the timeframe in seconds must be an exact multiple of the stored resolution in seconds.
  • Calendar (w/M/y): the stored resolution must divide a whole day (86400 seconds) evenly.

Gold (GC) is stored at 10-second resolution, for example, so "30s" is available on it but "15s" is not. A timeframe that does not line up is rejected rather than silently rounded.


Quick reference card

EnumValues
OrderType1=Limit, 2=Market, 3=StopLimit, 4=Stop
OrderSide0=Buy, 1=Sell
OrderStatus1=Partial, 2=Filled, 3=Canceled, 6=Pending
PositionType1=Long, 2=Short
AggregateBarUnit1=Second, 2=Minute, 3=Hour, 4=Day

Copy-paste this into the top of your strategy for quick reference:

# === Enum Constants ===
# OrderType
LIMIT, MARKET, STOP_LIMIT, STOP = 1, 2, 3, 4
# OrderSide
BUY, SELL = 0, 1
# OrderStatus
PARTIAL, FILLED, CANCELED, PENDING = 1, 2, 3, 6
# PositionType
LONG, SHORT = 1, 2
# AggregateBarUnit
SECOND, MINUTE, HOUR, DAY = 1, 2, 3, 4