【问题标题】:Using the same variable in multiple functions in a class-TWS在一个类的多个函数中使用相同的变量-TWS
【发布时间】:2021-11-13 12:03:49
【问题描述】:

我在一个函数中创建了一个变量conID,我想在另一个函数中使用它。这两个函数都在一个类中。

问题是在第二个函数中调用了第一个函数,所以self.reqSecDefOptParams 调用了第一个函数。之后conID 收到它的值。如果我尝试在第二个函数中输出condID,我不能,它说它的值仍然是None。有没有办法先调用第一个函数,然后在同一个函数中输出值?

第一个函数:

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

第二个功能:

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

更新:连接到套接字时出现错误。我能做什么?

错误:4 10167 请求的市场数据未订阅。显示延迟的市场数据。 错误:4 10090 部分请求的市场数据未订阅。独立于订阅的报价仍然活跃。延迟的市场数据可用。AAPL NASDAQ.NMS/TOP/ALL EReader 线程中未处理的异常 回溯(最近一次通话最后): 文件“C:\Programming\TWS\source\pythonclient\ibapi\reader.py”,第 34 行,运行中 数据 = self.conn.recvMsg() 文件“C:\Programming\TWS\source\pythonclient\ibapi\connection.py”,第 99 行,在 recvMsg buf = self._recvAllMsg() _recvAllMsg 中的文件“C:\Programming\TWS\source\pythonclient\ibapi\connection.py”,第 119 行 buf = self.socket.recv(4096) OSError: [WinError 10038] 尝试对非套接字的操作进行操作

进程以退出代码 0 结束

【问题讨论】:

  • 你不能。如果您希望它可用于其他方法,请将其设为 属性
  • 或者从一种方法返回值并将其传递给第二种方法(尽管如果它在多种方法中使用,是的,将其作为属性可能更有意义)
  • 局部变量确实是定义它们的函数或方法的局部变量——所以不,你不能这样做。
  • 这能回答你的问题吗? Passing variables between methods in Python?
  • 不,我不知道如何实现。

标签: python function global-variables interactive-brokers tws


【解决方案1】:

你的最后一个问题有更多信息,我投了赞成票,所以我可以找到它,但它消失了。我将修复该代码,以便您了解它如何与 API 交互。

至少有两种方法可以获得期权合约。第一种只是询问它们但不填写所有参数,然后 contractDetails 将返回所有匹配的合约。第二种是只询问所有参数,但您不知道是否所有合约都被交易。

我在代码 cmets 中输入了数字,以了解程序流程是如何工作的。

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

【讨论】:

  • 布莱恩你是个传奇,谢谢!我以为我永远不会得到答案。我理解你的方法,但我不明白为什么我的方法不起作用(如果 reqContractDetails 返回 conID,为什么在 reqContractDetails 之后立即调用 reqSecDefOptParams 不起作用)。是否有可能循环通过许多不同的股票?我可以在开始时做一个 for in 吗?
  • reqContractDetails 没有立即得到conid,你必须等待回调。这就是我的代码中的第 4 步和第 5 步。你可以做很多股票,但我会用 reqId 跟踪所有内容,这样你就不会把它们都搞混了。
  • 它不再工作了;我得到一个错误。
【解决方案2】:

欢迎@LaForge1071!你有几种方法可以做到这一点!您可能会这样做的一种方法是将变量传递给这样的新函数

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


def func_b(var):
    print(var)

func_a()

或者,我不推荐这个,你可以像这样使用全局范围来解决这个问题,

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


def func_b():
    print(foo)

func_a()

【讨论】:

  • 感谢您的回答。但我不能将此原则应用于我的问题。我在另一个函数(start)中调用一个函数,然后我希望得到这个值,我现在可以在函数(start)中使用它
  • @LaForge1071 没有一个具体的例子,看看你的评论和原来的问题,我看不出为什么它不起作用?或者您可以使用 return 将 function_b 的值返回给 function_a
【解决方案3】:

你说两个函数都在一个类中,所以可以将变量声明为类变量:

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)
    

【讨论】:

  • 感谢您的回答,但由于某种原因我不能这样做,因为在 func_b 中调用了 func_a 并且我的值没有打印出来。
【解决方案4】:

你可以在init函数中声明这个变量,就像c/c++中的构造函数一样。

def __init__(self):
      self.foo = init_value

【讨论】:

  • 感谢您的回答,但我试过了,但仍然没有帮助。我的猜测是它是函数的架构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 2019-03-30
  • 2014-12-14
相关资源
最近更新 更多