---
title: "1.1.4 Order types: market, limit, stop and more"
description: "Market, limit, stop, stop-limit, trailing, MOC/LOC, IOC/FOK, iceberg and bracket/OCO orders, with a matching engine and stops through a gap."
url: "https://pythonparatrading.com/en/python-trading-course/level-1/order-types-explained/"
lang: "en"
image: "https://pythonparatrading.com/og/en/python-trading-course/level-1/order-types-explained.png"
---

# 1.1.4 · Order types

> The order type decides what is sacrificed: price, execution or control. This lesson codes a small matching engine against NOVA's book, simulates three stops on a gap day and models the life cycle of an order as a state machine.

- Course: [Level 1: Financial data, markets and analysis](https://pythonparatrading.com/en/python-trading-course/level-1/)
- Module: 1.1 · How markets work
- Duration: 60 min
- Prerequisites: [1.1.2 · Sessions, auctions, holidays and calendars](https://pythonparatrading.com/en/python-trading-course/level-1/trading-sessions-auctions-and-market-calendars/), [1.1.3 · Order book: bid, ask, spread and depth](https://pythonparatrading.com/en/python-trading-course/level-1/order-book-bid-ask-spread-depth/)

## By the end of this lesson

- Tell market, limit, stop, stop-limit and trailing orders apart by what they guarantee (execution or price) and what they risk.
- Compute the average price of a market order by walking the book and decide whether an IOC or FOK order gets executed.
- Simulate stops on bars and explain why in a gap the stop is executed far from its price and the stop-limit may not be executed.
- Choose the right time in force (DAY, GTC, IOC, FOK, on close or on open) and linked orders (bracket, OCO) for a system.
- Model the life cycle of an order (new, accepted, partial, filled, cancelled, rejected, expired) and reject impossible transitions.

## Price or execution: the dilemma of every order

An order tells the broker what to buy or sell, how much and under what conditions. Every variant that exists comes
from one basic decision:

- **Market order.** Execute now, at whatever price there is. It guarantees execution (if there is a counterparty) and
  does not guarantee the price.
- **Limit order.** Execute only at a price equal to or better than the limit. It guarantees the price and does not
  guarantee execution.

A limit buy above the best ask is *marketable*: it is executed immediately, like a market order, but with a cap. A
limit buy below the best bid stays in the book, at the end of the queue at its price, and waits (lesson 1.1.3). The
other types add to these two a **condition** (a trigger price, a time, a minimum size) or a **relationship** with
other orders.

*Fig. — Where each order type waits relative to the best bid and the best ask (schematic).* Diagram with two columns, buy and sell, on a price scale with the best ask above and the best bid below, separated by the spread (highlighted). Buy side: the limit waits below the bid, the market order pays the ask and the stop sits above the ask. Sell side: the limit waits above the ask, the market order gets the bid and the stop sits below the bid.

The figure places each type relative to the book. Limit orders wait on the “good” side of the price: buys below, sells
above. Stops wait on the “bad” side: a sell stop sits below the bid and is triggered if the price falls to it; a buy
stop, above the ask. Market orders do not wait: they cross the spread.

## A twenty-line matching engine

The best way to understand an order is to execute it. This engine walks the levels of one side of the book in
priority order and returns the fills. It uses NOVA's L2 snapshot at 15:00 New York time from lesson 1.1.3, with the
best ask at 52.75.

```python
import pandas as pd

l2 = pd.read_parquet("nova_libro_l2.parquet")
foto = l2[l2["ts"] == "2025-06-02 19:00:00+00:00"]
asks = foto[foto["lado"] == "ask"].sort_values("precio")
bids = foto[foto["lado"] == "bid"].sort_values("precio",
                                                ascending=False)
lado_venta = list(zip(asks["precio"], asks["tamano"]))
lado_compra = list(zip(bids["precio"], bids["tamano"]))
medio = (asks["precio"].iloc[0] + bids["precio"].iloc[0]) / 2
lado_venta[:4]
```
```output
[(52.75, 1870), (52.76, 9900), (52.77, 13280), (52.78, 17322)]
```

```python
def recorre(niveles, cantidad, limite=None, compra=True):
    """Execute against `niveles` [(price, size)] up to `cantidad`.
    With `limite`, do not go past that price.
    Return (fills, remainder)."""
    ejecuciones, resto = [], cantidad
    for precio, tam in niveles:
        if limite is not None and (precio > limite if compra
                                   else precio < limite):
            break
        q = min(resto, tam)
        ejecuciones.append((precio, q))
        resto -= q
        if resto == 0:
            break
    return ejecuciones, resto

def resumen(ejecuciones, medio):
    q = sum(c for _, c in ejecuciones)
    pm = sum(p * c for p, c in ejecuciones) / q
    return {"acciones": q, "niveles": len(ejecuciones),
            "precio_medio": round(float(pm), 4),
            "sobre_medio_cent": round(float(100 * abs(pm - medio)), 2)}

for n in (2_000, 30_000):
    ejec, resto = recorre(lado_venta, n)
    print(f"market buy of {n}:", resumen(ejec, medio))
```
```output
market buy of 2000: {'acciones': 2000, 'niveles': 2, 'precio_medio': 52.7507, 'sobre_medio_cent': 0.56}
market buy of 30000: {'acciones': 30000, 'niveles': 4, 'precio_medio': 52.7671, 'sobre_medio_cent': 2.21}
```

A market buy of 2,000 shares is filled with the whole first level (1,870 shares at 52.75) and 130 from the second, at
52.76: average price 52.7507, 0.56 cents above the mid. One of 30,000 walks four levels and pays on average 52.7671:
2.21 cents over the mid, almost four times more per share. That is the order's **impact**, the cost that grows with
size (lesson 1.1.5 turns it into a curve):

*Fig. — Market buy of up to 30,000 shares against the NOVA book at 15:00 New York time: price of the last level reached and average price paid.* Steps of the marginal price, from 52.75 for the first 1,870 shares to 52.76, 52.77 and 52.78, and the average price curve, rising smoothly from 52.75 to 52.7671 at 30,000 shares (highlighted). A line marks the book mid price, 52.745.

## Time in force: DAY, GTC, IOC and FOK

Besides the price, an order carries a **time in force**, which says how long it lives:

| Time in force | What it does | When to use it |
|---|---|---|
| DAY | Lives until the end of the session and expires | Default at almost every broker; daily systems |
| GTC | Lives until it is executed or cancelled (brokers usually cap it at a number of days) | Stops and targets of multi-day positions |
| IOC | Executes what it can right away and cancels the rest | Taking liquidity without leaving a trace in the book |
| FOK | Everything right away or nothing | When a partial fill is useless (pairs, hedges) |
| On open (OPG, MOO, LOO) | Only takes part in the opening auction | Systems that decide with the previous close |
| On close (MOC, LOC) | Only takes part in the closing auction | Rebalancing, matching the closing price |

With the previous engine, IOC and FOK take two lines:

```python
def limitada(niveles, cantidad, limite, validez, compra=True):
    ejec, resto = recorre(niveles, cantidad, limite, compra)
    if validez == "FOK" and resto > 0:
        return [], cantidad, "cancelled: not enough"
    if validez == "IOC":
        estado = "filled" if resto == 0 else f"cancels {resto}"
        return ejec, resto, estado
    return ejec, resto, f"{resto} rest in the book"

for validez in ("IOC", "FOK", "DAY"):
    ejec, resto, estado = limitada(lado_venta, 15_000, 52.76, validez)
    print(validez, "fills", sum(q for _, q in ejec), "·", estado)
```
```output
IOC fills 11770 · cancels 3230
FOK fills 0 · cancelled: not enough
DAY fills 11770 · 3230 rest in the book
```

At 52.76 or better there are only 11,770 shares. The IOC takes them and cancels the 3,230 that are missing; the FOK
executes nothing; the DAY executes the same as the IOC and leaves a buy of 3,230 shares at 52.76 in the book, which
becomes the new best bid: it has crossed the spread and now defines it.

On-open and on-close orders are matched in the auctions (lesson 1.1.2). On the NYSE there are market variants (MOO,
MOC) and limit variants (LOO, LOC); MOC and LOC orders can be sent, modified or cancelled until 15:50, and after that
only those that reduce the published imbalance are accepted[^1].

[^1]: NYSE, “NYSE opening and closing auctions” fact sheet (accessed on October 21, 2026).

## Stop, stop-limit and trailing through a gap

A **stop** is a dormant order with a trigger price. A sell stop at 62.50 does nothing while the price is above it;
when a trade prints at 62.50 or lower, it becomes a **market order**. A **stop-limit** becomes a **limit order**: “if
it falls to 62.50, sell, but not below 62.30”. A **trailing stop** moves the trigger behind the price: it stays, for
example, 2.5% below the high reached since the entry, and only moves up.

The difference between the three matters in **gaps**: when the price jumps from one level to another without going
through the levels in between, typically from a close to the next open after news. NOVA reported earnings after the
close on Thursday, October 24, 2024 and on Friday it opened 5.1% lower:

```python
diario = pd.read_csv("nova_diario_sin_ajustar.csv",
                     parse_dates=["fecha"])
diario["hueco_pct"] = 100 * (diario["apertura"]
                             / diario["cierre"].shift() - 1)
tramo = diario[diario["fecha"].between("2024-10-21", "2024-10-28")]
tramo.set_index("fecha").round(2)
```
```output
            apertura  maximo  minimo  cierre   volumen  hueco_pct
fecha
2024-10-21     63.27   64.32   62.90   64.30  13820466       0.02
2024-10-22     64.26   64.47   63.74   64.07   9126443      -0.06
2024-10-23     63.93   64.67   63.76   64.19   8728289      -0.22
2024-10-24     64.11   64.60   63.21   63.40   9874612      -0.12
2024-10-25     60.14   60.87   59.51   59.59  51399629      -5.14
2024-10-28     59.25   59.33   57.11   58.02  18793763      -0.57
```

A system buys at the close of October 21, at 64.30, and protects the position in three ways: a stop at 62.50, a
62.50/62.30 stop-limit valid for the day and a 2.5% trailing stop. The 5-minute bars let you simulate when each one is
triggered. The rule for executing a stop on bars is the honest one: if the bar **opens** below the stop, the sell goes
out at the open; if it opens above and its low touches it, it goes out at the stop (and even that is optimistic: in
reality, at the first price traded afterwards).

```python
barras = pd.read_parquet("nova_barras_5min.parquet")
barras = (barras[barras["ts"] > "2024-10-21 20:00"]
          .reset_index(drop=True))
entrada = 64.30

def stop_venta(barras, stop):
    for b in barras.itertuples():
        if b.minimo <= stop:
            return b.ts, min(b.apertura, stop)
    return None, None

def trailing_venta(barras, entrada, pct):
    maximo = entrada
    for b in barras.itertuples():
        stop = maximo * (1 - pct)
        if b.minimo <= stop:
            return b.ts, min(b.apertura, stop), stop
        maximo = max(maximo, b.maximo)
    return None, None, None

def stop_limit_venta(barras, stop, limite, validez="DAY"):
    disparo = None
    for b in barras.itertuples():
        if disparo is None and b.minimo <= stop:
            disparo = b.ts
            if b.apertura > stop:           # no gap: goes out at the stop
                return disparo, b.ts, stop
        if disparo is not None:
            if validez == "DAY" and b.ts.date() > disparo.date():
                return disparo, None, None  # expired unexecuted
            if b.maximo >= limite:
                return disparo, b.ts, max(limite, b.apertura)
    return disparo, None, None

ts, px = stop_venta(barras, 62.50)
print("stop 62.50:      trigger", ts, "· sell at", px)
ts, px, nivel = trailing_venta(barras, entrada, 0.025)
print(f"trailing 2.5%:   trigger {ts} · level {nivel:.2f}",
      f"· sell at {px}")
d, ts, px = stop_limit_venta(barras, 62.50, 62.30)
print("stop-limit DAY:  trigger", d, "· sell:", px)
```
```output
stop 62.50:      trigger 2024-10-25 13:30:00+00:00 · sell at 60.14
trailing 2.5%:   trigger 2024-10-25 13:30:00+00:00 · level 63.05 · sell at 60.14
stop-limit DAY:  trigger 2024-10-25 13:30:00+00:00 · sell: None
```

All three are triggered in the same bar, the one at the open of October 25 (13:30 UTC, 9:30 New York time):

- The **stop** at 62.50 sells at 60.14, the open: $2.36 per share below its price. The stop is not a guaranteed price;
  it is the condition for a market order to be born.
- The **trailing** stop, which had raised its level to 63.05 with the 64.67 high of October 23, sells exactly the
  same, at 60.14. In a gap, a tighter stop is no help at all.
- The **stop-limit** is triggered, but its 62.30 limit is $1.43 above the highest price of the day, 60.87. At 16:00 it
  expires unexecuted and the position stays open, unprotected.

The figure at the top draws it bar by bar. And what if the stop-limit were GTC?

```python
disparo, ts, px = stop_limit_venta(barras, 62.50, 62.30, validez="GTC")
print("executed", ts, "at", px)
entre = barras[(barras["ts"] > disparo) & (barras["ts"] < ts)]
print("low while waiting:", entre["minimo"].min(),
      "on", entre.loc[entre["minimo"].idxmin(), "ts"].date())
```
```output
executed 2025-01-16 16:55:00+00:00 at 62.3
low while waiting: 53.51 on 2025-01-03
```

It is executed almost three months later, on January 16, 2025, when NOVA returns to 62.30. Along the way the stock
reaches 53.51 on January 3, almost $9 below the limit. For a portfolio this is the opposite of protection: the
stop-limit avoids selling badly in the gap in exchange for not selling at all while the price keeps falling.

<aside class="callout" data-kind="riesgo">

A backtest that executes stops at their exact price, without looking at the open, gives away money on every gap. For
NOVA, $2.36 per share on October 25, 2024, 3.7% of the entry price, in a single day. Simulate stops with the bar's
open when it is already below, and with daily bars assume the worst: if the day opens below, the sell goes out at the
open.

</aside>

## The life cycle of an order

An order does not simply go from “sent” to “filled”. The broker and the market send back states, and a real system
has to react to each one: a partial fill leaves a position different from the one planned; a rejection (for
insufficient funds, a price out of range, a closed market) means there is no position.

```mermaid
stateDiagram-v2
  [*] --> New
  New --> Accepted
  New --> Rejected
  Accepted --> Partial
  Accepted --> Filled
  Accepted --> Cancelled
  Accepted --> Expired
  Partial --> Filled
  Partial --> Cancelled
  Partial --> Expired
  Filled --> [*]
  Cancelled --> [*]
  Rejected --> [*]
  Expired --> [*]
```

Three states are final as far as the order is concerned, though not as far as the position is: an order **cancelled**
or **expired** after a partial fill has left shares in the account. Modeling it as a state machine avoids the most
common mistakes, such as cancelling an order that was already filled or counting a fill twice:

```python
TRANSICIONES = {
    "nueva": {"aceptada", "rechazada"},
    "aceptada": {"parcial", "ejecutada", "cancelada", "expirada"},
    "parcial": {"parcial", "ejecutada", "cancelada", "expirada"},
}

class Orden:
    def __init__(self, cantidad):
        self.cantidad, self.ejecutada = cantidad, 0
        self.estado, self.historial = "nueva", ["nueva"]

    def pasa(self, estado):
        if estado not in TRANSICIONES.get(self.estado, set()):
            raise ValueError(f"cannot go from {self.estado} to {estado}")
        self.estado = estado
        self.historial.append(estado)

    def ejecuta(self, q):
        if self.ejecutada + q > self.cantidad:
            raise ValueError("fill larger than the order")
        self.ejecutada += q
        lleno = self.ejecutada == self.cantidad
        self.pasa("ejecutada" if lleno else "parcial")

# the IOC for 15,000 shares at 52.76 against the 15:00 book
o = Orden(15_000)
o.pasa("aceptada")
for _, q in recorre(lado_venta, 15_000, limite=52.76)[0]:
    o.ejecuta(q)
o.pasa("cancelada")     # IOC: the rest is cancelled
print(" -> ".join(o.historial), "·", o.ejecutada, "shares")
```
```output
nueva -> aceptada -> parcial -> parcial -> cancelada · 11770 shares
```

The states are code keys, so they print in Spanish: `nueva` (new), `aceptada` (accepted), `parcial` (partial),
`ejecutada` (filled), `cancelada` (cancelled). A filled order cannot be cancelled. If the system tries (because it
received the confirmation late, for example), the state machine stops it instead of letting the error reach the
account:

```python raises
o2 = Orden(2_000)
o2.pasa("aceptada")
o2.ejecuta(2_000)
o2.pasa("cancelada")
```
```output
ValueError: cannot go from ejecutada to cancelada
```

## Linked orders: bracket and OCO

An **OCO** (*one cancels the other*) is two linked orders: when one is executed, the system cancels the other. The
typical combination is a profit target (limit sell above) and a stop loss (stop sell below). A **bracket** adds the
entry: the OCO pair is only activated when the entry is executed.

```mermaid
flowchart TB
  E[Limit entry] -->|filled| A[Activates OCO]
  A --> TP[Limit target]
  A --> SL[Stop loss]
  TP -->|executed| C1[Cancels the stop]
  SL -->|executed| C2[Cancels target]
```

Having the broker manage the link has an advantage: if the system goes down, the exit orders remain on the server.
The risk lies in partial fills: if the target is half executed, the stop has to be reduced to the remaining quantity,
and not every broker does it the same way. A system that sends brackets must read what its broker does and check it
in a paper trading account.

## Other orders that show up in the data

- **Iceberg.** A limit order with a visible part and a hidden reserve that is replenished (lesson 1.1.3).
- **Hidden.** A limit order that is not visible at all in the book; it usually loses priority to visible orders at the
  same price.
- **Pegged.** Its price follows the best bid, the best ask or the midpoint; it is what is matched in the dark pool of
  lesson 1.1.1.
- **Broker algorithms (TWAP, VWAP).** They are not market order types, but programs that split a large order into many
  small ones over the day. They are the source of many of the 100-share trades on the tape.

| Type | Guarantees | Main risk | Typical use in a system |
|---|---|---|---|
| Market | Execution | Price, especially with a thin book | Exits that cannot wait |
| Limit | Price | Not being executed | Patient entries, liquidity provision |
| Stop | Trigger | Gap: execution far from the stop | Stop loss |
| Stop-limit | Price after the trigger | Being unable to exit | Breakout entries with a cap |
| Trailing | Follows the price | Same as the stop | Protecting profits |
| MOC / LOC | Closing price | Imbalance; sending before the cutoff time | Rebalancing, at-the-close systems |
| IOC / FOK | Leaves no trace | Partial or no execution | Taking liquidity in a controlled way |
| Bracket / OCO | Automatic exit | Badly linked partials | Positions with a target and a stop |

## Exercises

1. Compute the average price and the levels walked by a market sell of 25,000 shares against the 15:00 book and
   compare it with a buy of the same size. Why do they not cost the same?

**Solution.**

```python
for lado, niveles, nombre in ((False, lado_compra, "sell"),
                              (True, lado_venta, "buy")):
    ejec, resto = recorre(niveles, 25_000, compra=lado)
    print(nombre, resumen(ejec, medio))
```
```output
sell {'acciones': 25000, 'niveles': 3, 'precio_medio': 52.7345, 'sobre_medio_cent': 1.05}
buy {'acciones': 25000, 'niveles': 3, 'precio_medio': 52.7645, 'sobre_medio_cent': 1.95}
```

Both walk three levels, but the sell pays 1.05 cents per share over the mid and the buy 1.95, almost double. The
reason lies in the first level: the sell finds 13,432 shares at the best bid, half a cent from the mid, and the buy
only 1,870 at the best ask, so most of the buy is executed at the second and third levels (lesson 1.1.3). If the sell
were for 40,000 shares, things would change: beyond the third buy level there is hardly anything. An asymmetric book
charges buyers and sellers differently, and the asymmetry changes with size.

2. On June 2, 2025 a system buys NOVA at the 9:30 open (open of the first bar) with a bracket: target 0.5% above and
   stop 0.5% below. With the 5-minute bars, which one is executed first? What would you do if the same bar touched
   both?

**Solution.**

```python
todas = pd.read_parquet("nova_barras_5min.parquet")
dia = todas[todas["ts"].dt.date == pd.Timestamp("2025-06-02").date()]
ent = dia["apertura"].iloc[0]
tp, sl = round(ent * 1.005, 2), round(ent * 0.995, 2)
print("entry", ent, "· target", tp, "· stop", sl)
for b in dia.itertuples():
    toca_tp, toca_sl = b.maximo >= tp, b.minimo <= sl
    if toca_tp or toca_sl:
        print(b.ts.strftime("%H:%M UTC"), "target" if toca_tp else "",
              "stop" if toca_sl else "")
        break
```
```output
entry 53.35 · target 53.62 · stop 53.08
13:55 UTC  stop
```

The stop is hit in the 13:55 UTC bar (9:55 New York time), 25 minutes after the entry, and the OCO cancels the
target. The first bar that touches one of the two levels decides the exit. If the same bar touched both, with bars you
cannot know which came first: the prudent rule is to assume the stop (the worst case) or to drop down to
higher-resolution data, such as the trades in `nova_operaciones.parquet`.

3. A daily system enters at the open with market orders and exits with a 3% GTC stop. Propose a better set of orders
   and justify each change.

**Solution.**

Entry: an on-open order (OPG or MOO) instead of a market order at 9:30, to be matched in the auction, at a single
price and with plenty of liquidity, rather than in the first seconds of continuous trading, when the spread is wider
(lesson 1.1.3). If a cap is wanted, an LOO. Exit: the stop can remain a stop (not a stop-limit), because what matters
is getting out; but the backtest must simulate it with the open on gaps. If the strategy also has a target, link
target and stop in an OCO managed by the broker, so that the exit does not depend on the system being alive. And in
every case, handle partial fills and rejections with the state machine.

## Self-assessment

1. What does a market order guarantee and what does it not?

   - A. It guarantees the price, not the execution
   - B. It guarantees execution if there is a counterparty, not the price
   - C. It guarantees both
   - D. It guarantees neither

   *Answer B: It guarantees execution if there is a counterparty, not the price.* A market order is executed against whatever is in the book, level by level, until it is complete. In NOVA's 15:00 book, a market buy of 30,000 shares pays on average 52.7671, almost two cents above the best ask.

2. An IOC limit buy for 15,000 shares at 52.76 arrives at a book with 1,870 shares at 52.75 and 9,900 at 52.76. What happens?

   - A. Nothing is executed
   - B. 15,000 are executed, the last ones at 52.77
   - C. 11,770 shares are executed and the rest is cancelled
   - D. 11,770 are executed and the rest stays in the book

   *Answer C: 11,770 shares are executed and the rest is cancelled.* IOC (immediate or cancel) executes what it can right away within the limit and cancels the rest. With FOK (fill or kill) nothing would be executed, because there are not 15,000 shares at 52.76 or better.

3. On October 25, 2024 NOVA opens at 60.14 after closing at 63.40. What does a stop-limit sell with stop 62.50 and limit 62.30, valid for the day, do?

   - A. It is executed at 62.30
   - B. It is executed at 60.14
   - C. It is not triggered
   - D. It is triggered but not executed: the price does not return to 62.30 for the whole session and the order expires

   *Answer D: It is triggered but not executed: the price does not return to 62.30 for the whole session and the order expires.* The stop is triggered by the first trade below 62.50, which is the open at 60.14. A limit sell at 62.30 is then born, which is only executed at 62.30 or higher. The day's high is 60.87, so the order expires unexecuted and the position stays open.

4. What is an OCO order?

   - A. Two linked orders: when one is executed, the other is cancelled
   - B. An order executed at the close
   - C. An order that is only executed in full
   - D. A hidden order

   *Answer A: Two linked orders: when one is executed, the other is cancelled.* OCO (*one cancels the other*) links two orders, typically a profit target and a stop. A bracket is an entry with an exit OCO that is activated when the entry is executed.

5. A system decides with the day's close and wants to execute in the NYSE closing auction. Which order, and when?

   - A. A market order at 16:00
   - B. An MOC (or LOC) sent before 15:50, with the signal computed from data before that time
   - C. A stop at the closing price
   - D. A GTC

   *Answer B: An MOC (or LOC) sent before 15:50, with the signal computed from data before that time.* NYSE on-close orders are accepted, modified or cancelled until 15:50; after that only those that reduce the published imbalance are allowed. The signal cannot use the closing price, which does not yet exist when the order has to be sent (lesson 1.1.2).

## Key points

- Every order chooses between certainty of execution (market) and certainty of price (limit). The others are combinations of these two with a condition.
- A market order walks the book: its cost grows with size. For NOVA, 2,000 shares pay 0.56 cents over the mid and 30,000, 2.21.
- A stop is a dormant market order: in a gap it is executed at the first available price, far from the stop. A stop-limit protects the price, but may not be executed and leave the position open.
- Time in force matters as much as the type: DAY, GTC, IOC, FOK, on open or on close.
- Linked orders (bracket, OCO) and the life cycle (partial, cancelled, expired) are what a real system has to manage, and what a backtest usually ignores.

## Resources

### Research

- [Quantitative Models and Algorithmic Execution](https://pythonparatrading.com/en/quantitative-models-algorithmic-execution/) · Research-0009 · 11 min
- [Limit Order Book - Aggregated Market Liquidity](https://pythonparatrading.com/en/limit-order-book-and-market-liquidity/) · Research-0008 · 11 min

### Documentation

- [NYSE: Opening and Closing Auctions (MOO, LOO, MOC, LOC and their schedules)](https://www.nyse.com/publicdocs/nyse/markets/nyse/NYSE_Opening_and_Closing_Auctions_Fact_Sheet.pdf) · nyse.com
- [Investor.gov (SEC): Types of Orders](https://www.investor.gov/introduction-investing/investing-basics/how-stock-markets-work/types-orders) · investor.gov

### Data

- [Level 1 data: NOVA 5-minute bars, 2024-2025 (Parquet)](https://pythonparatrading.com/curso/datos/nivel-1/nova_barras_5min.parquet) · Download · nova_barras_5min.parquet

Previous lesson: [1.1.3 · Order book: bid, ask, spread and depth](https://pythonparatrading.com/en/python-trading-course/level-1/order-book-bid-ask-spread-depth/)

Next lesson: [1.1.5 · Costs, settlement, leverage and margin](https://pythonparatrading.com/en/python-trading-course/level-1/trading-costs-settlement-leverage-and-margin/)
