0

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

5
  • 1
    You can't. If you want it to be available to the other method, make it an attribute. Commented Sep 19, 2021 at 12:26
  • Or return the value from one method and pass it into the second method (although if it's being used in multiple methods, ya, making it an attribute likely makes more sense) Commented Sep 19, 2021 at 12:29
  • Local variables are indeed local to the function or method they're defined in — so no you can't do this. Commented Sep 19, 2021 at 12:34
  • Does this answer your question? Passing variables between methods in Python? Commented Sep 20, 2021 at 8:23
  • No, I don't see how I can implement this. Commented Sep 22, 2021 at 12:30

4 Answers 4

1

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
Sign up to request clarification or add additional context in comments.

4 Comments

Brian you are a legend, thank you! I thought I would never get an answer. I understand your approach, but I don't understand why didn't my approach work(why didn't reqSecDefOptParams work when called right after reqContractDetails if reqContractDetails returns the conID). Would it be possible to cycle through many different stocks? Can I just do a for in start to do this?
reqContractDetails doesn't get the conid right away, you have to wait for the callback. That's where step #4 and #5 are in my code. You can do many stocks but I would keep track of everything in a dict with reqId so you don't get them all mixed up.
It is not working again;I get an error.
Hi, Brian. One more question. How can I print out the option prices? I try print(self.greeks), but it is empty.
0

Welcome @LaForge1071! You have a few ways you can do this! One way you might do this is by passing the variable to the new function like this

def func_a():
    foo = 'bar'
    func_b(foo)


def func_b(var):
    print(var)

func_a()

or, and I don't recommend this, you can use global scope to solve this like so,

def func_a():
    global foo
    foo = 'bar'
    func_b()


def func_b():
    print(foo)

func_a()

2 Comments

Thanks for the answer. but I can't apply this principle to my problem. I call a function inside another function(start) and then I hope to get this value which I can now use in the function(start)
@LaForge1071 Without a specific example, looking at your comment and the original question I can't see why It wouldn't work? or you could user return to return the value from function_b to function_a
0

You said both function are in one class, so maybe declare the variable to be a class variable:

class A:
   def __init__(self):
      self.foo = None


   def func_a(self):
      self.foo = "Hello"


   def func_b(self):
      if self.foo is not None:
         print(self.foo)
    

1 Comment

Thanks for the answer, but for some reason I can't do that because func_a is called in func_b and my value does not print out.
0

you can declare this variable in init funciton ,just like constrution function in c/c++.

def __init__(self):
      self.foo = init_value

1 Comment

Thanks for the answer, but I tried this and it still doesn't help. My guess is that it is the architecture of the functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.