# Common Definition

Every enumerated value this API uses, and the MT5 integer behind it.

The API always speaks **symbolic strings** (`BUY_LIMIT`, `GTC`, `IN`). The MT5 integers are listed
so you can reconcile against an MT5 terminal, the MT5 Manager API, or a raw `mst` / `mt5RetCode`
field.

> New values may be added to any enum without notice. **Treat an unrecognised value as "something I
> do not model"** — log it and carry on. Do not crash and do not silently coerce it to a default.
>
> Where the trade server reports an MT5 integer this API does not map, the symbol-specification
> enums (`tradeMode`, `executionMode`, `swapMode`, `swap3Days`) and `ORDER_UPDATE.ot` carry
> `UNKNOWN_<n>`, `n` being the raw integer.

## Security type

Per endpoint, in each endpoint's spec block.

| Value | API key | Signature |
| - | - | - |
| `NONE` | no | no |
| `MARKET_DATA` | yes | no |
| `USER_STREAM` | yes | no |
| `USER_DATA` | yes | yes |
| `TRADE` | yes | yes |

## Order side

| Value | MT5 | Notes |
| - | - | - |
| `BUY` | `OP_BUY` = 0 | |
| `SELL` | `OP_SELL` = 1 | |

On a `DEAL` event `S` is the side of the **deal**, which is the opposite of the position's side when
`en` is `OUT`.

## Order type

| Value | MT5 `EnOrderType` | Pending | Requires |
| - | - | - | - |
| `MARKET` | `OP_BUY` = 0 / `OP_SELL` = 1 | no | `side` |
| `BUY_LIMIT` | `OP_BUY_LIMIT` = 2 | yes | `price` below the ask |
| `SELL_LIMIT` | `OP_SELL_LIMIT` = 3 | yes | `price` above the bid |
| `BUY_STOP` | `OP_BUY_STOP` = 4 | yes | `price` above the ask |
| `SELL_STOP` | `OP_SELL_STOP` = 5 | yes | `price` below the bid |
| `BUY_STOP_LIMIT` | `OP_BUY_STOP_LIMIT` = 6 | yes | `price` + `stopLimitPrice` |
| `SELL_STOP_LIMIT` | `OP_SELL_STOP_LIMIT` = 7 | yes | `price` + `stopLimitPrice` |

`OP_CLOSE_BY` = 8 (close one position with an opposite one) exists on MT5 but is **not exposed** in
v1 — you cannot send it. Close positions individually with `DELETE /v1/position`. An order of that
type placed outside this API can still surface: `ORDER_UPDATE.ot` reports it as `CLOSE_BY`, and
market orders passing through the book as `BUY` / `SELL`; an MT5 type this API does not know is
reported as `UNKNOWN_<n>`.

## Time in force

Sent as `timeInForce`, reported on orders as `tif`.

| Value | MT5 `EnOrderTime` | Meaning |
| - | - | - |
| `GTC` | `ORDER_TIME_GTC` = 0 | Good till cancelled. Default. |
| `DAY` | `ORDER_TIME_DAY` = 1 | Cancelled at the end of the trading day. |
| `GTD` | `ORDER_TIME_SPECIFIED` = 2 | Good till the `expiration` timestamp. |
| `GTD_DAY` | `ORDER_TIME_SPECIFIED_DAY` = 3 | Good until 00:00 of the `expiration` day, or the nearest trading time. |

`GTD` and `GTD_DAY` require `expiration`. Only values present in the symbol's `expirationModes`
(from `GET /v1/exchangeInfo`) are accepted; anything else is `-4012`.

## Order status

Reported as `status` on REST, `X` on `ORDER_UPDATE`.

### Market executions

| Value | Terminal | Meaning |
| - | - | - |
| `ACCEPTED` | no | Durably queued, not yet confirmed by the trade server. |
| `PARTIALLY_FILLED` | no | Part of the requested volume executed (MT5 answered `10010 DONE_PARTIAL`, or the fills so far add up to less than `volume`). `executedVolume` is what has actually filled. More `DEAL` events may follow. |
| `FILLED` | yes | Executed. `executedVolume` equals the requested volume. |
| `REJECTED` | yes | Refused by the trade server. `mt5RetCode` says why. |
| `IN_DOUBT` | no | The service cannot determine whether the operation reached the trade server. Reconcile before acting. |

`PARTIALLY_FILLED` applies to `POST /v1/order` with `type=MARKET`, to `DELETE /v1/position` and to
each leg of `DELETE /v1/allOpenPositions`. `executedVolume` accumulates across the distinct deals
that fill the order and `price` is their **volume-weighted average**; a redelivered deal never
double-counts.

### Pending orders

| Value | MT5 `EnOrderState` | Terminal |
| - | - | - |
| `NEW` | `ORDER_STATE_STARTED` = 0, `ORDER_STATE_PLACED` = 1, `ORDER_STATE_REQUEST_ADD` = 7, `ORDER_STATE_REQUEST_MODIFY` = 8, `ORDER_STATE_REQUEST_CANCEL` = 9 | no |
| `PARTIALLY_FILLED` | `ORDER_STATE_PARTIAL` = 3 | no |
| `FILLED` | `ORDER_STATE_FILLED` = 4 | yes |
| `CANCELED` | `ORDER_STATE_CANCELED` = 2 | yes |
| `EXPIRED` | `ORDER_STATE_EXPIRED` = 6 | yes |
| `REJECTED` | `ORDER_STATE_REJECTED` = 5 | yes |

MT5 states 7, 8 and 9 are transient gateway states ("a request to add/modify/cancel is being
processed"). They map to `NEW` because the order is still live. The raw value is on `mst` if you
need the distinction.

## Order state (raw MT5)

The `mst` field on `ORDER_UPDATE`, unmapped.

| MT5 `EnOrderState` | Value | Meaning |
| - | - | - |
| `ORDER_STATE_STARTED` | 0 | Checked, awaiting processing. |
| `ORDER_STATE_PLACED` | 1 | Accepted and placed. |
| `ORDER_STATE_CANCELED` | 2 | Cancelled by the client. |
| `ORDER_STATE_PARTIAL` | 3 | Partially filled. |
| `ORDER_STATE_FILLED` | 4 | Filled in full. |
| `ORDER_STATE_REJECTED` | 5 | Rejected by the broker. |
| `ORDER_STATE_EXPIRED` | 6 | Cancelled on expiration. |
| `ORDER_STATE_REQUEST_ADD` | 7 | Placement request in flight. |
| `ORDER_STATE_REQUEST_MODIFY` | 8 | Modification request in flight. |
| `ORDER_STATE_REQUEST_CANCEL` | 9 | Cancellation request in flight. |

## Deal entry

The `entry` field on `GET /v1/userTrades`, `en` on the `DEAL` event.

| Value | MT5 `EnDealEntry` | Meaning |
| - | - | - |
| `IN` | `ENTRY_IN` = 0 | Entering the market, or adding volume to a position. |
| `OUT` | `ENTRY_OUT` = 1 | Exiting, or partially closing. |
| `INOUT` | `ENTRY_INOUT` = 2 | Closed a position and opened an opposite one in the same deal. Netting accounts only — it does not occur under hedging. |
| `OUT_BY` | `ENTRY_OUT_BY` = 3 | Closed simultaneously with an opposite position ("close by"). |

Realised profit is non-zero only on `OUT`, `INOUT` and `OUT_BY`.

## Deal action (raw MT5)

Only `DEAL_BUY` and `DEAL_SELL` deals are exposed by this API. The rest are listed so you recognise
them if you reconcile against an MT5 statement: they are the reason `GET /v1/userTrades` does not
sum to the account balance.

| MT5 `EnDealAction` | Value | Exposed |
| - | - | - |
| `DEAL_BUY` | 0 | yes, `side: "BUY"` |
| `DEAL_SELL` | 1 | yes, `side: "SELL"` |
| `DEAL_BALANCE` | 2 | no — deposit / withdrawal |
| `DEAL_CREDIT` | 3 | no — credit granted or removed |
| `DEAL_CHARGE` | 4 | no |
| `DEAL_CORRECTION` | 5 | no |
| `DEAL_BONUS` | 6 | no |
| `DEAL_COMMISSION` | 7 | no |
| `DEAL_COMMISSION_DAILY` | 8 | no |
| `DEAL_COMMISSION_MONTHLY` | 9 | no |
| `DEAL_AGENT_DAILY` | 10 | no |
| `DEAL_AGENT_MONTHLY` | 11 | no |
| `DEAL_INTERESTRATE` | 12 | no |
| `DEAL_BUY_CANCELED` | 13 | no |
| `DEAL_SELL_CANCELED` | 14 | no |
| `DEAL_DIVIDEND` | 15 | no |
| `DEAL_DIVIDEND_FRANKED` | 16 | no |
| `DEAL_TAX` | 17 | no |
| `DEAL_AGENT` | 18 | no |
| `DEAL_SO_COMPENSATION` | 19 | no |
| `DEAL_SO_COMPENSATION_CREDIT` | 20 | no |

Balance-affecting actions surface as an [`ACCOUNT_UPDATE`](/user-data-streams/account_update.md)
event instead.

## Position direction

| Value | MT5 `EnPositionAction` |
| - | - |
| `BUY` | `POSITION_BUY` = 0 |
| `SELL` | `POSITION_SELL` = 1 |

Positions are **hedged**: a symbol can hold any number of `BUY` and `SELL` positions at once, each
with its own `positionId`.

## Entity change action

The `x` field on `ORDER_UPDATE`, `POSITION_UPDATE` and `ACCOUNT_UPDATE`.

| Value | Meaning |
| - | - |
| `NEW` | The entity appeared. |
| `UPDATE` | The entity changed. |
| `DELETE` | The entity is gone (`ORDER_UPDATE`, `ACCOUNT_UPDATE`). |
| `CLOSE` | The position is gone (`POSITION_UPDATE` only). |

## Symbol trade mode

`tradeMode` on `GET /v1/exchangeInfo`.

| Value | MT5 `EnTradeMode` | Meaning |
| - | - | - |
| `DISABLED` | `TRADE_DISABLED` = 0 | No trading at all. |
| `LONG_ONLY` | `TRADE_LONGONLY` = 1 | Only long positions may be opened. Rejects with `-4013`. |
| `SHORT_ONLY` | `TRADE_SHORTONLY` = 2 | Only short positions may be opened. Rejects with `-4014`. |
| `CLOSE_ONLY` | `TRADE_CLOSEONLY` = 3 | Existing positions may be closed; nothing new may be opened. Rejects with `-4015`. |
| `FULL` | `TRADE_FULL` = 4 | Unrestricted. |

## Symbol execution mode

`executionMode` on `GET /v1/exchangeInfo`.

| Value | MT5 `EnExecutionMode` | Meaning |
| - | - | - |
| `REQUEST` | `EXECUTION_REQUEST` = 0 | Request execution — the broker quotes, you accept. Requotes (`-5001`) are expected. |
| `INSTANT` | `EXECUTION_INSTANT` = 1 | Instant execution at the quoted price, subject to requote. |
| `MARKET` | `EXECUTION_MARKET` = 2 | Market execution — filled at the server's price, no requote, slippage possible. |
| `EXCHANGE` | `EXECUTION_EXCHANGE` = 3 | Exchange execution against the book. |

Execution mode determines whether a market order can be requoted and which fill modes apply.

## Fill mode

`fillModes` on `GET /v1/exchangeInfo`. Not settable per order in v1 — the service picks a policy the
symbol allows.

| Value | MT5 `EnOrderFilling` | `EnFillingFlags` bit | Meaning |
| - | - | - | - |
| `FOK` | `ORDER_FILL_FOK` = 0 | 1 | Fill completely or cancel. |
| `IOC` | `ORDER_FILL_IOC` = 1 | 2 | Fill what is available, cancel the rest. |
| `RETURN` | `ORDER_FILL_RETURN` = 2 | — | Return the remainder to the book. Pending orders. |
| `BOC` | `ORDER_FILL_BOC` = 3 | 4 | Passive — cancel if it would fill immediately. |

`RETURN` has no flag bit in the symbol configuration, so it **never appears in `fillModes`**; it is
listed here only so `ORDER_FILL_RETURN` is recognisable. A fill policy the symbol does not allow is
`-4017`.

## Order modes

`orderModes` on `GET /v1/exchangeInfo` — which order categories the symbol permits.

| Value | MT5 `EnOrderFlags` | Value |
| - | - | - |
| `MARKET` | `ORDER_FLAGS_MARKET` | 1 |
| `LIMIT` | `ORDER_FLAGS_LIMIT` | 2 |
| `STOP` | `ORDER_FLAGS_STOP` | 4 |
| `STOP_LIMIT` | `ORDER_FLAGS_STOP_LIMIT` | 8 |
| `SL` | `ORDER_FLAGS_SL` | 16 |
| `TP` | `ORDER_FLAGS_TP` | 32 |
| `CLOSE_BY` | `ORDER_FLAGS_CLOSEBY` | 64 |

`SL` and `TP` being absent means the symbol does not accept stop-loss / take-profit levels at all —
sending `sl` or `tp` is then `-4016`.

## Swap mode

`swapMode` on `GET /v1/exchangeInfo`. Determines the unit of `swapLong` / `swapShort`.

| Value | MT5 `EnSwapMode` | `swapLong`/`swapShort` unit |
| - | - | - |
| `DISABLED` | `SWAP_DISABLED` = 0 | no swap charged |
| `BY_POINTS` | `SWAP_BY_POINTS` = 1 | symbol points |
| `BY_SYMBOL_CURRENCY` | `SWAP_BY_SYMBOL_CURRENCY` = 2 | `currencyBase` |
| `BY_MARGIN_CURRENCY` | `SWAP_BY_MARGIN_CURRENCY` = 3 | `currencyMargin` |
| `BY_GROUP_CURRENCY` | `SWAP_BY_GROUP_CURRENCY` = 4 | account deposit currency |
| `BY_INTEREST_CURRENT` | `SWAP_BY_INTEREST_CURRENT` = 5 | percent of the current price |
| `BY_INTEREST_OPEN` | `SWAP_BY_INTEREST_OPEN` = 6 | percent of the open price |
| `REOPEN_BY_CLOSE_PRICE` | `SWAP_REOPEN_BY_CLOSE_PRICE` = 7 | points; the position is closed and reopened nightly |
| `REOPEN_BY_BID` | `SWAP_REOPEN_BY_BID` = 8 | points; the position is closed and reopened nightly |
| `BY_PROFIT_CURRENCY` | `SWAP_BY_PROFIT_CURRENCY` = 9 | `currencyProfit` |

Under `REOPEN_BY_CLOSE_PRICE` and `REOPEN_BY_BID` the trade server **closes and reopens** the
position every night. The `positionId` changes and you will see a `POSITION_UPDATE` with
`x: "CLOSE"` followed by a new one — this is not a trading event. Handle it, or your bookkeeping
will report a phantom round trip every night.

## Swap 3-days

`swap3Days` on `GET /v1/exchangeInfo` — the weekday triple swap is charged.

| Value | MT5 `EnSwapDays` |
| - | - |
| `SUNDAY` | 0 |
| `MONDAY` | 1 |
| `TUESDAY` | 2 |
| `WEDNESDAY` | 3 |
| `THURSDAY` | 4 |
| `FRIDAY` | 5 |
| `SATURDAY` | 6 |
| `DISABLED` | 7 |

`DISABLED` (MT5 `SWAP_DAY_DISABLED`) means the symbol charges no triple swap on any day.

## Kline interval

| Value | Minutes |
| - | - |
| `1m` | 1 |
| `5m` | 5 |
| `15m` | 15 |
| `30m` | 30 |
| `1h` | 60 |
| `2h` | 120 |
| `4h` | 240 |
| `1d` | 1440 |

Buckets are aligned to the Unix epoch in UTC. `1w` and `1M` are not supported.

## Rate limit type

`rateLimits[].rateLimitType` on `GET /v1/exchangeInfo`.

| Value | Meaning |
| - | - |
| `REQUEST_WEIGHT` | Weighted request budget. |
| `ORDERS` | Order-affecting request budget. |

`interval` is `SECOND`, `MINUTE`, `HOUR` or `DAY`; `intervalNum` multiplies it.

## MT5 request return codes (`mt5RetCode`)

Passed through unchanged whenever the trade server answered. These are MT5's
`MT_RET_REQUEST_*` codes; the `msg` and `code` in the error envelope are our mapping of them, and
this column is the raw truth.

| `mt5RetCode` | MT5 constant | Meaning | Maps to |
| - | - | - | - |
| 10004 | `MT_RET_REQUEST_REQUOTE` | Requote in response to the request. | `-5001` |
| 10006 | `MT_RET_REQUEST_REJECT` | Request rejected. | `-5007` |
| 10007 | `MT_RET_REQUEST_CANCEL` | Request cancelled. | `-5010` |
| 10008 | `MT_RET_REQUEST_PLACED` | Order placed. **Success** for a pending order. | `status: "NEW"` |
| 10009 | `MT_RET_REQUEST_DONE` | Request fulfilled. **Success.** | `status: "FILLED"` |
| 10010 | `MT_RET_REQUEST_DONE_PARTIAL` | Partially fulfilled. **Success.** | `status: "PARTIALLY_FILLED"` |
| 10011 | `MT_RET_REQUEST_ERROR` | Common request error. | `-5007` |
| 10012 | `MT_RET_REQUEST_TIMEOUT` | Request timed out. Execution status unknown. | `-5008` |
| 10013 | `MT_RET_REQUEST_INVALID` | Invalid request. | `-5017` |
| 10014 | `MT_RET_REQUEST_INVALID_VOLUME` | Invalid volume. | `-4004` |
| 10015 | `MT_RET_REQUEST_INVALID_PRICE` | Invalid price. | `-4002` |
| 10016 | `MT_RET_REQUEST_INVALID_STOPS` | Wrong stop levels or price. | `-4009` |
| 10017 | `MT_RET_REQUEST_TRADE_DISABLED` | Trade is disabled. | `-4011` |
| 10018 | `MT_RET_REQUEST_MARKET_CLOSED` | Market is closed. | `-4010` |
| 10019 | `MT_RET_REQUEST_NO_MONEY` | Not enough money. | `-2018` |
| 10020 | `MT_RET_REQUEST_PRICE_CHANGED` | Price has changed. | `-5002` |
| 10021 | `MT_RET_REQUEST_PRICE_OFF` | No price. | `-5003` |
| 10022 | `MT_RET_REQUEST_INVALID_EXP` | Invalid order expiration. | `-4012` |
| 10023 | `MT_RET_REQUEST_ORDER_CHANGED` | Order has been changed. | `-5004` |
| 10024 | `MT_RET_REQUEST_TOO_MANY` | Too many trade requests in flight. | `-5011` |
| 10025 | `MT_RET_REQUEST_NO_CHANGES` | Request contains no changes. | `-5005` |
| 10026 | `MT_RET_REQUEST_AT_DISABLED_SERVER` | Autotrading disabled on the server. | `-5012` |
| 10027 | `MT_RET_REQUEST_AT_DISABLED_CLIENT` | Autotrading disabled on the client side. | `-5012` |
| 10028 | `MT_RET_REQUEST_LOCKED` | Request blocked by the dealer. | `-5013` |
| 10029 | `MT_RET_REQUEST_FROZEN` | Order or position too close to market to modify. | `-4021` |
| 10030 | `MT_RET_REQUEST_INVALID_FILL` | Fill mode is not supported. | `-4017` |
| 10031 | `MT_RET_REQUEST_CONNECTION` | No connection. | `-5015` |
| 10032 | `MT_RET_REQUEST_ONLY_REAL` | Allowed only for real accounts. | `-5014` |
| 10033 | `MT_RET_REQUEST_LIMIT_ORDERS` | Order count limit reached. | `-4018` |
| 10034 | `MT_RET_REQUEST_LIMIT_VOLUME` | Volume limit reached. | `-4020` |
| 10035 | `MT_RET_REQUEST_INVALID_ORDER` | Invalid or prohibited order type. | `-5016` |
| 10036 | `MT_RET_REQUEST_POSITION_CLOSED` | Position is already closed. | `-5006` |
| 10038 | `MT_RET_REQUEST_INVALID_CLOSE_VOLUME` | Close volume exceeds the position volume. | `-4024` |
| 10039 | `MT_RET_REQUEST_CLOSE_ORDER_EXIST` | An order to close this position already exists. | `-4025` |
| 10040 | `MT_RET_REQUEST_LIMIT_POSITIONS` | Open position limit reached. | `-4019` |
| 10041 | `MT_RET_REQUEST_REJECT_CANCEL` | Request rejected, order cancelled by a routing rule. | `-5018` |
| 10042 | `MT_RET_REQUEST_LONG_ONLY` | Only long positions are allowed on the symbol. | `-4013` |
| 10043 | `MT_RET_REQUEST_SHORT_ONLY` | Only short positions are allowed on the symbol. | `-4014` |
| 10044 | `MT_RET_REQUEST_CLOSE_ONLY` | Only position closing is allowed on the symbol. | `-4015` |
| 10045 | `MT_RET_REQUEST_PROHIBITED_BY_FIFO` | Closure not allowed by the FIFO rule. | `-4023` |
| 10046 | `MT_RET_REQUEST_HEDGE_PROHIBITED` | Hedge positions are prohibited for the group. | `-4022` |

Codes 10001-10003 (`INWAY`, `ACCEPTED`, `PROCESS`), 10005 (`PRICES`) and 10037
(`EXECUTION_SKIPPED`, internal) are intermediate or internal and are never surfaced as a terminal
`mt5RetCode`.

> 10046 can occur even though this API is hedging-only: the account's **group** can forbid holding
> opposite positions on the same symbol. It is a group setting, not an API mode.

Full error-code list with exact messages: [Error Codes](/error-codes.md).
