0

Currently working on a project that uses Binance Websockets to fetch data of the coin prices and makes calculations with the data.

The number of coins that I calculate is dynamic (varies from 150 to ~250).

The ASYNC function is called calculate(client, queue, coin)

It takes the following arguments:

  1. client: The Binance Async client (python-binance library)
  2. queue: A queue where opportunities get passed in if the calculation has a positive outcome
  3. coin: The coin e.g. BTC

The calculate function contains a while 1 (infinitive) loop, so the calculations keep on running.

At the moment the main function uses asyncio.gather to combine the calculate functions for the different coins (150 - ~250)

async def main(queue):

await asyncio.gather(
    calculate(client, queue, 'BTC'),
    calculate(client, queue, 'ETH'),
    calculate(client, queue, 'BNB'),
    calculate(client, queue, 'LINK'),
    calculate(client, queue, 'SHIB'),
    calculate(client, queue, 'ADA'),
    calculate(client, queue, 'XRP'),
    calculate(client, queue, 'VET')
    # This continues for the the other +100 coins
    )


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(queue))

This is not a pretty way of writing the code and it is very inefficient if I want to change the coins. Using an API I fetch the coins that need to be calculated. So I need to manually update the 100+ lines which call the function for each coin and update some other files to ensure that everything runs smooth.

What would be a good solution for this issue?

I've seen threading/ multithreading / more complex uses of asyncio, but I couldn't see how to apply it to this issue.

Help would be much appreciated.

T. de Jong
  • 91
  • 1
  • 1
  • 6

1 Answers1

1

You want to create a list of the coins to call calculate() on, use that list to create a list of calculations, and then use a starred expression unpack that list as arguments to asyncio.gather():

async def main(queue):
    coins = ['BTC', 'ETH', 'BNB']  # Add more coins as desired.
    calculations = [calculate(client, queue, coin) for coin in coins]

    await asyncio.gather(*calculations)  # Use a starred expression to unpack the list.


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(queue))
Andrew
  • 904
  • 5
  • 17
  • Do you think that asyncio gather is the best method to use here? – T. de Jong Oct 07 '21 at 12:33
  • 1
    @T.deJong I haven't used `asyncio` very much, so I'm not sure if `gather()` is the best method for what you're doing. But here's a post on the differences between `wait()` and `gather()` which might be helpful: https://stackoverflow.com/questions/42231161/asyncio-gather-vs-asyncio-wait – Andrew Oct 07 '21 at 21:10
  • All right, that provided some more insight in the differences thanks! Do you have experience in (multi)treading and if so, would that be good to use here? – T. de Jong Oct 08 '21 at 06:48