'simultaneous (async) work - getting msg receiving and placing order/selling in auto bot w websocket

''' I would like to get async working for purchasing ordering while continuously getting realtime price update by websocket receving. However, when I execute the code below, I found the result like the below, which is in a order, not simultaneously. so, want to do work function - Purchase() when 'if' is made, while restarting Fucntion - Main() to get the realtime price at the same time. can you help to advice?

KRW-BTC 50493000.0 65190905111.72767
구매할 때가 되었다
구매할 때가 되었다2
구매할 때가 되었다3
KRW-ETH 3728000.0 42981406234.81617
KRW-ETH 3729000.0 42981416234.80089
KRW-BTC 50532000.0 65191256384.92567
구매할 때가 되었다
구매할 때가 되었다2
구매할 때가 되었다3
'''

async def main(wm):
i=int(0)
while i<1 : 
    global code, close, volume
    data = wm.get()
    code, close, volume=data['code'], data['trade_price'], data['acc_trade_price']
    #timestamp=datetime.datetime.fromtimestamp(data['trade_timestamp'] / 1000)
    #open = data['opening_price']
    #high=data['high_price']
    #low=data['low_price']
    print(code, close , volume)
    if code == 'KRW-BTC' and close >50200000:
        await purchase()
    
            
async def purchase():
    print("구매할 때가 되었다")
    await asyncio.sleep(1)
    print("구매할 때가 되었다2")
    await asyncio.sleep(1)
    print("구매할 때가 되었다3")
    await asyncio.sleep(1)  


if __name__ == "__main__":
    wm = pyupbit.WebSocketManager("ticker", coinlist)
    loop = asyncio.new_event_loop()
    tasks = loop.create_task(main(wm))

    try:
        loop.run_until_complete(tasks)
        loop.run_forever()        
    except KeyboardInterrupt as exc:
        logging.info('Quit.')
    finally:
        print("Closing Loop")
        loop.close()


Solution 1:[1]

the results are in sequence because the next iteration of the while loop cannot run until await purchase() returns, the easiest way to get more concurrency is to treat your main function as a "worker" e.g.

import asyncio
import operator
import pyupbit

async def worker(wm):
    while True: 
        data = await asyncio.to_thread(wm.get)
        code, close, volume = operator.itemgetter('code', 'trade_price', 'acc_trade_price')(data)
        if code == 'KRW-BTC' and close > 50200000:
            await purchase()

WORKERS = 10  # scale as desired

async def main():
    wm = pyupbit.WebSocketManager("ticker", coinlist)
    workers = [asyncio.create_task(worker(wm)) for _ in range(WORKERS)]
    await asyncio.gather(*workers)

if __name__ == "__main__":
    asyncio.run(main())

the above will allow 10 purchase()'s to be awaited concurrently, and u can increase it as u see fit

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1