在 class-TWS 的多个函数中使用相同的变量

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

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

问题是在第二个函数中调用了第一个函数,所以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 请求的市场数据未被订阅。显示延迟的市场数据。 Error: 4 10090 部分请求的行情数据未被订阅。订阅独立报价仍然是 active.Delayed 市场数据是 available.AAPL 纳斯达克。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() 文件“C:\Programming\TWS\source\pythonclient\ibapi\connection.py”,第 119 行,在 _recvAllMsg 中 缓冲区 = self.socket.recv(4096) OSError:[WinError 10038] 尝试对不是套接字的对象进行操作

进程已完成,退出代码为 0

欢迎@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()

你说这两个函数在一个 class 中,所以也许将变量声明为 class 变量:

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)
    

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

def __init__(self):
      self.foo = init_value

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

交互

至少有两种方式可以获得期权合约。第一个是只询问它们但不填写所有参数,然后 contractDetails 将 return 所有匹配的合同。第二种是只询问所有参数,但你不会知道是否所有合约都已交易。

我在代码注释中添加了数字,以了解程序流程的工作原理。

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