Search code examples
pythonfunctionglobal-variablesinteractive-brokerstws

Using the same variable in multiple functions in a class-TWS


I created a variable conID in one function and I want to use it in another. Both functions are inside a class.

The problem is that in the second function the first function is called, so self.reqSecDefOptParams calls the first function. And after that conID receives it value. If I try to output condID in the second function I can't, it says its value is still None. Is there a way to first call the first function and then output the value in the same function?

The first function:

def contractDetails(self, reqId: int, contractDetails: ContractDetails):
    string = str((contractDetails))
    letter_list = string.split(",")
    print(letter_list)
    conID = letter_list[90]  # the variable I need

The second function:

def start(self):
   # using the variable again
   self.reqSecDefOptParams(1, contract.symbol, "", "STK", conID)

Update: I get an error connecting to the socket. What can I do?

Error: 4 10167 Requested market data is not subscribed. Displaying delayed market data. Error: 4 10090 Part of requested market data is not subscribed. Subscription-independent ticks are still active.Delayed market data is available.AAPL NASDAQ.NMS/TOP/ALL unhandled exception in EReader thread Traceback (most recent call last): File "C:\Programming\TWS\source\pythonclient\ibapi\reader.py", line 34, in run data = self.conn.recvMsg() File "C:\Programming\TWS\source\pythonclient\ibapi\connection.py", line 99, in recvMsg buf = self._recvAllMsg() File "C:\Programming\TWS\source\pythonclient\ibapi\connection.py", line 119, in _recvAllMsg buf = self.socket.recv(4096) OSError: [WinError 10038] An operation was attempted on something that is not a socket

Process finished with exit code 0


Solution

  • Your last question had more information, I upvoted so I could find it but it disappeared. I will just fix up that code so you can see how it works in interaction with the API.

    There are at least 2 ways to get option contracts. The first is just ask for them but don't fill out all the parameters, then contractDetails will return all matching contracts. The second is to just ask for all parameters but you won't know if all contracts are traded.

    I put numbers in the code comments for an idea of how the program flow works.

    from ibapi.client import EClient
    from ibapi.wrapper import EWrapper
    from ibapi.common import TickerId, SetOfFloat, SetOfString, MarketDataTypeEnum
    from ibapi.contract import Contract, ContractDetails
    from ibapi.ticktype import TickType
    
    
    class TestApp(EClient, EWrapper):
        def __init__(self):
            EClient.__init__(self, self)
            self.underlyingContract = None
            self.opts = []
            self.optParams = ()
            self.greeks = []
    
        def error(self, reqId:TickerId, errorCode:int, errorString:str):
            print("Error: ", reqId, "", errorCode, "", errorString)
    
        def nextValidId(self, orderId):
            self.start() #1
    
        def contractDetails(self, reqId:int, contractDetails:ContractDetails, ):
            if contractDetails.contract.secType == "OPT":#2,3 (2 contracts, P+C)
                self.opts.append(contractDetails.contract)
            
            if contractDetails.contract.secType == "STK":#4
                self.underlyingContract = contractDetails.contract
                self.reqSecDefOptParams(3,self.underlyingContract.symbol,"","STK",
                                        self.underlyingContract.conId)#5
                
        def contractDetailsEnd(self, reqId):
            print("\ncontractDetails End\n")#3,4
    
        def securityDefinitionOptionParameter(self, reqId:int, exchange:str,
                                              underlyingConId:int, tradingClass:str, multiplier:str,
                                              expirations:SetOfString, strikes:SetOfFloat):
            #6
            self.optParams = (exchange, underlyingConId, tradingClass, multiplier, expirations, strikes)
            
        def securityDefinitionOptionParameterEnd(self, reqId:int):
            print("SecurityDefinitionOptionParameterEnd. ReqId",reqId)
            # make a contract out of params or just use contract from earlier
            if len(self.opts) > 0:
                self.reqMktData(4,self.opts[0],"",False,False,[])#7
    
        def tickOptionComputation(self, reqId:TickerId, tickType:TickType,
                                  impliedVol:float, delta:float, optPrice:float, pvDividend:float,
                                  gamma:float, vega:float, theta:float, undPrice:float):
            self.greeks.append([optPrice,delta,impliedVol,undPrice]) #8
            # just stop after first callback but you could set a time or something else
            # if you don't get data, the program won't end unless you ctrl-c or something
            self.stop() #9
            
        def start(self):
            # get some option contracts, not all
            opts = Contract()
            opts.symbol = 'AAPL'
            opts.secType = 'OPT'
            opts.exchange = 'SMART'
            opts.currency = 'USD'
            opts.strike="140"
            #opts.right="P" # ambiguous so as to get multiple contracts
            opts.multiplier="100"
            opts.lastTradeDateOrContractMonth = '20211015'
            self.reqContractDetails(1, opts)  #2
    
            # get just underlying conId
            underlying = Contract()
            underlying.symbol = 'AAPL'
            underlying.secType = 'STK'
            underlying.exchange = 'SMART'
            underlying.currency = 'USD'
            self.reqContractDetails(2, underlying) #4
            
            # in case you don't have data subscription
            self.reqMarketDataType(MarketDataTypeEnum.DELAYED)
            
        def stop(self):
            self.disconnect() #10
    
    app = TestApp()
    app.connect("127.0.0.1", 7497, 123)
    app.run() # starts a reader thread that will block until disconnect()
    
    #11 after disconnect, program can continue
    # I just do this so I can use spyder variable inspector but you could print
    uc = app.underlyingContract
    opts = app.opts
    params = app.optParams
    greeks = app.greeks