def test_readFields(self): text1 = "ABCD" text2 = "123" msg = comm.make_msg(comm.make_field(text1) + comm.make_field(text2)) (size, text, rest) = comm.read_msg(msg) fields = comm.read_fields(text) self.assertEqual(len(fields), 2, "incorrect number of fields") self.assertEqual(fields[0].decode(), text1) self.assertEqual(fields[1].decode(), text2)
def test_make_field(self): text = "ABCD" field = comm.make_field(text) self.assertEqual(field[-1], "\0", "terminator not good") self.assertEqual(len(field[0:-1]), len(text), "payload size not good") self.assertEqual(field[0:-1], text, "payload not good")
def make_fields(self): flds = OrderCondition.make_fields(self) + \ [comm.make_field(self.isMore), comm.make_field(self.valueToString()), ] return flds
def make_fields(self): flds = OrderCondition.make_fields(self) + \ [comm.make_field(self.secType), comm.make_field(self.exchange), comm.make_field(self.symbol)] return flds
def make_fields(self): flds = [] flds.append( comm.make_field("a" if self.isConjunctionConnection else "o")) return flds
def make_fields(self): flds = ContractCondition.make_fields(self) + \ [comm.make_field(self.triggerMethod), ] return flds
def make_fields(self): flds = OperatorCondition.make_fields(self) + \ [comm.make_field(self.conId), comm.make_field(self.exchange), ] return flds
def send_msg(self, msg): """Mock send to ib by interpreting and placing on receive queue. Args: msg: message to be sent (i.e., interpreted and queued) """ logger.debug('entered with message %s', msg) (size, msg2, buf) = read_msg(msg) logger.debug('size, msg, buf: %d, %s, %s ', size, msg2, buf) fields = read_fields(msg2) logger.debug('fields: %s', fields) recv_msg = b'' ####################################################################### # get version and connect time (special case - not decode able) ####################################################################### if msg == b'API\x00\x00\x00\x00\tv100..157': current_dt = datetime.now( tz=timezone(offset=timedelta(hours=5))).\ strftime('%Y%m%d %H:%M:%S') # recv_msg = b'\x00\x00\x00\x1a157\x0020210301 23:43:23 EST\x00' recv_msg = b'\x00\x00\x00\x1a157\x00' \ + current_dt.encode('utf-8') + b' EST\x00' ####################################################################### # reqId (get next valid requestID) # b'\x00\x00\x00\x0871\x002\x000\x00\x00' ####################################################################### elif int(fields[0]) == OUT.START_API: logger.info('startAPI detected') # recv_msg = b'\x00\x00\x00\x069\x001\x001\x00' if self.reqId_timeout: # if testing timeout case recv_msg = make_msg('0') # simulate timeout else: # build the normal next valid id message recv_msg = make_msg( make_field(IN.NEXT_VALID_ID) + make_field('1') + make_field('1')) logger.debug('recv_msg: %s', recv_msg) ####################################################################### # Handle special test cases for request disconnect and timeout ####################################################################### elif self.simulate_request_disconnect: # if testing timeout case time.sleep(2) # allow some time for request to get into wait loop recv_msg = b'' # simulate disconnect elif self.simulate_request_timeout: recv_msg = make_msg('0') # simulate timeout ####################################################################### # reqMatchingSymbols ####################################################################### elif int(fields[0]) == OUT.REQ_MATCHING_SYMBOLS: logger.info('reqMatchingSymbols detected') reqId = int(fields[1]) pattern = fields[2].decode(errors='backslashreplace') logger.debug('pattern: %s', pattern) # construct start of receive message for wrapper build_msg = make_field(IN.SYMBOL_SAMPLES) + make_field(reqId) # find pattern matches in mock contract descriptions symbol_starts_with_pattern = \ self.contract_descriptions['symbol'].map( lambda symbol: symbol.startswith(pattern)) match_descs = \ self.contract_descriptions[symbol_starts_with_pattern] # match_descs = self.contract_descriptions.loc[ # self.contract_descriptions['symbol'].str. # startswith(pattern)] # limit the number found as ib does num_found = min(self.MAX_CONTRACT_DESCS_RETURNED, match_descs.shape[0]) # add the number of descriptions to the receive message build_msg = build_msg + make_field(num_found) for i in range(num_found): build_msg = build_msg \ + make_field(match_descs.iloc[i].conId) \ + make_field(match_descs.iloc[i].symbol) \ + make_field(match_descs.iloc[i].secType) \ + make_field(match_descs.iloc[i].primaryExchange) \ + make_field(match_descs.iloc[i].currency) \ + make_field(len(match_descs.iloc[i].derivativeSecTypes)) for dvt in match_descs.iloc[i].derivativeSecTypes: build_msg = build_msg + make_field(dvt) recv_msg = make_msg(build_msg) ####################################################################### # reqContractDetails ####################################################################### elif int(fields[0]) == OUT.REQ_CONTRACT_DATA: logger.info('reqContractDetails detected') version = int(fields[1]) reqId = int(fields[2]) conId = int(fields[3]) # construct start of receive message for wrapper start_msg = make_field(IN.CONTRACT_DATA) \ + make_field(version) \ + make_field(reqId) # find pattern matches in mock contract descriptions # fow now, just conId match_descs = self.contract_descriptions.loc[ self.contract_descriptions['conId'] == conId] for i in range(len(match_descs)): build_msg = start_msg \ + make_field(match_descs.iloc[i].symbol) \ + make_field(match_descs.iloc[i].secType) \ + make_field(match_descs.iloc[i]. lastTradeDateOrContractMonth) \ + make_field(match_descs.iloc[i].strike) \ + make_field(match_descs.iloc[i].right) \ + make_field(match_descs.iloc[i].exchange) \ + make_field(match_descs.iloc[i].currency) \ + make_field(match_descs.iloc[i].localSymbol) \ + make_field(match_descs.iloc[i].marketName) \ + make_field(match_descs.iloc[i].tradingClass) \ + make_field(match_descs.iloc[i].conId) \ + make_field(match_descs.iloc[i].minTick) \ + make_field(match_descs.iloc[i].mdSizeMultiplier) \ + make_field(match_descs.iloc[i].multiplier) \ + make_field(match_descs.iloc[i].orderTypes) \ + make_field(match_descs.iloc[i].validExchanges) \ + make_field(match_descs.iloc[i].priceMagnifier) \ + make_field(match_descs.iloc[i].underConId) \ + make_field(match_descs.iloc[i].longName) \ + make_field(match_descs.iloc[i].primaryExchange) \ + make_field(match_descs.iloc[i].contractMonth) \ + make_field(match_descs.iloc[i].industry) \ + make_field(match_descs.iloc[i].category) \ + make_field(match_descs.iloc[i].subcategory) \ + make_field(match_descs.iloc[i].timeZoneId) \ + make_field(match_descs.iloc[i].tradingHours) \ + make_field(match_descs.iloc[i].liquidHours) \ + make_field(match_descs.iloc[i].evRule) \ + make_field(match_descs.iloc[i].evMultiplier) \ + make_field(match_descs.iloc[i].secIdListCount) for tv in match_descs.iloc[i].secIdList: build_msg += make_field(tv) build_msg += make_field(match_descs.iloc[i].aggGroup) \ + make_field(match_descs.iloc[i].underSymbol) \ + make_field(match_descs.iloc[i].underSecType) \ + make_field(match_descs.iloc[i].marketRuleIds) \ + make_field(match_descs.iloc[i].realExpirationDate) \ + make_field(match_descs.iloc[i].stockType) recv_msg = make_msg(build_msg) self.msg_rcv_q.put(recv_msg, timeout=5) build_msg = make_field(IN.CONTRACT_DATA_END) \ + make_field(version) \ + make_field(reqId) recv_msg = make_msg(build_msg) ####################################################################### # queue the message to be received ####################################################################### self.msg_rcv_q.put(recv_msg, timeout=5)