how to unset goodAfterTime ?
2
I am able to set the goodAfterTime field as expected for a standing order, e.g. to "20250113 15:59:00 US/Eastern", and it seems to work as expected. However, I would also like to be able to reset the field to "", so as to remove the goodAfterTime constraint, allowing the order to fill immediately. I can't get this to work. I am able to reset the field to "", and to re-place the order, but the goodAfterTime field on the standing order is not reset. (See code below.) (The order stays in "presubmit" status, and in the TWS GUI, if I examine the fields via the order-modification panel, it still shows the original goodAfterTime value.) Checking the "audit trail" of messages through the TWS GUI, I see that the goodAfterTime field seems to transmit as a numeric field number 168. As far as I can tell, even after I reset goodAfterTime, that field is not being transmitted with the new value of "". I've been banging my head against this for several hours now. What am I doing wrong? help!? thank you, -Neal Code to set the field: order.goodAfterTime = "20250113 15:59:00 US/Eastern" order.tif = "GTC" ib.placeOrder(contract, order) Code to unset it: order.goodAfterTime = "" order.tif = "GTC" ib.placeOrder(self.contract, self.order)
|
How to check TWS connectivity?
5
Using the API, what is a good way to check if the TWS is connected to IB servers?
|
Option Open Interest
3
I'm trying to get an option open interest using ib_async, but it does not show the open interest at all. The code I have using ib_async is: from ib_async import * ib = IB() ib.connect('127.0.0.1', 4001, clientId=138) ib.reqMarketDataType(1) option1 = [Option('GOOGL', '20250117', 195, 'C', 'SMART')] ib.qualifyContracts(option1[0]) a=ib.reqMktData(option1[0],genericTickList='100',snapshot=False, regulatorySnapshot=False) print(a) print("-") b=ib.reqTickers(Option('GOOGL', '20250117', 195, 'C', 'SMART')) print("Volume ", b[0].volume) print("callOpenInterest ", b[0].callOpenInterest) print("putOpenInterest", b[0].putOpenInterest) print("impliedVolatility ", b[0].impliedVolatility) ib.disconnect() the output of this code is Ticker(contract=Option(conId=584786601, symbol='GOOGL', lastTradeDateOrContractMonth='20250117', strike=195.0, right='C', multiplier='100', exchange='SMART', currency='USD', localSymbol='GOOGL 250117C00195000', tradingClass='GOOGL')) - Volume 1385.0 callOpenInterest nan putOpenInterest nan impliedVolatility nan which means that open interest is missing. Using the IBKR TWS API I can get the open interest but the way to there is a bit less user friendly from ibapi.client import EClient from ibapi.wrapper import EWrapper from ibapi.contract import Contract from ibapi.ticktype import TickTypeEnum import threading import time class IBApp(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) self.call_open_interest = None self.reqId = 1 self.oi_received = False # Flag to track if tick 27 was received def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=''): print(f"Error. Id: {reqId}, Code: {errorCode}, Msg: {errorString}") def tickSize(self, reqId: int, tickType: int, size: float): if tickType == TickTypeEnum.OPTION_CALL_OPEN_INTEREST: self.call_open_interest = size self.oi_received = True #set flag to true print(f"TickSize. TickerId:", reqId, "TickType:", tickType, "Size: ", size) else: print("Not the expected tick type") def tickSnapshotEnd(self, reqId): print(f"TickSnapshotEnd. Ticker Id: {reqId}") def run_loop(app): app.run() if __name__ == "__main__": app = IBApp() app.connect("127.0.0.1", 4001, clientId=20) api_thread = threading.Thread(target=run_loop, args=(app,), daemon=True) api_thread.start() time.sleep(1) contract = Contract() contract.symbol = "GOOGL" contract.secType = "OPT" contract.exchange = "SMART" contract.currency = "USD" contract.lastTradeDateOrContractMonth = "20250117" contract.strike = 195 contract.right = "C" contract.multiplier = "100" app.reqMktData(app.reqId, contract, genericTickList='101', snapshot=False, regulatorySnapshot=False, mktDataOptions=[]) #request tick 27 time.sleep(5) # Wait for a reasonable time for data if app.oi_received: #check flag print(f"Option Call Open Interest Size: {app.call_open_interest}") else: print("Did not receive Option Call Open Interest data within the timeout.") app.disconnect() The output of this code is Error. Id: -1, Code: 2104, Msg: Market data farm connection is OK:usfarm.nj Error. Id: -1, Code: 2104, Msg: Market data farm connection is OK:usopt Error. Id: -1, Code: 2104, Msg: Market data farm connection is OK:usfarm Error. Id: -1, Code: 2107, Msg: HMDS data farm connection is inactive but should be available upon demand.ushmds Error. Id: -1, Code: 2158, Msg: Sec-def data farm connection is OK:secdefnj Not the expected tick type Not the expected tick type Not the expected tick type Not the expected tick type Not the expected tick type Not the expected tick type Not the expected tick type TickSize. TickerId: 1 TickType: 27 Size: 21890 Not the expected tick type Option Call Open Interest Size: 21890 Does anyone use ib_async to get the option open interest and if so could you please share the way to request this data?
|
Anyone used the Web API?
2
I run a bot using the ib_async wrapper but when TWS connectivity is unstable, it runs into issues. Before working to fix this, I'd like to understand if anyone has used the Web API and how that experience has been in terms of connectivity, market data, order execution etc. Thank you!
|
How to place multiple orders AT THE SAME TIME?
9
I want to place two orders and they are OCA. I have defined the ocsGroup to bind these two orders, HOWEVER, I found I cannot place two orders just one after another. I need to insert an ib.sleep(2) between the two placeOrder to make them work Sometimes, the first order will just fire while the second order will wait for 2s to arrive.... Can someone help me with this? oca_group = f"OCA_Group_{datetime.now().strftime('%Y%m%d%H%M%S')}" # Create the Buy Stop order (do not transmit yet) buy_stop_order = Order( action='BUY', totalQuantity=ORDER_QUANTITY, orderType='STP', auxPrice=buy_stop_price, tif='DAY', ocaGroup=oca_group, ocaType=1, # OCA type transmit=True ) # Create the Sell Stop order (this will transmit the group) sell_stop_order = Order( action='SELL', totalQuantity=ORDER_QUANTITY, orderType='STP', auxPrice=sell_stop_price, tif='DAY', ocaGroup=oca_group, ocaType=1, transmit=True # Transmit the group ) # Submit the OCA order group print(f"Submitting Buy Stop and Sell Stop orders. OCA Group: {oca_group}") ib.placeOrder(stock, buy_stop_order) # Create the Buy Stop order without transmitting ib.sleep(2) ##### I REALY WANT TO REMOVE THIS 2S AND MAKE SURE THEY ARE PLACED AT THE SAME TIME############# ib.placeOrder(stock, sell_stop_order) # Create and transmit the Sell Stop order (activates the group)
|
How to attach a stop loss order (Child) to a buy order(Parent)?
2
Hi folk, I am new to the IB_async API... I want to sent a buy order as a parent order and attach a trailing stop order as a child order. The child will only be fired as long the parent order is fired. Can anyone tells me if the following code is right? Thanks a lot. from ib_async import * import random # Connect to Interactive Brokers ib = IB() ib.connect('127.0.0.1', 4004, clientId=1) # Define the Tesla stock contract tesla_contract = Stock('TSLA', 'SMART', 'USD') # Generate a unique order ID parent_order_id = ib.client.getReqId() # Create the parent buy limit order parent_order = LimitOrder( action='BUY', totalQuantity=100, lmtPrice=100.00, tif='GTC', # Good-Til-Canceled outsideRth=True, # Allow order outside regular trading hours orderId=parent_order_id, transmit=False # Transmit with child order ) # Create the child trailing stop sell order child_order = Order( action='SELL', orderType='TRAIL', totalQuantity=100, trailingPercent=None, # Use None to specify trailing amount in absolute dollars auxPrice=5.00, # Trailing amount in dollars tif='GTC', # Good-Til-Canceled outsideRth=True, # Allow order outside regular trading hours parentId=parent_order_id, transmit=True # Transmit the entire order (parent and child) ) # Place both orders ib.placeOrder(tesla_contract, parent_order) ib.placeOrder(tesla_contract, child_order) # Disconnect from IB ib.disconnect()
|
How to watch for option assignment/settlement?
6
I’m looking for a way to watch for options assignment/settlement on expiration. Is there an event that I can subscribe to that will notify me when this occurs and provide information about options settlement?
|
Loaded Historical Data Ruquest
3
Hello all, I'm trying to get 1-hr and 15-min data for an ETF going back 10 years but the most the API will get is 7 years for 1-hr bars and 2 years for 15-min bars. Longer timeframe requests keep timing out. IB's support told me there's no restriction in TWS or the IB API, and that I may want to check if the ib_async wrapper is causing the timeout, especially because it's a lot of data and the request will take time. Anyone know if this could be the case, and/or how to manage it? Secondly, I tried to get smaller chunks of data (1 yr at a time) but that request also timed out. Below is my code, would love help confirming if it looks correct. The intent of this request is to get data starting 10 years ago (12/2/2014) until 12/2/1025. Thank you so much! ib.reqHistoricalData( contract, endDateTime='20151202 23:59:59', durationStr='10 Y', barSizeSetting='15 mins', whatToShow='TRADES', useRTH=True, keepUpToDate=False, formatDate=2)
|
Issue with Retrieving Real-Time Option Data (Bid, Ask, Delta) via TWS API and ib_insync
9
Hi everyone, I’m new to using the TWS API and ib_insync for retrieving real-time option chain data. I have a real-time data subscription for both stocks and options. However, when I attempt to fetch option data such as bid, ask, and delta for SPY options, I cannot get valid data.... Here’s what I’m trying to do: Retrieve option data for the nearest SPY options. Include strikes within 5% up and down from the current price. Get basic data like bid, ask, and delta. While I can retrieve the option chain and strike information, the bid, ask, and delta values are missing or in the output. Am I missing any configuration steps, or is there a known issue with fetching real-time option data like this? I’d greatly appreciate your help or guidance on this matter. Thank you! Here’s a snippet of my code and the output: CODE: from ib_async import IB, Stock, Option, util import pandas as pd # Start the event loop util.startLoop() # Create an IB instance and connect to the server ib = IB() ib.connect(port=4004, clientId=1) # Define the stock contract stock = Stock(symbol="SPY", exchange="SMART", currency="USD") # Replace "SPY" with another symbol to test ib.qualifyContracts(stock) # Fetch the current market price of the stock ticker = ib.reqTickers(stock)[0] current_price = ticker.marketPrice() print(f"Current market price for {stock.symbol}: {current_price:.2f}") # Define the percentage range for filtering option strikes price_range_percentage = 3 # Default ±5%, adjustable price_range = ( current_price * (1 - price_range_percentage / 100), current_price * (1 + price_range_percentage / 100) ) print(f"Price range: {price_range[0]:.2f} - {price_range[1]:.2f} (±{price_range_percentage}%)") # Fetch the option chain for the stock chains = ib.reqSecDefOptParams(stock.symbol, '', stock.secType, stock.conId) chain = next(c for c in chains if c.exchange == 'SMART') # Get the most recent expiration date recent_expiration = sorted(chain.expirations)[0] print(f"Most recent expiration date: {recent_expiration}") # Filter valid strikes within the price range (integer strikes only) valid_strikes = [ strike for strike in chain.strikes if price_range[0] <= strike <= price_range[1] and strike.is_integer() ] # Create option contracts for valid strikes (CALL and PUT options) rights = ['P', 'C'] # P: Put, C: Call contracts = [] for strike in valid_strikes: for right in rights: contract = Option( symbol=stock.symbol, lastTradeDateOrContractMonth=recent_expiration, strike=strike, right=right, exchange='SMART', tradingClass=chain.tradingClass ) contracts.append(contract) # Qualify contracts and fetch market data contracts = ib.qualifyContracts(*contracts) tickers = ib.reqTickers(*contracts) # Separate market data for CALL and PUT options call_data, put_data = [], [] for t in tickers: try: # Extract option greeks (e.g., Delta) delta = t.modelGreeks.delta if t.modelGreeks else None delta_percentage = f"{delta * 100:.2f}%" if delta is not None else None # Store option data data = { "Symbol": t.contract.symbol, "Expiration": t.contract.lastTradeDateOrContractMonth, "Strike": t.contract.strike, "Right": t.contract.right, "Bid": t.bid, "Ask": t.ask, "Last": t.last, "Volume": t.volume, "Delta (%)": delta_percentage, } if t.contract.right == 'C': # Call option call_data.append(data) elif t.contract.right == 'P': # Put option put_data.append(data) except Exception: pass # Skip any invalid data # Convert CALL and PUT data into Pandas DataFrames call_df = pd.DataFrame(call_data) put_df = pd.DataFrame(put_data) # Display CALL and PUT option data print("\nCALL Options:") print(call_df) print("\nPUT Options:") print(put_df) # Save the data to CSV files call_df.to_csv(f"{stock.symbol}_call_options.csv", index=False) put_df.to_csv(f"{stock.symbol}_put_options.csv", index=False) # Disconnect from the server ib.disconnect() My output (ONLY the CALL Part, as the PUT part is the same): Current market price for SPY: 589.10 Price range: 571.43 - 606.77 (±3%) Most recent expiration date: 20241121 CALL Options: Symbol Expiration Strike Right Bid Ask Last Volume Delta (%) 0 SPY 2024112
|
Did Interactive broker start charging subscription fees for standard market data?
When trying to retrieve a simple stock data, i now receive an error message: from ib_insync import * util.startLoop() ib = IB() ib.connect('127.0.0.1', 7498, clientId=10) contract = Stock('APPL', 'SMART', 'USD') ib.reqMktData(contract, '', False, False) Error message: Error 10089, reqId 4: Requested market data requires additional subscription for API. See link in 'Market Data Connections' dialog for more details.Delayed market data is available.AAPL NASDAQ.NMS/TOP/ALL, contract: Stock(symbol='AAPL', exchange='SMART', currency='USD') Is there any change in IB subscription policy? Thank you,
|
Placing Trailing Stop Limit Orders
5
Hello, Anyone who uses this order type, can you please confirm whether this code is correct to create an order with 1% trail? Most interested in the 'trailingPercent' field i.e. whether to pass the percent value as 1 or 0.01. Are there any other fields needed for the order to correctly execute? Thanks so much! trailingStopOrder = ibi.Order(action=closingAction, totalQuantity=acccountPosition.position, orderType='TRAIL LIMIT', trailingPercent=1, account=acccountPosition.account, outsideRth= True, tif= "DAY")
|
Cannot receive market data - it used to work before...
Hi, I have the following script: ticker = 'AAPL' algo_params={AlgoParam.Z_THRESH: 3} symbol = Symbol(ticker, 100, IbAsyncContractService.createContract(ticker, SecType.STOCK)) Algorithm = ZCalcAlgorithm(symbol, algo_params) app.run_algo(Algorithm) where run_algo function is just this: def run_algo(self, algorithm: IAlgorithm): symbol = algorithm.symbol self.qualifyContracts(symbol.contract) self.reqMarketDataType(1) self.symbols[symbol.name] = symbol self.algos[symbol.name] = algorithm self.reqMktData(symbol.contract) I receive the following error: (It has worked before) Error 10089, reqId 130: Requested market data requires additional subscription for API. See link in 'Market Data Connections' dialog for more details.Delayed market data is available.BA NYSE/TOP/ALL, contract: Stock(conId=4762, symbol='BA', exchange='SMART', primaryExchange='NYSE', currency='USD', localSymbol='BA', tradingClass='BA') P.S. when I log in to my account using the web, I receive the attached massage (uploaded file) which disappears a moment later.
|
Expected behavior after `ib.disconnect()`
2
The following behavior puzzles me (due to my poor understanding of the underlying asyncio mechanics). 1st, the program requests market data. A callback is attached. The callback will call `disconnect`. There is also a callback for the `disconnectedEvent`. When the program is executed, the `on_tick` callback is called. `isConnected` returns first True and then False, yet neither the `on_disconnect` function is ever called nor does the program ever continue its execution after the statement ib.run(). How can this be explained, and is there a way I can make the program continue after disconnecting? For example, I have implemented a shutdown timer, and the only way I managed to actually end the program is with os._exit(0) Code: from ib_async import Ticker, IB, Forex def on_tick(ticker: Ticker): print("Disconnecting") print(f"Is connected={ib.client.isConnected()}") ib.client.disconnect() print(f"Is connected={ib.client.isConnected()}") def on_disconnect(): print("Disconnected") ib = IB() ib.connect(host='127.0.0.1', port=4001, clientId=1) contract = Forex('GBPUSD', 'IDEALPRO') ib.qualifyContracts(contract) ticker = ib.reqMktData(contract) ticker.updateEvent += on_tick ib.disconnectedEvent += on_disconnect ib.run() print("End") # never executed
|
async orders getting stuck in "preSumbitted" status
6
I have some code below that functions as intended like 80% of the time but for some reason, random orders are not being placed in IBKR. When I debug the issue, it seems that certain orders never make it past this "preSumbitted" status, despite being completely valid orders that I'm trying to send to IBKR. I tried using "sleeps" (IB, Time, and asyncio), but I can't seem to get this to work 100% of the time. Is there something wrong with my async logic here? It's a pretty simple script that uses a polygon.io WebSocket. from polygon import WebSocketClient from polygon.websocket.models import WebSocketMessage import pandas as pd import numpy as np import datetime import time from ib_insync import IB, Stock, LimitOrder, Order import asyncio import nest_asyncio nest_asyncio.apply() t = 'AAPL' client = WebSocketClient("xxx") # hardcoded api_key is used client.subscribe("AM." + t) # all aggregates #Connect IBKR ib = IB() ib.connect('127.0.0.1', 7496, clientId=0) #Change for paper async def handle_msg(msgs: List[WebSocketMessage]): for m in msgs: data = {'ticker': [m.symbol], 'close': [m.close], 'vwap': [m.vwap], 'start_timestamp': [m.start_timestamp], 'end_timestamp': [m.end_timestamp]} data['start_timestamp'] = pd.to_datetime(data['start_timestamp'], unit='ms') data['end_timestamp'] = pd.to_datetime(data['end_timestamp'], unit='ms') data['gtd_buy'] = data['end_timestamp'] + pd.Timedelta(seconds=58) data['gtd_buy'] = data['gtd_buy'].astype(str).str.replace('-', '') gtd = data['gtd_buy'][0] df = pd.DataFrame(data) buy = np.where(df.close < df.vwap, 1, 0) print(df.head(1), buy[0]) pos = pd.DataFrame(ib.positions()) #Buy if buy[0] == 1: if pos.shape[0] == 0: contract = Stock(t, 'SMART', 'USD') ib.qualifyContracts(contract) curr_dt = datetime.datetime.now() order = LimitOrder('BUY', totalQuantity = 1, lmtPrice = m.close, tif = 'GTD', goodTillDate = gtd, hidden=True) order.orderId = int(curr_dt.timestamp()) print('Buy Triggered', order.orderId) trade = ib.placeOrder(contract, order) await asyncio.sleep(30) async def main(): await asyncio.gather(client.connect(handle_msg))
|
Industry / Sector SIC Code in scanner?
I tried using SIC as filter tag with the value 3674 (semiconductors) to request data from ib_insync, but it seems that I get companies like MRK which has nothing to do with this SIC code. Any idea about that? Thanks
|
ib.trades() and nightly restarts
2
My intent to have my script run all the time, however I have some issues with the way that ib.trades(), returns after TWS restarts itself automatically through the auto-restart feature. util.df(ib.trades()) I have a simple function called called post_midnight_refresh(), that does some log cycling, some basic cleanup, as well as refreshes some variables (and basically disconnects and reconnects after TWS restarts). I understand that I don't have to do that, because as I understand, IB_async library will handle the disconnect / reconnect automatically, however, in order to test why ib. trades() seems to be returned previous day traded symbols, I decided to disconnect and reconnect manually. However that doesn't seem to fix the issue. Any idea how I can get ib.trades() to return only the trades for that day? If I close my python script in Windows and reopen the script (the next day), then all works fine, and ib.trades() just returns trades that I did today, (and not everything from today and yesterday) ib.disconnect() ib.client.reset() ib.connect('127.0.0.1', 7496, clientId=0) I also tried to do this before I call ib.trades() to make sure that trades are accurate, but that doesn't seem to fix it either. ib.reqAllOpenOrders() ib.reqOpenOrders() # Bind previous opened orders ib.reqAutoOpenOrders() # Bind all future orders Also, do I actually have to call the above prior to calling ib.trades() ?
|
Anyone used Cython?
I'd like to speed up my Python code by using Cython. Has anyone else done this? If so, how was your experience?
|
Subscription
6
Just a reminder that this group uses a paid subscription model for groups.io. The current cost is $20 per month. Please use the Sponsor this Group button on the main page: /g/ib-async The current year was covered by only a couple of people, I think everyone that is getting a benefit should donate a couple of dollars. At the current amount of members, if everyone put in $5, that would cover another year. $5 or $10 per year is pretty inexpensive for a forum like this. The button automatically adds it to the group.io account and the monthly fees then come out of there. I would also like to ask if anyone would be interested in being an admin to the group! I don't like the risk of myself being the only one able to manage the group and to accept pending members. If I'm away, a person could wait a week or two to get approved as a member. Not to mention what happened to the last group admin... I believe I am older than Ewald was. Thanks, Mel Pryor
|
How to get RTH bars
6
I'm using the code below to get 1 hour bars, but noticed that the last bar of the previous day is for the 7pm hour, not the 3pm hour, despite setting useRTH to True. Anyone know why that would be? Thanks! bars_hist_1h = ib.reqHistoricalData( contract, endDateTime='', durationStr='2 W', barSizeSetting='1 hour', whatToShow='TRADES', useRTH=True, keepUpToDate=False, formatDate=2)
|
asyncio example
8
Hi, Ewald at some point had an example of using asyncio in one of his notebook examples. But I cant find it in the new ib_async or the previous ib_insync. Was it removed at some point.....if so, question (1), does anyone know where i could find this example? I have been using ib_insync for several years in a way that runs through a series of executions then ends. I now want to take this to another level where the program runs and monitors for a given opportunity continuously through the day session.......so I am assuming i may need to learn how to implement with asyncio, given comments on this S.O question https://stackoverflow.com/questions/76348014/running-ib-insyn-in-a-while-true-loop-that-buys-and-sells-on-tws-instance question (2) can anyone point me to any specific examples that help me understand how to implement an algo as a continuously running/monitoring process? This part is hard for me as I am a self-taught programmer, and according to the S.O link there seem to be some pitfalls in doing this. Finally, thank you so much to the extremely generous people who have taken up Ewalds legacy in continuing this library. Regards B.
|