{"action":"created","issue":{"url":"https://api.github.com/repos/kroitor/ccxt/issues/7","repository_url":"https://api.github.com/repos/kroitor/ccxt","labels_url":"https://api.github.com/repos/kroitor/ccxt/issues/7/labels{/name}","comments_url":"https://api.github.com/repos/kroitor/ccxt/issues/7/comments","events_url":"https://api.github.com/repos/kroitor/ccxt/issues/7/events","html_url":"https://github.com/kroitor/ccxt/issues/7","id":241312758,"number":7,"title":"Batch fetch operations","user":{"login":"nmiculinic","id":3183610,"avatar_url":"https://avatars0.githubusercontent.com/u/3183610?v=4","gravatar_id":"","url":"https://api.github.com/users/nmiculinic","html_url":"https://github.com/nmiculinic","followers_url":"https://api.github.com/users/nmiculinic/followers","following_url":"https://api.github.com/users/nmiculinic/following{/other_user}","gists_url":"https://api.github.com/users/nmiculinic/gists{/gist_id}","starred_url":"https://api.github.com/users/nmiculinic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmiculinic/subscriptions","organizations_url":"https://api.github.com/users/nmiculinic/orgs","repos_url":"https://api.github.com/users/nmiculinic/repos","events_url":"https://api.github.com/users/nmiculinic/events{/privacy}","received_events_url":"https://api.github.com/users/nmiculinic/received_events","type":"User","site_admin":false},"labels":[{"id":604886966,"url":"https://api.github.com/repos/kroitor/ccxt/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"closed","locked":false,"assignee":{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false},"assignees":[{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false}],"milestone":null,"comments":22,"created_at":"2017-07-07T16:18:48Z","updated_at":"2017-08-22T05:22:24Z","closed_at":"2017-08-22T05:22:24Z","body":"I see following three unified API operations which would ideally have their batch equivalent:\r\n\r\n* fetchOrderBook (symbol): Fetch an order book for a particular product trading symbol.\r\n* fetchTrades (symbol): Fetch recent trades for a particular trading symbol.\r\n* fetchTicker (symbol): Fetch latest ticker data by trading symbol.\r\n\r\nI'm using python syntax\r\n\r\nThus for example istead of:\r\n```\r\nex = some_exchange\r\nex.fetchTicker(\"BTC/ETH\"), ex.fetchTicker(\"DSH/BTC\")\r\n```\r\n\r\nI could write (executor would be instace of https://docs.python.org/3/library/concurrent.futures.html):\r\n```\r\nex.batchFetchTicker([\"BTC/ETH\", \"DSH/BTC\"], executor=exec)\r\n```\r\n\r\nOr by using asyncio and python3.5+ syntax:\r\n```\r\nawait ex.batchFetchTicker([\"BTC/ETH\", \"DSH/BTC\"])\r\n```\r\n\r\nSome markets implement batch REST API, for example kraken uses comma separated symbol lists. Others like GDAX have no such option, and this method could be implemented in fallback mode using fetchX functions (with taking care of concurrent HTTP request, and not executing them sequentially)."},"comment":{"url":"https://api.github.com/repos/kroitor/ccxt/issues/comments/323922183","html_url":"https://github.com/kroitor/ccxt/issues/7#issuecomment-323922183","issue_url":"https://api.github.com/repos/kroitor/ccxt/issues/7","id":323922183,"user":{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false},"created_at":"2017-08-22T05:22:24Z","updated_at":"2017-08-22T05:22:24Z","body":"Hi!\r\n\r\nCurrently:\r\n1. we have support for [fetchTickers](https://github.com/kroitor/ccxt/wiki/Manual#all-at-once) where applicable\r\n2. also have support for [async/await](https://github.com/kroitor/ccxt/wiki/Manual#synchronous-vs-asynchronous-calls)\r\n3. and have [usage examples for asyncio](https://github.com/kroitor/ccxt/tree/master/examples/py)\r\n\r\nHaving the above, the task of making batch_fetch_* with respect to the exchanges' rateLimit is as trivial as writing [the following short snippet](https://github.com/kroitor/ccxt/blob/master/examples/py/async-generator-multiple-tickers.py) (you can wrap it in a function easily):\r\n\r\n```Python\r\n# -*- coding: utf-8 -*-\r\n\r\nimport asyncio\r\nimport ccxt.async as ccxt\r\n\r\n#------------------------------------------------------------------------------\r\n\r\nasync def poll(tickers):\r\n    i = 0\r\n    kraken = ccxt.kraken()\r\n    while True:\r\n        symbol = tickers[i % len(tickers)]\r\n        yield (symbol, await kraken.fetch_ticker(symbol))\r\n        i += 1\r\n        await asyncio.sleep(kraken.rateLimit / 1000)\r\n\r\n#------------------------------------------------------------------------------\r\n\r\nasync def main():\r\n    async for (symbol, ticker) in poll(['BTC/USD', 'ETH/BTC', 'BTC/EUR']):\r\n        print(symbol, ticker)\r\n\r\n#------------------------------------------------------------------------------\r\n\r\nasyncio.get_event_loop().run_until_complete(main())\r\n```\r\n\r\nBasically, this is how you batch_fetch sequentially from the same exchange.\r\nYou can also do it in parallel in one go for multiple exchanges.\r\n\r\nWe don't want to restrict the polling rate, so to keep everything explicit we leave it up to the user to design his event loop. That is at least until we implement an internal poller inside the library (hopefully soon). Until then, I think like closing this issue and maybe we will return to it later to unify it even more (if needed).\r\n\r\n\r\n\r\n"}}
{"actor":{"display_login":"kroitor"}}