Time in Force
Control how long an order remains active.
| Value | Name | Description |
|---|---|---|
day | Day Order | Expires at end of trading day |
gtc | Good Til Cancelled | Remains active until filled or cancelled |
gtd | Good Til Date | Remains active until specified date |
opg | Market on Open | Executes at market open |
cls | Market on Close | Executes at market close (MOC) |
ioc | Immediate or Cancel | Fill immediately or cancel |
fok | Fill or Kill | Fill entirely immediately or cancel |
Examples
Day Order (Default)
{
"timeInForce": "day"
}
Good Til Cancelled
{
"timeInForce": "gtc"
}
Market on Close
{
"timeInForce": "cls"
}
Good Til Date
gtd keeps the order live until a specific moment, then cancels it. Pair timeInForce: "gtd" with expiresAt and a timezone.
{
"timeInForce": "gtd",
"expiresAt": "2026-08-15T16:00:00",
"timezone": "America/New_York"
}
Validation rules on the create and update signal endpoints:
expiresAtis required whentimeInForceisgtd, and only valid in that case.timezoneis required whenexpiresAtis supplied.expiresAtmust be in the future when interpreted in the supplied timezone.expiresAtmust be within 90 days from now.
How gtd is enforced depends on whether the broker supports a native GTD time-in-force on order submit. UTM picks the path automatically and records which one ran on the Order.gtdMode field so callers can detect the reliability difference without having to know broker-by-broker behaviour.
| Broker | GTD mode | Resilience to UTM outage at expiry |
|---|---|---|
| TradeStation | Broker-native | Broker cancels the order at expiresAt even if UTM is down. |
| Alpaca | UTM-emulated | UTM submits as gtc and schedules a server-side cancel. If UTM is down at the expiry moment, the cancel does not fire. |
The caller-facing contract is the same regardless of mode: Order.timeInForce keeps the original gtd value and Order.expiresAt carries the requested expiry. On the emulated path UTM also writes Order.gtdCancellationJobId referencing the queued cancel; on the native path that field stays null.
Order.gtdMode
Order.gtdMode is set by UTM at order-submit time. It can take one of:
"broker"- the broker accepted a native GTD time-in-force with an explicit expiry. The broker cancels at expiry regardless of UTM uptime."emulated"- UTM submitted the order asgtcand scheduled a server-side cancel atexpiresAt. UTM must be up at the expiry moment for the cancel to fire.null- the order is notgtd, so the field is not applicable.
The signal-create response does not carry gtdMode; the mode is determined when the order is placed at the broker, not when the signal is created. Callers that need the mode should read it from the order detail endpoint.
Broker submission cutoffs for CLS
UTM sends cls to Alpaca as cls and to TradeStation as CLO, TradeStation's own at-close duration. TradeStation has no CLS duration. cls orders must reach the broker before its submission cutoff. Orders submitted past the cutoff are rejected. Cutoffs are expressed as minutes before market close so they apply correctly on short trading days (e.g. half-day Thanksgiving session) without special handling.
| Broker | CLS cutoff (minutes before close) | Regular session ET equivalent |
|---|---|---|
| Alpaca | 10 | 3:50 PM |
| TradeStation | 10 | 3:50 PM |
Alpaca additionally requires cls orders to be submitted after 7:00 PM ET on the prior session — that is broker-side window opening behaviour, separate from the UTM cutoff guard described below.
UTM at-close safety behaviour
When strategy auto-close, or an exit rule with exitOrderType: "moc", sends an at-close order, UTM checks the broker's cutoff before sending. Paper and SIM accounts follow exactly the same rule as live accounts, on every broker: Alpaca paper gets cls and TradeStation SIM gets CLO.
- Before the cutoff, the order is sent at-close.
- At or after the cutoff (see table above), UTM downgrades the order from
clstoday. The order then fills against the order book at close rather than being rejected. UTM logs a warning and writes anorder.moc_downgradeaudit row on the trade, with reasonpast_cutoff, when the downgraded order is sent. The trade's audit timeline shows it as "Sent as market". An order UTM stops before the broker (for example the live trading guard) gets no such row, and neither does an order sent at-close.
If a broker refuses an at-close order, the order is recorded as rejected like any other refusal. UTM does not retry it as a market order.
Paper fills may not match the closing auction. Alpaca's paper account accepts cls, but Alpaca says paper fills against the current quote rather than the closing print, so compare paper results with the fill price recorded on the order.
Signals submitted manually or via webhook are sent with whatever timeInForce the caller specifies and must meet broker submission windows independently.
To stay clear of the cutoff on live accounts, configure autoCloseMinutesBefore on your strategy with at least 15 minutes of buffer. The 15-minute floor exists because it sits at or above every supported broker's CLS cutoff. The default is 30 minutes, which gives adequate margin for all supported brokers.