Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need help using ib_insync with qasync #34

Open
romanrdgz opened this issue Apr 7, 2021 · 2 comments
Open

Need help using ib_insync with qasync #34

romanrdgz opened this issue Apr 7, 2021 · 2 comments
Labels
question Further information is requested

Comments

@romanrdgz
Copy link

romanrdgz commented Apr 7, 2021

First of all, thanks for your work and your efforts to get asyncio to work with Pyqt5. I am missing more examples and a tutorial here, and that's probably my main issue. I am currently having trouble combining ib_insync with pyqt5. The former is an async library to connect to the API of Interactive brokers, which can be used without asyncio knowledge by nesting loops and applying a monkey-patch. Nevertheless, when combining with PyQt and my application gets more complex, things start to fall apart, so I'm trying to go to manual async control of ib_insync.

Hence, I wrote a small example script which runs a Pyqt5 application with 2 buttons. One will connect to the brokerage using ib_insync's connectAsync function. My first problem is located right here, as despite having wrote the example based on yours, Python is telling me the following error:
...\Python38-32\lib\site-packages\qasync\__init__.py:275: RuntimeWarning: coroutine 'MainWindow.connect_to_tws' was never awaited

My second problem is that ib_insync also contains blocking calls, such as qualifyContracts, which is to be tested with the second button once connected.

I am aware that this is a very specific appplication that would require you to have ib_insync and a brokerage account with IB, but it would really help me if you could have a look at my code in order to detect what am I doing wrong:

import asyncio
from ib_insync import IB, util, Stock
import functools
from PyQt5 import QtCore, QtGui, QtWidgets, uic
import qasync
from qasync import asyncSlot, asyncClose, QApplication, QThreadExecutor
import sys
import traceback


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        uic.loadUi('mainwindow.ui', self)
        self.loop = asyncio.get_event_loop()
        
        # Connect widgets signals
        self.connect_button.pressed.connect(self.connect_button_action)
        self.refresh_portfolio_button.pressed.connect(self.portfolio_button_action)
    
    async def connect_to_tws(self):
        self.ib_client = IB()
        self.ib_client.client.setConnectOptions('+PACEAPI')
        self.ib_client.client.MaxRequests = 0 # Disables throttling
        self.ib_client.connectAsync('127.0.0.1', 7496, clientId=21)
        self.connect_button.setEnabled(False)
        self.refresh_portfolio_button.setEnabled(True)
        
    @asyncClose
    async def closeEvent(self, event):
        await self.session.close()
        
    @asyncSlot()
    async def connect_button_action(self):
        # Connect to IB
        with QThreadExecutor(1) as exec:
            await self.loop.run_in_executor(exec, self.connect_to_tws)
        
    @asyncSlot()
    async def portfolio_button_action(self):
        print('button_action_event')
        try:
            self.portfolio_table.setEnabled(False)
            self.portfolio_progress_bar.setVisible(True)
            
            tasks = list()
            tasks.append(self.loop.create_task(self.get_portfolio_data()))
            self.loop.run_until_complete(asyncio.wait(tasks))
        except Exception as e:
            traceback.print_tb(e.__traceback__)
            print(e)
            
    async def get_portfolio_data(self):
        futures = [self.loop.run_in_executor(None, self.blocking_call)]
        results = await asyncio.gather(*futures)
        return results
        
    def blocking_call(self):
        contract = Stock('ADBE', 'SMART', 'USD')
        print('Thread: before qualifyContracts call')
        self.ib_client.qualifyContracts(contract)
        print('Thread: after qualifyContracts call')
        return contract
        
    def on_portfolio_update_completed(self):
        self.portfolio_table.setEnabled(True) # TODO: data to be loaded to the table. Doesn't matter for the test purpose
        self.portfolio_progress_bar.setVisible(False)
        print('Finished thread task')
        
        
async def main():
    def close_future(future, loop):
        loop.call_later(10, future.cancel)
        future.cancel("Close Application")
        
    loop = asyncio.get_event_loop()
    future = asyncio.Future()
    
    window = None
    try:
        app = QApplication.instance()
        app.setStyle('fusion')
        if hasattr(app, 'aboutToQuit'):
            getattr(app, 'aboutToQuit').connect(functools.partial(close_future, future, loop))
        window = MainWindow()
        window.show()
    except Exception as e:
        print(traceback.format_exc())
        print(e)
        if window is not None and window.ib is not None and window.ib.isConnected():
            window.ib.disconnect()
            print('Disconnected from IB')
        sys.exit(0)
        
    await future
    return True


if __name__ == '__main__':
    try:
        qasync.run(main())
    except asyncio.exceptions.CancelledError:
        print(e)
        sys.exit(0)

Thanks in advance

@fredy0219
Copy link

I have a similar problem here. Anybody can help?

@hosaka
Copy link
Collaborator

hosaka commented Apr 11, 2023

I'm gonna mark this as non-issue, until someone comes along who can help with the code.

@hosaka hosaka added the question Further information is requested label Apr 11, 2023
@hosaka hosaka changed the title Troubles starting my journey with qasync Need help using ib_insync with qasync Apr 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants