이 멀티 스레딩을 사용하여 API 메시지를 처리하는 방법을 예입니다 : 여기
는 코드입니다. app.run()은 별도의 스레드로 시작되며 TWS API 응답을 수신합니다. 주 프로그램은 ContractDetails에 대한 5 개의 요청을 보낸 다음 주 프로그램은 응답을 기다리는 10 초입니다. 응답이 처리 될 준비가되면 TWS API 메시지는 응용 프로그램 인스턴스 및 간단한 세마포어 신호에 저장됩니다.
내 첫 번째 멀티 스레딩 프로그램입니다. 모든 의견을 환영합니다.
from ibapi import wrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper #just for decorator
from ibapi.common import *
from ibapi.contract import *
from ibapi.ticktype import *
#from OrderSamples import OrderSamples
import threading
import time
class myThread (threading.Thread):
def __init__(self, app, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.app = app
def run(self):
print ("Starting application in separate thread:", self.name, "threadID:", self.threadID )
self.app.run()
print ("Exiting " + self.name)
class TestApp(wrapper.EWrapper, EClient):
def __init__(self):
wrapper.EWrapper.__init__(self)
EClient.__init__(self, wrapper=self)
self.started = False
self.nextValidOrderId = 0
self.reqData = {} # store data returned by requests
self.reqStatus = {} # semaphore of requests - status End will indicate request is finished
@iswrapper
def nextValidId(self, orderId:int):
print("setting nextValidOrderId: %d", orderId)
self.nextValidOrderId = orderId
@iswrapper
def error(self, reqId:TickerId, errorCode:int, errorString:str):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
@iswrapper
# ! [contractdetails]
def contractDetails(self, reqId: int, contractDetails: ContractDetails):
super().contractDetails(reqId, contractDetails)
# store response in reqData dict, for each request several objects are appended into list
if not reqId in self.reqData:
self.reqData[reqId] = []
self.reqData[reqId].append(contractDetails) # put returned data into data storage dict
# ! [contractdetails]
@iswrapper
# ! [contractdetailsend]
def contractDetailsEnd(self, reqId: int):
super().contractDetailsEnd(reqId)
print("ContractDetailsEnd. ", reqId, "\n") # just info
self.reqStatus[reqId] = 'End' # indicates the response is ready for further processing
# ! [contractdetailsend]
def main():
app = TestApp()
app.connect("127.0.0.1", 4001, clientId=123)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
app.twsConnectionTime()))
thread1App = myThread(app, 1, "Thread-1") # define thread for sunning app
thread1App.start() # start app.run(] as infitnite loop in separate thread
print('Requesting MSFT contract details:')
contract = Contract()
contract.symbol = "MSFT"
contract.secType = "STK"
contract.currency = "USD"
contract.exchange = ""
app.reqStatus[210] = 'Sent' # set request status to "sent to TWS"
app.reqContractDetails(210, contract)
print('Requesting IBM contract details:')
contract.symbol = "IBM"
app.reqStatus[211] = 'Sent'
app.reqContractDetails(211, contract)
print('Requesting IBM contract details:')
contract.symbol = "GE"
app.reqStatus[212] = 'Sent'
app.reqContractDetails(212, contract)
print('Requesting IBM contract details:')
contract.symbol = "GM"
app.reqStatus[213] = 'Sent'
app.reqContractDetails(213, contract)
print('Requesting IBM contract details:')
contract.symbol = "BAC"
app.reqStatus[214] = 'Sent'
app.reqContractDetails(214, contract)
i = 0
while i < 100: # exit loop after 10 sec (100 x time.sleep(0.1)
i = i+1
for reqId in app.reqStatus:
if app.reqStatus[reqId] == 'End':
for contractDetails in app.reqData[reqId]:
print("ContractDetails. ReqId:", reqId, contractDetails.summary.symbol,
contractDetails.summary.secType, "ConId:", contractDetails.summary.conId,
"@", contractDetails.summary.exchange)
app.reqStatus[reqId] = 'Processed'
time.sleep(0.1)
app.done = True # this stops app.run() loop
if __name__ == "__main__":
main()
는 귀하의 의견 주셔서 너무 감사합니다. 나는 그것을 시도하고 싶어하지만 어떤 이유로 나는 "server error"msg를 얻고 있으며이 순간 TWS에 로그인 할 수 없다. 일단 내가 연결하고 코드를 시험해 볼 수있게되면 이것을 대답으로 표시 할 것입니다. 감사. –
edemo/demouser를 사용하여 로그인하여 테스트 할 수 있습니다. 그게 내가 한 짓이야. 나는 실제 계정이나 데모 계정을 암시하는 7496을 사용하고 있음을 알고 있습니다. 데모 또는 페이퍼 어카운트를 가지고 테스트 해보는 것이 좋습니다 (일반적으로 용지는 포트 7497 임). 코드가있는 – brian
: self.done = True, Run run breaks. 및 오류 발생 : thread-1 : 예외, _recvAllMsg의 줄 113, buf = self.socket.recv (4096) AttributeError : 'NoneType'개체에 'recv'특성이 없습니다. 나는 그것이 .disconnection으로 인한 것이라고 생각했다. 같은 문제가 보이십니까? 어떤 방법으로 안전하게 연결을 끊고 프로그램을 종료 할 수 있습니까? 감사. –