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

  • 1
    You can't. If you want it to be available to the other method, make it an _attribute_. – jonrsharpe Sep 19 '21 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) – Carcigenicate Sep 19 '21 at 12:29
  • Local variables are indeed local to the function or method they're defined in — so no you can't do this. – martineau Sep 19 '21 at 12:34
  • Does this answer your question? [Passing variables between methods in Python?](https://stackoverflow.com/questions/9520075/passing-variables-between-methods-in-python) – mkrieger1 Sep 20 '21 at 08:23
  • No, I don't see how I can implement this. – La Forge1071 Sep 22 '21 at 12:30

4 Answers4

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
brian
  • 10,619
  • 4
  • 21
  • 79
  • 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? – La Forge1071 Sep 25 '21 at 11:55
  • 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. – brian Sep 25 '21 at 12:22
  • It is not working again;I get an error. – La Forge1071 Oct 01 '21 at 09:30
  • Hi, Brian. One more question. How can I print out the option prices? I try print(self.greeks), but it is empty. – La Forge1071 Feb 08 '22 at 18:24
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()
  • 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) – La Forge1071 Sep 20 '21 at 17:32
  • @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 – Justin.Arnold Sep 21 '21 at 12:35
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)
    
Drachen
  • 72
  • 6
  • 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. – La Forge1071 Sep 19 '21 at 13:44
0

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

def __init__(self):
      self.foo = init_value
mutong
  • 31
  • 1
  • 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. – La Forge1071 Sep 20 '21 at 17:33