The trading terminal

What your customers see and do — demo and live accounts, funding from the platform wallet, the terminal layout, placing and managing orders, margin in plain words, and every reason an order gets refused.

8 min readUpdated 3 August 2026terminal, orders, accounts, margin, deposits, withdrawals

The customer-facing product is one page: /forex-trading/trade. There is no separate accounts area — accounts, funding and statements open as views over the chart from the terminal header, because a trader should never have to leave the market to move money.

Trading accounts

A customer can hold up to three DEMO and three LIVE accounts. Each one is bound to their user record at creation; there is no pool to claim from.

Lists the caller's trading accounts with live equity and margin
Creates a DEMO or LIVE account

DEMO is the funnel and it works the moment the extension is active. On the first visit to the terminal one demo account is provisioned automatically, in the first configured account currency, seeded with 10,000 units of paper money. Deposits are refused on demo accounts — that seed is the whole balance. There is no KYC gate.

LIVE requires three things to be true: fxTradingEnabled is on, the customer's country is not on the geo-block list, and — when the platform's KYC system is enabled — they hold an approved KYC level carrying the trade_forex feature. Platforms with KYC switched off skip that last check entirely.

The account currency is fixed at creation and chosen from the operator's list. It never changes afterwards, because the deals ledger is denominated in it and re-denominating a ledger is not a thing you can do safely.

Each account carries its own leverage knob, defaulting to 100. Effective leverage on any trade is the minimum of that, the symbol group's leverage and the account tier's cap — so a customer setting 500 on a group capped at 50 gets 50.

Funding a live account

Transfers from a platform wallet into a trading account

The transfer is instant and atomic: the platform wallet is debited and the trading account credited inside one transaction, with idempotency on both ledgers. The source wallet must be FIAT, SPOT or ECO in the same currency as the trading account — there is no conversion step. A customer with a USD trading account and only a EUR wallet gets a clear error rather than a surprise exchange rate.

A FxTradingDepositConfirmation email and an in-app notification follow.

Requests a withdrawal back to a platform wallet

Withdrawals are two-phase and gated on free margin. The withdrawable amount is max(0, min(balance, equity − usedMargin)), computed inside the same row lock as the debit, with margin reserved by any in-flight external orders added to usedMargin. On top of that:

  • Blocked entirely while the account's margin level is below its margin-call level and positions are open.
  • Blocked while pricing for any open position is stale, because a wrong equity number here pays out money that is not there.
  • Subject to rolling daily and monthly limits stored per account (defaults 5,000 and 50,000).

The trading account is debited immediately and a PENDING FX_TRADING_WITHDRAW wallet transaction is queued. The platform wallet is only credited when an operator approves it — see Withdrawal approvals.

The risk disclosure

When fxTradingRiskWarningEnabled is on, the first entry to the terminal shows a blocking leveraged-trading risk disclosure, and the order ticket carries a persistent risk notice thereafter.

Records the risk-disclosure acknowledgment

The acknowledgment is stored server-side per account, so it survives a new device or a cleared browser. It is idempotent — a repeat call returns the original timestamp.

Country restrictions

The geo-block list is enforced on the way in, never on the way out. Blocked countries are refused (403) at account creation, order placement, pending-order modification and deposits. Closing a position, cancelling an order and withdrawing are deliberately never blocked: a policy change must not trap someone's money.

The customer's country is resolved from approved KYC data first, then the self-declared profile country, then the CDN geo header (cf-ipcountry). A match on any signal blocks, so neither a VPN nor an edited profile bypasses a verified identity. A user with no resolvable country is allowed — the platform has no mandatory country capture before KYC, and blocking unknowns would lock out every pre-KYC demo visitor.

The terminal at a glance

Every visible instrument with its live bid, ask and day change, grouped by asset class, searchable and filterable. A symbol that is not currently quoting shows its state rather than a stale price.

Candles for the selected symbol with the usual timeframes, back-filled from the provider's history and extended live from the tick stream. Closed-session ranges are never fabricated — a gap in the chart is a real gap in the market.

Side, order type, size in lots, optional stop loss, take profit and trailing distance, plus a live readout of the margin the order will consume and the commission it will cost.

Three tabs — Positions, Orders and History — with the account's totals in the header row.

Sizes in the ticket are entered in lots and converted to base units against the instrument's contract size before they reach the API. The minimum, maximum and step come from the instrument's limits, so a stock with a one-share minimum and an FX pair with a 0.01-lot minimum both behave correctly without the customer knowing why.

Client-side validation in the ticket is a hint layer only. Session state, delayed-data policy, size limits, stops distance and margin are all enforced by the backend, and its message is surfaced verbatim — so when a customer quotes an error at you, it is the server's words.

The gear icon opens terminal settings: a font-scale control and an order confirmation toggle, which is off by default. Both persist in the browser.

Placing orders

Places a market or pending order

Four order types are accepted.

Type Behaviour
MARKET Fills instantly at the marked-up ask (buy) or bid (sell)
LIMIT Rests below the market for a buy, above for a sell
STOP Rests above the market for a buy, below for a sell
STOP_LIMIT A stop trigger that then places a limit

Pending orders take a time in force:

  • GTC — good till cancelled.
  • GTD — good till a date you supply, which must be in the future.
  • DAY — expires at the session close. Only placeable while the session is open, because otherwise there is no close to expire against.

Pending orders reserve no margin. The hedge-aware free-margin check runs at trigger time instead, and an account that can no longer afford the position gets the order rejected rather than filled. That is a deliberate trade-off: reserving margin on resting orders would let a customer lock up their whole balance with orders that may never fill.

A pending order can be placed while the market is closed — it parks and triggers on reopen ticks.

Placement rules

Both paths enforce the same gates, because a pending order is not a harmless row: when it triggers it opens a real position with the levels it was placed with.

  • Size must sit within the instrument's minimum, maximum and step.
  • A pending order's price must not be instantly triggerable, and must sit at least stopsLevel points away from the current marked-up price.
  • Attached stop loss and take profit are validated against the price the order will actually enter at, not the current market — so a pending buy whose stop loss sits above its own entry is refused rather than opening a position that closes itself on the next tick.
  • A requestNonce makes the placement idempotent. A retry after a dropped response returns the original order rather than opening a second position.

Managing what is open

Modifies a pending order's prices, levels and expiry
Cancels a pending order — no funds move
Modifies a position's stop loss, take profit and trailing distance
Closes a position fully or partially

Trailing stops are server-side. The distance is set in points and the engine moves the stop on every favourable tick, whether or not the customer's browser is open.

Partial closes book a PARTIAL_CLOSE deal and leave the remainder open with its levels intact.

The Orders tab also shows recently rejected orders with their rejection reason until the customer dismisses them, so a pending order that failed its margin check at trigger time does not just silently disappear.

What a trade costs

Three separate charges, and it is worth being able to explain all three:

  1. The spread. The difference between what the provider quotes and what the customer gets, set by the symbol group's spreadMarkupPips. Paid implicitly at entry.
  2. Commission. commissionPerLot in the account currency, charged in full at open and priced as a round turn, so there is no second charge at close. Zero on every seeded group except US Stocks.
  3. Swap. Overnight financing at 17:00 New York, triple on the group's triple-swap day. Can be a credit rather than a charge, depending on the instrument's swap points.

Margin, in plain words

Used margin is what the open positions require: roughly position value ÷ effective leverage, per symbol, converted into the account currency.

Equity is balance + floating profit and loss.

Free margin is equity − used margin — how much more the account could commit.

Margin level is equity ÷ used margin × 100. This is the number that matters:

Margin level What happens
Comfortably above the margin-call level Normal trading
Below the margin-call level (default 100%) Email and in-app warning; margin-increasing orders refused; withdrawals blocked
Below the stop-out level (default 50%) Positions force-closed, largest loser first, until the level recovers
Balance still negative after everything closed Zeroed by negative-balance protection, if the account tier has it on

Hedging is cheap by default. With hedgedMarginRate at 0, margin per symbol is charged on the larger side only, so a fully hedged pair costs what one leg costs.

Why an order gets refused

Every one of these is a real, distinct message the API returns:

The symbol is not in the QUOTING state — either the feed has gone stale past the configured threshold, or the provider's WebSocket is not connected at all. This is the most common refusal on a misconfigured install and it is almost always the provider, not the order. See Troubleshooting.

The instrument's session calendar says so. The terminal shows the next open time. Pending orders can still be placed and will trigger on reopen.

The instrument is flagged delayed and fxTradingDelayedStocksTradable is off. Seeded stocks and index ETFs carry that flag. Turning the setting on when your provider plan does not actually stream real-time equities hands customers guaranteed latency arbitrage against your book.

The message states exactly how much was required and how much was available, in the account currency. It folds in commission and any margin reserved by in-flight external orders.

Only risk-reducing orders are accepted at this point. Closing is still allowed.

An operator has flipped the per-account kill-switch. Closes are still permitted; only new orders are blocked.

fxTradingEnabled is off. Demo accounts are unaffected.

The market is being wound down. Existing positions can still be closed.

The USD hub pair needed to convert this instrument's quote currency into the account currency is not listed and quoting. List it, or restrict account currencies to ones your catalog can convert.

The statement

The account's immutable deal ledger

Every balance-affecting event, newest first, each row carrying the balance it left behind: fills, commission, swaps, deposits, withdrawals and operator adjustments. The sum of the ledger equals the account balance — a reconciler verifies exactly that every five minutes and alerts if it ever stops being true.

This is what a customer should be pointed at in a dispute, and it is the same data the operator sees in the admin Deals Ledger.

Next