Trading Futures with IBridgePy: ES, MES, and NQ Complete Guide
Why Trade Futures with Python?
Futures contracts like ES (S&P 500 E-mini), MES (Micro E-mini S&P 500), and NQ (Nasdaq 100 E-mini) are among the most liquid instruments in the world. With IBridgePy, you can automate futures trading strategies using Python and execute them through Interactive Brokers with just a few lines of code.
Defining Futures Contracts in IBridgePy
Unlike stocks, futures require additional parameters: the expiry date and the exchange. IBridgePy uses superSymbol() to define futures contracts:
# Define an ES futures contract (December 2026 expiry)
es_contract = superSymbol(secType='FUT', symbol='ES', currency='USD',
exchange='CME', expiry='20261218')
# Define an MES micro futures contract
mes_contract = superSymbol(secType='FUT', symbol='MES', currency='USD',
exchange='CME', expiry='20261218')
# Define an NQ futures contract
nq_contract = superSymbol(secType='FUT', symbol='NQ', currency='USD',
exchange='CME', expiry='20261218')
The expiry parameter uses the format YYYYMMDD and should match the contract expiration date on the CME.
Placing Futures Orders
Once you have defined the contract, placing orders works the same as with stocks:
def handle_data(context, data):
mes = superSymbol(secType='FUT', symbol='MES', currency='USD',
exchange='CME', expiry='20261218')
# Buy 1 MES contract at market
order_id = order(mes, 1)
order_status_monitor(order_id, 'Filled', waitingTimeInSeconds=30)
fill_price = get_order(order_id).avgFillPrice
print(f'Bought 1 MES at {fill_price}')
Understanding cost_basis for Futures Positions
A critical difference between stocks and futures in IBridgePy is how get_position().cost_basis works. For futures, Interactive Brokers returns the dollar-multiplied value, not the raw price.
| Contract | Multiplier | Fill Price | cost_basis Value |
|---|---|---|---|
| MES | $5 | 5,400 | 27,000 |
| ES | $50 | 5,400 | 270,000 |
| MNQ | $2 | 19,500 | 39,000 |
| NQ | $20 | 19,500 | 390,000 |
To convert cost_basis back to the actual entry price, divide by the multiplier:
# Get entry price for MES position
mes_position = get_position(mes_contract)
entry_price = mes_position.cost_basis / 5 # MES multiplier is 5
print(f'MES entry price: {entry_price}')
# For ES
es_position = get_position(es_contract)
es_entry = es_position.cost_basis / 50 # ES multiplier is 50
Complete Strategy Example: MES with Stop Loss and Profit Target
def initialize(context):
context.mes = superSymbol(secType='FUT', symbol='MES', currency='USD',
exchange='CME', expiry='20261218')
context.in_position = False
def handle_data(context, data):
if not context.in_position:
# Enter long position
order_id = order(context.mes, 1)
order_status_monitor(order_id, 'Filled', waitingTimeInSeconds=30)
# Use avgFillPrice for precise stop/target levels
fill_price = get_order(order_id).avgFillPrice
# Place bracket: 20-point stop, 40-point target
stop_price = fill_price - 20
target_price = fill_price + 40
order(context.mes, -1, style=StopOrder(stop_price))
order(context.mes, -1, style=LimitOrder(target_price))
context.in_position = True
print(f'Entry: {fill_price} | Stop: {stop_price} | Target: {target_price}')
Important Tips for Futures Trading with IBridgePy
- Roll dates: Futures expire quarterly. Update the
expiryparameter before the contract rolls (typically the Thursday before the third Friday of March, June, September, or December for index futures). - Market hours: CME futures trade nearly 24 hours (Sunday 6pm to Friday 5pm ET with a daily halt from 5pm-6pm ET). Your strategy's scheduling should account for this.
- Margin: Futures require margin, not the full notional value. Check your account's available margin before placing orders.
- Position size:
get_position(contract).amountreturns the number of contracts held, positive for long and negative for short.
For more on order types and position management, visit the IBridgePy documentation or explore our tutorials.
