# How to Use Contingency Orders (OCO, OTO, OUO) in Nautilus Trader

> Master contingency orders in Nautilus Trader. Learn to implement OCO, OTO, and OUO strategies using the ContingencyType enum and OrderFactory API for efficient trading.

- Repository: [Nautech Systems/nautilus_trader](https://github.com/nautechsystems/nautilus_trader)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Contingency orders in Nautilus Trader are controlled through the `ContingencyType` enumeration defined in [`nautilus_trader/model/enums.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/enums.py), enabling OCO (One-Cancels-Other), OTO (One-Triggers-Other), and OUO (One-Updates-Other) patterns via `OrderList` and `OrderFactory` APIs.**

Nautilus Trader provides native support for contingency orders, allowing traders to link multiple orders with specific execution dependencies. This functionality is implemented through the `ContingencyType` enum and the `OrderList` data structure, which manages relationships between parent and child orders. Understanding how to configure these contingency types is essential for implementing advanced order management strategies such as brackets and stop-loss attachments.

## Understanding Contingency Types in Nautilus Trader

The `ContingencyType` enum in [`nautilus_trader/model/enums.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/enums.py) defines three distinct linking behaviors:

| Type | Meaning | Typical Use |
|------|---------|-------------|
| **OCO** | *One‑Cancels‑Other* – two mutually exclusive orders; when one fills, the other is automatically cancelled. | Separate take‑profit / stop‑loss orders that should not both execute. |
| **OTO** | *One‑Triggers‑Other* – a primary "entry" order that, once executed, activates a secondary order (or list). | Opening a position and immediately attaching a stop‑loss that should only appear after the entry fills. |
| **OUO** | *One‑Updates‑Other* – a primary order that, after execution, spawns two or more *child* orders that are linked to the parent. | A bracket where a filled entry order creates both a stop‑loss and a take‑profit order that are tied to the same parent. |

The enum definition at lines 237-242:

```python

# https://github.com/nautechsystems/nautilus_trader/blob/develop/nautilus_trader/model/enums.py#L237-L242

class ContingencyType(Enum):
    NO_CONTINGENCY = 0
    OCO = 1          # One‑Cancels‑Other

    OTO = 2          # One‑Triggers‑Other

    OUO = 3          # One‑Updates‑Other (bracket)

```

## Where Contingency Logic Lives in the Source Code

| Concern | Primary source file(s) |
|---------|------------------------|
| `ContingencyType` enum | [`nautilus_trader/model/enums.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/enums.py) |
| Order definitions (`MarketOrder`, `LimitOrder`, `StopMarketOrder`) | `nautilus_trader/model/orders/*.py` |
| Grouping & linking (`OrderList`, contingency helpers) | [`nautilus_trader/model/orders/list.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/list.py) |
| Factory helpers (`OrderFactory.bracket`, `generate_order_list_id`) | [`nautilus_trader/model/orders/factory.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/factory.py) |
| Execution‑engine handling of contingent orders (e.g., OCO cancellation) | [`nautilus_trader/execution/reports.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/execution/reports.py) (contingency conversion) |
| Tests that illustrate each pattern | [`tests/unit_tests/model/test_orders.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/tests/unit_tests/model/test_orders.py), [`tests/unit_tests/trading/test_strategy.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/tests/unit_tests/trading/test_strategy.py) |

## Implementing OCO (One-Cancels-Other) Orders

OCO contingency orders ensure that when one order fills, its counterpart is automatically cancelled. This is essential for stop-loss and take-profit pairs.

```python
from nautilus_trader.model.enums import ContingencyType, OrderSide
from nautilus_trader.model.orders import LimitOrder, StopMarketOrder
from nautilus_trader.model.identifiers import OrderListId
from nautilus_trader.trading.commands import SubmitOrderList
from nautilus_trader.model.orders import OrderList

# Build two mutually exclusive orders

take_profit = LimitOrder(
    instrument_id=instrument.id,
    side=OrderSide.SELL,
    quantity=qty,
    price=take_profit_price,
    contingency_type=ContingencyType.OCO,
    order_list_id=OrderListId("OL-01"),
)

stop_loss = StopMarketOrder(
    instrument_id=instrument.id,
    side=OrderSide.SELL,
    quantity=qty,
    trigger_price=stop_price,
    contingency_type=ContingencyType.OCO,
    order_list_id=OrderListId("OL-01"),
)

# Submit together – the broker will cancel the other order when one fills.

submit = SubmitOrderList(order_list=OrderList(
    order_list_id=OrderListId("OL-01"),
    orders=[take_profit, stop_loss],
))
trader.submit(submit)

```

Both orders share the same `order_list_id` and have `contingency_type=ContingencyType.OCO`. The execution engine handles the cancellation logic when one fills.

## Implementing OTO (One-Triggers-Other) Orders

OTO orders create a dependency where the secondary order only becomes active after the primary order fills. This is commonly used to attach stop-losses to entry orders.

```python
from nautilus_trader.model.enums import ContingencyType, OrderSide
from nautilus_trader.model.orders import MarketOrder, StopMarketOrder
from nautilus_trader.model.identifiers import OrderListId
from nautilus_trader.trading.commands import SubmitOrderList
from nautilus_trader.model.orders import OrderList

# Entry order – will be placed first

entry = MarketOrder(
    instrument_id=instrument.id,
    side=OrderSide.BUY,
    quantity=qty,
    contingency_type=ContingencyType.OTO,
    order_list_id=OrderListId("OL-02"),
)

# Child order – becomes active only after entry fills

stop = StopMarketOrder(
    instrument_id=instrument.id,
    side=OrderSide.SELL,
    quantity=qty,
    trigger_price=stop_price,
    parent_order_id=entry.client_order_id,   # linked to entry

    contingency_type=ContingencyType.NO_CONTINGENCY,
    order_list_id=OrderListId("OL-02"),
)

submit = SubmitOrderList(order_list=OrderList(
    order_list_id=OrderListId("OL-02"),
    orders=[entry, stop],
))
trader.submit(submit)

```

The entry order uses `ContingencyType.OTO`, while the child references the entry via `parent_order_id`. The `OrderList.is_oto()` helper in [`nautilus_trader/model/orders/list.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/list.py) validates this structure.

## Implementing OUO (One-Updates-Other) Bracket Orders

OUO is the standard pattern for **bracket orders**, where a filled entry spawns multiple linked children (typically stop-loss and take-profit). The `OrderFactory.bracket()` method in [`nautilus_trader/model/orders/factory.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/factory.py) automates this construction.

```python
from nautilus_trader.model.enums import OrderSide
from nautilus_trader.trading.commands import SubmitOrderList

# Using the built‑in OrderFactory (found in nautilus_trader/model/orders/factory.py)

bracket = strategy.order_factory.bracket(
    instrument_id=instrument.id,
    side=OrderSide.BUY,
    quantity=qty,
    sl_trigger_price=stop_price,   # stop‑loss trigger

    tp_price=take_profit_price,    # take‑profit limit

    entry_tags=["ENTRY"],
    sl_tags=["STOP_LOSS"],
    tp_tags=["TAKE_PROFIT"],
)

# `bracket` is an OrderList with the exact layout shown in the tests:

# - entry order: contingency_type = OTO

# - stop‑loss:   contingency_type = OUO, parent = entry

# - take‑profit: contingency_type = OUO, parent = entry

trader.submit(SubmitOrderList(order_list=bracket))

```

This factory method generates an `OrderList` where the entry uses `ContingencyType.OTO` and both children use `ContingencyType.OUO` with `parent_order_id` referencing the entry. This structure is validated in [`tests/unit_tests/model/test_orders.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/tests/unit_tests/model/test_orders.py) lines 1868‑1881.

## Summary

- **ContingencyType enum**: Located in [`nautilus_trader/model/enums.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/enums.py), defines `OCO`, `OTO`, and `OUO` behaviors.
- **OCO orders**: Set `contingency_type=ContingencyType.OCO` on both orders with a shared `order_list_id` to ensure mutual cancellation.
- **OTO orders**: Use `ContingencyType.OTO` on the primary order and set `parent_order_id` on the secondary order to delay activation until the primary fills.
- **OUO bracket orders**: Leverage `OrderFactory.bracket()` in [`nautilus_trader/model/orders/factory.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/factory.py) to automatically create entry orders with linked stop-loss and take-profit children using `ContingencyType.OUO`.
- **Order linking**: All contingent orders require proper `order_list_id` assignment and, where applicable, `parent_order_id` references to maintain the execution hierarchy.

## Frequently Asked Questions

### What is the difference between OTO and OUO in Nautilus Trader?

**OTO (One-Triggers-Other)** creates a simple dependency where a single secondary order activates after the primary order fills. **OUO (One-Updates-Other)** is designed for complex brackets where the primary order spawn multiple child orders (e.g., stop-loss and take-profit) that are all linked to the same parent. While OTO handles one-to-one relationships, OUO manages one-to-many relationships with synchronized lifecycle management.

### How do I link orders for OCO contingency in Nautilus Trader?

To implement **OCO (One-Cancels-Other)**, assign `ContingencyType.OCO` to both orders and ensure they share the same `OrderListId`. When submitting, wrap both orders in an `OrderList` and submit via `SubmitOrderList`. The execution engine monitors fills and automatically cancels the remaining order when either one executes, as handled in the reporting layer within [`nautilus_trader/execution/reports.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/execution/reports.py).

### Can I create bracket orders without using OrderFactory?

Yes, you can manually construct **OUO bracket orders** by creating the entry order with `ContingencyType.OTO`, then creating separate stop-loss and take-profit orders with `ContingencyType.OUO` and their `parent_order_id` fields set to the entry order's `client_order_id`. Group all three orders under a single `OrderList` with a shared `OrderListId` and submit them together. However, using `OrderFactory.bracket()` in [`nautilus_trader/model/orders/factory.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/factory.py) reduces boilerplate and ensures correct contingency type assignment.

### Where is the execution logic for contingency order cancellation handled?

The core definitions for contingency types reside in [`nautilus_trader/model/enums.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/enums.py), while the grouping logic is managed in [`nautilus_trader/model/orders/list.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/model/orders/list.py). When orders are executed, the conversion and reporting of contingency states occur in [`nautilus_trader/execution/reports.py`](https://github.com/nautechsystems/nautilus_trader/blob/main/nautilus_trader/execution/reports.py), which handles the broker-side communication for OCO cancellations and OTO activations. The `OrderList` structure ensures that the execution engine maintains the proper hierarchy between parent and child orders throughout the order lifecycle.