Skip to content

Manage Orders Effectively

Problem Statement

You need to create, monitor, and manage trading orders efficiently using FiveTwenty. This guide provides practical solutions for common order management scenarios including creating different order types, handling order lifecycle, and implementing robust order management strategies.

When you need this guide:

  • Creating market, limit, or stop orders programmatically
  • Implementing order validation and error handling
  • Building order management workflows
  • Tracking order execution and lifecycle
  • Handling order modifications and cancellations

Prerequisites:

  • FiveTwenty installed and configured
  • Valid OANDA account (practice or live)
  • Basic understanding of trading order types

Solution Steps

Choose the Right Order Pattern

OANDA supports different order workflows. Choose the pattern that matches your trading style:

OnFill Pattern (Recommended): Set TP/SL when creating orders ```python

import asyncio import os import time import logging from decimal import Decimal

from fivetwenty import AsyncClient, Environment, Client from fivetwenty.models import ( StopLossOrderRequest, TrailingStopLossOrderRequest, GuaranteedStopLossOrderRequest, TakeProfitOrderRequest, OrderRequest, MarketOrderRequest, LimitOrderRequest, MarketIfTouchedOrderRequest, Order, OrderResponse, Position, Trade, ClientPrice, OrderFillTransaction ) from fivetwenty.exceptions import FiveTwentyError

async def main() -> None: """Demonstrate OnFill pattern for immediate risk protection upon order execution.""" # Step 1: Initialize AsyncClient with practice environment for safe testing # OnFill pattern applies risk management instantly when orders execute client = AsyncClient( token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"), # Environment-based auth environment=Environment.PRACTICE # Practice mode prevents real money risk ) account_id = "your-account-id" # Replace with your actual OANDA account ID

# Step 2: Place market order with automatic risk management
# OnFill orders activate take profit and stop loss immediately upon execution
await client.orders.post_market_order(
    account_id=account_id,            # Account for order execution
    instrument="EUR_USD",              # Major currency pair with high liquidity
    units=1000,                       # Position size: 1,000 units EUR long
    take_profit=Decimal("1.1100"),    # Automatic TP: locks in profits at 1.1100
    stop_loss=Decimal("1.0900"),      # Automatic SL: limits losses at 1.0900
)
# Success Risk management is now active automatically - no additional API calls needed
print("Analysis Market order placed with automatic risk management")
print("Target Take profit: 1.1100 | Security Stop loss: 1.0900")

if name == "main": # Step 3: Execute the OnFill pattern demonstration # This pattern is recommended for most trading scenarios requiring immediate protection asyncio.run(main()) ```

**Post-Trade Pattern**: Add TP/SL to existing trades
<!-- fragment: partial post-trade pattern example -->
```python

import asyncio import os

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

async def post_trade_example() -> None: """Demonstrate post-trade pattern for adding risk management after market analysis.""" # Step 1: Initialize client for sequential trade and risk management setup # Post-trade pattern allows market analysis between trade and risk management client = AsyncClient( token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"), # Environment auth environment=Environment.PRACTICE # Safe testing environment ) account_id = "your-account-id" # Replace with your OANDA account ID

# Step 2: First create trade without immediate risk management
# This approach allows market analysis before setting protective levels
market_response = await client.orders.post_market_order(
    account_id=account_id,    # Account for trade execution
    instrument="EUR_USD",      # Currency pair to trade
    units=1000,              # Position size: 1,000 units EUR long
)
print("Analysis Market order executed - analyzing market conditions...")

# Step 3: Extract trade information from order response
# Trade ID is required to attach risk management orders
trade_info = market_response.order_fill_transaction["tradeOpened"]
trade_id = trade_info["tradeID"]  # Unique identifier for this trade
print(f"Business Trade opened with ID: {trade_id}")

# Step 4: Add take profit order based on market analysis
# Separate API call allows dynamic pricing based on current conditions
tp_request = TakeProfitOrderRequest(
    tradeID=trade_id,      # Links TP order to specific trade
    price="1.1100"         # Profit target level determined by analysis
)
tp_response = await client.orders.post_order(account_id, tp_request)
tp_order_id = tp_response.order_create_transaction['id']
print(f"Target Take profit order created: {tp_order_id}")
print("Success Post-trade risk management successfully applied")
```

**When to Use Each:**
- **OnFill**: Most trading scenarios, immediate risk management
- **Post-Trade**: Adding risk management after market analysis, modifying existing levels

Implement Post-Trade Risk Management

Problem: Add risk management orders to existing trades after they've been created and analyzed.

Use Case: You've opened a position and want to add or modify stop loss and take profit levels based on subsequent market analysis, or you need more sophisticated risk management than the OnFill pattern provides.

Step-by-Step Post-Trade Risk Management

import asyncio
import os

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import (
    AccountID,
    GuaranteedStopLossOrderRequest,
    StopLossOrderRequest,
    TakeProfitOrderRequest,
    TrailingStopLossOrderRequest,
)

async def implement_post_trade_risk_management() -> None:
    """Implement comprehensive post-trade risk management for systematic trade protection."""
    # Step 1: Initialize AsyncClient with context manager for automatic cleanup
    # Context manager ensures proper connection closure after operations complete
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment-based auth
        environment=Environment.PRACTICE  # Practice mode for safe testing
    ) as client:
        account_id = AccountID("your-account-id")  # Replace with your OANDA account ID

        # Step 2: Create initial trade without immediate risk management
        # This approach allows market analysis before setting protective levels
        print("Analysis Creating initial position for risk management demonstration...")
        market_response = await client.orders.post_market_order(
            account_id=account_id,    # Account for trade execution
            instrument="EUR_USD",      # Major currency pair with high liquidity
            units=10000,              # Position size: Buy 10,000 EUR (larger size for demo)
        )
        print("Success Market order executed successfully")

        # Step 3: Extract trade information from order fill response
        # Trade ID is essential for linking risk management orders to specific trades
        if (
            market_response.order_fill_transaction
            and "tradeOpened" in market_response.order_fill_transaction
        ):
            trade_info = market_response.order_fill_transaction["tradeOpened"]
            trade_id = trade_info["tradeID"]  # Unique trade identifier from OANDA
            entry_price = trade_info["price"]  # Actual fill price for calculations
            print(f"Business Trade opened: ID {trade_id} at price {entry_price}")

            # Step 4: Add take profit order for systematic profit capture
            # Take profit locks in gains when price reaches target level
            print("Target Adding take profit order for profit protection...")
            tp_request = TakeProfitOrderRequest(
                tradeID=trade_id,        # Links TP to specific trade
                price="1.1150",          # Target price: 150 pips profit (aggressive target)
                timeInForce="GTC",       # Good Till Cancelled: remains active until filled
            )
            print(f"   TP request prepared for trade {trade_id}: target 1.1150")

            # Step 5: Execute take profit order creation
            tp_response = await client.orders.post_order(account_id, tp_request)
            tp_order_id = tp_response.order_create_transaction["id"]
            print(f"   Success Take profit order created: {tp_order_id}")

            # Step 6: Add stop loss order for systematic loss limitation
            # Stop loss protects against adverse price movement beyond acceptable risk
            print("Security Adding stop loss order for capital protection...")
            sl_request = StopLossOrderRequest(
                tradeID=trade_id,        # Links SL to specific trade
                price="1.0950",          # Stop price: 50 pips risk (conservative risk)
                timeInForce="GTC",       # Persistent protection until triggered
            )
            print(f"   SL request prepared for trade {trade_id}: stop at 1.0950")

            # Step 7: Execute stop loss order creation
            sl_response = await client.orders.post_order(account_id, sl_request)
            sl_order_id = sl_response.order_create_transaction["id"]
            print(f"   Success Stop loss order created: {sl_order_id}")

            # Step 8: Confirm comprehensive risk management is now active
            print(f"\nData Post-Trade Risk Management Summary:")
            print(f"   Trade ID: {trade_id}")
            print(f"   Entry Price: {entry_price}")
            print(f"   Take Profit: 1.1150 (TP Order: {tp_order_id})")
            print(f"   Stop Loss: 1.0950 (SL Order: {sl_order_id})")
            print(f"   Risk-Reward: 50 pips risk / 150 pips reward = 1:3 ratio")
            print("   Success Comprehensive protection now active")

Distance-Based Stop Loss

from fivetwenty import AsyncClient
from fivetwenty.models import StopLossOrderRequest

# Alternative: Distance-based stop loss (dynamic pricing)
async def add_distance_based_stop_loss(client: AsyncClient, account_id: str, trade_id: str) -> str:
    """Add stop loss based on distance rather than fixed price for adaptive risk management."""
    # Step 1: Create distance-based stop loss request
    # Distance-based stops automatically adjust with entry price changes
    distance_sl_request = StopLossOrderRequest(
        tradeID=trade_id,            # Links stop loss to specific trade
        distance="0.0050",           # 50 pips from entry price (dynamic calculation)
        timeInForce="GTC",           # Good Till Cancelled: persistent protection
    )
    print(f"💯 Distance-based stop loss prepared: 50 pips for trade {trade_id}")
    print("   Info Distance automatically adjusts with entry price")

    # Step 2: Execute distance-based stop loss order
    # OANDA calculates actual stop price based on entry price + distance
    response = await client.orders.post_order(account_id, distance_sl_request)
    order_id = response.order_create_transaction["id"]
    print(f"   Success Distance-based stop loss created: {order_id}")
    print("   Data Stop price will be exactly 50 pips from trade entry")
    return order_id

Trailing Stop Loss

from fivetwenty import AsyncClient
from fivetwenty.models import TrailingStopLossOrderRequest

async def add_trailing_stop_loss(client: AsyncClient, account_id: str, trade_id: str) -> str:
    """Add trailing stop loss that follows favorable price movement for dynamic profit protection."""
    # Step 1: Create trailing stop loss request for dynamic risk management
    # Trailing stops automatically move with favorable price action while maintaining protection
    tsl_request = TrailingStopLossOrderRequest(
        tradeID=trade_id,          # Links trailing stop to specific trade
        distance="0.0030",         # 30 pips trailing distance (tight protection)
        timeInForce="GTC",         # Good Till Cancelled: follows price indefinitely
    )
    print(f"🎏 Trailing stop loss prepared: 30 pips for trade {trade_id}")
    print("   Info Stop will follow price upward but never move down")

    # Step 2: Execute trailing stop loss order
    # OANDA manages trailing automatically - stop moves up with price, never down
    response = await client.orders.post_order(account_id, tsl_request)
    order_id = response.order_create_transaction["id"]
    print(f"   Success Trailing stop created: {order_id}")
    print("   Data Will follow price with 30 pip buffer, locking in profits")
    print("   Secure Provides dynamic profit protection as price moves favorably")
    return order_id

Guaranteed Stop Loss

from fivetwenty import AsyncClient
from fivetwenty.models import GuaranteedStopLossOrderRequest, StopLossOrderRequest

async def add_guaranteed_stop_loss(client: AsyncClient, account_id: str, trade_id: str) -> str:
    """Add guaranteed stop loss with premium cost for absolute execution certainty."""
    try:
        # Step 1: Create guaranteed stop loss request
        # Guaranteed stops ensure execution at specified price regardless of market gaps
        gsl_request = GuaranteedStopLossOrderRequest(
            tradeID=trade_id,          # Links GSL to specific trade
            price="1.0900",            # Guaranteed execution price (absolute protection)
            timeInForce="GTC",         # Persistent until triggered
        )
        print(f"Security Guaranteed stop loss prepared for trade {trade_id}")
        print("   Info GSL guarantees execution even during market gaps")

        # Step 2: Execute guaranteed stop loss order
        # OANDA charges premium for execution guarantee during volatile markets
        response = await client.orders.post_order(account_id, gsl_request)
        order_id = response.order_create_transaction["id"]

        # Step 3: Check and display premium cost for guaranteed execution
        # Premium compensates OANDA for execution risk during market gaps
        if "guaranteedExecutionPremium" in response.order_create_transaction:
            premium = response.order_create_transaction["guaranteedExecutionPremium"]
            print(f"   Balance Guaranteed execution premium: {premium}")
            print("   Info Premium ensures execution during market volatility")

        print(f"   Success Guaranteed stop loss created: {order_id}")
        print("   Secure Absolute protection against slippage and gaps")

    except Exception:
        # Step 4: Handle cases where guaranteed stops are not available
        # Some instruments or market conditions may not support guaranteed stops
        print("⚠️ Guaranteed stop loss not available for this instrument")
        print("   Processing Falling back to regular stop loss protection...")
        # Fallback to regular stop loss
        return await add_regular_stop_loss(client, account_id, trade_id)
    else:
        return order_id


async def add_regular_stop_loss(client: AsyncClient, account_id: str, trade_id: str) -> str:
    """Add regular stop loss as fallback protection when guaranteed stops unavailable."""
    # Step 1: Create standard stop loss request as fallback
    # Regular stops provide protection but may experience slippage during gaps
    sl_request = StopLossOrderRequest(
        tradeID=trade_id,          # Links stop to specific trade
        price="1.0900",            # Stop trigger price (subject to slippage)
        timeInForce="GTC",         # Persistent protection
    )
    print(f"Security Regular stop loss prepared for trade {trade_id}")
    print("   Info Standard protection with potential slippage during gaps")

    # Step 2: Execute regular stop loss order
    response = await client.orders.post_order(account_id, sl_request)
    order_id = response.order_create_transaction["id"]
    print(f"   Success Regular stop loss created: {order_id}")
    print("   Data Provides standard risk protection at no premium cost")
    return order_id

Error Handling for Post-Trade Orders

from fivetwenty import AsyncClient
from fivetwenty.exceptions import FiveTwentyError
from fivetwenty.models import TakeProfitOrderRequest


async def robust_post_trade_setup(client: AsyncClient, account_id: str, trade_id: str) -> None:
    """Add risk management with comprehensive error handling."""
    try:
        # Attempt to add take profit
        tp_request = TakeProfitOrderRequest(
            tradeID=trade_id,
            price="1.1200",
            timeInForce="GTC",
        )
        print(f"Robust take profit prepared for trade {trade_id}")

        tp_response = await client.orders.post_order(account_id, tp_request)
        tp_order_id = tp_response.order_create_transaction['id']
        print(f"Success Take profit order added successfully: {tp_order_id}")

    except FiveTwentyError as e:
        error_msg = str(e)

        if "TRADE_DOESNT_EXIST" in error_msg:
            print("Error Trade no longer exists - may have been closed")
        elif "INSUFFICIENT_MARGIN" in error_msg:
            print("Error Insufficient margin for risk management orders")
        elif "PRICE_INVALID" in error_msg:
            print("Error Invalid price level - adjust take profit price")
        else:
            print("Error Unexpected error occurred")

    except Exception:
        print("Error System error occurred")

When to Use Post-Trade Pattern

Best for:

  • Complex Strategies: Multi-leg strategies requiring careful timing
  • Market Analysis: Adding risk management after technical/fundamental analysis
  • Dynamic Management: Adjusting levels based on market conditions
  • Position Scaling: Adding risk management to partially closed positions

Not Recommended for:

  • Basic Strategies: OnFill pattern is more efficient
  • High-Frequency Trading: Additional API calls add latency
  • Basic Risk Management: OnFill covers most use cases

Create Market Orders for Immediate Execution

Problem: Execute trades immediately at current market price.

The following example demonstrates how to create market orders using the FiveTwenty SDK. Market orders execute immediately at the best available price, making them ideal for quick entries and exits:

import os
from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName

async def place_market_order() -> None:
    """Demonstrate placing market orders for immediate trade execution at current market prices."""
    # Step 1: Initialize AsyncClient with practice environment for safe testing
    # Market orders provide immediate execution but accept current market price (no price control)
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment-based auth
        environment=Environment.PRACTICE  # Always use practice for examples to prevent real money risk
    ) as client:

        # Example 1: Basic market order for immediate position entry
        # Market orders execute immediately at best available price when submitted
        print("Analysis Example 1: Basic market order (immediate execution)")
        response = await client.orders.post_market_order(
            account_id=AccountID("101-004-12345678"),  # Replace with your OANDA account ID
            instrument=InstrumentName("EUR_USD"),      # Major currency pair with high liquidity
            units=1000,                                # Position size: positive = buy, negative = sell
            client_request_id="market-order-001",     # Optional: for tracking/debugging purposes
        )
        order_id = response.order_create_transaction['id']
        print(f"   Success Market order placed: {order_id}")
        print("   Info Executed immediately at current market price")

        # Example 2: Market order with built-in risk management (OnFill pattern)
        # This approach sets stop-loss and take-profit levels automatically when order fills
        print("\nAnalysis Example 2: Market order with automatic risk management")
        response = await client.orders.post_market_order(
            account_id=AccountID("101-004-12345678"),  # Replace with your OANDA account ID
            instrument=InstrumentName("EUR_USD"),      # Same currency pair for consistency
            units=1000,                                # Same position size for comparison
            take_profit=Decimal("1.1050"),            # Automatic profit-taking at 1.1050
            stop_loss=Decimal("1.0950"),              # Automatic loss-limiting at 1.0950
        )
        order_id = response.order_create_transaction['id']
        print(f"   Success Market order executed successfully: {order_id}")
        print("   Security Order filled at market price with protective stops active")
        print("   Target Take Profit: 1.1050 | Stop Loss: 1.0950")
        print("   ✨ Risk management activated automatically upon fill")

Create Limit Orders for Precise Entry

Problem: Enter positions only when price reaches your target level.

This example shows how to create limit orders that execute only when the market reaches your specified price. Limit orders give you price control but no guarantee of execution:

import os
from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName


async def place_limit_order() -> None:
    """Demonstrate placing limit orders for precise entry price control and patient positioning."""
    # Step 1: Initialize AsyncClient for limit order demonstration
    # Limit orders provide price control but execution is not guaranteed
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment auth
        environment=Environment.PRACTICE  # Safe testing environment
    ) as client:

        # Step 2: Place limit order with precise entry requirements
        # Limit orders only execute when market reaches your specified price or better
        print("Target Placing limit order for precise entry control...")
        response = await client.orders.post_limit_order(
            account_id=AccountID("101-004-12345678"),  # Replace with your OANDA account ID
            instrument=InstrumentName("GBP_USD"),      # British Pound vs US Dollar pair
            units=500,                                # Position size: 500 GBP long
            price=Decimal("1.2500"),                  # Entry price: Buy only when price drops to 1.2500
            time_in_force="GTC",                      # Good Till Cancelled: stays active until filled
            take_profit=Decimal("1.2600"),            # Profit target: 100 pips above entry
            stop_loss=Decimal("1.2400"),              # Risk limit: 100 pips below entry
        )
        order_id = response.order_create_transaction['id']
        print(f"   Success Limit order placed successfully: {order_id}")
        print(f"   Balance Entry Price: 1.2500 (waits for market to reach this level)")
        print(f"   Target Take Profit: 1.2600 (100 pips target)")
        print(f"   Security Stop Loss: 1.2400 (100 pips risk)")
        print("   Wait Order will wait patiently until price reaches 1.2500 or better")

Create Stop Orders for Breakout Trading

Problem: Enter positions when price breaks above/below key levels.

Here's how to create stop orders for breakout trading strategies. Stop orders become market orders when the trigger price is reached, making them ideal for momentum trading:

import os
from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName


async def place_stop_order() -> None:
    """Demonstrate placing stop orders for breakout trading and momentum capture strategies."""
    # Step 1: Initialize AsyncClient for stop order demonstration
    # Stop orders become market orders when trigger price is reached (breakout trading)
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment auth
        environment=Environment.PRACTICE  # Safe testing environment
    ) as client:

        # Step 2: Place buy stop order for upward breakout strategy
        # Buy stop triggers when price breaks above resistance level (momentum trading)
        print("Starting Placing buy stop order for upward breakout strategy...")
        response = await client.orders.post_stop_order(
            account_id=AccountID("101-004-12345678"),  # Replace with your OANDA account ID
            instrument=InstrumentName("EUR_USD"),      # Major currency pair for breakout trading
            units=1000,                               # Position size: 1,000 EUR long on breakout
            price=Decimal("1.1100"),                  # Stop activation: triggers when price hits 1.1100
            price_bound=Decimal("1.1110"),            # Maximum slippage: won't pay more than 1.1110
            time_in_force="GFD",                     # Good for day: expires at market close
            take_profit=Decimal("1.1150"),            # Profit target: 50 pips above breakout
            stop_loss=Decimal("1.1050"),             # Risk limit: 50 pips below breakout
            client_request_id="breakout-strategy-001", # Tracking ID for strategy monitoring
        )
        order_id = response.order_create_transaction['id']
        print(f"   Success Stop order placed successfully: {order_id}")
        print(f"   Data Breakout Trigger: 1.1100 (becomes market order when hit)")
        print(f"   Security Price Protection: won't pay more than 1.1110 (slippage control)")
        print(f"   Target Take Profit: 1.1150 (50 pips momentum target)")
        print(f"   Security Stop Loss: 1.1050 (50 pips breakout failure protection)")
        print("   Time Expires at end of trading day if not triggered")

Create Market-If-Touched Orders for Support/Resistance Trading

Problem: Enter positions when price touches support/resistance levels.

This example demonstrates Market-If-Touched (MIT) orders, which execute at market price when a specified trigger level is reached. These are perfect for entering positions at support or resistance levels:

import os
from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName


async def place_market_if_touched_order() -> None:
    """Demonstrate placing market-if-touched orders for support/resistance level trading."""
    # Step 1: Initialize AsyncClient for MIT order demonstration
    # MIT orders execute at market price when trigger level is touched (perfect for S/R trading)
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment auth
        environment=Environment.PRACTICE  # Safe testing environment
    ) as client:

        # Step 2: Place MIT order for support level bounce strategy
        # MIT triggers at support touch, then executes at current market price
        print("Target Placing Market-If-Touched order for support bounce strategy...")
        response = await client.orders.post_market_if_touched_order(
            account_id=AccountID("101-004-12345678"),  # Replace with your OANDA account ID
            instrument=InstrumentName("GBP_USD"),      # British Pound for support/resistance trading
            units=750,                                # Position size: 750 GBP long on bounce
            price=Decimal("1.2400"),                  # Support level trigger: activates when touched
            price_bound=Decimal("1.2390"),            # Slippage limit: won't pay less than 1.2390
            time_in_force="GTC",                     # Good till cancelled: persistent until triggered
            take_profit=Decimal("1.2500"),            # Profit target: 100 pips bounce target
            stop_loss=Decimal("1.2350"),             # Risk limit: 50 pips below support break
            client_request_id="support-bounce-001",   # Strategy tracking identifier
        )
        order_id = response.order_create_transaction['id']
        print(f"   Success MIT order placed successfully: {order_id}")
        print(f"   Data Support Touch: 1.2400 (triggers when price reaches this level)")
        print(f"   Security Price Protection: won't buy below 1.2390 (10 pip slippage limit)")
        print(f"   Target Take Profit: 1.2500 (100 pips bounce target from support)")
        print(f"   Security Stop Loss: 1.2350 (50 pips protection if support fails)")
        print("   Infinity Perfect for support/resistance trading strategies")

Use the Unified Order Interface for Flexibility

Problem: Need to create different order types programmatically based on strategy logic.

import os
import time
from decimal import Decimal
from typing import Any

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import (
    AccountID,
    InstrumentName,
    LimitOrderRequest,
    MarketOrderRequest,
    StopOrderRequest,
    TimeInForce,
)


<!-- fragment: partial unified order interface example -->
```python
async def create_order_by_type(order_type: str, price: Decimal | None = None) -> Any:
    """Create orders dynamically by type using the unified order interface for flexible strategy implementation."""
    # Step 1: Initialize AsyncClient for unified order interface demonstration
    # Unified interface allows programmatic order creation based on strategy logic
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),  # Environment auth
        environment=Environment.PRACTICE  # Safe testing for dynamic order creation
    ) as client:
        account_id = AccountID("101-004-12345678")  # Replace with your OANDA account ID
        instrument = InstrumentName("USD_JPY")      # Japanese Yen pair for demo
        units = 1000                               # Standard position size for all order types

        # Step 2: Build order request dynamically based on strategy requirements
        # Different order types serve different strategic purposes in trading
        print(f"Config Building {order_type} order request for {instrument}...")

        if order_type == "market":
            # Market order for immediate execution (speed over price control)
            order_request = MarketOrderRequest(
                instrument=instrument,    # Currency pair to trade
                units=units,             # Position size
            )
            print("   Lightning Market order: immediate execution at current price")

        elif order_type == "limit":
            # Limit order for precise price control (price over speed)
            if price is None:
                raise ValueError("Limit orders require price parameter")
            order_request = LimitOrderRequest(
                instrument=instrument,        # Currency pair to trade
                units=units,                 # Position size
                price=str(price),            # Exact entry price requirement
                timeInForce=TimeInForce.GTC, # Good till cancelled
            )
            print(f"   Target Limit order: precise entry at {price}")

        elif order_type == "stop":
            # Stop order for breakout trading (momentum capture)
            if price is None:
                raise ValueError("Stop orders require price parameter")
            order_request = StopOrderRequest(
                instrument=instrument,        # Currency pair to trade
                units=units,                 # Position size
                price=str(price),            # Breakout trigger price
                timeInForce=TimeInForce.GTC, # Good till cancelled
            )
            print(f"   Starting Stop order: breakout trigger at {price}")

        else:
            msg = f"Unsupported order type: {order_type}"
            raise ValueError(msg)

        print(f"   Success {order_type.title()} order request created for {instrument}")

        # Step 3: Execute order using unified interface
        # Single interface handles all order types consistently
        result = await client.orders.post_order(
            account_id=account_id,                                    # Account for execution
            order_request=order_request,                             # Order specification
            client_request_id=f"{order_type}-order-{int(time.time())}", # Unique tracking ID
        )
        order_id = result.order_create_transaction['id']
        print(f"   Success Unified {order_type} order created: {order_id}")
        print(f"   Data Order processed through unified interface successfully")
        return result

Monitor and Track Order Status

Problem: Track order execution and handle different outcomes.

import os

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


async def monitor_order_execution(account_id: AccountID, order_id: str) -> None:
    """Monitor order execution status."""
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        # Get current order status
        order = await client.orders.get_order(account_id, order_id)
        state = order["state"]
        print(f"Order state checked: {state}")
        print("Order fill information retrieved")

        # Check if order is still pending
        if state == "PENDING":
            print("Order is waiting for execution")

            # Get all pending orders for context
            pending_response = await client.orders.get_pending_orders(account_id)
            pending_count = len(pending_response["orders"])
            print(f"Pending orders retrieved: {pending_count} total")

        elif state == "FILLED":
            print("Order execution confirmed")

        elif state == "CANCELLED":
            print("Order was cancelled")

Implement Order Validation and Error Handling

Problem: Robust order validation to prevent common errors.

import os
import time
from decimal import Decimal
from typing import Any

from fivetwenty import AsyncClient, Environment
from fivetwenty.exceptions import FiveTwentyError
from fivetwenty.models import AccountID, InstrumentName


async def place_validated_order(
    account_id: AccountID,
    instrument: InstrumentName,
    units: int,
    order_type: str = "market",
    price: Decimal | None = None,
) -> Any:
    """Place validated order with comprehensive checks."""
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        try:
            # Validate account has sufficient balance
            account = await client.accounts.get_account(account_id)
            available_balance = Decimal(account.nav)
            print(f"Account balance: {available_balance}")

            # Validate instrument is tradeable
            instruments = await client.accounts.get_account_instruments(
                account_id, instruments=[instrument]
            )
            print(f"Retrieved {len(instruments)} instrument(s)")

            if not instruments:
                msg = f"Instrument {instrument} not available"
                raise ValueError(msg)

            instrument_info = instruments[0]
            if not instrument_info.tradeable:
                msg = f"Instrument {instrument} not currently tradeable"
                raise ValueError(msg)

            # Validate order size
            min_units = abs(int(instrument_info.minimum_trade_size))
            max_units = abs(int(instrument_info.maximum_order_units))

            if abs(units) < min_units:
                msg = f"Order size {units} below minimum {min_units}"
                raise ValueError(msg)
            if abs(units) > max_units:
                msg = f"Order size {units} exceeds maximum {max_units}"
                raise ValueError(msg)

            # Place order based on type
            if order_type == "market":
                response = await client.orders.post_market_order(
                    account_id=account_id,
                    instrument=instrument,
                    units=units,
                    client_request_id=f"validated-{order_type}-{int(time.time())}",
                )
            elif order_type == "limit" and price:
                response = await client.orders.post_limit_order(
                    account_id=account_id,
                    instrument=instrument,
                    units=units,
                    price=price,
                    client_request_id=f"validated-{order_type}-{int(time.time())}",
                )

            else:
                msg = "Invalid order type or missing price for limit order"
                raise ValueError(msg)

            order_id = response.order_create_transaction['id']
            print(f"Validated {order_type} order created: {order_id}")

            return response

        except FiveTwentyError as e:
            print("OANDA API error encountered")
            print("Error code logged")
            raise
        except ValueError as e:
            print("Validation error occurred")
            raise

Cancel and Modify Orders

Problem: Manage pending orders by cancelling or replacing them.

import os
from datetime import datetime, timedelta, timezone

from fivetwenty import AsyncClient, Environment
from fivetwenty.exceptions import FiveTwentyError
from fivetwenty.models import AccountID


async def manage_pending_orders(account_id: AccountID) -> None:
    """Manage pending orders with cancellation logic."""
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        # Get all pending orders
        pending_response = await client.orders.get_pending_orders(account_id)
        pending_orders = pending_response["orders"]
        print(f"Found {len(pending_orders)} pending orders")

        for order in pending_orders:
            order_id = order["id"]

            # Cancel old orders (example: cancel orders older than 1 hour)
            order_time = datetime.fromisoformat(
                order["createTime"].replace("Z", "+00:00")
            )
            stale_order_threshold_hours = 1
            if datetime.now(timezone.utc) - order_time > timedelta(hours=stale_order_threshold_hours):
                try:
                    cancel_response = await client.orders.cancel_order(
                        account_id,
                        order_id,
                    )
                    cancelled_order_id = cancel_response.order_cancel_transaction.id if cancel_response.order_cancel_transaction else order_id
                    print(f"Order cancelled successfully: {cancelled_order_id}")

                except FiveTwentyError as e:
                    if e.error_code == "ORDER_DOESNT_EXIST":
                        print("Order already processed")
                    else:
                        raise

Implement Batch Order Operations

Problem: Create multiple related orders efficiently.

The following example shows how to create multiple related orders in a single operation. This technique is essential for complex trading strategies that require coordinated order placement:

import asyncio
import os
import time
from dataclasses import dataclass
from decimal import Decimal
from typing import Any

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName


@dataclass
class BracketOrderParams:
    account_id: AccountID
    instrument: InstrumentName
    entry_price: Decimal
    take_profit: Decimal
    stop_loss: Decimal
    units: int

async def create_bracket_order(params: BracketOrderParams) -> Any:
    """Create a bracket order: entry + take profit + stop loss."""
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        # Create entry order
        entry_order = await client.orders.post_limit_order(
            account_id=params.account_id,
            instrument=params.instrument,
            units=params.units,
            price=params.entry_price,
            client_request_id=f"bracket-entry-{int(time.time())}",
        )

        entry_order_id = entry_order.order_create_transaction.id
        print(f"Entry order created successfully: {entry_order_id}")

        # Wait for entry order to fill, then create protective orders
        # In practice, you'd use webhooks or streaming for real-time updates
        await asyncio.sleep(1)  # Brief pause for demo

        # Check if entry filled
        order_status = await client.orders.get_order(params.account_id, entry_order_id)
        status_state = order_status["state"]
        print(f"Entry order status: {status_state}")

        if status_state == "FILLED":
            # Create protective orders
            tasks = []

            # Take profit order (opposite direction)
            tp_task = client.orders.post_limit_order(
                account_id=params.account_id,
                instrument=params.instrument,
                units=-params.units,  # Opposite direction to close position
                price=params.take_profit,
                client_request_id=f"bracket-tp-{int(time.time())}",
            )
            tasks.append(tp_task)

            # Stop loss order (opposite direction)
            sl_task = client.orders.post_limit_order(
                account_id=params.account_id,
                instrument=params.instrument,
                units=-params.units,  # Opposite direction to close position
                price=params.stop_loss,
                client_request_id=f"bracket-sl-{int(time.time())}",
            )
            tasks.append(sl_task)

            # Execute protective orders concurrently
            results = await asyncio.gather(*tasks, return_exceptions=True)

            for i, result in enumerate(results):
                order_type = "Take Profit" if i == 0 else "Stop Loss"
                if isinstance(result, Exception):
                    print(f"{order_type} order placement failed: {result}")
                else:
                    order_id = result.order_create_transaction.id
                    print(f"{order_type} order created successfully: {order_id}")

        return entry_order

Verification

Confirm Order Creation

import os

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

async def example_order_handling():
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")
        order_type = "market"

        # Create example response
        response = await client.orders.post_market_order(
            account_id=account_id,
            instrument="EUR_USD",
            units=1000
        )

        # Check order was created successfully
        if response.order_create_transaction is None:
            order_error_msg = "Order transaction is None"
            raise ValueError(order_error_msg)
        if response.order_create_transaction.id is None:
            transaction_error_msg = "Order transaction ID is None"
            raise ValueError(transaction_error_msg)

        # For market orders, verify immediate fill
        if order_type == "market":
            if response.order_fill_transaction is None:
                fill_error_msg = "Market order fill transaction is None"
                raise ValueError(fill_error_msg)
            print("Order filled successfully")

Verify Order Parameters

import os

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName

async def verify_order_parameters() -> None:
    """Verify order parameters match your request."""
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")
        order_id = "12345"  # Example order ID
        instrument = InstrumentName("EUR_USD")
        units = 1000

        # Confirm order details match your request
        order_details = await client.orders.get_order(account_id, order_id)
        print(f"Order details retrieved for {order_id}")
        if order_details["instrument"] != str(instrument):
            raise ValueError("Order instrument mismatch")
        if int(order_details["units"]) != units:
            raise ValueError("Order units mismatch")

Monitor Account Impact

import os

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

async def monitor_account_impact() -> None:
    """Monitor account balance and positions after order."""
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")

        # Check account balance and positions after order
        account = await client.accounts.get_account(account_id)
        nav = account.nav
        print(f"Account NAV retrieved: {nav}")
        print("Unrealized P&L retrieved")

Troubleshooting

Common Order Errors

"INSUFFICIENT_MARGIN" Error:

import os
from decimal import Decimal

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

async def check_insufficient_margin() -> None:
    """Check for insufficient margin error."""
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")
        required_margin = Decimal("1000.00")  # Example required margin

        # Check available margin before placing order
        account = await client.accounts.get_account(account_id)
        available_margin = Decimal(account.margin_available)
        if available_margin < required_margin:
            msg = f"Insufficient margin for order: {available_margin} < {required_margin}"
            print(msg)

"INSTRUMENT_NOT_TRADEABLE" Error:

import os

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

async def check_instrument_tradeable() -> None:
    """Check if instrument is tradeable."""
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")

        # Verify instrument is currently tradeable
        instruments = await client.accounts.get_account_instruments(account_id)
        tradeable_instruments = [i for i in instruments if i.tradeable]
        print(f"Found {len(tradeable_instruments)} tradeable instruments out of {len(instruments)} total")

"PRICE_PRECISION_EXCEEDED" Error:

# Use proper price precision for instrument
import os
from decimal import Decimal

from fivetwenty import AsyncClient, Environment
from fivetwenty.models import AccountID, InstrumentName
from fivetwenty._internal.utils import quantize_price

async def check_price_precision() -> None:
    """Handle price precision correctly."""
    # Example setup for demonstration
    async with AsyncClient(
        token=os.environ.get("FIVETWENTY_OANDA_TOKEN", "demo-token"),
        environment=Environment.PRACTICE
    ) as client:
        account_id = AccountID("101-004-12345678")
        instrument = InstrumentName("EUR_USD")
        your_price = Decimal("1.10555")

        # Get instrument precision
        instrument_info = await client.accounts.get_account_instruments(
            account_id, instruments=[instrument]
        )
        precision = instrument_info[0].display_precision
        print(f"Instrument precision: {precision}")

        # Quantize price correctly
        quantized_price = quantize_price(precision, your_price)
        print(f"Price quantized from {your_price} to {quantized_price}")

Order Timing Issues

Orders Not Filling:

  • Check market hours for the instrument
  • Verify price is reasonable (not too far from current market)
  • Consider using Market orders for immediate execution

Order Rejection:

  • Validate all required parameters are provided
  • Check account permissions and trading restrictions
  • Ensure instrument symbols are correct (use InstrumentName enum)

Performance Optimization

Rate Limiting:

from asyncio import Semaphore
from typing import Any

from fivetwenty import AsyncClient

# Limit concurrent requests
MAX_CONCURRENT_ORDERS = 5
semaphore = Semaphore(MAX_CONCURRENT_ORDERS)

async def rate_limited_order(client: AsyncClient, order_params: Any) -> Any:
    """Place orders with rate limited order placement."""
    async with semaphore:
        result = await client.orders.post_order(**order_params)
        print(f"Rate-limited order placed: {result.order_create_transaction['id']}")
        return result

Error Recovery:

import asyncio
from typing import Any

from fivetwenty import AsyncClient
from fivetwenty.exceptions import FiveTwentyError

DEFAULT_MAX_RETRIES = 3

async def robust_order_placement(client: AsyncClient, order_params: Any, max_retries: int = DEFAULT_MAX_RETRIES) -> Any:
    """Place orders with robust order placement with retry logic."""
    for attempt in range(max_retries):
        try:
            result = await client.orders.post_order(**order_params)
            print(f"Order placed successfully on attempt {attempt + 1}")
            return result
        except FiveTwentyError as e:
            if e.error_code in ["RATE_LIMIT_EXCEEDED", "SERVICE_UNAVAILABLE"]:
                BACKOFF_BASE = 2
                wait_time = BACKOFF_BASE**attempt  # Exponential backoff
                await asyncio.sleep(wait_time)
                continue
            else:
                raise  # Don't retry for non-transient errors

    msg = f"Order failed after {max_retries} attempts"
    raise Exception(msg)

Advanced Patterns

Order State Machine

import asyncio
from datetime import datetime
from enum import Enum
from typing import Any

from fivetwenty import AsyncClient
from fivetwenty.models import AccountID


class OrderState(Enum):
    """Define order state enumeration."""

    CREATED = "created"
    PENDING = "pending"
    FILLED = "filled"
    CANCELLED = "cancelled"
    REJECTED = "rejected"


class OrderManager:
    """Manage order lifecycle."""

    def __init__(self, client: AsyncClient) -> None:
        """Initialize order manager."""
        self.client = client
        self.orders: dict[str, dict[str, Any]] = {}

    async def track_order(self, account_id: AccountID, order_id: str) -> None:
        """Track order through its lifecycle."""
        while True:
            order = await self.client.orders.get_order(account_id, order_id)
            order_state = order["state"]
            state = OrderState(order_state.lower())
            print(f"Order {order_id} state: {order_state}")

            self.orders[order_id] = {
                "state": state,
                "last_updated": datetime.now(),
                "details": order,
            }

            if state in [
                OrderState.FILLED,
                OrderState.CANCELLED,
                OrderState.REJECTED,
            ]:
                break

            POLLING_INTERVAL_SECONDS = 1
            await asyncio.sleep(POLLING_INTERVAL_SECONDS)  # Poll interval

Risk Management Integration

from decimal import Decimal
from typing import Any

from fivetwenty import AsyncClient
from fivetwenty.models import AccountID

class RiskManagedOrderSystem:
    """Manage orders with risk controls."""

    def __init__(self, client: AsyncClient, max_daily_loss: Decimal) -> None:
        """Initialize risk managed order system."""
        self.client = client
        self.max_daily_loss = max_daily_loss
        self.daily_loss = Decimal("0")

    async def place_order_with_risk_check(
        self, account_id: AccountID, **order_params: Any
    ) -> Any:
        """Place order with risk checks."""
        # Check daily loss limit
        if self.daily_loss >= self.max_daily_loss:
            msg = "Daily loss limit exceeded"
            raise ValueError(msg)

        # Calculate potential loss for this order
        potential_loss = self._calculate_potential_loss(order_params)
        print(f"Potential loss for order: {potential_loss}")

        if self.daily_loss + potential_loss > self.max_daily_loss:
            msg = "Order would exceed daily loss limit"
            raise ValueError(msg)

        # Place order if risk checks pass
        result = await self.client.orders.post_order(
            account_id=account_id,
            **order_params,
        )
        print(f"Risk-managed order placed: {result.order_create_transaction['id']}")
        return result

    def _calculate_potential_loss(self, order_params: Any) -> Decimal:
        """Calculate potential loss for order."""
        # Placeholder implementation
        potential_loss = Decimal("0")
        print(f"Calculated potential loss: {potential_loss}")
        return potential_loss

Need more specific help? Check these related guides:

```