def __init__(self, api_key=None, api_secret=None, api_passphrase=None, ticker_span=100): self.api_key = api_key self.api_secret = api_secret self.api_passphrase = api_passphrase self.client = Client(api_key, api_secret, api_passphrase, sandbox=False) self.ticker_span = ticker_span #Number of candlestick data points to acquire self.kline_data = [] self.historical_data = [] now = int(time.time()) self.kline_data = np.array( self.client.get_kline_data('BTC-USDT', '1min', (now - self.ticker_span * 60), now)) self.historical_data = pd.DataFrame(self.kline_data, columns=[ 'TimeStamp', 'Open', 'Close', 'High', 'Low', 'Tx Amount', 'Tx Volume' ]) self.candle_stick = self.kline_data[0] #Most recenr candle stick info self.update_indicators()
def __init__(self, auth): self.api_uri = 'https://openapi-sandbox.kucoin.com' self.api_key = auth['api_key'] self.api_secret = auth['api_secret'] self.api_passphrase = auth['api_passphrase'] self.client = Client(self.api_key, self.api_secret, self.api_passphrase)
def KuCoinBalance(): print "Connecting To KuCoin..." time.sleep(1) client = KC_Client(KC_API_KEY, KC_API_SECRET) DefaultCoins = ["BTC", "ETH", "KCS", "NEO", "USDT"] wallets = {} for Wallet in client.get_all_balances(): # if float(Balance["Total"]): if float(Wallet["balance"]) or Wallet["coinType"] in DefaultCoins: print "\tRetrieving %s Wallet Data" % Wallet["coinType"] wallets.update({ Wallet["coinType"]: { "Address": "0", "Available": Wallet["balanceStr"], "Symbol": Wallet["coinType"], "Name": Wallet["coinType"], "NativeBalance": "0.0", "NativeCurrency": "USDT", "OnHold": Wallet["freezeBalanceStr"], "TotalAmount": Wallet["balanceStr"] } }) wallets.update({"ExchangeName": "KuCoin.com"}) print return wallets
def __init__(self, key, secret): self.logger = Logger(__name__) try: self.client = Client(key, secret) except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e)
def __init__(self): self.disabled = False api_key = env_cfg("KUCOIN_KEY") api_secret = env_cfg('KUCOIN_SECRET') if api_key is None or api_secret is None: self.disabled = True log.info( "Disable KUCOIN because either api_key or api_secret not available" ) else: self.client = Client(api_key, api_secret) self.cache = ExpiringDict(max_len=200, max_age_seconds=60)
class Kucoin: def __init__(self, key, secret): self.logger = Logger(__name__) try: self.client = Client(key, secret) except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e) def getBalances(self): try: result = self.client.get_all_balances() balances = {} for currency in result: name = currency['coinType'].upper() value = float(currency['balance']) if value > Config.BALANCE_ZERO: balances[name] = value return balances except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e)
def __init__(self, api_server: str, api_key: str, secret_key: str, timeout: float, requests_params=None): assert (isinstance(api_server, str)) assert (isinstance(api_key, str)) assert (isinstance(secret_key, str)) assert (isinstance(timeout, float)) self.api_server = api_server self.api_key = api_key self.secret_key = secret_key self.timeout = timeout self.client = Client(api_key, secret_key)
class Trader: new_table = False SMA_PERIOD = 20 EMA_PERIOD = 10 def __init__(self, api_key=None, api_secret=None, api_passphrase=None, ticker_span=100): self.api_key = api_key self.api_secret = api_secret self.api_passphrase = api_passphrase self.client = Client(api_key, api_secret, api_passphrase, sandbox=False) self.ticker_span = ticker_span #Number of candlestick data points to acquire self.kline_data = [] self.historical_data = [] now = int(time.time()) self.kline_data = np.array( self.client.get_kline_data('BTC-USDT', '1min', (now - self.ticker_span * 60), now)) self.historical_data = pd.DataFrame(self.kline_data, columns=[ 'TimeStamp', 'Open', 'Close', 'High', 'Low', 'Tx Amount', 'Tx Volume' ]) self.candle_stick = self.kline_data[0] #Most recenr candle stick info self.update_indicators() def update_indicators( self): #Call this to update the CP, SMA, and EMA arrays self.get_cp() self.get_sma() self.get_ema() return self.cp, self.sma, self.ema def get_ema(self, period=EMA_PERIOD): closing_price = [] for items in reversed(list(self.historical_data.loc[:, 'Close'])): closing_price.append(float(items)) #Gives a list var = np.array(closing_price) self.ema = np.flip(talib.EMA(var, timeperiod=period)).tolist() def get_sma(self, period=SMA_PERIOD): closing_price = [] for items in reversed(list(self.historical_data.loc[:, 'Close'])): closing_price.append(float(items)) #Gives a list var = np.array(closing_price) self.sma = np.flip(talib.SMA(var, timeperiod=period)).tolist() def get_cp(self): closing_price = [] for items in reversed(list(self.historical_data.loc[:, 'Close'])): closing_price.append(float(items)) #Gives a list self.cp = np.flip(closing_price).tolist()
def Activate_Client(): global client try: client = Client(API_KEY, API_SECRET) print('Client Activated With API Key [{}].'.format(API_KEY)) except Exception as Client_Error: print('There Was A Client Activation Error Trying Again.') Activate_Client()
def get_historical_klines_tv(symbol, interval, start_str, end_str=None): """Get Historical Klines from Kucoin (Trading View) See dateparse docs for valid start and end string formats http://dateparser.readthedocs.io/en/latest/ If using offset strings for dates add "UTC" to date string e.g. "now UTC", "11 hours ago UTC" :param symbol: Name of symbol pair e.g BNBBTC :type symbol: str :param interval: Trading View Kline interval :type interval: str :param start_str: Start date string in UTC format :type start_str: str :param end_str: optional - end date string in UTC format :type end_str: str :return: list of OHLCV values """ # init our array for klines klines = [] client = Client("", "", "") # convert our date strings to seconds start_ts = date_to_seconds(start_str) # if an end time was not passed we need to use now if end_str is None: end_str = 'now UTC' end_ts = date_to_seconds(end_str) kline_res = client.get_kline_data(symbol, interval, start_ts, end_ts) # print(kline_res) # check if we got a result if 't' in kline_res and len(kline_res['t']): # now convert this array to OHLCV format and add to the array for i in range(1, len(kline_res['t'])): klines.append( (kline_res['t'][i], kline_res['o'][i], kline_res['h'][i], kline_res['l'][i], kline_res['c'][i], kline_res['v'][i])) # finally return our converted klines return klines
def __init__(self, balance_percent_value, coin_name): #api_key = '602e39d9a2644e0006e7e2c2' #603e5c8473b5c50006582528 db = DB() config = db.connection.all() self.api_key = config[0]['api_key'] #api_secret = '2db4483e-2a76-4c2c-b533-f64a80a25c6d' self.api_secret = config[0]['api_secret'] self.api_passphrase = config[0]['api_pass'] #, sandbox=True self.client = Client(self.api_key, self.api_secret, self.api_passphrase) self.base_coin = config[1]['base_coin'] self.balance_percent = balance_percent_value self.pair = coin_name + "-" + self.base_coin
def display_order_book(pair): client = Client("", "", "") # get order book stdscr = curses.initscr() curses.curs_set(0) stdscr.addstr(0, 0, str("Pair: " + pair)) stdscr.addstr(5, 0, "------------------------------------------------") stdscr.addstr(6, 0, "Ask Price") stdscr.addstr(6, 14, "Ask Size") stdscr.addstr(6, 27, "Bid Price") stdscr.addstr(6, 40, "Bid Size") while True: try: orderbook = client.get_order_book(pair) depth = min(20, (min(len(orderbook["asks"]), len(orderbook["bids"])))) ask_prices, ask_sizes, bid_prices, bid_sizes = [], [], [], [] mid_price = str((float(orderbook["asks"][0][0]) + float(orderbook["bids"][0][0])) / 2.0) total_ask_volume = 0.0 total_bid_volume = 0.0 spread = float(orderbook["asks"][0][0]) - float(orderbook["bids"][0][0]) stdscr.addstr(2, 0, "Spread: " + str(spread)) for i in range(depth): total_ask_volume += float(orderbook["asks"][i][1]) total_bid_volume += float(orderbook["bids"][i][1]) stdscr.addstr(1, 0, "Mid Price: " + mid_price) stdscr.addstr(i+7, 0, str(orderbook["asks"][i][0])) stdscr.addstr(i+7, 14, str(orderbook["asks"][i][1])) stdscr.addstr(i+7, 27, str(orderbook["bids"][i][0])) stdscr.addstr(i+7, 40, str(orderbook["bids"][i][1])) stdscr.refresh() stdscr.addstr(3, 0, "Ask Volume: " + str(total_ask_volume)) stdscr.addstr(4, 0, "Bid Volume: " + str(total_bid_volume)) stdscr.refresh() time.sleep(2) stdscr.refresh() except KeyboardInterrupt: curses.curs_set(1) curses.endwin() break curses.curs_set(1) curses.endwin()
class Kucoin: def __init__(self): self.client = Client(s.KUCOIN_API_KEY, s.KUCOIN_API_SECRET, s.KUCOIN_API_PASSPHRASE) def get_ticker(self, symbol): _symbol = "-".join(symbol) try: item = self.client.get_ticker(_symbol) except (KucoinAPIException, Exception) as err: raise ValueError(str(err)) try: item.update(self.client.get_24hr_stats(_symbol)) except (KucoinAPIException, Exception) as err: raise ValueError(str(err)) item.update(ticker=symbol[0]) return item
async def getkuorderbooks(): exlist = ['GAS/NEO', "GAS/BTC", 'NEO/BTC', 'NEO/USDT', 'NEO/ETH', 'QTUM/NEO', 'QTUM/BTC', 'LTC/NEO', 'LTC/BTC', 'LTC/ETH'] client = Client(Key, Secret, language='en_US') obs = {} for ex in exlist: sym = ex.replace("/", "-") try: obs[ex] = await getorder(client, sym) except BaseException as e: print("Error in getting %s:%s" % (ex, e)) return obs
class KucoinLogic(BaseExchangeBL): def __init__(self, account_name='', api_key='', api_secret=''): super().__init__("kucoin", account_name, api_key, api_secret) self.kucoinClient = KucoinClient(self.api_key, self.api_secret) def getSymbolsFromExchange(self): data = self.kucoinClient.get_coin_list() symbols = set([]) for item in data: if item['coin'] not in symbols: symbols.add((item['coin'], self.exchangeName)) return symbols
def get_account_assets(): client = Client( os.environ["kucoin_key"], os.environ["kucoin_secret"], os.environ["kucoin_passphrase"], ) balances = client.get_accounts() assets = [] for balance in balances: symbol = balance["currency"] amount = float(balance["balance"]) exchange = "kucoin" asset = Asset(symbol=symbol, amount=amount, exchange=exchange) if int(amount * 1e18) > 0: assets.append(asset) return assets
class KucoinApi: def __init__(self, auth): self.api_uri = 'https://openapi-sandbox.kucoin.com' self.api_key = auth['api_key'] self.api_secret = auth['api_secret'] self.api_passphrase = auth['api_passphrase'] self.client = Client(self.api_key, self.api_secret, self.api_passphrase) def get_markets(self): markets = self.client.get_markets() return markets def check_keys(self): pass
class KucoinExchange: def __init__(self): self.disabled = False api_key = env_cfg("KUCOIN_KEY") api_secret = env_cfg('KUCOIN_SECRET') if api_key is None or api_secret is None: self.disabled = True log.info( "Disable KUCOIN because either api_key or api_secret not available" ) else: self.client = Client(api_key, api_secret) self.cache = ExpiringDict(max_len=200, max_age_seconds=60) def is_disabled(self): return self.disabled def name(self): return self.__class__.__name__ def get_balances(self): if self.disabled: raise EnvironmentError("{} is disabled".format(self.name())) if self.cache.get('balances'): return self.cache.get('balances') get_account_response = self.client.get_all_balances() balances = [{ 'exchange': 'KUCOIN', 'currency': b.get('coinType'), 'available': float(b.get('balance')) } for b in get_account_response if float(b.get('balance')) > 0] self.cache['balances'] = balances return balances
# manager.py from kucoin.client import Client import config import logging import sys import math log_format = '%(asctime)s:%(levelname)s:%(name)s: %(message)s' logging.basicConfig(filename='AMPL_manager.log', level=logging.INFO, format=log_format) client = Client(config.api_key, config.api_secret, config.api_passphrase) def truncate(number, digits): stepper = 10.0**digits return math.trunc(stepper * number) / stepper def place_order(order, stop=None): total_value = config.initial_investment * order['multiple'] price = truncate(total_value / AMPL_total_qty, 4) sell_qty = truncate(AMPL_total_qty * order['amount'], 2) if stop: stop_price = price else: stop_price = None logging.info( f'New order: {order["multiple"]}x initial value, {sell_qty:.2f}AMPL @ {price:.2f}USD' ) return client.create_limit_order(symbol=config.market,
#!/usr/bin/env python # coding=utf-8 from kucoin.client import Client from kucoin.exceptions import KucoinAPIException, KucoinRequestException, KucoinResolutionException import pytest import requests_mock client = Client('api_key', 'api_secret') def test_invalid_json(): """Test Invalid response Exception""" with pytest.raises(KucoinRequestException): with requests_mock.mock() as m: m.get('https://api.kucoin.com/v1/open/currencies', text='<head></html>') client.get_currencies() def test_api_exception(): """Test API response Exception""" with pytest.raises(KucoinAPIException): with requests_mock.mock() as m: json_obj = { "code": "UNAUTH", "msg": "Signature verification failed", "success": False, "timestamp": 1510287654892
from datetime import datetime # ______________________________________________________________________ project_folder = '/home/foxcodenine/Desktop/foxtraders_v1.0' load_dotenv(os.path.join(project_folder, '.env'), override=True) # ______________________________________________________________________ api_key = os.getenv('API_KEY') api_secret = os.getenv('API_SECRET') api_passphrase = os.getenv('API_PASSPHRASE') client = Client(api_key, api_secret, api_passphrase) # ______________________________________________________________________ currencies = client.get_currencies() def find_crypto(crypto, message): crypto = crypto.upper() for m in message: if m['name'] == crypto: pprint.pprint(m) # find_crypto('BTc', currencies)
import os.path import time import hmac import hashlib from decimal import * try: from urllib import urlencode from urlparse import urljoin except ImportError: from urllib.parse import urlencode from urllib.parse import urljoin from kucoin.client import Client kucoin_api_key = 'api_key' kucoin_api_secret = 'api_secret' client = Client(api_key='5b35631b09e5a168abec621a', api_secret='d564e70a-f45e-49cd-b13c-a31fa5bbbb9d') args = sys.argv ticker = args[1] starttime = datetime.datetime.now( datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f%Z") while (1): try: filename = ticker.split('-')[0] + "_order_book3.txt" filepath = os.path.join('kucoin_data', filename) filename1 = ticker.split('-')[0] + "_recentOrders3.txt" filepath1 = os.path.join('kucoin_data', filename1) print("Kucoin scraper 1.1 aggregating data to ", filename, " and ",
from kucoin.client import Client import datetime import numpy as np def gravity(bvolume, avolume, bprice, aprice): mid_volume = bvolume + avolume w1 = bvolume / mid_volume w2 = avolume / mid_volume return sum([(w1 * aprice), (w2 * bprice)]) client = Client(api_key='5b35631b09e5a168abec621a', api_secret='d564e70a-f45e-49cd-b13c-a31fa5bbbb9d') starttime = datetime.datetime.now( datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f%Z") hist_bestBid, hist_bestAsk, hist_spread, hist_midpoint, hist_volume, hist_midpointVolume, hist_gravity = [], [], [], [], [], [], [] n = 60 while (1): time = datetime.datetime.now( datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f%Z") market_data = client.get_order_book('OMX-BTC', limit=9999) recent_orders = client.get_recent_orders('OMX-BTC', limit=9999) print(recent_orders) break buys, sells = market_data['BUY'], market_data['SELL'] hist_bestBid.append(buys[0][0]) hist_bestAsk.append(sells[0][0]) hist_midpoint.append(np.mean([hist_bestAsk[-1], hist_bestBid[-1]]))
def __init__(self): # Output parameters, debug is not useful to normal users self.debug = True self.verbose = True # Modify this according to your personal parameters # Keys are top secret, delete them from your account if ever published self.simulate = True self.play_with_gains = True self.api_key = "thereisakeyhere" self.secret_key = "thereisakeyherebutitsasecret" self.api_client = Client(self.api_key, self.secret_key) # Fund rules are the limit you are allowing the bot to trade with, usd estimated with USDT self.fund_rules = { 'BTC': { 'no_touch_coins': 0, 'max_coins': 0.01, 'max_percent': 100 }, 'ETH': { 'no_touch_coins': 0, 'max_coins': 0.1, 'max_percent': 100 }, 'NEO': { 'no_touch_coins': 0, 'max_coins': 0.5, 'max_percent': 100 }, 'USDT': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, 'KCS': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, 'BCH': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, } self.time_limit = { # Longest time allowed for api calls 'get_book': 0.4, 'get_prices': 1 } self.gap_limit_percent = 0.001 # Minimum path earnings default at 0.1% # Don't touch this unless you know what you are doing self.rate_limits, self.call_count, self.last_timestamp = 1200, 0, 0 # Request limiter per minute, burst distribution self.trade_fee = 1 - 0.001 # Deduced from bought asset if self.simulate: self.balances = {'BTC': 0.1, 'ETH': 1, 'NEO': 0.5} else: self.balances = {} self.liquidations, self.liquidation_limit = [], 0.02 # Max tolerable loss default at 1%, fee not included self.tradePrecision, self.pairs, self.gains, self.min_amount, self.path_blacklist = {}, {}, {}, {}, {} self.paths, self.order_ids = [], ["", "", "", ""] self.last_min_calculation = 0 # Last time the minimum amount for a trade was calculated signal.signal(signal.SIGINT, self.exit_program) signal.signal(signal.SIGTERM, self.exit_program) self.program_running = True self.start_engine()
class Bot: def __init__(self): # Output parameters, debug is not useful to normal users self.debug = True self.verbose = True # Modify this according to your personal parameters # Keys are top secret, delete them from your account if ever published self.simulate = True self.play_with_gains = True self.api_key = "thereisakeyhere" self.secret_key = "thereisakeyherebutitsasecret" self.api_client = Client(self.api_key, self.secret_key) # Fund rules are the limit you are allowing the bot to trade with, usd estimated with USDT self.fund_rules = { 'BTC': { 'no_touch_coins': 0, 'max_coins': 0.01, 'max_percent': 100 }, 'ETH': { 'no_touch_coins': 0, 'max_coins': 0.1, 'max_percent': 100 }, 'NEO': { 'no_touch_coins': 0, 'max_coins': 0.5, 'max_percent': 100 }, 'USDT': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, 'KCS': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, 'BCH': { 'no_touch_coins': 0, 'max_coins': 0, 'max_percent': 100 }, } self.time_limit = { # Longest time allowed for api calls 'get_book': 0.4, 'get_prices': 1 } self.gap_limit_percent = 0.001 # Minimum path earnings default at 0.1% # Don't touch this unless you know what you are doing self.rate_limits, self.call_count, self.last_timestamp = 1200, 0, 0 # Request limiter per minute, burst distribution self.trade_fee = 1 - 0.001 # Deduced from bought asset if self.simulate: self.balances = {'BTC': 0.1, 'ETH': 1, 'NEO': 0.5} else: self.balances = {} self.liquidations, self.liquidation_limit = [], 0.02 # Max tolerable loss default at 1%, fee not included self.tradePrecision, self.pairs, self.gains, self.min_amount, self.path_blacklist = {}, {}, {}, {}, {} self.paths, self.order_ids = [], ["", "", "", ""] self.last_min_calculation = 0 # Last time the minimum amount for a trade was calculated signal.signal(signal.SIGINT, self.exit_program) signal.signal(signal.SIGTERM, self.exit_program) self.program_running = True self.start_engine() def loop(self): while self.program_running: self.log_debug("Starting new loop") # Refresh min amount if necessary if time.time() - 600 > self.last_min_calculation: self.calculate_min_amount() # Refresh blacklist self.refresh_blacklist() # Get symbols sell price success = self.reload_prices() if not success: continue # Calculate path coefficients self.log_debug("get_paths_data") path_prices = self.get_paths_data() self.log_verbose("Found {} potential path".format( len(path_prices))) self.log_verbose("Gains since started = {}".format(self.gains)) # Iterate over path in descending values for path in sorted(path_prices, key=lambda p: p["path_value"], reverse=True): path_value, coin1 = path["path_value"], path["coin1"] buy = [None, path["buy1"], path["buy2"], path["buy3"]] sym = [None, path["sym1"], path["sym2"], path["sym3"]] unique_string = "%.8f%s%s%s" % (path_value, sym[1], sym[2], sym[3]) if unique_string in self.path_blacklist: self.log_verbose("Skipping path of the blacklist") continue self.log_verbose( "Path val=%.8f;Buy(%r) %s;Buy(%r) %s;Buy(%r) %s" % (path_value, buy[1], sym[1], buy[2], sym[2], buy[3], sym[3])) # Get books details and check quantity books = [None, [], [], []] error, success = False, 0 # Call order books for i in range(1, 4): success, books[i] = self.get_order_book(buy[i], sym[i]) if not success or books[i] is None or len(books[i]) < 1: success = False break # Skip the rest if an error happened if not success: self.log_verbose("Order books could not be retrieved") break else: self.log_debug("Received all order books") # Calculate optimized quantity and price, factor in fees balance = self.balances[coin1] order1, order2, order3 = books[1].pop(), books[2].pop( ), books[3].pop() self.calc_path(balance, order1, order2, order3, path) earned, spent = path["earned"], path["spent"] # Check if the path is worth walking gains = self.apply_precision(earned - spent, coin1) min_gains = 0.1**(self.tradePrecision[coin1] - 2) if spent <= 0 or earned / spent < 1 + self.gap_limit_percent or gains < min_gains: self.log_verbose( "Path is not profitable anymore : spend %.8f get %.8f" % (spent, earned)) self.path_blacklist["%.8f%s%s%s" % (path_value, sym[1], sym[2], sym[3])] = time.time() break if False and gains < self.tradePrecision[path["coin1"]]: self.log_verbose( "Gains are too small (%.8f), skipping path" % gains) break self.log_info("Spending %.8f to earn %.8f : %s >> %s >> %s " % (spent, earned, sym[1], sym[2], sym[3])) if not self.simulate: self.program_running = False # Everything is okay close the path self.order_ids = ["", "", "", ""] warm_time = 0.01 success = self.execute_order(1, path) # Execute trade 1 A-B if success: time.sleep(warm_time) success = self.execute_order(2, path) # Execute trade 2 B-C if success: time.sleep(warm_time) success = self.execute_order( 3, path) # Execute trade 3 C-B if success: # Update available balances and gains if coin1 not in self.gains: self.gains[coin1] = 0 self.gains[coin1] = self.apply_precision( self.gains[coin1] + gains, coin1) if self.play_with_gains: self.balances[coin1] = self.apply_precision( self.balances[coin1] + gains, coin1) break # Liquidate stuck balances self.liquidate() # Wait if necessary if len(path_prices) < 1: self.log_debug("No path found, forced wait of 100ms") time.sleep(0.1) current_time = time.time() loop_wait = self.call_count * (60 / self.rate_limits) - ( current_time - self.last_timestamp) self.call_count = 0 if loop_wait > 0: self.log_verbose("Waiting %.6f seconds before next iteration" % loop_wait) time.sleep(loop_wait) self.last_timestamp = current_time self.exit_message() # SERIOUS BUSINESS, TRIPLE CHECK ! def execute_order(self, order_num, path, force_price=0, force_qty=0, is_liquidation=False): buy, symbol, quantity, price = path["buy%d" % order_num], path[ "sym%d" % order_num], path["qty%d" % order_num], path["price%d" % order_num] order_placed, order_executed, limit_reached, order_canceled = False, False, False, False if force_price > 0: price = force_price if force_qty > 0: quantity = force_qty if buy: deal_type = 'SELL' else: deal_type = 'BUY' if self.simulate: while not order_executed and not order_canceled: # Place order while not order_placed: self.log_verbose( "Trying to place %s order on %s : [Price: %.8f - Quantity: %.8f]" % (deal_type, symbol, price, quantity)) try: if buy: self.api_call("create_sell_order") time.sleep(0.05) self.log_verbose("Successfully placed sell order") else: self.api_call("create_buy_order") time.sleep(0.05) self.log_verbose("Successfully placed buy order") order_placed = True except KucoinAPIException as e: # No use in simulation if e.code is "NO_BALANCE": # Previous order not or partially filled, only order 2 or 3 self.log_verbose( "Previous order not filled, cancel it and liquidate" ) if not is_liquidation: self.feed_liquidator(order_num - 1, path) else: self.log_error( "Error while placing %s order. Verifying if order has been placed" % deal_type) warm_time = 0.3 time.sleep(warm_time) # Check order status if is_liquidation and self.simulate: # Too shit to calculate return True ret, loaded_book = None, False while not loaded_book: try: # Load books if buy: self.api_call("get_buy_orders") ret = self.api_client.get_buy_orders(symbol, limit=1) else: self.api_call("get_sell_orders") ret = self.api_client.get_sell_orders(symbol, limit=1) # Check if loaded if ret is not None and len(ret) > 0: loaded_book = True elif not is_liquidation: self.feed_liquidator(order_num, path) except KucoinAPIException as e: self.log_error( "Error during API call : error {} : {}".format( e.status_code, e.response)) if (buy and ret[0][0] >= price) or (not buy and ret[0][0] <= price): self.log_verbose("%s order filled : %.8f %s for %.8f " % (deal_type, quantity, symbol, price)) return True # Cancel order else: order_canceled = False while not order_canceled: try: self.log_verbose( "Order not executed, trying to cancel") order_canceled = True self.log_verbose("Order canceled") except: self.log_verbose( "Failed to cancel order, trying again") if not is_liquidation: self.feed_liquidator(order_num, path) return False # WARNING : Not a simulation anymore! Real money to be lost # Real money : cancel order to check execution, check dealt orders for remaining money, liquidate remaining else: # Place order while not order_placed: self.log_verbose( "Trying to place %s order on %s : [Price: %.8f - Quantity: %.8f]" % (deal_type, symbol, price, quantity)) try: if buy: self.api_call("create_sell_order") else: self.api_call("create_buy_order") ret = self.api_client.create_order(symbol=symbol, order_type=deal_type, price="%.8f" % price, amount="%.8f" % quantity) self.order_ids[order_num] = ret["orderOid"] self.log_verbose("Successfully placed order") order_placed = True except KucoinAPIException as e: if e.code == "NO_BALANCE": # Previous order not or partially filled, only order 2 or 3 self.log_verbose( "No balance, previous order may not be filled yet, checking" ) if not is_liquidation: # Check and cancel + liquidate previous order if necessary success = self.check_order(order_num - 1, path) if not success: return False self.log_verbose( "No problem with the previous order, continuing" ) order_placed = True else: self.log_error( "Error during API call : error {} : code {} : {}". format(e.status_code, e.code, e.response)) self.log_error( "Exception while placing %s order. Stop EVERYTHING" % deal_type) self.program_running = False return False # Check if order has been dealt success = self.check_order(order_num, path) return success def check_order(self, order_num, path): buy = path["buy%d" % order_num] symbol = path["sym%d" % order_num] quantity = path["qty%d" % order_num] price = path["price%d" % order_num] spent, earned = path["spent"], path["earned"] if buy: deal_type = 'SELL' precision_coin = path["coin%d" % order_num] else: deal_type = 'BUY' precision_coin = path["coin%d" % ((order_num % 3) + 1)] oid = self.order_ids[order_num] check_cancel = True # Check order execution order_failed, book_is_valid = False, True while not order_failed: time.sleep(0.020) try: self.api_call("get_dealt_orders") ret = self.api_client.get_symbol_dealt_orders( symbol=symbol, order_type=deal_type, limit=20) except KucoinAPIException as e: self.log_error("Error {}: {}".format(e.status_code, e.response)) time.sleep(0.05) # Limit spam if failure # Check if order active dealt_amount = 0 for order in ret["datas"]: if order["orderOid"] == oid: dealt_amount = dealt_amount + order["amount"] # Check the book ret = None filled_rate = 100 * dealt_amount / quantity self.log_debug("Completed %.1f percent of order" % filled_rate) if filled_rate > 99.9: self.log_debug( "Dealt threshold reached, order successfully executed") return True else: if book_is_valid: # Load order book try: if deal_type == "SELL": self.api_call("get_buy_orders") ret = self.api_client.get_buy_orders(symbol, limit=1) else: self.api_call("get_sell_orders") ret = self.api_client.get_sell_orders(symbol, limit=1) if ret and len(ret) > 0: book_line = ret.pop() if not ((deal_type == "SELL" and book_line[0] >= price) or (deal_type == "BUY" and book_line[0] <= price)): self.log_debug( "No more order in the book to close") book_is_valid = False else: self.log_debug("The book contains nothing") book_is_valid = False except KucoinAPIException as e: self.log_error("Error {}: {}".format( e.status_code, e.response)) else: order_failed = True # Try to cancel, if order is dealt it will not work while check_cancel: try: self.api_call("cancel_order") self.api_client.cancel_order(order_id=oid, order_type=deal_type) self.log_verbose( "Order %d not dealt or partially, cancelled." % order_num) check_cancel = False except KucoinAPIException as e: if e.status_code != 404: self.log_error("Error {}: {}".format( e.status_code, e.response)) time.sleep(0.1) # Limit spam if failure else: self.log_verbose( "Order not found, already dealt or never created") return True # Order can't be cancelled, it has been dealt # Handle failure # Fetch dealt orders loaded_orders = False ret = None while not loaded_orders: try: self.api_call("get_symbol_dealt_orders") ret = self.api_client.get_symbol_dealt_orders( symbol=symbol, order_type=deal_type, limit=20) loaded_orders = True except KucoinAPIException as e: self.log_error("Error {}: {}".format(e.status_code, e.response)) time.sleep(0.1) # Get dealt balance for order dealt_amount = 0 for deal in ret["datas"]: dealt_amount = self.apply_precision(dealt_amount + deal["amount"], precision_coin) spent_amount = self.apply_precision( dealt_amount * (2 - self.trade_fee), precision_coin) remaining = self.apply_precision("qty%d" % order_num - spent_amount, precision_coin) self.log_verbose( "Cancelled order detail : %.8f dealt; %.8f remaining" % (dealt_amount, remaining)) # Refactor the path to match the quantities new_spent = self.apply_precision(spent * remaining / quantity, path["coin1"]) new_earned = self.apply_precision(earned * remaining / quantity, path["coin1"]) path["spent"], path["earned"] = new_spent, new_earned path["qty%d" % order_num] = remaining # Create new path if order 1 or 2 partially dealt if order_num != 3 and dealt_amount > 0: if buy: new_precision = path["coin%d" % (order_num + 1)] else: new_precision = path["coin%d" % (((order_num + 1) % 3) + 1)] artificial_spent = self.apply_precision( spent * dealt_amount / quantity, path["coin1"]) artificial_earned = self.apply_precision( earned * dealt_amount / quantity, path["coin1"]) new_qty = self.apply_precision( path["qty%d" % order_num + 1] * dealt_amount / quantity, path[new_precision]) if new_qty > self.min_amount[new_precision]: # Create a new path only for liquidation artificial_path = dict(path_value=path["path_value"], coin1=path["coin1"], coin2=path["coin2"], coin3=path["coin3"], buy1=path["buy1"], buy2=path["buy2"], buy3=path["buy3"], sym1=path["sym1"], sym2=path["sym2"], sym3=path["sym3"], spent=artificial_spent, earned=artificial_earned, qty1=path["qty1"], qty2=path["qty2"], qty3=path["qty3"], price1=path["price1"], price2=path["price2"], price3=path["price3"]) # Mod quantity artificial_path["qty%d" % order_num + 1] = new_qty self.feed_liquidator(order_num + 1, artificial_path) if order_num != 1: # Add to liquidation if it failed if remaining > self.min_amount[precision_coin]: self.log_verbose( "Order %d failed, add to liquidation : Qty %.8f; Price %.8f; Sym %s; Buy%s" % (order_num, path["qty%d" % order_num], price, symbol, buy)) self.feed_liquidator(order_num, path) else: self.log_verbose( "Insufficient quantity remaining, no need to liquidate %s" % precision_coin) else: self.log_verbose("Order %d failed, no need to liquidate %s" % (order_num, path["coin1"])) return False def feed_liquidator(self, order_num, path, force_down=False): if order_num is 1: return coin1, spent = path["coin1"], path["spent"] buy, symbol, quantity, price = path["buy%d" % order_num], path[ "sym%d" % order_num], path["qty%d" % order_num], path["price%d" % order_num] self.log_verbose( "Order %d failed, add to liquidation : Qty %.8f; Price %.8f; Sym %s; Buy%s" % (order_num, quantity, price, symbol, buy)) self.liquidations.append({ "force_down": force_down, "failed_sym": symbol, "max_loss": self.liquidation_limit, "spent": spent, "path": path }) # Update available balances and gains if coin1 not in self.gains: self.gains[coin1] = 0 self.balances[coin1] = self.apply_precision( self.balances[coin1] - spent, coin1) self.gains[coin1] = self.apply_precision(self.gains[coin1] - spent, coin1) def liquidate(self): if not self.simulate: return liquidated = [] list_len, index = len(self.liquidations), 0 while index < list_len: entry = self.liquidations[index] index = index + 1 # Define the coins to deal with force_down, path, spent, max_loss, failed_sym = entry[ "force_down"], entry["path"], entry["spent"], entry[ "max_loss"], entry["failed_sym"] earned = path["earned"] if failed_sym is path[ "sym2"]: # Try trade up first then down if not profitable order_num = 2 if force_down: # Trade down coin, coin1 = path["coin2"], path["coin3"] buy = path["buy2"] qty = path["qty2"] if buy: price = path["price2"] * spent / earned else: price = path["price2"] * earned / spent else: # Trade up, default coin, coin1 = path["coin2"], path["coin1"] buy = not path["buy1"] qty = self.apply_precision(path["qty1"] * self.trade_fee, coin1) price = path["price1"] else: # Trade down order_num = 3 coin, coin1 = path["coin3"], path["coin1"] buy = path["buy3"] qty = path["qty3"] if buy: price = path["price3"] * spent / earned else: price = path["price3"] * earned / spent self.log_debug( "Initial values : price %.8f; qty %.8f; spent %.8f" % (price, qty, spent)) # Define the symbol if coin in self.pairs and coin1 in self.pairs[coin]: symbol = self.pairs[coin][coin1]["symbol"] else: symbol = self.pairs[coin1][coin]["symbol"] self.log_debug("Trying to liquidate %s on symbol %s" % (coin, symbol)) # Get books for coin to coin1 success, book = self.get_order_book(buy, symbol, limit=25) if not success or book is None or len(book) < 1: self.log_error("Error during api call for liquidation of %s" % coin) continue # Check if prices and quantity if buy: book.sort(key=lambda order: order[0], reverse=True) limit_price, max_qty = book[0][0], book[0][1] book.pop() while max_qty < qty and len( book ) > 0: # Consume orders until qty and price are good order = book.pop() limit_price = order[0] max_qty = max_qty + order[1] self.log_debug( "Calculated : qty %.8f; max_qty %.8f; price %.8f; limit_price %.8f" % (qty, max_qty, price, limit_price)) if max_qty < qty or limit_price < price * (1 - max_loss): if failed_sym is path["sym2"]: self.log_verbose( "Order 2 liquidation failed, changing trade order") entry["force_down"] = not force_down self.log_verbose( "Couldn't liquidate sell, buy price is too low : %.8f at quantity %.8f" % (limit_price, max_qty)) continue # Too low to sell back else: book.sort(key=lambda order: order[0]) limit_price, max_qty = book[0][0], book[0][1] book.pop() min_qty = qty * (1 - max_loss) max_price = price * (qty / min_qty) while max_qty < min_qty and len( book ) > 0: # Consume orders until qty and price are good order = book.pop() limit_price = order[0] max_qty = max_qty + order[1] self.log_debug( "Calculated : min_qty %.8f; max_qty %.8f; max_price %.8f; limit_price %.8f; price %.8f" % (min_qty, max_qty, max_price, limit_price, price)) if max_qty < min_qty or limit_price > max_price: if failed_sym is path["sym2"]: entry["force_down"] = not force_down self.log_verbose( "Couldn't liquidate buy, sell price is too high : %.8f at quantity %.8f" % (limit_price, min_qty)) continue # Too expensive to buy back dust_qty = 0 leftover_balance = (price * qty) - (min_qty * limit_price) if leftover_balance > 0: dust_qty = leftover_balance / limit_price self.log_debug( "dust_qty %.8f;leftover %.8f;qty %.8f; price %.8f;min_qty %.8f;limit_price %.8f" % (dust_qty, leftover_balance, qty, price, min_qty, limit_price)) qty = self.apply_precision(min_qty + dust_qty, coin) # Execute order success = self.execute_order(order_num, path, force_price=limit_price, force_qty=qty, is_liquidation=True) if not success: self.log_error( "Error during order execution for liquidation of %s" % coin) else: self.log_verbose("Successfully liquidated %.8f %s for %.8f" % (qty, symbol, limit_price)) liquidated.append(index - 1) if failed_sym is path[ "sym2"] and force_down: # Add the third step to liquidation path["earned"] = path["spent"] if buy: overspend_ratio = price / limit_price path["qty3"] = self.apply_precision( path["qty3"] / overspend_ratio, path["coin3"]) else: overspend_ratio = path["qty2"] / qty path["qty3"] = self.apply_precision( path["qty3"] / overspend_ratio, path["coin1"]) new_max_loss = max_loss - (overspend_ratio - 1) self.liquidations.append({ "force_down": False, "failed_sym": path["sym3"], "max_loss": new_max_loss, "spent": spent, "path": path }) list_len = list_len + 1 else: if buy: total = qty * limit_price * self.trade_fee else: total = qty * self.trade_fee self.balances[coin1] = self.apply_precision( self.balances[coin1] + total, coin1) self.gains[coin1] = self.apply_precision( self.gains[coin1] + total, coin1) for index in list(reversed(liquidated)): # Remove solved liquidations self.log_debug("Removing liquidation entry : {}".format( self.liquidations[index])) del self.liquidations[index] def refresh_blacklist(self): for unique_string in list(self.path_blacklist.keys()): if self.path_blacklist[unique_string] < time.time() - 10: self.log_debug("Remove path from blacklist : %s" % unique_string) del self.path_blacklist[unique_string] def get_order_book(self, buy, sym, limit=1): self.api_call("get_buy/sell_orders") start_get_book = time.time() book, success = [], False # Call the book try: if buy: book = self.api_client.get_buy_orders(sym, limit=limit) else: book = self.api_client.get_sell_orders(sym, limit=limit) success = True except: success = False self.log_error("Failed to load the order book for %s" % sym) # Handle max allowed time if time.time() - start_get_book > self.time_limit['get_book']: success = False self.log_verbose("Book request took too long") return success, book def calc_path(self, balance1, order1, order2, order3, path): # Data format : {balance, book1, book2, book3} self.log_debug("Calculating path prices and quantity") coin1, coin2, coin3 = path["coin1"], path["coin2"], path["coin3"] buy1, buy2, buy3 = path["buy1"], path["buy2"], path["buy3"] # Down the path # Hop 1 if buy1: balance1 = self.apply_precision(balance1, coin1) qty = min(order1[1], balance1) # Max I can sell balance2 = (qty * order1[0]) * self.trade_fee else: max_price = (order1[0] * order1[1]) order_buy_price = min(max_price, balance1) # Max I can spend balance2 = (order_buy_price / order1[0]) * self.trade_fee balance2 = self.apply_precision(balance2, coin2) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance1, order1, buy1)) # Hop 2 if buy2: qty = min(order2[1], balance2) # Max I can sell balance3 = (qty * order2[0]) * self.trade_fee else: max_price = (order2[0] * order2[1]) order_buy_price = min(max_price, balance2) # Max I can spend balance3 = (order_buy_price / order2[0]) * self.trade_fee balance3 = self.apply_precision(balance3, coin3) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance2, order2, buy2)) # Hop 3 if buy3: qty = min(order3[1], balance3) # Max I can sell earned = (qty * order3[0]) * self.trade_fee else: max_price = (order3[0] * order3[1]) order_buy_price = min(max_price, balance3) # Max I can spend earned = (order_buy_price / order3[0]) * self.trade_fee earned = self.apply_precision(earned, coin1) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance3, order3, buy3)) self.log_debug("Down path final balance : %.8f" % earned) # Up the path balance1, balance2, balance3 = earned, 0, 0 # Hop 3 if buy3: qty3 = self.apply_precision( (balance1 / self.trade_fee) / order3[0], coin3) # Qty sold balance3 = qty3 else: qty3 = self.apply_precision(balance1 / self.trade_fee, coin1) # Qty bought balance3 = qty3 * order3[0] balance3 = self.apply_precision(balance3, coin3) self.log_debug("Up path : balance %.8f; Order %r; isBuy %s" % (balance1, order3, buy3)) # Hop 2 if buy2: qty2 = self.apply_precision( (balance3 / self.trade_fee) / order2[0], coin2) # Qty sold balance2 = qty2 else: qty2 = self.apply_precision(balance3 / self.trade_fee, coin3) # Qty bought balance2 = qty2 * order2[0] balance2 = self.apply_precision(balance2, coin2) self.log_debug("Up path : balance %.8f; Order %r; isBuy %s" % (balance3, order2, buy2)) # Hop 1 if buy1: qty1 = self.apply_precision( (balance2 / self.trade_fee) / order1[0], coin1) # Qty sold spent = qty1 else: qty1 = self.apply_precision(balance2 / self.trade_fee, coin2) # Qty bought spent = qty1 * order1[0] spent = self.apply_precision(spent, coin1) self.log_debug("Up path : balance %.8f; Order %r; isBuy %s" % (balance2, order1, buy1)) self.log_debug("Up path final balance is %.8f" % spent) # Down the path again, adjusting precision self.log_debug("Adjusting precision and values") balance1, balance2, balance3 = spent, 0, 0 # Hop 1 if buy1: qty1 = balance1 # Max I can sell balance2 = (qty1 * order1[0]) * self.trade_fee else: qty1 = self.apply_precision(balance1 / order1[0], coin2) balance2 = qty1 * self.trade_fee balance2 = self.apply_precision(balance2, coin2) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance1, order1, buy1)) # Hop 2 if buy2: qty2 = balance2 # Max I can sell balance3 = (qty2 * order2[0]) * self.trade_fee else: qty2 = self.apply_precision(balance2 / order2[0], coin3) balance3 = qty2 * self.trade_fee balance3 = self.apply_precision(balance3, coin3) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance2, order2, buy2)) # Hop 3 if buy3: qty3 = balance3 # Max I can sell earned = (qty3 * order3[0]) * self.trade_fee else: qty3 = self.apply_precision(balance3 / order3[0], coin1) earned = qty3 * self.trade_fee earned = self.apply_precision(earned, coin1) self.log_debug("Down path : balance %.8f; Order %r; isBuy %s" % (balance3, order3, buy3)) self.log_debug("Down path final balance : %.8f" % earned) path["qty1"], path["qty2"], path["qty3"] = qty1, qty2, qty3 path["price1"], path["price2"], path["price3"] = order1[0], order2[ 0], order3[0] path["spent"], path["earned"] = spent, earned def get_paths_data(self): path_prices = [] trade_fee = self.trade_fee**3 pairs = self.pairs for path in self.paths: p0, p1, p2 = path[0], path[1], path[2] if p0 in self.balances and self.balances[p0] > 0: path_value, buy1, buy2, buy3 = 1, False, False, False # First hop if path[1] in pairs[p0]: if pairs[p0][path[1]]["sell"] <= 0: continue path_value = path_value / pairs[p0][p1]["sell"] sym1 = "%s-%s" % (p1, p0) else: path_value = path_value * pairs[p1][p0]["buy"] sym1 = "%s-%s" % (p0, p1) buy1 = True # Second hop if path[1] in pairs and p2 in pairs[p1]: if pairs[p1][p2]["sell"] <= 0: continue path_value = path_value / pairs[p1][p2]["sell"] sym2 = "%s-%s" % (p2, p1) else: path_value = path_value * pairs[p2][p1]["buy"] sym2 = "%s-%s" % (p1, p2) buy2 = True # Third hop if p2 in pairs and p0 in pairs[p2]: if pairs[p2][p0]["sell"] <= 0: continue path_value = path_value / pairs[p2][p0]["sell"] sym3 = "%s-%s" % (p0, p2) else: path_value = path_value * pairs[p0][p2]["buy"] sym3 = "%s-%s" % (p2, p0) buy3 = True path_value = path_value * trade_fee if path_value - self.gap_limit_percent > 1: path_prices.append({ "path_value": path_value, "coin1": p0, "coin2": p1, "coin3": p2, "buy1": buy1, "buy2": buy2, "buy3": buy3, "sym1": sym1, "sym2": sym2, "sym3": sym3 }) self.log_debug(path_prices) return path_prices def apply_precision(self, amount, coin): return float( format(amount - (0.1**self.tradePrecision[coin]), '.%df' % self.tradePrecision[coin])) def reload_prices(self): self.log_debug("reload_prices") start_get_prices = time.time() req = None try: self.api_call("get_trading_symbols") req = self.api_client.get_trading_symbols() success = True if time.time() - start_get_prices > self.time_limit[ 'get_prices']: # Error if call too long success = False except KucoinAPIException as e: print("Error during request : error {} : {} ".format( e.status_code, e.message)) success = False if success: pairs = self.pairs # prices = self.prices for symbol in req: coin_type, coin_type_pair, sell, buy = symbol[ "coinType"], symbol["coinTypePair"], symbol.get( "sell", 0), symbol.get("buy", 0) if coin_type_pair in pairs and coin_type in pairs[ coin_type_pair]: if sell is None: sell = 0 if buy is None: buy = 0 if buy == 0 or 1 - sell / buy >= 0.03: sell, buy = 0, 0 pairs[coin_type_pair][coin_type]["sell"] = sell pairs[coin_type_pair][coin_type]["buy"] = buy self.log_debug(pairs) return success def calculate_min_amount(self): self.reload_prices() margin = 1.1 usd_btc = self.pairs['USDT']['BTC']['sell'] for coinType in self.pairs['BTC']: usd_price = self.pairs['BTC'][coinType]['sell'] * usd_btc * margin if usd_price == 0: usd_price = 1000000 # No data, play it safe self.min_amount['coinType'] = 1 / math.log10(usd_price) self.min_amount['BTC'] = 1 / math.log10(usd_btc * margin) self.last_min_calculation = time.time() def start_engine(self): # Load list of pairs self.get_pairs_list() # Get list of coins self.get_coins_info() # Load funds available for trading based on balances, rules and volume self.get_avail_funds() self.log_info("Funds available for trading are : {}".format( self.balances)) # load prices self.calculate_min_amount() # Start analysis & trade loop self.loop() def get_pairs_list(self): try: self.api_call("get_trading_symbols") req = self.api_client.get_trading_symbols() except KucoinAPIException as e: print("Error during request : error {} : {} ".format( e.status_code, e.message)) self.get_pairs_list() return # Add all pairs to the list for pair in req: if pair["trading"]: if pair["coinTypePair"] not in self.pairs: self.pairs[pair["coinTypePair"]] = {} # self.prices["{}-{}".format(pair["coinType"], pair["coinTypePair"])] = { "buy": 0, "sell": 0 } self.pairs[pair["coinTypePair"]][pair["coinType"]] = { "buy": 0, "sell": 0, "symbol": pair["symbol"] } # Remove symbol with only one pair for QC1 in list(self.pairs.keys()): count = 0 coin = QC1 for AC1 in list(self.pairs[QC1].keys()): coin = AC1 if AC1 in self.pairs: # AC1 is a quote coin for QC2 in list(self.pairs[AC1].keys()): if QC2 in self.pairs[QC1] or (QC2 in self.pairs and QC1 in self.pairs[QC2]): self.paths.append([QC1, AC1, QC2]) count = count + 1 else: # AC1 is not a quote coin for QC2 in list(self.pairs.keys()): if AC1 in self.pairs[QC2].keys(): if QC1 != QC2: if QC1 in self.pairs[QC2] or QC2 in self.pairs[ QC1]: self.paths.append([QC1, AC1, QC2]) count = count + 1 if count == 0: del (self.pairs[QC1][coin]) # Count pairs pairs_count = 0 for QC1 in self.pairs.keys(): pairs_count = pairs_count + len(self.pairs[QC1]) self.log_debug("All tradable pairs ({}) are : \n{}".format( pairs_count, self.pairs)) def get_coins_info(self): try: self.api_call("get_coin_list") coins = self.api_client.get_coin_list() for coin in coins: self.tradePrecision[coin["coin"]] = coin["tradePrecision"] except KucoinAPIException as e: print("Error during request : error {} : {} ".format( e.status_code, e.message)) self.get_coins_info() return def get_avail_funds(self): # No real money for now # Get account balance try: self.api_call("get_all_balances") all_balances = self.api_client.get_all_balances() except KucoinAPIException as e: print("Error during request : error {} : {} ".format( e.status_code, e.message)) self.get_avail_funds() return for coin in all_balances: free_balance = coin["balance"] if free_balance > 0: self.balances[coin["coinType"]] = free_balance self.log_debug("All balances in account : {}".format(self.balances)) # Apply manual rules for symbol in list(self.balances.keys()): # Remove if symbol not in self.fund_rules: del (self.balances[symbol]) continue initial_balance = self.balances[symbol] # Remove no touch coins from balance if self.balances[symbol] > self.fund_rules[symbol][ 'no_touch_coins']: self.balances[symbol] = self.balances[ symbol] - self.fund_rules[symbol]['no_touch_coins'] else: del (self.balances[symbol]) # limit the available balance to the max percentage allowed percent_limit = initial_balance * self.fund_rules[symbol][ 'max_percent'] / 100 if self.balances[symbol] > percent_limit: self.balances[symbol] = percent_limit self.log_verbose("{} limited to {}% of total : {}".format( symbol, self.fund_rules[symbol]["max_percent"], "%.2f" % self.balances[symbol])) # limit to the max of coins allowed if self.balances[symbol] > self.fund_rules[symbol]['max_coins']: self.balances[symbol] = self.fund_rules[symbol]['max_coins'] self.log_verbose( "{} balance exceed max_coins rule, limiting to {}{}". format(symbol, self.balances[symbol], symbol)) def api_call(self, command): self.call_count = self.call_count + 1 if self.call_count > 200: sys.exit() self.log_debug("API call : {} , counter: {}".format( command, self.call_count)) def exit_message(self): self.log_info("Program interrupted, session stats :") self.log_info("Gains : \n{}".format(self.gains)) self.log_verbose("Pending liquidations : \n{}".format( self.liquidations)) self.log_verbose( "Final trading balance (Depends on balance rules) : \n{}\n".format( self.balances)) def exit_program(self, signum, frame): self.log_info("Interrupt signal received : SIG %d" % signum) self.program_running = False @staticmethod def log_error(*text): print('%.6f [ERR]' % time.time(), *text) @staticmethod def log_info(*text): print('%.6f [INF]' % time.time(), *text) def log_debug(self, *text): if self.debug: print('%.6f [DBG]' % time.time(), *text) def log_verbose(self, *text): if self.verbose: print('%.6f [VRB]' % time.time(), *text)
import pandas as pd import ta import datetime import math import numpy as np import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import dash_core_components as dcc import dash_html_components as html import dash from dash.dependencies import Input, Output #initiates Kucoin account from kucoin.client import Client client = Client("CLIENTKEY", "SECRETKEY", "PASSPHRASE") #GMail Credentials MY_ADDRESS = '' PASSWORD = '' s = smtplib.SMTP(host='smtp.gmail.com', port=587) s.starttls() s.login(MY_ADDRESS, PASSWORD) #initiates emails msg = MIMEMultipart() msg['From'] = MY_ADDRESS msg['To'] = MY_ADDRESS msg['Subject'] = "KuCoin Trading Bot" #exception module from kucoin.exceptions import KucoinAPIException
binance_gas_add = "AexzA2PoEytX3nKwTpx4fgXovFPhUzydxb" poloniex_btc_add = "1KGFzwUrLtQc8GfmWT8NRV4XfikbYKFqZh" kucion_btc_add = "14eg4a5q1tucRcBipC8aD5tS4a5i9gb5hv" binance_btc_add = "14eg4a5q1tucRcBipC8aD5tS4a5i9gb5hv" poloniex_bitcoin_withdrawl_fee = 0.0005 binance_bitcoin_withdrawl_fee = 0.001 kucoin_bitcoin_withdrawl_fee = 0.0005 binance_trading_fee = 0.001 kucoin_trading_fee = 0.001 poloniex_trading_fee = 0.0015 binance_client = BinanceClient(binance_api_key, binance_api_secret) poloniex_client = poloniex.Poloniex(poloniex_api_key, poloniex_api_secret) kucion_client = KucoinClient(kucoin_api_key, kucoin_api_secret) fixes = [{ 'coinmarketcap': 'MIOTA', 'binance': 'IOTA' }, { 'coinmarketcap': 'BCH', 'binance': 'BCC' }] max_principal_btc = 0.1 def main(): while True: df = pd.read_csv("gas-btc.csv")
async def parser(message): config.read('config.ini') binance_key = config['Binance']['binance_key'] binance_sec = config['Binance']['binance_sec'] kucoin_key = config['Kucoin']['kucoin_key'] kucoin_sec = config['Kucoin']['kucoin_sec'] kucoin_api_pass = config['Kucoin']['kucoin_api_pass'] coinmarketcap_apikey = config['API']['coinmarketcap_apikey'] blockfrost_apikey = config['API']['blockfrost_apikey'] ada_address = config['Addresses']['ada_address'] bnb_address = config['Addresses']['bnb_address'] total = [] USDT = 0. RUB = 0. # * Getting coins info from Binance try: client = binance.Client(binance_key, binance_sec) await client.load() accinfo = await client.fetch_account_information(receive_window=None) for coin in accinfo['balances']: if coin['asset'] == "USDT": USDT += float(coin['free']) elif coin['asset'] == "RUB": RUB += float(coin['free']) else: amount = float(coin['free']) ticker = coin['asset'] + "USDT" if amount > 0.000001: print(ticker[:-4] + f" amount: {amount}") coin.pop('locked') coin['amount'] = float(coin.pop('free')) total.append(coin) await client.close() except: print("Wrong Binance credentials.") bot.send_message(message.chat.id, "You entered wrong Binance credentials.") # * Getting the amount of ADA on Yoroi link_cardano = "https://cardano-mainnet.blockfrost.io/api/v0/addresses/" headers = {'project_id': blockfrost_apikey} session = Session() session.headers.update(headers) try: response = session.get(link_cardano + ada_address) data = json.loads(response.text) except (ConnectionError, Timeout, TooManyRedirects) as e: print(e) try: ada_amount = float(data['amount'][0]['quantity']) except: ada_amount = 0 bot.send_message( message.chat.id, "You entered wrong ADA address or Blockfrost API key.") if ada_amount > 1e+6: ada_amount /= 1e+6 print(f"Found {ada_amount} ADA in Cardano Wallet") if not any(d['asset'] == 'ADA' for d in total): total.append({'asset': 'ADA', 'amount': ada_amount}) else: for x in total: if x['asset'] == 'ADA': x['amount'] += ada_amount # * Getting the coins from BNB Wallet bnb_api_link = "https://dex.binance.org/api/v1/account/" response = urlopen(bnb_api_link + bnb_address) data_json = (json.loads(response.read()))['balances'] for coin in data_json: amount = float(coin['free']) ticker = coin['symbol'] if "CBB" in ticker: ticker = ticker[:-4] if amount > 0.000001: if not any(d['asset'] == ticker for d in total): total.append({'asset': ticker, 'amount': amount}) print( f"creating {ticker} with {amount} in total | From BNB Wallet" ) else: for coin in total: if coin['asset'] == ticker: coin['amount'] += amount print( f"adding to {ticker} {amount} in total | From BNB Wallet" ) break # *Getting coins from Kucoin try: client = Client(kucoin_key, kucoin_sec, kucoin_api_pass) kucoininfo = client.get_accounts() for coin in kucoininfo: if coin['type'] != 'trade': continue amount = float(coin['balance']) ticker = coin['currency'] if amount > 0.000001 and ticker != "USDT": if not any(d['asset'] == ticker for d in total): total.append({'asset': ticker, 'amount': amount}) print( f"creating {ticker} with {amount} in total | From Kucoin" ) else: for coin in total: if coin['asset'] == ticker: coin['amount'] += amount print( f"adding to {ticker} {amount} in total | From Kucoin" ) break except: print("Wrong Kucoin credentials.") bot.send_message(message.chat.id, "You entered wrong Kucoin credentials.") try: coinmarketcap_url = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest" alltickers = "" for coin in total: alltickers += (coin['asset'] + ",") alltickers = alltickers[:-1] parameters = {'symbol': alltickers} headers = { 'Accepts': 'application/json', 'X-CMC_PRO_API_KEY': coinmarketcap_apikey, } session = Session() session.headers.update(headers) response = session.get(coinmarketcap_url, params=parameters) data = json.loads(response.text) print("Got prices from Coinmarketcap") for coin in total: ticker = coin['asset'] coin['price'] = data['data'][ticker]['quote']['USD']['price'] coin['value_in_USD'] = coin['price'] * coin['amount'] total = [ i for i in total if not (i['value_in_USD'] < include_with_value_higher_than) ] total = sorted(total, key=itemgetter('value_in_USD'), reverse=True) balance = 0. for coin in total: balance += coin['value_in_USD'] balance += USDT + (RUB / 74) balance = round(balance, 2) reply_msg = "*Total balance is " + str(balance) + " $*" + "\n\n" reply_msg += "*In coins:*\n" for coin in total: if coin['amount'] >= 1: amount = str(round(coin['amount'], 2)) else: amount = str(round(coin['amount'], 6)) reply_msg += coin['asset'] + ": " + amount + " | " + \ str(round(coin['value_in_USD'], 2)) + " $\n" reply_msg += "\n*In fiat:*\n" + str(round(USDT, 2)) + " $\n" if RUB != 0: reply_msg += str(round(RUB, 2)) + " ₽\n" bot.reply_to(message, reply_msg, parse_mode='Markdown') except: print("Wrong API key for Coinmarketcap") bot.send_message(message.chat.id, "You entered wrong Coinmarketcap API key.")
class KUCoin(): global client global api_key global api_secret global api_pasphrase global balance_percent global pair global base_coin def __init__(self, balance_percent_value, coin_name): #api_key = '602e39d9a2644e0006e7e2c2' #603e5c8473b5c50006582528 db = DB() config = db.connection.all() self.api_key = config[0]['api_key'] #api_secret = '2db4483e-2a76-4c2c-b533-f64a80a25c6d' self.api_secret = config[0]['api_secret'] self.api_passphrase = config[0]['api_pass'] #, sandbox=True self.client = Client(self.api_key, self.api_secret, self.api_passphrase) self.base_coin = config[1]['base_coin'] self.balance_percent = balance_percent_value self.pair = coin_name + "-" + self.base_coin def getcurprice(self, pair): ticker = self.client.get_ticker(pair) return float(ticker['price']) def getAccounts(self, ): accounts = self.client.get_accounts() return accounts def get_max_position_available(self, currency, pair): accounts = self.getAccounts() for account in accounts: if account['currency'] == currency: balance = account['balance'] break price = self.getcurprice(pair) to_use = (float(balance) * self.balance_percent) / 100 decide_position_to_use = to_use / price return decide_position_to_use def create_sell_order(self, pair, quantity, price): order = self.client.create_limit_order(pair, Client.SIDE_SELL, price, quantity) print(order) return order def create_market_order(self): maxquantity = 0.0 try: maxquantity = round( 0.9 * self.get_max_position_available(self.base_coin, self.pair)) if maxquantity > 0.0: # place a market buy order order = self.client.create_market_order(pair, Client.SIDE_BUY, size=maxquantity) print("Done") if not order['orderId']: return "No Order Created Yet" else: return "Max quantity " + str( maxquantity) + "for Current Pair " + pair except KucoinAPIException as e: return e.message
time.sleep(2) exit() if __name__ == "__main__": parser = argparse.ArgumentParser( description="Find price gap within a platform") parser.add_argument('--coin', help='coin to be scanned, separated by dash(-).') parser.add_argument('--platform', help='Platform to trade.') parser.add_argument('--market', default='BTC-ETH', help='The two markets to trade against.') args = parser.parse_args() scan_coins = args.coin.split('-') # Get API credentials from AWS S3 bucket. abs_path = Path(Path(__file__).resolve().parents[1], CREDENTIALS_FILENAME) secret_downloader.download_secret(str(abs_path)) with abs_path.open('r') as f: credentials = json.load(f)[args.platform] markets = args.market.split('-') client = Client(credentials['api_key'], credentials['secret_key']) helper = Helper(client, markets[0], markets[1]) semaphore = threading.BoundedSemaphore(value=1) t3 = conrl() t3.start()