You just bought 100 shares of AAPL on TWS. The price starts moving against you. You scramble to enter a stop loss, fumble with the order ticket, and by the time you submit it the stock has already dropped $2. Or worse — the price spikes in your favor, you hesitate on the take profit, and watch your unrealized gain evaporate.
Bracket orders solve this. One click, one submission, and your entry, stop loss, and take profit all go live simultaneously. The problem is that Interactive Brokers makes this far more powerful — and far more confusing — than most brokers. TWS has bracket orders, attached orders, OCA groups, OCO logic, and conditional orders, all with different behaviors and configuration screens.
I run an automated USDJPY momentum strategy through IB Gateway, and every single trade uses bracket-style risk management. This guide covers everything from the basic TWS bracket click to Python API bracket orders, with the specific settings that actually matter in production.
What Is a Bracket Order?
A bracket order is three orders bundled together:
1. Parent order — Your entry (buy or sell)
2. Take profit (limit order) — Closes the position at your target price 3. Stop loss (stop order) — Closes the position at your maximum loss priceThe key behavior: when either the take profit or stop loss fills, the other one automatically cancels. This is called OCO (One Cancels Other) logic. You never end up with a dangling stop loss after you have already taken profit, or vice versa.
IB calls the stop loss and take profit "child orders" or "attached orders" — they are linked to the parent and cannot exist without it.
Method 1: Quick Bracket from the Order Ticket (Fastest)
This is the method most traders should start with.
Step-by-Step:
1. Open TWS and navigate to your watchlist or chart
2. Click the bid or ask to create a new order (or right-click → Trade → Order Ticket) 3. In the order row, you will see your entry order. Right-click on this order row 4. Select Attach → Bracket Order 5. TWS instantly adds two child orders below your entry: - A LMT (limit) order on the opposite side — this is your take profit - A STP (stop) order on the opposite side — this is your stop loss 6. Set your prices: Click on the Lmt Price column for the take profit and the Aux Price (stop price) column for the stop loss 7. Transmit — Click Transmit or press T. All three orders are submitted togetherWhat You See:
BUY 100 AAPL @ MKT ← Parent (entry)
└─ SELL 100 AAPL LMT 195 ← Take profit (child)
└─ SELL 100 AAPL STP 175 ← Stop loss (child)
The child orders appear indented under the parent. They will not activate until the parent fills. Once the parent fills, both children go live. When one child fills, the other is cancelled automatically.
Method 2: Bracket Order Presets (Set Once, Apply Always)
If you always use the same risk-reward ratio — say, 2:1 — you can configure bracket presets so every new order automatically comes with attached stop loss and take profit.
Step-by-Step:
1. Go to Edit → Global Configuration (or File → Global Configuration on some versions)
2. Navigate to Orders → Order Presets 3. Select the instrument type you trade (Stocks, Forex, Futures, etc.) 4. In the Order Defaults section, check Bracket 5. Configure your bracket: - Profit Offset: Distance in price or percentage for the take profit - Loss Offset: Distance in price or percentage for the stop loss - Offset Type: Choose between absolute price offset or percentage 6. Click Apply and OKNow, every time you create a new order for that instrument type, TWS automatically attaches a bracket. You can still modify the prices before transmitting.
Offset Examples:
| Setting | Entry Price | Take Profit | Stop Loss |
|---|---|---|---|
| Profit: 5.00, Loss: 3.00 (absolute) | $180.00 | $185.00 | $177.00 |
| Profit: 2%, Loss: 1% (percentage) | $180.00 | $183.60 | $178.20 |
Method 3: Manual OCA (One Cancels All) Groups
Sometimes you need more flexibility than a standard bracket. Maybe you want to attach three take profit levels at different prices, or link orders across different instruments. That is where OCA groups come in.
OCA is the generalized version of OCO. Instead of just two orders canceling each other, you can put any number of orders into a group where filling one cancels all the others.
Step-by-Step:
1. Create your entry order and submit it (or wait for it to fill if you want to attach to an existing position)
2. Create your exit orders separately — for example, a limit sell at $195 and a stop sell at $175 3. On each exit order, find the OCA Group field in the order row (you may need to add this column: right-click on column headers → Customize Layout → add OCA Group) 4. Type the same group name in both orders — for example, "AAPL_exit" 5. Set the OCA Type: choose "Cancel with Block" (safest — cancels remaining orders and blocks any new ones in the group) 6. Transmit both ordersOCA Types Explained:
| OCA Type | Behavior |
|---|---|
| Cancel with Block | One fills → others cancelled + group blocked from new orders. Best for most traders. |
| Reduce with Block | One fills → others have quantity reduced by the filled amount + block. Good for scaling out. |
| Reduce without Block | One fills → others quantity-reduced, but you can add new orders to the group. Advanced. |
Method 4: Attached Orders via the Order Ticket
The full Order Ticket dialog gives you the most control over bracket orders.
Step-by-Step:
1. Right-click on any instrument → Trade → Order Ticket
2. Configure your entry order (action, quantity, order type, price) 3. Click the Misc tab (or look for the Attached Orders section at the bottom of the ticket) 4. Under Attached Orders, you will see options: - Profit Taker: Enable and set your limit price - Stop Loss: Enable and set your stop price - Trailing Stop: Enable and set a trailing amount instead of a fixed stop 5. Configure each attached order independently — you can set different time-in-force, order types, and conditions 6. Click TransmitWhen to Use This vs Quick Bracket:
The Order Ticket method is better when you need:
- Different order types for the stop — for example, a stop-limit instead of a stop-market
- Trailing stops instead of fixed stops
- Different time-in-force — maybe your entry is DAY but your stop is GTC (Good Till Cancel)
- Conditional logic — triggering the bracket based on price, time, or margin conditions
Stop Loss Types: Which One to Use
IB offers several stop order types. Choosing the wrong one can mean the difference between a controlled exit and a disaster.
STP (Stop Market)
- Triggers at your stop price, then executes as a market order
- Guarantees execution but not price
- Best for: Liquid instruments (SPY, AAPL, EURUSD, USDJPY) where the market-stop spread is minimal
- Risk: In a fast-moving gap, you may fill significantly worse than your stop price
STP LMT (Stop Limit)
- Triggers at your stop price, then places a limit order at your limit price
- Guarantees price but not execution
- Best for: Illiquid instruments where a market stop could fill at absurd levels
- Risk: If the price gaps through your limit, the order sits unfilled and you remain in the losing trade
TRAIL (Trailing Stop)
- The stop price moves with the market — follows the price up (for longs) and locks in gains
- You set a trailing amount (fixed or percentage)
- Best for: Trending strategies where you want to let winners run
- Risk: In choppy markets, you get stopped out by noise
My Recommendation
For most traders: use STP (stop market) for the stop loss and LMT for the take profit. You want guaranteed exit on the downside and price certainty on the upside.
For the automated USDJPY strategy I run, I use stop-market orders exclusively for stops. Forex is liquid enough that slippage on stops is typically 0-2 pips. A stop-limit that does not fill defeats the entire purpose of risk management.
Bracket Orders with the IB Python API
If you are building or running an automated trading system on IB, here is how to create bracket orders programmatically using the ibapi library.
The Code
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import Order
def create_bracket_order(
parent_id: int,
action: str,
quantity: float,
limit_price: float,
take_profit_price: float,
stop_loss_price: float
) -> list[Order]:
"""Create a bracket order: entry + take profit + stop loss."""
# Parent order (entry)
parent = Order()
parent.orderId = parent_id
parent.action = action
parent.orderType = "LMT"
parent.totalQuantity = quantity
parent.lmtPrice = limit_price
parent.transmit = False # Do NOT transmit yet
# Take profit (child)
take_profit = Order()
take_profit.orderId = parent_id + 1
take_profit.action = "SELL" if action == "BUY" else "BUY"
take_profit.orderType = "LMT"
take_profit.totalQuantity = quantity
take_profit.lmtPrice = take_profit_price
take_profit.parentId = parent_id
take_profit.transmit = False # Still do not transmit
# Stop loss (child)
stop_loss = Order()
stop_loss.orderId = parent_id + 2
stop_loss.action = "SELL" if action == "BUY" else "BUY"
stop_loss.orderType = "STP"
stop_loss.totalQuantity = quantity
stop_loss.auxPrice = stop_loss_price
stop_loss.parentId = parent_id
stop_loss.transmit = True # NOW transmit all three
return [parent, take_profit, stop_loss]
Key Details:
1. transmit = False on the parent and first child. Only the last child sets transmit = True. This ensures all three orders are submitted atomically. If you set transmit = True on the parent, it fires immediately without the bracket.
2. parentId links the children to the parent. IB uses this to establish the OCA relationship automatically.
3. Order IDs must be sequential: parent = N, take profit = N+1, stop loss = N+2. Use reqIds() to get the next valid ID from IB.
Submitting the Bracket:
# Create the contract
contract = Contract()
contract.symbol = "USD"
contract.secType = "CASH"
contract.currency = "JPY"
contract.exchange = "IDEALPRO"
# Create bracket orders
bracket = create_bracket_order(
parent_id=next_order_id,
action="BUY",
quantity=25000,
limit_price=148.50,
take_profit_price=149.50,
stop_loss_price=147.50
)
# Submit all three
for order in bracket:
app.placeOrder(order.orderId, contract, order)
Common API Pitfalls:
- Order ID reuse: Each order ID must be unique across the session. If you reuse an ID, IB rejects it silently or modifies the existing order
- Transmit flag ordering: If you accidentally set
transmit = Trueon the parent, the entry fires without stop/take profit protection. Always set the last child to transmit - Paper vs live differences: Paper trading accounts sometimes behave differently with bracket orders — fills are simulated and OCA cancellation timing can vary
- Connection drops: If your API connection drops after the parent fills but before children are confirmed, the children still exist on IB's servers. They persist independently. Check
openOrders()on reconnection
Modifying a Live Bracket Order
After your bracket is live, you often need to adjust the stop loss or take profit — maybe moving the stop to breakeven after a favorable move, or widening the target.
Like what you're reading? Try it yourself — this link supports ChartedTrader at no cost to you.
Open an Interactive Brokers account →On TWS:
1. Find the child order in your Orders panel (it appears indented under the parent, or in the "Pending" orders list if the parent has already filled)
2. Click on the price cell you want to change 3. Edit the price 4. Press U (Update) or click the Transmit button to send the modificationVia API:
# Modify the stop loss price
stop_loss.auxPrice = 148.00 # Move stop to breakeven
app.placeOrder(stop_loss.orderId, contract, stop_loss)
Calling placeOrder with an existing order ID modifies the order instead of creating a new one. The parent-child linkage and OCA relationship are preserved.
Moving Stop to Breakeven (The Most Common Modification)
Once the trade moves in your favor by a certain amount, moving the stop to your entry price eliminates risk. In my USDJPY strategy, I move the stop to breakeven after a 30-pip favorable move.
The logic:
if current_price - entry_price >= 0.30: # 30 pips
new_stop = entry_price # Breakeven
stop_loss.auxPrice = new_stop
app.placeOrder(stop_loss.orderId, contract, stop_loss)
Bracket Orders on IBKR Mobile and Client Portal
TWS is the most powerful interface for bracket orders, but you can create basic brackets from other IB platforms too.
IBKR Mobile:
1. Tap on an instrument → Trade
2. Set your entry order 3. Tap Bracket (or look for the attach/bracket toggle) 4. Set profit and stop offsets 5. SubmitThe mobile interface is simpler — you get the standard bracket but not OCA groups or conditional orders.
Client Portal (Web):
1. Go to Trade → select your instrument
2. Create your order 3. Look for Attach Stop Loss and Attach Profit Taker options 4. Set prices and submitClient Portal is fine for basic brackets on stocks. For forex, futures, or anything requiring precision, use TWS.
Common Mistakes and How to Avoid Them
1. Forgetting to Set Stop Loss as GTC
By default, TWS creates bracket children with DAY time-in-force. If your entry fills at 3:59 PM, your stop loss expires one minute later when the market closes. The next morning you wake up to an unprotected position.
Fix: Set time-in-force to GTC (Good Till Cancel) for both the stop loss and take profit. You can configure this in your bracket presets under Global Configuration.2. Using Stop-Limit Instead of Stop-Market for Protection
Stop-limit orders can skip. If the price gaps past your stop-limit price, the order sits unfilled and your loss keeps growing. For risk management, stop-market is almost always the right choice.
3. Quantity Mismatch Between Parent and Children
If your entry is for 100 shares but your stop loss is for 50, you are only half-protected. Always verify that all three orders in the bracket have the same quantity.
4. Modifying the Parent After Submission
If you try to modify the parent order's quantity or price after it has filled, IB may reject the modification. Only modify the child orders (stop and take profit) once the parent has executed.
5. Not Accounting for Commissions in Your Levels
If your take profit is 10 pips away on a 25,000-unit USDJPY position, the commission ($2 per side on IB) eats into that. Calculate net P&L after commissions when setting your levels.
Bracket Orders vs Manual Stop + Limit: Why Brackets Win
You might think: "I will just submit the entry first, then add a stop and take profit manually." Here is why that is worse:
| Bracket Order | Manual Separate Orders | |
|---|---|---|
| Submission | All three at once | Sequential — gap between entry and protection |
| OCO logic | Automatic | You must set up OCA manually |
| Parent-child linkage | Built in | None — orphaned orders if you forget to cancel |
| Risk window | Zero | Seconds to minutes while you type the stop |
| API reliability | Atomic via transmit flag | Race condition if connection drops mid-submission |
---
Start Trading with Interactive Brokers
If you are looking for a broker that offers professional-grade bracket orders, OCO logic, and API access for automated risk management, open an Interactive Brokers account here. IB is one of the few brokers that gives retail traders the same order infrastructure that institutional desks use.
*Disclosure: The link above is a referral link. You may receive up to $1,000 in IBKR stock when you sign up and fund your account. This does not affect the content of this guide.*
---
> 📊 Automating your IB reports? Use Flex Queries + Python to pull trade data automatically →
> 📡 Need market data? Figure out which IB data subscription you actually need →
> 🔐 IB Key 2FA giving you trouble? Fix every common IB Key failure mode →
> New to IBKR? Open an account through our link and get up to $1,000 in free IBKR stock (NASDAQ: IBKR). No catch — it is part of their official referral program.
FAQ
Can I create a bracket order for an existing position?
Not directly. Bracket orders are attached to a new entry order. If you already have a position, create separate stop and take profit orders and link them with an OCA group (Method 3 above).
Do bracket orders work on all IB instrument types?
Bracket orders work on stocks, options, futures, forex, and bonds on TWS. Some exotic instruments or thinly traded contracts may not support all order types (for example, stop-market orders are not available on some futures exchanges — check IB's order type availability page for your specific contract).
What happens to bracket children if I cancel the parent before it fills?
All children are cancelled automatically. The bracket is treated as a unit — cancelling the parent kills the entire bracket.
Can I use a trailing stop as the stop loss in a bracket?
Yes. In the Order Ticket (Method 4), select TRAIL as the stop loss type instead of STP. Set your trailing amount and it will follow the price while keeping the take profit as a fixed limit. Both are still linked via OCA — whichever triggers first cancels the other.
Do bracket orders work in IB's paper trading account?
Yes, but with caveats. Paper trading simulates fills, and the OCA cancellation timing can be slightly different from live. Test your bracket logic in paper, but do not assume the exact same fill behavior in live trading.