Send a Stop Order
Place a BUY STOP on SPY far above market. The trigger never fires, so the order rests. Watch it acknowledge, then cancel it.
What this shows
- Taking the order id off
next_valid_id, whichconnect()fires before it returns. - An
Orderwithorder_type = "STP"and the trigger price inaux_price.lmt_priceis unused for a plain stop. tif = "GTC", so it survives the close rather than expiring with the day.order_statuscallbacks:PreSubmittedthenSubmittedwhile it rests,Cancelledonce the cancel lands.cancel_order(order_id, "").
What comes back
The same order_status stream as any other order. A resting stop shows no
fills: filled stays 0 and remaining stays at the full quantity until the
trigger is touched.
Limits
A stop is held until its trigger is touched, then goes to the market as a market order. This example sets the trigger far above market so that never happens. On a real stop, the fill price is whatever the market gives you at that moment, not the trigger.
Paper account only.
Run it
IB_USERNAME=... IB_PASSWORD=... python examples/hello_stop_order.py
Source
"""Recipe: place a BUY STP on SPY far above market, watch Submitted, then cancel.
Usage:
IB_USERNAME=... IB_PASSWORD=... python examples/hello_stop_order.py
"""
import os
import threading
from ib_dx import EClient, EWrapper, Contract, Order
class OrderWrapper(EWrapper):
def __init__(self):
self.next_id = None
self.submitted = threading.Event()
self.cancelled = threading.Event()
def next_valid_id(self, order_id):
self.next_id = order_id
def order_status(self, order_id, status, filled, remaining,
avg_fill_price, perm_id, parent_id,
last_fill_price, client_id, why_held, mkt_cap_price):
print(f"[status] oid={order_id} status={status}")
if status == "Submitted":
self.submitted.set()
if status == "Cancelled":
self.cancelled.set()
def error(self, req_id, error_time, code, msg, advanced=""):
if code not in (2104, 2106, 2158):
print(f"[error] {code}: {msg}")
w = OrderWrapper()
c = EClient(w)
c.connect(
username=os.environ["IB_USERNAME"],
password=os.environ["IB_PASSWORD"],
paper=True,
)
threading.Thread(target=c.run, daemon=True).start()
order_id = w.next_id
spy = Contract()
spy.con_id = 756733
spy.symbol = "SPY"
spy.sec_type = "STK"
spy.exchange = "SMART"
spy.currency = "USD"
order = Order()
order.action = "BUY"
order.total_quantity = 1
order.order_type = "STP"
order.aux_price = 9999.0
order.tif = "GTC"
order.outside_rth = True
print(f"placing BUY 1 SPY STP 9999.00 (oid={order_id})")
c.place_order(order_id, spy, order)
w.submitted.wait(timeout=15)
print(f"cancelling oid={order_id}")
c.cancel_order(order_id, "")
w.cancelled.wait(timeout=15)
c.disconnect()