def test_ibgw_restart(ib_docker): subprocess.check_output( ['docker', 'container', 'stop', ib_docker]).decode().strip() subprocess.check_output( ['docker', 'container', 'start', ib_docker]).decode().strip() ib = IB() wait = 60 while not ib.isConnected(): try: IB.sleep(1) ib.connect('localhost', 4002, clientId=999) except: pass wait -= 1 if wait <= 0: break contract = Forex('EURUSD') bars = ib.reqHistoricalData( contract, endDateTime='', durationStr='30 D', barSizeSetting='1 hour', whatToShow='MIDPOINT', useRTH=True) # convert to pandas dataframe: df = util.df(bars) print(df)
class IbGateway: """Interactive Brokers functions to fetch data""" def __init__(self, host, port, clientId=0): self.ib_gateway = IB() self.ib_gateway.connect(host, port, clientId=clientId) def fundamental_data(self, contract): """Load fundamental data from Interactive Brokers""" ib_contract = Contract(**contract) fundamental_data = self.ib_gateway.reqFundamentalData( ib_contract, reportType="ReportsFinStatements") return xmltodict.parse(fundamental_data) def flush(self, tablename): """Remove all data from the table""" def ipmort_data(self, tablename, data): """Write data into the table""" def ping(self): """Pings Interactive Brokers gateway""" return self.ib_gateway.isConnected() def disconnect(self): """Disconnect from Interactive Brokers""" self.ib_gateway.disconnect()
def ping(): def timeout_handler(signum, frame): signal.alarm(0) raise TimeoutError('IB gateway timed out, please check your account & password') signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(120) ib = IB() while not ib.isConnected(): try: IB.sleep(1) ib.connect('localhost', 4001, clientId=1) except (ConnectionRefusedError, OSError) as e: if type(e) is TimeoutError: raise e logging.warning('Still waiting gateway connection..({})'.format(e)) ib.disconnect()
class Window(qt.QWidget): def __init__(self, host, port, clientId): qt.QWidget.__init__(self) self.edit = qt.QLineEdit('', self) self.edit.editingFinished.connect(self.add) self.table = TickerTable() self.connectButton = qt.QPushButton('Connect') self.connectButton.clicked.connect(self.onConnectButtonClicked) layout = qt.QVBoxLayout(self) layout.addWidget(self.edit) layout.addWidget(self.table) layout.addWidget(self.connectButton) self.connectInfo = (host, port, clientId) self.ib = IB() self.ib.pendingTickersEvent += self.table.onPendingTickers def add(self, text=''): text = text or self.edit.text() if text: contract = eval(text) if (contract and self.ib.qualifyContracts(contract) and contract not in self.table): ticker = self.ib.reqMktData(contract, '', False, False, None) self.table.addTicker(ticker) self.edit.setText(text) def onConnectButtonClicked(self, _): if self.ib.isConnected(): self.ib.disconnect() self.table.clearTickers() self.connectButton.setText('Connect') else: self.ib.connect(*self.connectInfo) self.ib.reqMarketDataType(2) self.connectButton.setText('Disonnect') for symbol in ('EURUSD', 'USDJPY', 'EURGBP', 'USDCAD', 'EURCHF', 'AUDUSD', 'NZDUSD'): self.add(f"Forex('{symbol}')") self.add("Stock('TSLA', 'SMART', 'USD')") def closeEvent(self, ev): asyncio.get_event_loop().stop()
class Window(QWidget): def __init__(self, host, port, clientId): QWidget.__init__(self) self.edit = QLineEdit('', self) self.edit.editingFinished.connect(self.add) self.connectButton = QPushButton('Connect') self.connectButton.clicked.connect(self.onConnectButtonClicked) layout = QVBoxLayout(self) layout.addWidget(self.edit) layout.addWidget(self.connectButton) self.graph = TickerGraph(self, width=5, height=4) self.graph.move(0, 0) layout.addWidget(self.graph) self.connectInfo = (host, port, clientId) self.ib = IB() def add(self, text=''): text = text #or self.edit.text() if text: contract = eval(text) if (contract and self.ib.qualifyContracts(contract)): data = self.ib.reqHistoricalData(contract, endDateTime='', durationStr='30 D', barSizeSetting='4 hours', whatToShow='MIDPOINT', useRTH=True) df = util.df(data) print(df["close"]) self.graph.plot(df["close"]) self.edit.setText(text) def onConnectButtonClicked(self, _): if self.ib.isConnected(): self.ib.disconnect() self.connectButton.setText('Connect') else: self.ib.connect(*self.connectInfo) self.connectButton.setText('Disconnect') self.add(f"Forex('" + str(self.edit.text()) + "')") def closeEvent(self, ev): asyncio.get_event_loop().stop()
def test_ibgw_interactive(ib_docker): ib = IB() wait = 120 while not ib.isConnected(): try: IB.sleep(1) ib.connect('localhost', 4002, clientId=999) except: pass wait -= 1 if wait <= 0: break contract = Forex('EURUSD') bars = ib.reqHistoricalData( contract, endDateTime='', durationStr='30 D', barSizeSetting='1 hour', whatToShow='MIDPOINT', useRTH=True) # convert to pandas dataframe: df = util.df(bars) print(df)
def ping(): def timeout_handler(signum, frame): signal.alarm(0) raise TimeoutError( 'IB gateway timed out, please check your account & password') signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(120) ib = IB() pingClientId = int(os.environ['IB_GATEWAY_PING_CLIENT_ID']) maxRetryCount = int(os.environ['ibAccMaxRetryCount']) retryCount = 0 while not ib.isConnected(): try: IB.sleep(1) ib.connect('localhost', 4001, clientId=pingClientId) except (ConnectionRefusedError, OSError) as e: retryCount += 1 if retryCount >= 30: raise ValueError("Invalid ib account") logging.warning('Still waiting gateway connection..({})'.format(e)) ib.disconnect()
class BrokerConnection(metaclass=Singleton): def __init__(self): self.ib = IB() def connect(self, host, port, client_id, callback=None): self.ib.connect(host, port, clientId=client_id) if callback: self.ib.connectedEvent += callback def disconnect(self): self.ib.disconnect() def isConnected(self): return self.ib.isConnected() def positions(self): return [ pos for pos in self.ib.positions() if pos.contract.secType == 'OPT' ] def reqMatchingSymbols(self, text_to_search): ''' Function IBApi::EClient::reqMatchingSymbols is available to search for stock contracts. The input can be either the first few letters of the ticker symbol, or for longer strings, a character sequence matching a word in the security name. https://interactivebrokers.github.io/tws-api/matching_symbols.html ''' return self.ib.reqMatchingSymbols(text_to_search) def getOptionChainContracts(self, contract): chain = self.ib.reqSecDefOptParams(contract.symbol, contract.exchange, contract.secType, contract.conId) qChain = self.ib.qualifyContracts(chain) #return util.df(qChain) return qChain
def init_ticker(self): self.ticker = self.ticker_in.text().upper() self.ticker_in.setText(self.ticker) # self.spot = Ydata_feed.get_latest(self.ticker) # self.spot_in.setText(str(self.spot['close'])) # if spot == None: print(self.ticker) self.spot = data_feed.get_data( self.ticker, 'STK', 'SMART', 'USD', duration="1 D", enddate=datetime.today().strftime("%Y%m%d %H:%M:%S %Z"), barsize='1 day') sleep(5) self.spot_in.setText(str(self.spot['close'][0])) self.div_in.setText(str(0)) # self.div_in.setText(str(Ydata_feed.get_div_yield(ticker))) exps(self.ticker) with open(tmp_file, newline='') as f: reader = csv.reader(f) self.exp_list = (datetime.strptime(i, "%Y%m%d") for i in list(reader)[0]) self.formatted_exp_list = list( (datetime.strftime(i, "%m-%d-%Y") for i in self.exp_list)) print(list(self.formatted_exp_list), len(list(self.formatted_exp_list))) d0 = datetime.today() #.strftime('%Y%m%d') dds = [] x = 0 for iii in self.formatted_exp_list: d1 = datetime.strptime(iii, '%m-%d-%Y') #.strftime('%Y%m%d') delta = d1 - d0 dd = delta.days dds.append(str(dd)) self.formatted_exp_list[x] = str( self.formatted_exp_list[x]) + " [" + str(dd) + "] " x += 1 print(dds, len(dds)) print(self.formatted_exp_list) self.comboBox_2.addItems(self.formatted_exp_list) for row in self.row_dic: # print(row,self.row_dic[row]) self.row_dic[row]['exp'].addItems(self.formatted_exp_list) if self.fill_pos == None: self.fill_pos = QPushButton('Fill Positions', self) self.horizontalLayout.addWidget(self.fill_pos) self.fill_pos.clicked.connect(self.fill_positions) ib = IB().connect('127.0.0.1', port, clientId=20) ib.disconnect() ib.waitOnUpdate(timeout=0.1) print('disconnected') print(ib.isConnected())
class Window(qt.QWidget): def __init__(self, host, port, clientId): qt.QWidget.__init__(self) self.vxxbLabel = qt.QLabel('VXXB') self.vxxbButton = qt.QPushButton('VXXB') self.tltLabel = qt.QLabel('TLT') self.tltButton = qt.QPushButton('TLT') self.gldLabel = qt.QLabel('GLD') self.gldButton = qt.QPushButton('GLD') self.vxxbButton.clicked.connect(self.onVXXBButtonClicked) self.gldButton.clicked.connect(self.onGLDButtonClicked) self.tltButton.clicked.connect(self.onTLTButtonClicked) self.pricedic = {} # self.edit = qt.QLineEdit('', self) # self.edit.editingFinished.connect(self.add) self.table = TickerTable() self.connectButton = qt.QPushButton('Connect') self.connectButton.clicked.connect(self.onConnectButtonClicked) layout = qt.QGridLayout(self)#qt.QVBoxLayout(self) layout.addWidget(self.vxxbLabel,0,0,1,2) layout.addWidget(self.vxxbButton,1,0,1,2) layout.addWidget(self.tltLabel,0,2,1,2) layout.addWidget(self.tltButton,1,2,1,2) layout.addWidget(self.gldLabel,0,4,1,2) layout.addWidget(self.gldButton,1,4,1,2) # layout.addWidget(self.edit) layout.addWidget(self.table,2,0,6,6) layout.addWidget(self.connectButton,9,2,1,2) self.connectInfo = (host, port, clientId) self.ib = IB() self.ib.pendingTickersEvent += self.table.onPendingTickers self.ib.pendingTickersEvent += self.onPendingTickersForLabels def add(self, contract): if (contract and self.ib.qualifyContracts(contract) and contract not in self.table): ticker = self.ib.reqMktData(contract, '', False, False, None) self.table.addTicker(ticker) def onConnectButtonClicked(self, _): if self.ib.isConnected(): self.ib.disconnect() self.table.clearTickers() self.connectButton.setText('Connect') else: self.ib.connect(*self.connectInfo) self.connectButton.setText('Disonnect') self.vxxb = Stock('VXXB',exchange='SMART') self.ib.qualifyContracts(self.vxxb) self.table.vxxbticker = self.ib.reqMktData(self.vxxb, '', False, False, None) self.tlt = Stock('TLT',exchange='ARCA') self.ib.qualifyContracts(self.tlt) self.table.tltticker = self.ib.reqMktData(self.tlt, '', False, False, None) self.gld = Stock('GLD',exchange='ARCA') self.ib.qualifyContracts(self.gld) self.table.gldticker = self.ib.reqMktData(self.gld, '', False, False, None) def closeEvent(self, ev): asyncio.get_event_loop().stop() def onPendingTickersForLabels(self, tickers): for ticker in tickers: if type(getattr(ticker,'contract'))==Stock: if ticker.contract.symbol=='VXXB': self.vxxbprice = ticker.marketPrice() self.vxxbLabel.setText('{0:0.2f}'.format(self.vxxbprice)) self.table.vxxbprice = self.vxxbprice self.pricedic['VXXB'] = self.vxxbprice # print('vxxb:'+str(ticker.marketPrice())) elif ticker.contract.symbol=='GLD': self.gldprice = ticker.marketPrice() self.gldLabel.setText('{0:0.2f}'.format(self.gldprice)) self.table.gldprice=self.gldprice self.pricedic['GLD'] = self.gldprice # print('gld:'+str(ticker.marketPrice())) else: self.tltprice = ticker.marketPrice() self.tltLabel.setText('{0:0.2f}'.format(self.tltprice)) self.table.tltprice=self.tltprice self.pricedic['TLT'] = self.tltprice # print('tlt:'+str(ticker.marketPrice())) def prepareOptionContract(self,stockcontract): contractPrice = self.pricedic[stockcontract.symbol] chains = self.ib.reqSecDefOptParams(stockcontract.symbol, '', stockcontract.secType,stockcontract.conId) chain = next(c for c in chains if c.exchange == 'SMART') # print(chain) strikes = sorted([strike for strike in chain.strikes if contractPrice - 2 < strike < contractPrice + 2]) expirations = sorted(exp for exp in chain.expirations)[:2] contracts = [Option(stockcontract.symbol, expiration, strike, 'P','SMART') for expiration in expirations for strike in strikes] # print(contracts) self.ib.qualifyContracts(*contracts) for ac in contracts: self.add(contract=ac) def onVXXBButtonClicked(self, _): if self.ib.isConnected(): self.table.clearTickers() self.prepareOptionContract(self.vxxb) self.table.symbolofticker = 'VXXB' def onGLDButtonClicked(self, _): if self.ib.isConnected(): self.table.clearTickers() self.prepareOptionContract(self.gld) self.table.symbolofticker = 'GLD' def onTLTButtonClicked(self, _): print('TLT') if self.ib.isConnected(): self.table.clearTickers() self.prepareOptionContract(self.tlt) self.table.symbolofticker = 'TLT'
async def asyncioJobGetRecentData(ib: IB, mydb: database.tradingDB, qc, additionalArgs={}): """get recent historical data for the contract specified in qc""" success = False a = ( f'attempting to get recent historical data chunk: {qc.symbol}, {qc.currency}' ) _logger.info(a) if not (isinstance(ib, IB) and ib.isConnected()): return success conId = qc.conId tableORM = utils.getValueFromDataFrame( mydb.MarketDataInfoTableDataFrame, whereColumn='conId', whereValue=conId, getColumn='tableORM') lastDateTimeOnDiskUTC = getLastDateTimeOnDiskUTC( mydb, tableORM.__table__) earliestDateTimeUTCAccordingToIB = getEarliestDateTimeUTCFromDataFrame( mydb, conId) # if there is no earliestDateTime according to IB, it makes no sense to try to retrieve data if pd.isnull(earliestDateTimeUTCAccordingToIB): success = True return (success) # duration time delta durationMaximumPandasTimeDeltaDefault = pd.Timedelta(weeks=4) # bar size delta barSizePandasTimeDeltaDefault = pd.Timedelta(minutes=1) # override defaults if values have been passed in additionalArgs durationMaximumPandasTimeDelta = additionalArgs.get( 'durationMaximumPandasTimeDelta', durationMaximumPandasTimeDeltaDefault) barSizePandasTimeDelta = additionalArgs.get( 'barSizePandasTimeDelta', barSizePandasTimeDeltaDefault) timeOutTimeHistoricalBars = additionalArgs.get( 'timeOutTimeHistoricalBars', 600) # we wish to get the most recent historical data # the end time is therefore utcnow nowUTC = pd.to_datetime( pd.datetime.utcnow()).tz_localize('UTC').floor('1 Min') endDateTimeUTC = nowUTC # the earliest possible start date time is endtime minus the maximum allowed time delta earliestStartDateTimeUTC = endDateTimeUTC - durationMaximumPandasTimeDelta # by default, the startDateTime is this earliest possible datetime startDateTimeUTC = earliestStartDateTimeUTC # if we found a lastDateTime on Disk, the startDateTime is modified if not pd.isnull(lastDateTimeOnDiskUTC): startDateTimeUTC = max(lastDateTimeOnDiskUTC, earliestStartDateTimeUTC) pass # for some reason, it is possible that the time on disk is in the future. # we therefore determine the startDateTime as the minimum between the startDateTime as calculated before # and the endDateTime startDateTimeUTC = min(startDateTimeUTC, endDateTimeUTC) # we can now calculate the time delta that we actually want to fetch durationPandasTimeDelta = endDateTimeUTC - startDateTimeUTC # define the objects used to calculate the IB strings for time deltas and bar size settings dTD = utils.CTimeDelta(durationPandasTimeDelta) bTD = utils.CTimeDelta(barSizePandasTimeDelta) # log info about the start of bar data retrieval tStart2 = pd.datetime.now() if not pd.isnull(earliestDateTimeUTCAccordingToIB): a = ( f'attempting to get recent historical data chunk: {qc.symbol}, {qc.currency}; startDT: {startDateTimeUTC} (durationString: {dTD.IB_Duration_String}); time: {tStart2}' ) else: a = ( f'attempting to get recent historical data chunk: {qc.symbol}, {qc.currency}; not performed because earliestDateTime is not given by IB; time: {tStart2}' ) pass _logger.info(a) # get the historical data bars # only get bars if the last value on disk is not utcnow bars = None timeOutOccured = None if not (nowUTC == lastDateTimeOnDiskUTC): [bars, timeOutOccured ] = getHistoricalDataBars(ib, qc, endDateTime='', durationStr=dTD.IB_Duration_String, barSizeSetting=bTD.IB_Bar_Size_String, timeOutTime=timeOutTimeHistoricalBars) if timeOutOccured is not None and timeOutOccured: a = (f'Timeout while requesting historical bars for contract {qc}') _logger.warn(a) pass # calculate the number of rows that have been retrieved nRows = 0 if bars is not None: nRows = len(bars) pass # persist result on disk # upsert the data persistMarketDataBarsOnDisk(bars, mydb, tableORM.__table__, doCorrection=True) # calculate the total number of rows on disk ssn = mydb.Session() nRowsTotal = ssn.query(tableORM.__table__).count() ssn.close() # log info about the end of bar data retrieval tEnd2 = pd.datetime.now() tDelta2 = tEnd2 - tStart2 a = ( f'finished to get recent historical data chunk: {qc.symbol}, {qc.currency}; startDT: {startDateTimeUTC} (durationString: {dTD.IB_Duration_String}); time: {tEnd2}; elapsedTime: {tDelta2}; rows: {nRows}; rowsTotal: {nRowsTotal}' ) _logger.info(a) success = True ssn.close() return success
class IBDataService: ip = "127.0.0.1" port = 4002 # 4001 for real trading def __init__(self): self.uid = random.randint(1000, 10000) print(f"init - UID: {str(self.uid)}") self.ib = IB() self.connect() def connect(self, *args): print(f"connectToIB - UID: {str(self.uid)}") if self.ib.isConnected() is False: print("CONNECTING ...") self.ib.connect("127.0.0.1", 4002, clientId=self.uid) print("CONNECTED") def disconnect(self, *args): print(f"connectToIB - UID: {str(self.uid)}") if self.ib.isConnected(): print("DISCONNECTING ...") self.ib.disconnect() print("DISCONNECTED ...") def getContractDetail(self, contract): print(f"getContractDetail - UID: {str(self.uid)}") data = self.ib.reqContractDetails(contract) # print(data) if len(data) > 0: return data[0] else: return None def getFuturesContractDetail(self, contract): print(f"getFuturesContractDetail - UID: {str(self.uid)}") data = self.ib.reqContractDetails(contract) if len(data) > 0: return data else: return None def getHistoricalData(self, contract, endDate="", duration="1 Y", barSize="1 day", price="MIDPOINT"): print(f"getHistoricalData - UID: {str(self.uid)}") data = self.ib.reqHistoricalData(contract, endDate, duration, barSize, price, 1, 1, False, []) return data async def startRealtimeData(self, contract, method): print(f"startRealtimeData - UID: {str(self.uid)}") self.ib.reqMktData(contract, "233", False, False) ticker = self.ib.reqTickByTickData(contract, TickDataType.LAST.value) ticker.updateEvent += method print(f"ENDS - startRealtimeData - UID: {str(self.uid)}") def stopRealtimeData(self, contract): print(f"stopRealtimeData - UID: {str(self.uid)}") self.ib.cancelMktData(contract) self.ib.cancelTickByTickData(contract, TickDataType.LAST.value) print(f"ENDS - stopRealtimeData - UID: {str(self.uid)}")
class IbManager(object): log_file = 'ib_manager' def __init__(self, ip: str, port: int, client_id: int): self._ib = IB() self._ib_ip: str = ip self._ib_port: int = port self._client_id: int = client_id self._subscribed_mkt_contracts: List[str] = [] self._subscribed_mkt_depth_contracts: List[str] = [] self._log: Log = Log.create(Log.path(self.log_file)) self._logger = self._log.get_logger('ibmanager') self._recorder: Recorder = Recorder(self._log) self._market_recorder: MarketRecorder = MarketRecorder( self._ib, self._recorder) self._account_recorder: AccountRecorder = AccountRecorder( self._ib, self._recorder) self._keep_connection_task: asyncio.Task = None self._ib.connectedEvent += self.on_ib_connected self._ib.disconnectedEvent += self.on_ib_disconnected self._reconnect_flag: bool = False def on_ib_connected(self) -> None: self._logger.info('connected with ib') self._reconnect_flag = False self._recover_subscriptions() def on_ib_disconnected(self) -> None: self._logger.warning('disconnected with ib') self._reconnect_flag = True if self._keep_connection_task is None: self._keep_connection_task = asyncio.create_task(self._reconnect()) async def _reconnect(self) -> None: while self._reconnect_flag: await asyncio.sleep(20) self._logger.info('try to reconnect ib gateway') await self.initialize() self._keep_connection_task = None def _recover_subscriptions(self) -> None: for contract in self._subscribed_mkt_contracts: self._logger.info(f'recover subscribe {str(contract)}') self._ib.reqMktData(contract) for contract in self._subscribed_mkt_depth_contracts: self._logger.info(f'recover subscribe depth {str(contract)}') self._ib.reqMktDepth(contract) async def initialize(self): if self._ib.isConnected(): return try: await self._ib.connectAsync(self._ib_ip, self._ib_port, clientId=self._client_id) accounts = self._ib.managedAccounts() if len(accounts) > 0: self._account_recorder.update_account(accounts[0]) self.update_account() except Exception: pass def update_account(self): self._ib.reqAccountSummaryAsync() async def find_symbols(self, pattern: str) -> List[str]: symbols = await self._ib.reqMatchingSymbolsAsync(pattern) contracts = [symbol.contract.nonDefaults() for symbol in symbols] return contracts def make_contract(self, **kwargs) -> Contract: return Contract.create(**kwargs) def sub_market(self, contract: Contract) -> str: if contract in self._subscribed_mkt_contracts: return 'already subscribe {}'.format(str(contract)) self._subscribed_mkt_contracts.append(contract) self._ib.reqMktData(contract) return 'subscribe {} success'.format(str(contract)) def unsub_market(self, contract: Contract) -> str: if contract not in self._subscribed_mkt_contracts: return 'not ever subscribe {}'.format(str(contract)) self._subscribed_mkt_contracts.append(contract) self._ib.cancelMktData(contract) return 'unsubscribe {} success'.format(str(contract)) def sub_market_depth(self, contract: Contract) -> str: if contract in self._subscribed_mkt_depth_contracts: return 'already subscribe depth {}'.format(str(contract)) self._subscribed_mkt_depth_contracts.append(contract) self._ib.reqMktDepth(contract) return 'subscribe depth {} success'.format(str(contract)) def unsub_market_depth(self, contract: Contract) -> str: if contract not in self._subscribed_mkt_depth_contracts: return 'not ever subscribe depth {}'.format(str(contract)) self._subscribed_mkt_contracts.remove(contract) self._ib.cancelMktDepth(contract) return 'unsubscribe depth {} success'.format(str(contract)) def place_order(self, contract: Contract, side: str, size: int, price: float) -> str: trade = self._place_order(contract, side, size, price) return str(trade) def _place_order(self, contract: Contract, side: str, size: int, price: float) -> Trade: side = side.upper() if side not in ('SELL', 'BUY'): return [f'invalid order type: {side}'] price = float(f'{round(float(price), 3):.3f}') order = LimitOrder(side, size, price, tif='GTC') trade = self._ib.placeOrder(contract, order) return trade def cancel_order(self, order_id: int) -> str: order_id = int(order_id) order = Order(orderId=order_id) trade = self._ib.cancelOrder(order) return str(trade) async def orders(self) -> List[str]: orders = await self._ib.reqOpenOrdersAsync() return [str(order) for order in orders] def portfolio(self) -> List[str]: results = self._ib.portfolio() return [str(value) for value in results]
class request(IB): def __init__(self, symbol, temp, client): self.symbol = symbol self.temp = temp instruments = pd.read_csv('instruments.csv').set_index('symbol') self.params = instruments.loc[self.symbol] self.market = str(self.params.market) self.exchange = str(self.params.exchange) self.tick_size = float(self.params.tick_size) self.digits = int(self.params.digits) self.leverage = int(self.params.leverage) self.client = client self.current_date() self._sundays_activation() self.ib = IB() print(self.ib.connect('127.0.0.1', 7497, self.client)) self.connected = self.ib.isConnected() ####### self.get_contract() self.interrumption = False #self.data = self.download_data(tempo=temp, duration='1 D') #self.ib.reqMktData(self.contract, '', False, False); self.ticker = self.ib.ticker(self.contract) ######### #self.ticker = self.ib.reqTickByTickData(self.contract, 'Last', 0) self.bars = self.ib.reqRealTimeBars(self.contract, 5, 'MIDPOINT', False) self.operable = True def operable_schedule(self): if self.weekday == 4 and pd.to_datetime( self.hour).time() > pd.to_datetime('18:00:00').time(): print('%s %s | Today is Friday and Market has Closed!' % (self.date, self.hour)) self.operable = False elif self.weekday == 5: print('%s %s | Today is Saturday and market is not Opened' % (self.date, self.hour)) self.operable = False else: self.operable = True def current_date(self): self.date = datetime.now().strftime('%Y-%m-%d') self.weekday = datetime.now().weekday() self.hour = datetime.now().strftime('%H:%M:%S') def _sundays_activation(self): hour = '18:00:05' if self.weekday == 6: if pd.to_datetime(self.hour).time() < pd.to_datetime(hour).time(): print('Today is Sunday. Bot activation is at 18:00:00') while True: self.current_date() if pd.to_datetime( self.hour).time() >= pd.to_datetime(hour).time(): print('Activation Done') self.send_telegram_message( '%s %s | Bot Activation Done' % (self.date, self.hour)) break def continuous_check_message(self, message): if datetime.now().minute == 0 and datetime.now().second == 0: self.send_telegram_message(message, type='info') def reconnection(self): if self.hour == '23:44:30' or self.hour == '16:59:30': self.interrumption = True self.ib.disconnect() self.connected = self.ib.isConnected() print('%s %s | Ib disconnection' % (self.date, self.hour)) print('Connected: %s' % self.connected) if self.hour == '23:46:00' or self.hour == '18:00:05': self.interrumption = False print('%s %s | Reconnecting...' % (self.date, self.hour)) while not self.connected: try: self.ib.connect('127.0.0.1', 7497, self.client) self.connected = self.ib.isConnected() if self.connected: print('%s %s | Connection reestablished!' % (self.date, self.hour)) print('Requesting Market Data...') self.bars = self.ib.reqRealTimeBars( self.contract, 5, 'MIDPOINT', False) print('Last Close of %s: %.2f' % (self.symbol, self.bars[-1].close)) print('%s Data has been Updated!' % self.symbol) except: print( '%s %s | Connection Failed! Trying to reconnect in 10 seconds...' % (self.date, self.hour)) self.ib.sleep(10) print('%s %s | %s Data has been Updated!' % (self.date, self.hour, self.symbol)) def _local_symbol_selection(self): '''Selects local symbol according to symbol and current date''' current_date = datetime.now().date() # csv file selection according to symbol if self.symbol in ['ES', 'RTY', 'NQ', 'MES', 'MNQ', 'M2K']: contract_dates = pd.read_csv( 'D:/Archivos/futuro/Algorithmics/Codes/My_Bots/Hermes/contract_dates/indexes_globex.txt', parse_dates=True) elif self.symbol in ['YM', 'MYM', 'DAX']: contract_dates = pd.read_csv( 'D:/Archivos/futuro/Algorithmics/Codes/My_Bots/Hermes/contract_dates/indexes_ecbot_dtb.txt', parse_dates=True) elif self.symbol in ['QO', 'MGC']: contract_dates = pd.read_csv( 'D:/Archivos/futuro/Algorithmics/Codes/My_Bots/Hermes/contract_dates/QO_MGC.txt', parse_dates=True) elif self.symbol in ['CL', 'QM']: contract_dates = pd.read_csv( 'D:/Archivos/futuro/Algorithmics/Codes/My_Bots/Hermes/contract_dates/CL_QM.txt', parse_dates=True) else: contract_dates = pd.read_csv( 'D:/Archivos/futuro/Algorithmics/Codes/My_Bots/Hermes/contract_dates/%s.txt' % symbol, parse_dates=True) # Current contract selection according to current date for i in range(len(contract_dates)): initial_date = pd.to_datetime( contract_dates.iloc[i].initial_date).date() final_date = pd.to_datetime( contract_dates.iloc[i].final_date).date() if initial_date <= current_date <= final_date: current_contract = contract_dates.iloc[i].contract break # local symbol selection local = current_contract if self.symbol in [ 'ES', 'RTY', 'NQ', 'MES', 'MNQ', 'M2K', 'QO', 'CL', 'MGC', 'QM' ]: local = '%s%s' % (self.symbol, current_contract) if self.symbol in ['YM', 'ZS']: local = '%s %s' % (self.symbol, current_contract) if self.symbol == 'MYM': local = '%s %s' % (self.symbol, current_contract) if self.symbol == 'DAX': local = 'FDAX %s' % current_contract return local def get_contract(self): if self.market == 'futures': local = self._local_symbol_selection() self.contract = Future(symbol=self.symbol, exchange=self.exchange, localSymbol=local) print( self.ib.reqContractDetails( self.contract)[0].contract.lastTradeDateOrContractMonth) '''expiration = self.ib.reqContractDetails(Future(self.symbol,self.exchange))[0].contract.lastTradeDateOrContractMonth self.contract = Future(symbol=self.symbol, exchange=self.exchange, lastTradeDateOrContractMonth=expiration)''' elif self.market == 'forex': self.contract = Forex(self.symbol) elif self.market == 'stocks': self.contract = Stock(symbol=self.symbol, exchange=self.exchange, currency='USD') def download_data(self, tempo, duration): pr = (lambda market: 'MIDPOINT' if market == 'forex' else 'TRADES')(self.market) historical = self.ib.reqHistoricalData(self.contract, endDateTime='', durationStr=duration, barSizeSetting=tempo, whatToShow=pr, useRTH=False, keepUpToDate=False) return historical def send_telegram_message(self, message, type='trades'): bot_token = '1204313430:AAGonra1LaFhyI1gCVOHsz8yAohJUeFgplo' bot_chatID = '-499850995' if type == 'trades' else '-252750334' url = 'https://api.telegram.org/bot%s/sendMessage?chat_id=%s&text=%s' % ( bot_token, bot_chatID, message) requests.get(url)
class AsyncIBDataProvider(GenericDataProvider): logger = logging.getLogger(__name__) def __init__(self, verbose: int, host: str, port: int, timeout: int, chunk_size: int, id=0, tz='America/New_York', **kwargs): super(AsyncIBDataProvider, self).__init__(self.logger, verbose, tz, chunk_size=chunk_size, **kwargs) self.port = port self.host = host self.timeout = timeout self.keep_alive = False if 'keep_alive' in kwargs: self.keep_alive = kwargs['keep_alive'] self.ib = IB() self.id = id def disconnect(self): self.ib.disconnect() def connect(self): if self.id == 0: id = int(random.uniform(1, 1000)) else: id = self.id self.logger.info( f"IBAsync: {self.host}:{self.port}, timeout={self.timeout}, id={id}" ) self.ib.connect(self.host, self.port, clientId=id, timeout=self.timeout, readonly=True) def _initialize(self): if not self.ib.isConnected(): self.connect() def _finish(self): if not self.keep_alive: self.disconnect() async def _get_data_internal_async(self, symbol_data: SymbolData, **kwargs) -> pd.DataFrame: return self._get_data_internal(symbol_data) def _get_data_internal(self, symbol_data: SymbolData) -> pd.DataFrame: self.logger.info(f"Getting symbol data: {symbol_data}") if symbol_data.timeframe == 'day': symbol, bars = self._get_daily(symbol_data.start, symbol_data.symbol, symbol_data.end) symbol = symbol_data.symbol.split('-')[0] dataframe = self._to_dataframe(bars) elif symbol_data.timeframe == '60min': now = f"{(datetime.now()):%Y-%m-%d %H:%M}" duration = '365 D' if symbol_data.start: diff = datetime.strptime( now, '%Y-%m-%d %H:%M') - datetime.strptime( symbol_data.start, '%Y-%m-%d %H:%M') if diff.days < 365: duration = f"{diff.days} D" symbol, bars = self._get_intraday(symbol_data.symbol, now, duration, '1 hour', symbol_data.rth_only) symbol = symbol_data.symbol.split('-')[0] dataframe = self._to_dataframe(bars, tz_fix=True) elif symbol_data.timeframe == '5min': now = f"{(datetime.now()):%Y-%m-%d %H:%M}" duration = '30 D' if symbol_data.start: diff = datetime.strptime( now, '%Y-%m-%d %H:%M') - datetime.strptime( symbol_data.start, '%Y-%m-%d %H:%M') if diff.days < 30: duration = f"{diff.days} D" symbol, bars = self._get_intraday(symbol_data.symbol, now, duration, '5 mins', symbol_data.rth_only) symbol = symbol_data.symbol.split('-')[0] dataframe = self._to_dataframe(bars, tz_fix=True) elif symbol_data.timeframe == '15min': now = f"{(datetime.now()):%Y-%m-%d %H:%M}" duration = '60 D' if symbol_data.start: diff = datetime.strptime( now, '%Y-%m-%d %H:%M') - datetime.strptime( symbol_data.start, '%Y-%m-%d %H:%M') if diff.days < 60: duration = f"{diff.days} D" symbol, bars = self._get_intraday(symbol_data.symbol, now, duration, '15 mins', symbol_data.rth_only) symbol = symbol_data.symbol.split('-')[0] dataframe = self._to_dataframe(bars, tz_fix=True) else: raise Exception(f"{symbol_data.timeframe} not implemented!") df = dataframe if dataframe.empty: self.logger.warning(f"Got empty df for {symbol_data}") else: df = self._post_process(dataframe, symbol, symbol_data.start, symbol_data.end, symbol_data.timeframe, symbol_data.transform) return df @staticmethod def exctract_symbol(ticker: str, type: str = 'STK', exchange: str = 'ARCA', currency: str = 'USD', expire='', multiplier='') -> tuple: if ticker.count('-') == 4: symbol, type, exchange, currency, multiplier = ticker.split('-') if type.isdigit(): expire = type type = "FUT" elif ticker.count('-') == 3: symbol, type, exchange, currency = ticker.split('-') if type.isdigit(): expire = type type = "FUT" elif ticker.count('-') == 2: if ticker.find('CASH') > -1: symbol, currency, exchange = ticker.split('-') symbol = symbol.replace('.', '') type = 'FX' else: a, b, c = ticker.split('-') if b.isdigit(): type = 'FUT' symbol = a exchange = c expire = b else: symbol = a exchange = b currency = c elif ticker.count('-') == 1: symbol, exchange = ticker.split('-') else: symbol = ticker return type, symbol, exchange, currency, expire, multiplier @staticmethod def parse_contract(ticker): """ Backtrader contract specification (https://www.backtrader.com/docu/live/ib/ib.html): TICKER # Stock type and SMART exchange TICKER-STK # Stock and SMART exchange TICKER-STK-EXCHANGE # Stock TICKER-STK-EXCHANGE-CURRENCY # Stock TICKER-CFD # CFD and SMART exchange TICKER-CFD-EXCHANGE # CFD TICKER-CDF-EXCHANGE-CURRENCY # Stock TICKER-IND-EXCHANGE # Index TICKER-IND-EXCHANGE-CURRENCY # Index TICKER-YYYYMM-EXCHANGE # Future TICKER-YYYYMM-EXCHANGE-CURRENCY # Future TICKER-YYYYMM-EXCHANGE-CURRENCY-MULT # Future TICKER-FUT-EXCHANGE-CURRENCY-YYYYMM-MULT # Future TICKER-YYYYMM-EXCHANGE-CURRENCY-STRIKE-RIGHT # FOP TICKER-YYYYMM-EXCHANGE-CURRENCY-STRIKE-RIGHT-MULT # FOP TICKER-FOP-EXCHANGE-CURRENCY-YYYYMM-STRIKE-RIGHT # FOP TICKER-FOP-EXCHANGE-CURRENCY-YYYYMM-STRIKE-RIGHT-MULT # FOP CUR1.CUR2-CASH-IDEALPRO # Forex TICKER-YYYYMMDD-EXCHANGE-CURRENCY-STRIKE-RIGHT # OPT TICKER-YYYYMMDD-EXCHANGE-CURRENCY-STRIKE-RIGHT-MULT # OPT TICKER-OPT-EXCHANGE-CURRENCY-YYYYMMDD-STRIKE-RIGHT # OPT TICKER-OPT-EXCHANGE-CURRENCY-YYYYMMDD-STRIKE-RIGHT-MULT # OPT :return: """ contract_type, symbol, exchange, currency, expire, multiplier = \ AsyncIBDataProvider.exctract_symbol(ticker) if contract_type == 'FX': return Forex(pair=symbol) if contract_type == 'IND': return Index(symbol, exchange, currency) if contract_type == 'FUT': return Future(symbol, expire, exchange, currency=currency, multiplier=multiplier) else: return Stock(symbol, exchange, currency) def _get_intraday(self, ticker: str, to_date: str, duration: str, barsize: str, rth_only: bool) -> (str, [BarData]): to_dt = datetime.strptime(f"{to_date}", '%Y-%m-%d %H:%M') contract = AsyncIBDataProvider.parse_contract(ticker) whatToShow = 'MIDPOINT' if isinstance(contract, (Forex, CFD, Commodity)) else 'TRADES' bars = self.ib.reqHistoricalData(contract, endDateTime=to_dt, durationStr=duration, barSizeSetting=barsize, whatToShow=whatToShow, useRTH=rth_only, formatDate=2) return contract.symbol, bars def _get_daily(self, from_date: str, ticker: str, to_date: str) -> (str, [BarData]): #TODO: strip HH:MM from start/end dates? from_dt = datetime.strptime(from_date, "%Y-%m-%d") today = datetime.strptime(to_date, "%Y-%m-%d") to_dt = datetime(today.year, today.month, today.day, 23, 59, 59) days = (to_dt - from_dt).days if days > 365: self.logger.warning(f"Historical data is limited to 365 Days. " f"Only requesting for year '{from_dt.year}'") days = 365 to_dt = datetime(from_dt.year, 12, 31, 23, 59, 59) if to_dt > datetime.today(): to_dt = None contract = AsyncIBDataProvider.parse_contract(ticker) whatToShow = 'MIDPOINT' if isinstance(contract, (Forex, CFD, Commodity)) else 'TRADES' # bars = self.ib.reqDailyBars(contract, 2016) bars = self.ib.reqHistoricalData(contract, endDateTime=to_dt, durationStr=F"{days} D", barSizeSetting='1 day', whatToShow=whatToShow, useRTH=True, formatDate=1) return contract.symbol, bars def _to_dataframe(self, bars, tz_fix=False): if tz_fix: data = [{ 'Date': pd.to_datetime( b.date.astimezone(self.tz).replace(tzinfo=None)), 'Open': b.open, 'High': b.high, 'Low': b.low, 'Close': b.close, 'Volume': b.volume } for b in bars] else: data = [{ 'Date': pd.to_datetime(b.date), 'Open': b.open, 'High': b.high, 'Low': b.low, 'Close': b.close, 'Volume': b.volume } for b in bars] if len(data) > 0: return pd.DataFrame(data).set_index('Date') else: return pd.DataFrame() def add_quotes(self, data, ticker): return data
import os import sys import time import logging import json import base64 from ib_insync import ibcontroller from ib_insync import IB from ib_insync.ibcontroller import Watchdog import ib_insync.util as util from updateConfig import updateIbcConfig, updateTwsConfig util.logToConsole(logging.DEBUG) logger = logging.getLogger(name=__name__) twsPort = os.getenv("TWS_PORT", "4001") if __name__ == "__main__": ib = IB() ib.connect('127.0.0.1', twsPort, clientId=10) time.sleep(5) if not ib.isConnected(): logging.debug('HEALTHCHECK: ib is not connected') sys.exit(1) else: logging.debug('HEALTHCHECK: ib is connected') sys.exit(0)
class Window(qt.QWidget): def __init__(self, host, port, clientId): qt.QWidget.__init__(self) self.setWindowTitle("Giulio's App") self.canvas = MplCanvas() # self.edit = qt.QLineEdit('', self) # self.edit.editingFinished.connect(self.add) self.table = HistoricalTable() self.MAList = [] self.MADict = {} self.connectButton = qt.QPushButton('Connect') self.connectButton.setStyleSheet( "border: 1px solid black; background: white") self.connectButton.resize(100, 32) self.connectButton.setGeometry(200, 150, 100, 40) self.connectButton.clicked.connect(self.onConnectButtonClicked) self.displayButton = qt.QPushButton('Display values') self.displayButton.setStyleSheet( "border: 1px solid black; background: white") self.displayButton.resize(100, 32) self.displayButton.clicked.connect(self.onDisplayButtonClicked) self.cancelAllButton = qt.QPushButton('CancelAll') self.cancelAllButton.setStyleSheet( "border: 1px solid black; background: white") self.cancelAllButton.resize(100, 32) self.cancelAllButton.setGeometry(200, 150, 100, 40) self.cancelAllButton.clicked.connect(self.onCancelAllButtonClicked) layout = qt.QVBoxLayout(self) # layout.addWidget(self.edit) layout.addWidget(self.table) #layout.addWidget(self.canvas) layout.addWidget(self.connectButton) layout.addWidget(self.cancelAllButton) # layout.addStretch(1) # self.fig = plt.figure() # self.ax = self.fig.add_subplot(1, 1, 1) self.xs = [] self.ys = [] # layout.addWidget(self.fig) self.connectInfo = (host, port, clientId) self.ib = IB() self.headers = [ 'symbol', 'bidSize', 'bid', 'ask', 'askSize', 'last', 'lastSize', 'close' ] self.id = 1 self.firstSignal = True self.isConnectionBroken = False self.firstma50 = 0 self.firstma200 = 0 self.availableCash = 0 self.ib.orderStatusEvent += self.order_status_cb self.ib.execDetailsEvent += self.exec_details_cb self.ib.errorEvent += self.error_cb self.ib.accountSummaryEvent += self.accountSummary self.ib.pendingTickersEvent += self.onPendingTickers # self.ib.pendingTickersEvent += self.table.onPendingTickers async def accountSummaryAsync(self, account: str = '') -> \ List[AccountValue]: if not self.wrapper.acctSummary: # loaded on demand since it takes ca. 250 ms await self.reqAccountSummaryAsync() if account: return [ v for v in self.wrapper.acctSummary.values() if v.account == account ] else: return list(self.wrapper.acctSummary.values()) def accountSummary(self, account: str = '') -> List[AccountValue]: if (account.tag == 'BuyingPower'): logging.info('account buying power - ' + account.value) accVal: float = 0.0 accVal = account.value self.availableCash = float(accVal) self.availableCash = round(self.availableCash, 2) logging.info('available cash - ' + str(self.availableCash)) logging.info("account summary:: " + str(account.account) + " " + account.tag + " " + account.value) return [] #self._run(self.accountSummaryAsync(account)) def error_cb(self, reqId, errorCode, errorString, contract): logging.error("error: " + str(reqId) + " , " + str(errorCode) + " , " + str(errorString)) logging.error("string - " + str(errorString)) """if(errorCode == 1100): logging.error("Connectivity between IB and TWS has been lost") self.isConnectionBroken = True if (errorCode == 1300): logging.error("socket connection dropped") self.isConnectionBroken = True if(errorCode == 2105): logging.error("HMDS data farm connection is broken") if ((errorCode == 2104 or errorCode == 2106) and self.isConnectionBroken == True): logging.info("HMDS data farm connection has been restored") self.reqData()""" def reqGlobalCancel(self): """ Cancel all active trades including those placed by other clients or TWS/IB gateway. """ self.ib.reqGlobalCancel() logging.info('reqGlobalCancel') def order_status_cb(self, trade): logging.info("order status for " + str(trade.order.orderId)) logging.info("Status filled and remaining - " + trade.orderStatus.status + " " + str(trade.orderStatus.filled) + " " + str(trade.orderStatus.remaining)) def exec_details_cb(self, trade, fill): logging.info("exec details for " + fill.contract.symbol + " with orderid " + str(fill.execution.orderId)) if (fill.execution.side == "Sell"): self.availableCash += fill.execution.price def onPendingTickers(self, tickers): for ticker in tickers: logging.info("ticker - " + str(ticker.contract.conId) + " " + str(ticker.contract.secType) + " " + ticker.contract.symbol + " " + ticker.contract.currency) for col, header in enumerate(self.headers): if col == 0: continue val = getattr(ticker, header) symbol = ticker.contract.symbol + (ticker.contract.currency if ticker.contract.secType == 'CASH' else '') ma = self.MADict[symbol] logging.info("Values - " + str(ticker.contract.secType) + " " + str(ticker.contract.conId) + " " + symbol + " " + str(header) + " " + str(col) + " val- " + str(val)) if (str(header) == 'bid'): ma.bid = val if (str(header) == 'ask'): ma.ask = val def onBarUpdate(self, bars, hasNewBar): self.xs.append(dt.datetime.now().strftime('%H:%M:%S.%f')) # logging.debug("bar update " + str(hasNewBar) + " for " + str(bars.reqId)) logging.info(bars[-1]) symbol = bars.contract.symbol + ( bars.contract.currency if bars.contract.secType == 'CASH' else '') ma = self.MADict[symbol] logging.info("update for " + ma.symbol) df = util.df(bars) # logging.debug(df) ma.setMAs(df) ma50 = ta.MA(df['close'], 50) ma200 = ta.MA(df['close'], 200) self.ys.append(ma50) self.xs = self.xs[-50:] self.ys = self.ys[-50:] # self.ax.clear() # self.ax.plot(self.xs, self.ys) plt.xticks(rotation=45, ha='right') plt.subplots_adjust(bottom=0.30) plt.title('50MA') plt.ylabel('MA') """logging.debug("ma50") logging.debug(ma50) logging.debug("ma200") logging.debug(ma200) logging.debug("last items") logging.debug(ma50.tail(1).item()) logging.debug(ma200.tail(1).item())""" orderList = ma.checkGCDC() if (orderList is not None): orderQuantity = 0 for order in orderList: if (order.orderType == "LMT"): if (order.action == "Buy"): order.totalQuantity = 1000 #(self.availableCash/ma.bid) * .01 self.availableCash -= (order.totalQuantity * order.trailStopPrice) logging.info("Placing buy order for " + ma.symbol + " " + str(ma.bid) + " with orderId " + str(order.orderId)) else: order.totalQuantity = 1000 #(self.availableCash/ma.ask) * .01 logging.info("Placing sell order for " + ma.symbol + " at " + str(ma.ask) + " with orderId " + str(order.orderId)) orderQuantity = order.totalQuantity else: if (order.orderType == "TRAIL"): order.totalQuantity = orderQuantity if (order.action == "Buy"): #order.totalQuantity = (self.availableCash / ma.bid) * .01 self.availableCash -= (order.totalQuantity * order.trailStopPrice) logging.info("Placing buy order for " + ma.symbol + " " + str(ma.bid) + " with orderId " + str(order.orderId)) else: #order.totalQuantity = (self.availableCash / ma.ask) * .01 logging.info("Placing sell order for " + ma.symbol + " at " + str(ma.ask) + " with orderId " + str(order.orderId)) logging.info("Placing " + order.action + " order for " + ma.symbol + " at " + str(order.trailStopPrice) + " " + str(ma.ask) + " with orderId " + str(order.orderId) + " " + str(trade.order.orderId)) trade = self.ib.placeOrder(bars.contract, order) if (ma.isOrderActive == False and ma.GCCheck == True): logging.info("order is not active and gccheck is true") self.MADict[symbol] = ma """if (ma.firstSignal == True): ma.firstma50 = round(ma50.tail(1).item(), 6) ma.firstma200 = round(ma200.tail(1).item(), 6) ma.firstSignal = False if (ma.firstma50 < ma.firstma200): logging.info("checking golden cross for " + ma.symbol + " : mas - " + str(ma.firstma50) + " " + str(ma.firstma200)) else: logging.info("checking death cross for " + ma.symbol + " : mas - " + str(ma.firstma50) + " " + str(ma.firstma200)) ma.GCCheck = False self.MADict[symbol] = ma else: prevma50 = ma.getMa50() prevma200 = ma.getMa200() currma50 = round(ma50.tail(1).item(), 6) currma200 = round(ma200.tail(1).item(), 6) if(ma.isOrderActive == False): if(ma.GCCheck == True): logging.info("golden cross check for " + ma.symbol) logging.info("prev mas - " + str(prevma50) + " " + str(prevma200)) logging.info("curr mas - " + str(currma50) + " " + str(currma200)) logging.info("curr bid and ask vals - " + str(ma.bid) + " " + str(ma.ask)) if((prevma50 <= prevma200) and (currma50 > currma200)): logging.info(("golden cross occured for " + ma.symbol)) ma.GCCheck = False if(ma.isOrderActive == False): ma.isOrderActive = True order = TrailOrder("Buy", 1000, ma.ask, 20) trade = self.ib.placeOrder(bars.contract, order) logging.info("Placing buy order for " + ma.symbol + " at " + str(order.trailStopPrice) + " " + str(ma.ask) + " with orderId " + str(order.orderId) + " " + str(trade.order.orderId)) self.MADict[symbol] = ma else: logging.info("death cross check for " + ma.symbol) logging.info("prev mas - " + str(prevma50) + " " + str(prevma200)) logging.info("curr mas - " + str(currma50) + " " + str(currma200)) if ((prevma50 >= prevma200) and (currma50 < currma200)): logging.info(("death cross occured for " + ma.symbol)) ma.GCCheck = True if (ma.isOrderActive == False): ma.isOrderActive = True order = TrailOrder("Sell", 1000, ma.bid, 20) trade = self.ib.placeOrder(bars.contract, order) logging.info("Placing sell order for " + ma.symbol + " at " + str(ma.bid) + " with orderId " + str(trade.order.orderId)) self.MADict[symbol] = ma """ ma.setMa50(round(ma50.tail(1).item(), 6)) ma.setMa200(round(ma200.tail(1).item(), 6)) self.MADict[symbol] = ma logging.debug("MAs for " + str(bars.contract.secType) + " " + str(bars.contract.symbol) + " " + bars.contract.currency + " , reqid: " + str(bars.reqId) + " " + str(ma50.values[-1]) + " " + str(ma200.values[-1]) + " : " + str(ma50.tail(1).item()) + " " + str(ma200.tail(1).item())) self.table.updateData(bars.reqId, round(ma50.tail(1).item(), 6), round(ma200.tail(1).item(), 6)) # logging.debug(ma50.values[-1]) # plt.close() # plot = util.barplot(bars) # clear_output(wait=True) # display(plot) def add_historical(self, text=''): logging.debug("text - " + text) logger.debug("logging") text = text or self.edit.text() if text: logging.debug('eval text ') # + eval(text)) contract = eval(text) logging.debug("requesting historical and mkt data for " + text) bars = self.ib.reqHistoricalData(contract, endDateTime='', durationStr='2000 S', barSizeSetting='10 secs', whatToShow='MIDPOINT', useRTH=True, formatDate=1, keepUpToDate=True) ticker = self.ib.reqMktData(contract, '', False, False, None) logging.info(bars[-1]) logging.debug("sectype " + str(bars.reqId) + " " + str(bars.contract.conId) + " " + bars.contract.secType + " " + bars.contract.symbol + " " + bars.contract.currency) self.table.addHistoricalData(bars.reqId, contract) df = util.df(bars) # with pd.option_context('display.max_rows', None, 'display.max_columns', # None): # more options can be specified also # logging.debug(df) close = pd.DataFrame(df, columns=['close']) logging.debug("close ") logging.debug(close) # df['pandas_SMA_3'] = df.iloc[:, 1].rolling(window=3).mean() # df.head() #ma50 = ta.MA(df['close'], 50) #ma200 = ta.MA(df['close'], 200) symbol = bars.contract.symbol + (bars.contract.currency if bars.contract.secType == 'CASH' else '') logging.info("symbol - " + symbol) ma = MovingAverages( self.ib, symbol, bars.reqId ) #, round(ma50.tail(1).item(), 6), round(ma200.tail(1).item(), 6)) ma.setMAs(df) self.MAList.append(ma) self.MADict[symbol] = ma """logging.debug("ma50") logging.debug(ma50) logging.debug("ma200") logging.debug(ma200) logging.debug("initial ma vals for " + symbol) logging.debug(ma50.tail(1).item()) logging.debug(ma200.tail(1).item())""" self.table.updateData(bars.reqId, round(ma.ma50.tail(1).item(), 6), round(ma.ma200.tail(1).item(), 6)) # sma = pd.SMA(df['close'].values, timeperiod=4) """portfolio = self.ib.portfolio()#.wrapper.portfolio.cash = 10000 logging.debug("portfolio") logging.debug(portfolio) positions = self.ib.positions() logging.debug("positions") for x in range(len(positions)): logging.debug(positions[x].contract.symbol) logging.debug(positions[x].position)""" # logging.debug(positions) bars.updateEvent += self.onBarUpdate logging.debug("reqid is " + str(bars.reqId) + " for " + bars.contract.symbol + " " + bars.contract.currency + " , sectype - " + bars.contract.secType) def onDisplayButtonClicked(self, _): logging.debug("MA values") for ma in self.MAList: logging.debug("symbol - " + " " + ma.symbol) logging.debug( str(ma.firstma50) + " " + str(ma.firstma200) + " " + str(ma.firstSignal) + " " + str(ma.ma50) + " " + str(ma.ma200)) for x in self.MADict: logging.debug(x) for x in self.MADict.values(): logging.debug("dict values - " + str(x.firstSignal) + " " + x.symbol + " " + str(x.firstma50) + " " + str(x.firstma200) + " " + str(x.ma50) + " " + str(x.ma200)) def onConnectButtonClicked(self, _): logging.debug("isconnected: " + str(self.ib.isConnected())) if self.ib.isConnected(): self.ib.disconnect() logging.debug("clearing data") self.table.clearData() self.connectButton.setText('Connect') logging.debug("done") else: logging.debug("trying to connect") # ib = IB() # ib.connect('127.0.0.1', 7497, clientId=3) self.ib.connect('127.0.0.1', 7497, clientId=2) # *self.connectInfo) logging.debug("connected - ") # + self.ib.isConnected()) # self.ib.reqMarketDataType(2) self.connectButton.setText('Disconnect') self.ib.reqAccountSummary() self.reqData() def onCancelAllButtonClicked(self): logging.info("Cancelling all open orders") #self.ib.connect('127.0.0.1', 7497, clientId=2) # *self.connectInfo) self.reqGlobalCancel() def reqData(self): #self.reqGlobalCancel() """for symbol in ('EURUSD', 'USDJPY', 'EURGBP', 'USDCAD', 'EURCHF', 'AUDUSD', 'NZDUSD'): logging.debug("requesting for " + symbol) self.add_historical(f"Forex('{symbol}')")""" #self.add_historical("Stock('TSLA', 'SMART', 'USD')") #self.add_historical("Stock('IBM', 'SMART', 'USD')") #self.add_historical("Stock('MSFT', 'SMART', 'USD')") self.add_historical("Stock('FB', 'SMART', 'USD')") def closeEvent(self, ev): logging.debug("closing") asyncio.get_event_loop().stop()