def _get_ib_futures_contract(self, futures_contract_object): """ Return a complete and unique IB contract that matches futures_contract_object This is expensive so not called directly, only by ib_futures_contract which does caching :param futures_contract_object: contract, containing instrument metadata suitable for IB :return: a single ib contract object """ # Convert to IB world instrument_object_with_metadata = futures_contract_object.instrument ibcontract = ib_futures_instrument(instrument_object_with_metadata) # Register the contract to make logging and error handling cleaner self.add_contract_to_register( ibcontract, log_tags=dict(instrument_code=instrument_object_with_metadata. instrument_code, contract_date=futures_contract_object.date)) # The contract date might be 'yyyymm' or 'yyyymmdd' contract_day_passed = futures_contract_object.contract_date.is_day_defined( ) if contract_day_passed: ## Already have the expiry contract_date = futures_contract_object.contract_date else: ## Don't have the expiry so lose the days at the end so it's just 'YYYYMM' contract_date = str(futures_contract_object.contract_date)[:6] ibcontract.lastTradeDateOrContractMonth = contract_date ## We allow multiple contracts in case we have 'yyyymm' and not specified expiry date for VIX ibcontract_list = self.ib_get_contract_chain(ibcontract) if len(ibcontract_list) == 0: ## No contracts found return missing_contract if len(ibcontract_list) == 1: ## OK no hassle, only one contract no confusion resolved_contract = ibcontract_list[0] else: ## It might be a contract with weekly expiries (probably VIX) ## We need to find the right one try: resolved_contract = resolve_multiple_expiries( ibcontract_list, instrument_object_with_metadata) except Exception as exception: self.log.warn( "%s could not resolve contracts: %s" % (str(instrument_object_with_metadata), exception.args[0])) return missing_contract return resolved_contract
def _get_vanilla_ib_futures_contract( self, futures_instrument_with_ib_data: futuresInstrumentWithIBConfigData, contract_date): """ Return a complete and unique IB contract that matches contract_object_with_ib_data This is expensive so not called directly, only by ib_futures_contract which does caching :param contract_object_with_ib_data: contract, containing instrument metadata suitable for IB :return: a single ib contract object """ # The contract date might be 'yyyymm' or 'yyyymmdd' ibcontract = ib_futures_instrument(futures_instrument_with_ib_data) contract_day_passed = contract_date.is_day_defined() if contract_day_passed: # Already have the expiry pass else: # Don't have the expiry so lose the days at the end so it's just # 'YYYYMM' contract_date = str(contract_date.date_str)[:6] ibcontract.lastTradeDateOrContractMonth = contract_date # We allow multiple contracts in case we have 'yyyymm' and not # specified expiry date for VIX ibcontract_list = self.ib_get_contract_chain(ibcontract) if len(ibcontract_list) == 0: # No contracts found return missing_contract if len(ibcontract_list) == 1: # OK no hassle, only one contract no confusion resolved_contract = ibcontract_list[0] else: # It might be a contract with weekly expiries (probably VIX) # We need to find the right one try: resolved_contract = resolve_multiple_expiries( ibcontract_list, futures_instrument_with_ib_data) except Exception as exception: self.log.warn( "%s could not resolve contracts: %s" % (str(futures_instrument_with_ib_data), exception.args[0])) return missing_contract return resolved_contract