Beispiel #1
0
def log_arbitrage(path):
    """ Check if there is an arbitrage and save it

    """
    os.makedirs(path, exist_ok=True)
    path_lp = os.path.join(path, "problem.lp")
    path_lpr = os.path.join(path, "problem_replaced.lp")
    path_sol = os.path.join(path, "problem.output")
    path_orderbook = os.path.join(path, "orderbook.json")
    path_pairs = os.path.join(path, "pairs.json")

    kraken = Kraken()
    kraken.load_key("keys/albus.key")

    pairs = query_tradable_pairs(kraken)
    pair_names = get_pairs_names(pairs)
    orderbook = query_orderbook(kraken, pair_names)

    save_json(path_orderbook, orderbook)
    save_json(path_pairs, pairs)

    prices = depth_matrix(orderbook, pairs)
    prices = head_depth_matrix(prices, n=2)

    save_lp(prices, path_lp)
    xs, _ = lp_variables_names(prices)
    lp_replace_variables(path_lp, path_lpr, xs)
    f = open(path_sol, 'w')
    subprocess.call(['lp_solve', path_lp], stdout=f)
    f.close()
    sol = lp_read_solution(path_sol)
    S, G = print_strategy(sol, xs)

    if 0 == len(S.keys()):
        shutil.rmtree(path)
Beispiel #2
0
def init(pairs, conffile, exchsfile):
    cf = json.load(open(exchsfile))
    cex = CEX(cf['cex_endpoint'], cf['cex_api_key'], cf['cex_api_secret'],
              cf['cex_id'])
    exmo = EXMO(cf['exmo_endpoint'], cf['exmo_api_key'], cf['exmo_api_secret'])
    kraken = Kraken(cf['kraken_endpoint'], cf['kraken_api_key'],
                    cf['kraken_api_secret'])

    global exchs
    exchs = [cex, exmo, kraken]

    with open(conffile, 'r') as fp:
        ocf = json.load(fp)

        for e in exchs:
            ename = e.__class__.__name__.lower()
            limits[ename] = {}
            for p in pairs:
                if p in ocf[ename]['converter'].keys():
                    if e == kraken:
                        ml1, ml2 = e.get_min_lot(p)
                    else:
                        ml1, ml2 = e.get_min_lot(ocf[ename]['converter'][p])
                    limits[ename][p] = [float(ml1), float(ml2)]

    return exchs, limits
Beispiel #3
0
def getData():
	print("Getting data...")
	EUR = getEURPrice()
	if (EUR != False):
		try:
			kraken = Kraken()
			res = kraken.getTickerSingle('BCHEUR')
			obj = {}
			obj['name'] = 'Bitcoin Cash'
			obj['symbol'] = 'BCH'
			obj['volume'] = res['BCHEUR']['v'][1]
			obj['price'] = str(float(res['BCHEUR']['c'][0])/EUR) 
		except Exception, e:
			print("Error getting JSON from kraken: "+str(e))
			return False
		
		return obj
Beispiel #4
0
def main():
    btf = Bitfinex()
    kkn = Kraken()
    gdax = Gdax()

    gc = authorize()
    print(update_sheet(gc, 'bitfinex', btf))
    print(update_sheet(gc, 'kraken', kkn))
    print(update_sheet(gc, 'gdax', gdax))
Beispiel #5
0
#!/bin/env python3

import sys

from kraken import Kraken

from functions import depth_format

k = Kraken()

arg = dict()

arg['pair'] = sys.argv[1] if len(sys.argv) > 1 else 'XXBTZEUR'
arg['count'] = '2000'

depth = k.query_public('Depth', arg)

try:
    print(depth_format(depth['result'], arg['pair']))
except:
    print(depth['error'])

import matplotlib.pyplot as plt
import numpy as np

v = list(np.cumsum(
    [float(x[1]) for x in depth['result']['XXBTZEUR']['bids']]))[::-1] + list(
        np.cumsum([float(x[1]) for x in depth['result']['XXBTZEUR']['asks']]))
p = list([float(x[0])
          for x in depth['result']['XXBTZEUR']['bids']])[::-1] + list(
              [float(x[0]) for x in depth['result']['XXBTZEUR']['asks']])
Beispiel #6
0
 def __init__(self, keys_file=None, quiet=False):
     # Create handle
     self.kraken = Kraken(keys_file='keys.json' if keys_file is None else keys_file)
     self.quiet = quiet
Beispiel #7
0
class KrakenData:

    def __init__(self, keys_file=None, quiet=False):
        # Create handle
        self.kraken = Kraken(keys_file='keys.json' if keys_file is None else keys_file)
        self.quiet = quiet

    def loadTrades(self, force_refresh=False, trades_file=None):
        # Load trades from file / download from API
        if trades_file is None: 'trades.json'
        self.trades, fresh = self.kraken.load_trades(trades_file, refresh_interval=0 if force_refresh else 60*60*6)
        if not self.quiet: print(f'Loaded {len(self.trades)} trades', '(updated)' if fresh else '(cached)')
        # Order them by time
        self.trades = sorted(self.trades, key=lambda trade: trade.time)

    def loadCurrentPrices(self):
        pairs = [f"{asset}USD" for asset in self.assets.keys() if asset != 'USD']
        tickers = self.kraken.get_tickers(pairs)
        self.current_prices = {'USD': 1.0}
        for ticker in tickers:
            self.current_prices[ticker.split_pair()[0]] = ticker.ask_price
        if not self.quiet: print('Loaded current prices')

    def processTrades(self):
        self.assets = {}
        for trade in self.trades:
            # Split pair into two assets
            a, b = trade.split_pair()
            if not a in self.assets: self.assets[a] = {'total_paid': 0.0, 'total_balance': 0.0, 'sell_profit': 0.0}
            #if not b in self.assets: self.assets[b] = {'total_paid': 0.0, 'total_balance': 0.0, 'sell_profit': 0.0}

            # How much we paid in USD
            cost_usd = 0.0
            if b == 'USD': cost_usd += trade.cost
            elif b == 'EUR': cost_usd += trade.cost * 1.2 # TODO: Calculate this accurately
            else: print(f'Unsupported currency: {b}');continue
            
            # Amount we bought/sold
            #amount = trade.cost / trade.price

            # Bought some crypto
            if trade.type == KrakenOrderType.BUY:
                self.assets[a]['total_paid'] += cost_usd # How much we paid
                self.assets[a]['total_balance'] += trade.amount # How much we got
            # Sold some
            elif trade.type == KrakenOrderType.SELL:
                if self.assets[a]['total_balance'] > EPSILON:
                    # Subtract from current balance keeping average in tact
                    curr_avg_price_usd = self.assets[a]['total_paid'] / self.assets[a]['total_balance']
                    self.assets[a]['total_paid'] -= curr_avg_price_usd * trade.amount
                    self.assets[a]['total_balance'] -= trade.amount
                    # Calculate profit we got from this sell
                    profit = cost_usd - curr_avg_price_usd * trade.amount
                    self.assets[a]['sell_profit'] += profit
                else:
                    # Bought something with deposited money
                    pass

        for asset, price in self.assets.items():
            if price['total_balance'] < EPSILON: 
                self.assets[asset]['average_price'] = None
            else:
                average_price = price['total_paid'] / price['total_balance']
                self.assets[asset]['average_price'] = average_price

    def calculateData(self):
        data = {'total_balance_usd': 0.0, 'total_live_profit': 0.0, 'total_closed_profit': 0.0, 'avg_live_profit_percentage': 0.0, 'assets': []}
        for asset in self.assets.keys():
            if self.assets[asset]['average_price'] is None: 
                continue

            # Get current balance
            balance = self.assets[asset]['total_balance']
            if asset in self.current_prices:
                data['total_balance_usd'] += balance * self.current_prices[asset]

            # Profit
            closed_profit = self.assets[asset]['sell_profit']
            data['total_closed_profit'] += closed_profit
            live_profit = (self.current_prices[asset] - self.assets[asset]['average_price']) * balance if balance > EPSILON else 0.0
            data['total_live_profit'] += live_profit

            # Append to data
            live_profit_percentage = (self.current_prices[asset] / self.assets[asset]['average_price'] * 100.0) - 100.0
            data['assets'].append({
                'asset': asset,
                'live_profit_percentage': live_profit_percentage,
                'live_profit_usd': live_profit,
                'average_price_usd': self.assets[asset]['average_price'],
                'closed_profit_usd': closed_profit,
                'balance': balance
            })

            data['avg_live_profit_percentage'] += live_profit_percentage
        data['avg_live_profit_percentage'] /= len(data['assets'])
        return data
#!/bin/env python3

import sys

import json

import time

from kraken import Kraken

# init krakenex API
k = Kraken(tier=3)

# load keys
k.load_key('keys/albus-test.key')

while (True):
    try:
        new_bal = k.query_private('Balance')['result']
    except:
        print("Cannot get balance")
        time.sleep(30)

    try:
        with open('data/balance.json', 'r') as fp:
            old_bal = json.load(fp)
    except:
        print("First run, a balance file will be created")
        old_bal = dict()

    if (old_bal != new_bal):
Beispiel #9
0
from kraken import Kraken
import json


def writeExample(name, result):
    fp = open('examples/' + name + '.json', 'w+')
    json.dump(result, fp, indent=5)
    fp.close()


k = Kraken()
writeExample('getAssetPairs', k.getAssetPairs())
writeExample('getAssetPair', k.getAssetPair(k.pairs.keys()[0]))
writeExample('getTicker', k.getTicker())
writeExample('getOrderBook', k.getOrderBook())
writeExample('getRecentTrades', k.getRecentTrades())
Beispiel #10
0
def run():
    print "Starting Arb"
    
    k = Kraken()
    last_eth_balance = float(load_last_eth_balance())
    dao_balance = k.dao_balance()
    
    eth_trade_price = round(calc_DAO2ETH_price(float(last_eth_balance), dao_balance), 5)

    if k.latest_price() > eth_trade_price:
        eth_trade_price = k.latest_price()
        
    trade_id = k.trade(price=eth_trade_price, lots=dao_balance)
    if trade_id:
        while k.order_status(trade_id) != 'closed':
            print "Waiting for trade to execute"
            time.sleep(5)
            
        # order was executed, check how much we made
        if k.order_status(trade_id) == 'closed':
            eth_balance = k.eth_balance()
            if eth_balance > last_eth_balance:
                print "Success! We made", eth_balance-last_eth_balance, "ethereum"
                save_last_eth_balance(eth_balance)
                send_sms(eth_balance)

                # now, send to shapeshift
                print "Shapeshift refid", k.withdrawn(eth_balance)

                # check account for DAO and if > 1 that means money are here
                while k.dao_balance() < 1:
                    time.sleep(5)

                # check if all ok and go again
                if k.dao_balance() > dao_balance:
                    print "We are going again!"
                    print "DAO Balance is", k.dao_balance()

            else:
                raise Exception
        else:
            raise Exception
Beispiel #11
0
from kraken import Kraken
from bittrex import Bittrex
from bitstamp import Bitstamp
from bitfinex import Bitfinex
from arbiter import Arbiter
from wallet import Wallet

kraken = Wallet(name='kraken',
                exchange=Kraken(),
                balance_usd=10000.0,
                balance_btc=1.0)
bittrex = Wallet(name='bittrex',
                 exchange=Bittrex(),
                 balance_usd=10000.0,
                 balance_btc=1.0)
bitstamp = Wallet(name='bitstamp',
                  exchange=Bitstamp(),
                  balance_usd=10000.0,
                  balance_btc=1.0)
bitfinex = Wallet(name='bitfinex',
                  exchange=Bitfinex(),
                  balance_usd=10000.0,
                  balance_btc=1.0)

a = Arbiter(wallets=[kraken, bittrex, bitstamp], trade_amount=0.25, delay=20)
a.arbitrate()
Beispiel #12
0
#!/bin/env python3

import sys

from tabulate import tabulate

from kraken import Kraken

k = Kraken()

# load keys
k.load_key('keys/albus-test.key')

orders = k.query_private('OpenOrders')

orders = orders['result']['open']

t = [{'pair':orders[key]['descr']['pair'],\
      'type':orders[key]['descr']['type'],\
      'price':orders[key]['descr']['price'],\
      'vol':orders[key]['vol'],\
      'key':key,\
      'status':orders[key]['status']} for key in orders.keys()]

print(tabulate(t, floatfmt="7.9f"))
Beispiel #13
0
class MarketMakerBot(SputnikSession):
    external_markets = {}
    yahoo = Yahoo()
    bitstamp = BitStamp()
    kraken = Kraken()

    def startAutomationAfterMarkets(self):
        self.get_external_market = task.LoopingCall(self.getExternalMarket)
        self.get_external_market.start(float(self.factory.rate) * 6)

        self.monitor_orders = task.LoopingCall(self.monitorOrders)
        self.monitor_orders.start(float(self.factory.rate) * 1)

        return True

    # See if we have any orders on a given side
    def cancelOrders(self, ticker, side):
        for id, order in self.orders.items():
            if order['is_cancelled'] or order['quantity_left'] <= 0:
                continue

            if order['side'] == side and order['contract'] == ticker:
                self.cancelOrder(id)

    def checkOrders(self, side):
        for id, order in self.orders.items():
            if order['is_cancelled'] or order['quantity_left'] <= 0:
                continue

            if order['side'] == side:
                return True

        return False

    @inlineCallbacks
    def getExternalMarket(self):
        try:
            bitstamp_book = yield self.bitstamp.getOrderBook('BTC/USD')
            btcusd_bid = bitstamp_book['bids'][0]['price']
            btcusd_ask = bitstamp_book['asks'][0]['price']
        except Exception as e:
            # Unable to get markets, just exit
            print "unable to get external market data from bitstamp: %s" % e
            raise e

        for ticker, market in self.markets.iteritems():
            new_ask = None
            new_bid = None

            if ticker not in self.factory.ignore_contracts:
                if market['contract_type'] == "cash_pair":
                    if ticker == "BTC/USD":
                        new_bid = btcusd_bid
                        new_ask = btcusd_ask
                    else:
                        currency = market['denominated_contract_ticker']

                        try:
                            # Get Yahoo quote
                            yahoo_book = yield self.yahoo.getOrderBook(
                                'USD/%s' % currency)
                            bid = yahoo_book['bids'][0]['price']
                            ask = yahoo_book['asks'][0]['price']
                        except Exception as e:
                            # Unable to get markets, just exit
                            print "unable to get external market data from Yahoo: %s" % e
                            continue

                        new_bid = btcusd_bid * bid
                        new_ask = btcusd_ask * ask
                elif market['contract_type'] == "futures":
                    got_spot = False
                    if ticker.startswith("USDBTC"):
                        # Ignore BTC and USD interest rates
                        new_bid_spot = 10000 / btcusd_ask
                        new_ask_spot = 10000 / btcusd_bid
                        # Assume 10bps USD risk-free rate
                        base_rate = 0.0010
                        got_spot = True
                    elif ticker.startswith("LTCBTC"):
                        kraken_book = yield self.kraken.getOrderBook('BTC/LTC')
                        btcltc_bid = kraken_book['bids'][0]['price']
                        btcltc_ask = kraken_book['asks'][0]['price']
                        new_bid_spot = 10000 / btcltc_ask
                        new_ask_spot = 10000 / btcltc_bid
                        # Assume 10% LTC risk-free rate
                        base_rate = 0.10
                        got_spot = True

                    if got_spot:
                        from datetime import datetime
                        import util
                        timedelta_to_expiry = util.timestamp_to_dt(
                            market['expiration']) - datetime.utcnow()
                        time_to_expiry = timedelta_to_expiry.total_seconds(
                        ) / (365.25 * 24 * 60 * 60)
                        # Assume 5% BTC risk-free rate
                        btc_rate = 0.0500
                        import math
                        forward_factor = Decimal(
                            math.exp((base_rate - btc_rate) * time_to_expiry))
                        new_bid = new_bid_spot * forward_factor
                        new_ask = new_ask_spot * forward_factor

                if new_ask is not None and new_bid is not None:
                    logging.info("%s: %f/%f" % (ticker, new_bid, new_ask))

                    # Make sure that the marketwe are making isn't crossed
                    if new_bid > new_ask:
                        tmp = new_bid
                        new_bid = new_ask
                        new_ask = tmp

                    # If it's matched or crossed make a spread just because
                    if self.price_to_wire(ticker,
                                          new_bid) >= self.price_to_wire(
                                              ticker, new_ask):
                        new_bid = min(new_bid, new_ask) - self.price_from_wire(
                            ticker, self.markets[ticker]['tick_size'])
                        new_ask = max(new_bid, new_ask) + self.price_from_wire(
                            ticker, self.markets[ticker]['tick_size'])

                    if ticker in self.external_markets:
                        if new_bid != self.external_markets[ticker]['bid']:
                            self.external_markets[ticker]['bid'] = new_bid
                            self.replaceBidAsk(ticker, new_bid, 'BUY')
                        if new_ask != self.external_markets[ticker]['ask']:
                            self.external_markets[ticker]['ask'] = new_ask
                            self.replaceBidAsk(ticker, new_ask, 'SELL')
                    else:
                        self.external_markets[ticker] = {
                            'bid': new_bid,
                            'ask': new_ask
                        }
                        self.replaceBidAsk(ticker, new_ask, 'SELL')
                        self.replaceBidAsk(ticker, new_bid, 'BUY')

    def replaceBidAsk(self, ticker, new_ba, side):
        self.cancelOrders(ticker, side)
        if self.markets[ticker]['contract_type'] == "futures":
            quantity = 10
        else:
            quantity = 2.5

        self.placeOrder(ticker, quantity, new_ba, side)

    def monitorOrders(self):
        for ticker, market in self.external_markets.iteritems():
            # Make sure we have orders open for both bid and ask
            for side in ['BUY', 'SELL']:
                total_qty = 0
                for id, order in self.orders.items():
                    if order['side'] == side and order[
                            'is_cancelled'] is False and order[
                                'contract'] == ticker:
                        total_qty += order['quantity_left']

                if self.markets[ticker]['contract_type'] == "futures":
                    qty_to_add = Decimal(10)
                else:
                    qty_to_add = Decimal(2.5)

                if qty_to_add > total_qty:
                    if side == 'BUY':
                        price = market['bid']
                    else:
                        price = market['ask']

                    self.placeOrder(ticker, qty_to_add - total_qty, price,
                                    side)
Beispiel #14
0
                         password=args.get("password"),
                         token_file=token_file)

    extent = geojson.load(open(geojson_file))
    satelit = SatelliteImagery("gbdx", "idaho-pansharpened")
    search = SearchScene(satelit, extent, headers=auth.headers())
    status, pipelineId = search.initiate()
    search.wait_till_job_is_done()

    # Searching Scene is done
    if search.status == "RESOLVED":
        search.retrieve()
        for metadata in search.results:
            # get detections and draw cars to image
            features = []
            kraken = Kraken(metadata.sceneId, extent, "cars", auth.headers())
            kraken.initiate()
            kraken.wait_till_job_is_done()
            if kraken.status == "RESOLVED":
                kraken.retrieve()
                features.extend(kraken.features)

                # download .ski file and extract image
                getimage = GetImage(sceneId=metadata.sceneId,
                                    extent=extent,
                                    headers=auth.headers())
                getimage.initiate()
                getimage.wait_till_job_is_done()
                if getimage.status == "RESOLVED":
                    getimage.retrieve()
                    rgb_image = getimage.skimage.imageRGB
from kraken import Kraken
import json
def writeExample(name,result):
	fp = open('examples/'+name+'.json','w+')
	json.dump(result,fp,indent=5)
	fp.close()
k = Kraken()
writeExample('getAssetPairs',k.getAssetPairs())
writeExample('getAssetPair',k.getAssetPair(k.pairs.keys()[0]))
writeExample('getTicker',k.getTicker())
writeExample('getOrderBook',k.getOrderBook())
writeExample('getRecentTrades',k.getRecentTrades())
Beispiel #16
0
#!/bin/env python3

from kraken import Kraken

import sys

k = Kraken()

# load keys
k.load_key('keys/albus.key')

arg = {'txid': ' '.join(sys.argv[1:])}

t = k.query_private('CancelOrder', arg)

print(t)
Beispiel #17
0
def run():
    print "Starting Arb"

    k = Kraken()
    last_eth_balance = float(load_last_eth_balance())
    dao_balance = k.dao_balance()

    eth_trade_price = round(
        calc_DAO2ETH_price(float(last_eth_balance), dao_balance), 5)

    if k.latest_price() > eth_trade_price:
        eth_trade_price = k.latest_price()

    trade_id = k.trade(price=eth_trade_price, lots=dao_balance)
    if trade_id:
        while k.order_status(trade_id) != 'closed':
            print "Waiting for trade to execute"
            time.sleep(5)

        # order was executed, check how much we made
        if k.order_status(trade_id) == 'closed':
            eth_balance = k.eth_balance()
            if eth_balance > last_eth_balance:
                print "Success! We made", eth_balance - last_eth_balance, "ethereum"
                save_last_eth_balance(eth_balance)
                send_sms(eth_balance)

                # now, send to shapeshift
                print "Shapeshift refid", k.withdrawn(eth_balance)

                # check account for DAO and if > 1 that means money are here
                while k.dao_balance() < 1:
                    time.sleep(5)

                # check if all ok and go again
                if k.dao_balance() > dao_balance:
                    print "We are going again!"
                    print "DAO Balance is", k.dao_balance()

            else:
                raise Exception
        else:
            raise Exception
Beispiel #18
0
def init(pairs, config, credentials):
    """
    :param pairs: list of pairs to be monitored
    :param config: dict with data about pairs, currencies and API of exchanges
    :param credentials: dict with exchanges' credentials
    :return: list of exchanges' classes and list of minimum allowed ordered volumes
    {
        "exch1" : {
            "pair1" : [minlot1, minlot2],
            "pair2" : [minlot1, minlot2],
            ...
        },
        ...
    }
    """
    try:
        cex = CEX(credentials['cex_endpoint'], credentials['cex_api_key'], credentials['cex_api_secret'], credentials['cex_id'])
        exmo = EXMO(credentials['exmo_endpoint'], credentials['exmo_api_key'], credentials['exmo_api_secret'])
        kraken = Kraken(credentials['kraken_endpoint'], credentials['kraken_api_key'], credentials['kraken_api_secret'])
        global exchs
        exchs = {cex, exmo, kraken}
        bad_exchs = set()
        try:
            for e in exchs:
                ename = e.__class__.__name__.lower()
                limits[ename] = {}
                for pair in pairs:
                    if pair in config[ename]['converter'].keys():
                        if e == kraken:
                            min_lots = e.get_min_lot(pair)
                        else:
                            min_lots = e.get_min_lot(config[ename]['converter'][pair])

                        if min_lots is None:
                            bad_exchs.add(e)
                        else:
                            limits[ename][pair] = min_lots
            for bad_exch in bad_exchs:
                exchs.remove(bad_exch)
        except KeyError as e:
            Time = datetime.datetime.utcnow()
            EventType = "KeyError"
            Function = "init"
            Explanation = "One or more of required keys in configuration file doesn't exist"
            EventText = e
            ExceptionType = type(e)
            print("{}|{}|{}|{}|{}|{}|{}".format(Time, EventType, Function, File, Explanation, EventText,
                                                ExceptionType))
            return {}, {}
        except Exception as e:
            Time = datetime.datetime.utcnow()
            EventType = "Error"
            Function = "init"
            Explanation = "Some error occurred while getting minimum lots"
            EventText = e
            ExceptionType = type(e)
            print("{}|{}|{}|{}|{}|{}|{}".format(Time, EventType, Function, File, Explanation, EventText,
                                                ExceptionType))
            return {}, {}
        return exchs, limits
    except KeyError as e:
        Time = datetime.datetime.utcnow()
        EventType = "KeyError"
        Function = "init"
        Explanation = "One or more of exchanges' credentials doesn't exist or has incorrect name"
        EventText = e
        ExceptionType = type(e)
        print("{}|{}|{}|{}|{}|{}|{}".format(Time, EventType, Function, File, Explanation, EventText,
                                            ExceptionType))
        return {}, {}
    except Exception as e:
        Time = datetime.datetime.utcnow()
        EventType = "Error"
        Function = "init"
        Explanation = "Some error occurred during initialization of exchanges"
        EventText = e
        ExceptionType = type(e)
        print("{}|{}|{}|{}|{}|{}|{}".format(Time, EventType, Function, File, Explanation, EventText,
                                            ExceptionType))
        return {}, {}
Beispiel #19
0
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from kraken import Kraken

from multiprocessing import Pool

k = Kraken()


def f(x):
    k.query_public("Time")
    return x


pool = Pool(processes=20)

pool.map(f, range(30))

pool.close()
pool.terminate()
pool.join()