Reputation: 106
I am trying to use CCXT to get the BTC bid and ask price across different exchanges, but running the code sequencially cannot get the price of a given moment correctly. Is there any way to execute them at the same time and return the correct price?
import ccxt
binance = ccxt.binance()
coinbase = ccxt.coinbase()
ftx = ccxt.ftx()
kraken = ccxt.kraken()
kucoin = ccxt.kucoin()
stat_list = binance.fetchTicker('BTC/USDT')
print('Binance', stat_list['bid'], stat_list['ask'])
stat_list = coinbase.fetchTicker('BTC-USD')
print('Coinbase', stat_list['bid'], stat_list['ask'])
stat_list = ftx.fetchTicker('BTC/USDT')
print('FTX', stat_list['bid'], stat_list['ask'])
stat_list = kraken.fetchTicker('BTC/USDT')
print('Kraken', stat_list['bid'], stat_list['ask'])
stat_list = kucoin.fetchTicker('BTC/USDT')
print('Kucoin', stat_list['bid'], stat_list['ask'])
Output:
Binance 20451.04 20451.33
Coinbase 20343.33 20552.61
FTX 20451.0 20452.0
Kraken 20454.5 20454.6
Kucoin 20450.9 20451.0
Upvotes: 3
Views: 633
Reputation: 11657
In programming, we use the term concurrency. So our task is to fetch ticker data concurrently. There are several approaches to do this in Python.
The multiprocessing
module can be used for fetching tickers from multiple exchanges. The example can be improved by using a pool and adding all the ticker data into a container and printing it at the end, rather than printing each ticker data separately (IO operations are relatively expensive.)
Multiprocessing is usually used for the CPU-bound tasks, such as intensive math calculations. Our task is IO-bound, that is heavy on IO operations. For these kind of tasks, we mostly use asynchronous programming.
The ccxt
module already contains support for async programming.
#!/usr/bin/python
import asyncio
import ccxt.async_support as ccxt
exchanges = [ccxt.binance(), ccxt.bybit(), ccxt.kucoin(), ccxt.bitpanda(),
ccxt.kraken()]
async def get_ticker(exchange):
data = await exchange.fetch_ticker('BTC/USDT')
await exchange.close()
return (exchange.name, data)
async def launch():
resps = await asyncio.gather(*map(get_ticker, exchanges))
for name, data in resps:
print(f"{name}: {data['bid']} {data['ask']}")
asyncio.run(launch())
This works by quickly launching all the (non-blocking) requests and starting a loop. The loop waits for all the responses to finish. So no task is waiting for other task to finish. In contrast, multiprocessing starts each blocking request in a separate processor/core. Both are able to do our tasks concurrently, but the asynchronous way is built-in the library, easier to use and the preferred way in IO heavy operations.
Upvotes: 1
Reputation: 106
With help from Ari Cooper-Davis, this is what I come up with. It seems like the bid and ask prices between the exchanges are still quite large.
from multiprocessing import Process
import ccxt
def func1():
binance = ccxt.binance()
stat_list = binance.fetchTicker('BTC/USDT')
print('Binance', stat_list['bid'], stat_list['ask'])
def func2():
coinbase = ccxt.coinbase()
stat_list = coinbase.fetchTicker('BTC-USD')
print('Coinbase', stat_list['bid'], stat_list['ask'])
def func3():
ftx = ccxt.ftx()
stat_list = ftx.fetchTicker('BTC/USDT')
print('FTX', stat_list['bid'], stat_list['ask'])
def func4():
kraken = ccxt.kraken()
stat_list = kraken.fetchTicker('BTC/USDT')
print('Kraken', stat_list['bid'], stat_list['ask'])
def func5():
kucoin = ccxt.kucoin()
stat_list = kucoin.fetchTicker('BTC/USDT')
print('Kucoin', stat_list['bid'], stat_list['ask'])
if __name__ == '__main__':
p1 = Process(target=func1)
p1.start()
p2 = Process(target=func2)
p2.start()
p3 = Process(target=func3)
p3.start()
p4 = Process(target=func4)
p4.start()
p5 = Process(target=func5)
p5.start()
Output:
FTX 20428.0 20429.0
Binance 20431.99 20432.15
Kucoin 20428.1 20429.6
Kraken 20430.5 20430.6
Coinbase 20311.53 20525.9
Upvotes: 1