Skip to content

Create, inspect and replace orders

An order is a request for an action; a trade is exposure created by a fill. Keep their IDs separate and inspect returned transactions before updating your application's state.

Choose an entry interface

Convenience methods cover market, limit, stop and market-if-touched orders. For fields not exposed by a convenience method, build the corresponding request model and call post_order(). For example, post_market_order() has no time_in_force argument; use MarketOrderRequest for IOC or other supported model fields.

This helper creates a practice limit order using caller-selected units and price:

from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import LimitOrderRequest


async def create_limit(client: AsyncClient, units: Decimal, price: Decimal) -> str:
    if client.config.environment != Environment.PRACTICE:
        message = "Use a practice account for this example"
        raise ValueError(message)
    request = LimitOrderRequest(instrument="EUR_USD", units=units, price=price)
    response = await client.orders.post_order(client.account_id, request)
    created = response.get("orderCreateTransaction")
    if created is None:
        message = "No creation transaction returned"
        raise RuntimeError(message)
    return created.id

A valid model is not assurance of server acceptance. Check instrument metadata and account restrictions. A marketable limit order can fill immediately, so creation does not mean it is still pending.

Inspect the lifecycle

Use get_order(account_id, order_id) for a known order and get_pending_orders() for currently pending orders. get_orders() returns an envelope and applies its filters and count; it is not an unbounded account-history dump.

from fivetwenty import AsyncClient


async def inspect_order(client: AsyncClient, order_id: str) -> None:
    response = await client.orders.get_order(client.account_id, order_id)
    order = response["order"]
    print(order.id, order.type, order.state)
    print(response["lastTransactionID"])

Use transaction history to explain creation, fills, cancellation and rejection. REJECTED is not an OrderState value in this SDK; rejection is represented through error responses and transaction types.

Replace or cancel a pending order

put_order() replaces an order through a cancel-and-create operation. Supply a complete replacement request and capture the new creation ID; do not keep treating the old ID as the active order. The response may contain cancellation, creation, fill or reissue details.

cancel_order() requests cancellation of a pending order. It does not close a trade that was already opened by a fill. Read the final order state when a cancellation races with execution.

Attach and update dependent orders

Use request-model *_on_fill fields to describe dependent orders for a newly opened trade. For an existing trade, use put_trade_orders(). Omitting an argument leaves that dependent order unchanged; None cancels it. The helper accepts model objects or partial dictionaries with OANDA field names.

See stop-loss management for exact examples. Placing related independent orders concurrently does not make them a server-side bracket or an atomic group.

Track outcomes, not just HTTP success

Persist identifiers and relevant response transactions. lastTransactionID is an account transaction cursor, not necessarily the order ID. RequestID identifies an HTTP request, and client extension IDs have their own meaning.

If the response is lost, resolve the unknown write outcome before resubmitting. The SDK deliberately avoids automatic write retries.