Beispiel #1
0
def get_binance(key, secret):
    """Get balance from binance exchange API."""

    client = BinClient(key, secret)
    acct = client.get_account()
    df = pd.DataFrame(acct['balances'])
    df['source'] = 'binance'

    df = df[['free', 'asset', 'source']]
    df.columns = ['balance', 'coin', 'source']

    return df
Beispiel #2
0
def ms_handler(bot, update):
	global last_evnt
	text = update.channel_post.text
	client = Client(key, secret_key)
	ord_book = client.get_order_book(symbol='BNBUSDT', limit=50)
	cur_evnt = text[-7:]
	if cur_evnt == last_evnt:
		return
	if cur_evnt == 'Buy BNB':
		text = 'BUY '  + '\n' + 'BIRDS: ' + ord_book['bids'][0][0] + '\n' + 'ASKS: ' + ord_book['asks'][0][0]
		last_evnt = cur_evnt
		#order = client.order_market_buy(symbol='BNBUSDT', quantity=quantity)
	else:
		text = 'SELL ' + '\n' + 'BIRDS: ' + ord_book['bids'][0][0] + '\n' + 'ASKS: '  + ord_book['asks'][0][0]
		last_evnt = cur_evnt
		#order = client.order_market_sell(symbol='BNBUSDT', quantity=quantity)
	bot.send_message(chat_id='-1001395901109', text=text)
Beispiel #3
0
class PublicAPI():
    def __init__(self):
        self.client = Client()

    def __truncate(self, f, n):
        return math.floor(f * 10**n) / 10**n

    def getClient(self):
        return self.client

    def getHistoricalData(self,
                          market='BTCGBP',
                          granularity='1h',
                          iso8601start='',
                          iso8601end=''):
        # validates the market is syntactically correct
        p = re.compile(r"^[A-Z]{6,12}$")
        if not p.match(market):
            raise TypeError('Binance market required.')

        # validates granularity is a string
        if not isinstance(granularity, str):
            raise TypeError('Granularity string required.')

        # validates the granularity is supported by Binance
        if not granularity in ['1m', '5m', '15m', '1h', '6h', '1d']:
            raise TypeError('Granularity options: 1m, 5m, 15m. 1h, 6h, 1d')

        # validates the ISO 8601 start date is a string (if provided)
        if not isinstance(iso8601start, str):
            raise TypeError('ISO8601 start integer as string required.')

        # validates the ISO 8601 end date is a string (if provided)
        if not isinstance(iso8601end, str):
            raise TypeError('ISO8601 end integer as string required.')

        # if only a start date is provided
        if iso8601start != '' and iso8601end == '':
            multiplier = 1
            if (granularity == '1m'):
                multiplier = 1
            elif (granularity == '5m'):
                multiplier = 5
            elif (granularity == '15m'):
                multiplier = 10
            elif (granularity == '1h'):
                multiplier = 60
            elif (granularity == '6h'):
                multiplier = 360
            elif (granularity == '1d'):
                multiplier = 1440

            # calculate the end date using the granularity
            iso8601end = str(
                (datetime.strptime(iso8601start, '%Y-%m-%dT%H:%M:%S.%f') +
                 timedelta(minutes=granularity * multiplier)).isoformat())

        if iso8601start != '' and iso8601end != '':
            print('Attempting to retrieve data from ' + iso8601start)
            resp = self.client.get_historical_klines(market, granularity,
                                                     iso8601start)

            if len(resp) > 300:
                resp = resp[:300]
        else:
            if granularity == '5m':
                resp = self.client.get_historical_klines(
                    market, granularity, '2 days ago UTC')
                resp = resp[-300:]
            elif granularity == '15m':
                resp = self.client.get_historical_klines(
                    market, granularity, '4 days ago UTC')
                resp = resp[-300:]
            elif granularity == '1h':
                resp = self.client.get_historical_klines(
                    market, granularity, '13 days ago UTC')
                resp = resp[-300:]
            elif granularity == '6h':
                resp = self.client.get_historical_klines(
                    market, granularity, '75 days ago UTC')
                resp = resp[-300:]
            elif granularity == '1d':
                resp = self.client.get_historical_klines(
                    market, granularity, '251 days ago UTC')
            else:
                raise Exception('Something went wrong!')

        # convert the API response into a Pandas DataFrame
        df = pd.DataFrame(resp,
                          columns=[
                              'open_time', 'open', 'high', 'low', 'close',
                              'volume', 'close_time', 'quote_asset_volume',
                              'number_of_trades',
                              'taker_buy_base_asset_volume',
                              'traker_buy_quote_asset_volume', 'ignore'
                          ])
        df['market'] = market
        df['granularity'] = granularity

        # binance epoch is too long
        df['open_time'] = df['open_time'] + 1
        df['open_time'] = df['open_time'].astype(str)
        df['open_time'] = df['open_time'].str.replace(r'\d{3}$',
                                                      '',
                                                      regex=True)

        if (granularity == '1m'):
            freq = 'T'
        elif (granularity == '5m'):
            freq = '5T'
        elif (granularity == '15m'):
            freq = '15T'
        elif (granularity == '1h'):
            freq = 'H'
        elif (granularity == '6h'):
            freq = '6H'
        else:
            freq = 'D'

        # convert the DataFrame into a time series with the date as the index/key
        try:
            tsidx = pd.DatetimeIndex(pd.to_datetime(df['open_time'], unit='s'),
                                     dtype='datetime64[ns]',
                                     freq=freq)
            df.set_index(tsidx, inplace=True)
            df = df.drop(columns=['open_time'])
            df.index.names = ['ts']
            df['date'] = tsidx
        except ValueError:
            tsidx = pd.DatetimeIndex(pd.to_datetime(df['open_time'], unit='s'),
                                     dtype='datetime64[ns]')
            df.set_index(tsidx, inplace=True)
            df = df.drop(columns=['open_time'])
            df.index.names = ['ts']
            df['date'] = tsidx

        # re-order columns
        df = df[[
            'date', 'market', 'granularity', 'low', 'high', 'open', 'close',
            'volume'
        ]]

        # correct column types
        df['low'] = df['low'].astype(float)
        df['high'] = df['high'].astype(float)
        df['open'] = df['open'].astype(float)
        df['close'] = df['close'].astype(float)
        df['volume'] = df['volume'].astype(float)

        # reset pandas dataframe index
        df.reset_index()

        return df

    def getTicker(self, market):
        # validates the market is syntactically correct
        p = re.compile(r"^[A-Z]{6,12}$")
        if not p.match(market):
            raise TypeError('Binance market required.')

        resp = self.client.get_symbol_ticker(symbol=market)

        if 'price' in resp:
            return float('{:.8f}'.format(float(resp['price'])))

        return 0.0
Beispiel #4
0
import websocket, json, pprint, talib, numpy
import config
from binance.client import Client
from binance.enums import *
import math

client = Client(config.API_KEY, config.API_SECRET, tld='com')

#exchange_info = client.get_exchange_info()
#for s in exchange_info['symbols']:
#    print(s['symbol'])

#order = client.create_order(symbol="ADAUSDT", side=SIDE_SELL, type=ORDER_TYPE_MARKET, quoteOrderQty=10)
#print(order)
asset_name = str("ADAUSDT".replace("USDT", ""))
order_info = client.get_asset_balance(asset=asset_name)
print(order_info['free'])
Beispiel #5
0
from binance.client import Client
from binance.websockets import BinanceSocketManager
from twisted.internet import reactor
from datetime import datetime
from numpy import array
from numpy import hstack

import sys
sys.path.insert(0, '..')
from config import binance_api_key, binance_api_secret
from data.get_data import get_binance_data
from data.prep_data import split_sequences_multivariate_multistep
from models.multivariate_multistep import vanilla, stacked, bidirectional

client = Client(api_key=binance_api_key, api_secret=binance_api_secret)
btc_price = {
    'error': False,
    'buy_next_period': False,
    'sell_next_period': False,
    'prev_period_price': 0
}
wallet = {'cash': 1000000, 'coins': 0, 'value': 1000000}


def refresh():
    seq_size, n_steps_in, n_steps_out = 360, 5, 2
    batch_size, num_epochs = 60, 100
    in_seq1 = array(
        get_binance_data('BTCBUSD', '1m', download=True,
                         col_name='close')[-seq_size:])
    in_seq2 = array(
Beispiel #6
0
from binance.client import Client
from binance.websockets import BinanceSocketManager
from time import sleep
import os

api_key = os.environ['API_KEY']
api_secret = os.environ['API_SECRET']
client = Client(api_key, api_secret)

klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017")
print(klines)


def process_message(msg):
    print("message type: {}".format(msg['e']))
    print(msg)
                # do something

#bm = BinanceSocketManager(client)
#bm.start_trade_socket('BNBBTC', process_message)
#bm.start()
def sell_alt(client: Client, alt: Coin, crypto: Coin):
    '''
    Sell altcoin
    '''
    trade_log = TradeLog(alt, crypto, True)
    alt_symbol = alt.symbol
    crypto_symbol = crypto.symbol
    ticks = {}
    for filt in client.get_symbol_info(alt_symbol + crypto_symbol)['filters']:
        if filt['filterType'] == 'LOT_SIZE':
            if filt['stepSize'].find('1') == 0:
                ticks[alt_symbol] = 1 - filt['stepSize'].find('.')
            else:
                ticks[alt_symbol] = filt['stepSize'].find('1') - 1
            break

    order_quantity = (math.floor(
        get_currency_balance(client, alt_symbol) * 10**ticks[alt_symbol]) /
                      float(10**ticks[alt_symbol]))
    logger.info('Selling {0} of {1}'.format(order_quantity, alt_symbol))

    alt_balance = get_currency_balance(client, alt_symbol)
    crypto_balance = get_currency_balance(client, crypto_symbol)
    logger.info('Balance is {0}'.format(alt_balance))
    order = None
    while order is None:
        order = client.order_market_sell(symbol=alt_symbol + crypto_symbol,
                                         quantity=(order_quantity))

    logger.info('order')
    logger.info(order)

    trade_log.set_ordered(alt_balance, crypto_balance, order_quantity)

    # Binance server can take some time to save the order
    logger.info("Waiting for Binance")
    time.sleep(5)
    order_recorded = False
    stat = None
    while not order_recorded:
        try:
            time.sleep(3)
            stat = client.get_order(symbol=alt_symbol + crypto_symbol,
                                    orderId=order[u'orderId'])
            order_recorded = True
        except BinanceAPIException as e:
            logger.info(e)
            time.sleep(10)
        except Exception as e:
            logger.info("Unexpected Error: {0}".format(e))

    logger.info(stat)
    while stat[u'status'] != 'FILLED':
        logger.info(stat)
        try:
            stat = client.get_order(symbol=alt_symbol + crypto_symbol,
                                    orderId=order[u'orderId'])
            time.sleep(1)
        except BinanceAPIException as e:
            logger.info(e)
            time.sleep(2)
        except Exception as e:
            logger.info("Unexpected Error: {0}".format(e))

    newbal = get_currency_balance(client, alt_symbol)
    while (newbal >= alt_balance):
        newbal = get_currency_balance(client, alt_symbol)

    logger.info('Sold {0}'.format(alt_symbol))

    trade_log.set_complete(stat['cummulativeQuoteQty'])

    return order
    def call_chart(self, other_args):
        """Process chart command"""
        if self.current_coin:
            parser = argparse.ArgumentParser(
                add_help=False,
                formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                prog="chart",
                description=
                """Display chart for loaded coin. You can specify currency vs which you want
                to show chart and also number of days to get data for.""",
            )

            if self.source == "cp":
                parser.add_argument(
                    "--vs",
                    default="usd",
                    dest="vs",
                    help="Currency to display vs coin",
                    choices=["usd", "btc", "BTC", "USD"],
                    type=str,
                )

                parser.add_argument(
                    "-d",
                    "--days",
                    default=30,
                    dest="days",
                    help="Number of days to get data for",
                    type=check_positive,
                )

            if self.source == "cg":
                parser.add_argument("--vs",
                                    default="usd",
                                    dest="vs",
                                    help="Currency to display vs coin")

                parser.add_argument(
                    "-d",
                    "--days",
                    default=30,
                    dest="days",
                    help="Number of days to get data for",
                )

            if self.source == "bin":
                client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
                interval_map = {
                    "1day": client.KLINE_INTERVAL_1DAY,
                    "3day": client.KLINE_INTERVAL_3DAY,
                    "1hour": client.KLINE_INTERVAL_1HOUR,
                    "2hour": client.KLINE_INTERVAL_2HOUR,
                    "4hour": client.KLINE_INTERVAL_4HOUR,
                    "6hour": client.KLINE_INTERVAL_6HOUR,
                    "8hour": client.KLINE_INTERVAL_8HOUR,
                    "12hour": client.KLINE_INTERVAL_12HOUR,
                    "1week": client.KLINE_INTERVAL_1WEEK,
                    "1min": client.KLINE_INTERVAL_1MINUTE,
                    "3min": client.KLINE_INTERVAL_3MINUTE,
                    "5min": client.KLINE_INTERVAL_5MINUTE,
                    "15min": client.KLINE_INTERVAL_15MINUTE,
                    "30min": client.KLINE_INTERVAL_30MINUTE,
                    "1month": client.KLINE_INTERVAL_1MONTH,
                }

                _, quotes = binance_model.show_available_pairs_for_given_symbol(
                    self.current_coin)

                parser.add_argument(
                    "--vs",
                    help="Quote currency (what to view coin vs)",
                    dest="vs",
                    type=str,
                    default="USDT",
                    choices=quotes,
                )

                parser.add_argument(
                    "-i",
                    "--interval",
                    help="Interval to get data",
                    choices=list(interval_map.keys()),
                    dest="interval",
                    default="1day",
                    type=str,
                )

                parser.add_argument(
                    "-l",
                    "--limit",
                    dest="limit",
                    default=100,
                    help="Number to get",
                    type=check_positive,
                )

            if self.source == "cb":
                interval_map = {
                    "1min": 60,
                    "5min": 300,
                    "15min": 900,
                    "1hour": 3600,
                    "6hour": 21600,
                    "24hour": 86400,
                    "1day": 86400,
                }

                _, quotes = coinbase_model.show_available_pairs_for_given_symbol(
                    self.current_coin)
                if len(quotes) < 0:
                    print(
                        f"Couldn't find any quoted coins for provided symbol {self.current_coin}"
                    )
                    return

                parser.add_argument(
                    "--vs",
                    help="Quote currency (what to view coin vs)",
                    dest="vs",
                    type=str,
                    default="USDT" if "USDT" in quotes else quotes[0],
                    choices=quotes,
                )

                parser.add_argument(
                    "-i",
                    "--interval",
                    help="Interval to get data",
                    choices=list(interval_map.keys()),
                    dest="interval",
                    default="1day",
                    type=str,
                )

                parser.add_argument(
                    "-l",
                    "--limit",
                    dest="limit",
                    default=100,
                    help="Number to get",
                    type=check_positive,
                )

            try:
                ns_parser = parse_known_args_and_warn(parser, other_args)

                if not ns_parser:
                    return

                if self.source in ["bin", "cb"]:
                    limit = ns_parser.limit
                    interval = ns_parser.interval
                    days = 0
                else:
                    limit = 0
                    interval = "1day"
                    days = ns_parser.days

                plot_chart(
                    coin=self.current_coin,
                    limit=limit,
                    interval=interval,
                    days=days,
                    currency=ns_parser.vs,
                    source=self.source,
                )

            except Exception as e:
                print(e, "\n")

        else:
            print(
                "No coin selected. Use 'load' to load the coin you want to look at.\n"
            )
Beispiel #9
0
class Trader(object):

    # Static variables
    logger = logging.getLogger("Trader")
    client = Client(API_KEY, API_SECRET)
    exchange_data_lock = threading.Lock()
    exchange_data = DictMap({})
    db_lock = threading.Lock()
    database = Database()
    close_prices = deque(maxlen=500)
    symbol_info = DictMap(client.get_symbol_info(symbol=TRADING_PAIR))
    order_queue = Queue()
    order_queue_lock = threading.Lock()
    analyzed_data = DictMap({})
    analyzed_data_lock = threading.Lock()
    buy_prices = []
    buy_prices_lock = threading.Lock()
    buying_lock = threading.Lock()
    selling_analyzed_data = DictMap({})
    buy_now_tracking = False

    def __init__(self):
        self.order_id = 0
        self.last_buy_price = None
        self.last_sell_price = None
        self.buying_lock_acquired = False
        self.partially_filled_wait_start_time = None
        self.order_wait_start_time = None
        self.stoploss_triggered = False

    def timeout(self, t, order_type='partially_filled'):
        """
        Check for timeout
        """
        if order_type == 'partially_filled':
            if int(time.time()) > (int(t) + PARTIALLY_FILLED_WAIT_TIME):
                return True
        else:
            if int(time.time()) > (int(t) + ORDER_WAIT_TIME):
                return True
        return False

    @staticmethod
    def get_exchange_data():
        """
        Get exchange data
        """
        def get_order_book(symbol):
            """
                {
                    "lastUpdateId": 1027024,
                    "bids": [
                        [
                            "4.00000000",     # PRICE
                            "431.00000000",   # QTY
                            []                # Can be ignored
                        ]
                    ],
                    "asks": [
                        [
                            "4.00000200",
                            "12.00000000",
                            []
                        ]
                    ]
                }
            """
            order_book = Trader.client.get_order_book(symbol=symbol, limit=10)
            return DictMap(order_book)

        def get_balance(asset):
            """
                {
                    "asset": "BTC",
                    "free": "4723846.89208129",
                    "locked": "0.00000000"
                }
            """
            balance = Trader.client.get_asset_balance(asset)
            return DictMap(balance)

        def get_order_book_ticker(symbol):
            """
                {
                    "symbol": "LTCBTC",
                    "bidPrice": "4.00000000",
                    "bidQty": "431.00000000",
                    "askPrice": "4.00000200",
                    "askQty": "9.00000000"
                }
            """
            ticker = Trader.client.get_orderbook_ticker(symbol=symbol)
            return DictMap(ticker)

        order_book = get_order_book(TRADING_PAIR)
        order_book_ticker = get_order_book_ticker(TRADING_PAIR)

        return DictMap({'order_book': order_book, 'ticker': order_book_ticker})

    @staticmethod
    def print_exchange_info():
        """
        Print exchange information
        """
        ask = Trader.exchange_data.ticker.askPrice
        bid = Trader.exchange_data.ticker.bidPrice
        diff = '%.8lf' % (float(ask) - float(bid))
        spread = '%.2lf' % ((float(ask) / float(bid) - 1) * 100)
        Trader.logger.info("*** ask: %s - bid: %s - diff: %s - spread: %s" %
                           (ask, bid, diff, spread))

    @staticmethod
    def update_exchange_info():
        """
        Update the exchange data periodically.
        Start as a daemon thread in main program
        """
        while True:
            Trader.logger.debug("Updating exchange data...")
            start_time = time.time()
            Trader.exchange_data_lock.acquire()
            try:
                Trader.exchange_data = Trader.get_exchange_data()
            except Exception as e:
                Trader.logger.exception(e)

            Trader.exchange_data_lock.release()
            Trader.print_exchange_info()
            end_time = time.time()
            time_diff = end_time - start_time
            if time_diff < UPDATE_EXCHANGE_WAIT_TIME:
                Trader.logger.debug("Sleeping ...")
                time.sleep(UPDATE_EXCHANGE_WAIT_TIME - time_diff)

    @staticmethod
    def get_order_status(order_id):
        """
            {
                "symbol": "LTCBTC",
                "orderId": 1,
                "clientOrderId": "myOrder1",
                "price": "0.1",
                "origQty": "1.0",
                "executedQty": "0.0",
                "status": "NEW",
                "timeInForce": "GTC",
                "type": "LIMIT",
                "side": "BUY",
                "stopPrice": "0.0",
                "icebergQty": "0.0",
                "time": 1499827319559
            }
        """
        order = Trader.client.get_order(orderId=order_id, symbol=TRADING_PAIR)
        return DictMap(order)

    def buy(self, quantity, price):
        """
        Create buy order
        """
        price = self.format_price(price)
        quantity = self.format_quantity(quantity)
        self.logger.info("Buying %s at %s..." % (str(quantity), str(price)))
        try:
            order = Trader.client.order_limit_buy(symbol=TRADING_PAIR,
                                                  quantity=quantity,
                                                  price=price,
                                                  newOrderRespType='RESULT')
        except Exception as e:
            self.logger.exception(e)
            raise
        self.last_buy_price = price
        self.logger.info("Buying order %s created." % order['orderId'])
        return order['orderId']

    def sell(self, quantity, price):
        """
        Create sell order
        """
        price = self.format_price(price)
        quantity = self.format_quantity(quantity)
        self.logger.info("Selling %s at %s..." % (str(quantity), str(price)))
        try:
            order = Trader.client.order_limit_sell(symbol=TRADING_PAIR,
                                                   quantity=quantity,
                                                   price=price,
                                                   newOrderRespType='RESULT')
        except Exception as e:
            self.logger.exception(e)
            raise
        self.last_sell_price = price
        self.logger.info("Selling order %s created." % order['orderId'])
        return order['orderId']

    def cancel(self, order_id):
        """
        Cancel open order
        """
        try:
            resp = Trader.client.cancel_order(symbol=TRADING_PAIR,
                                              orderId=order_id)
        except Exception as e:
            self.logger.exception(e)
            raise
        self.logger.info("Order %s has been cancelled." % resp['orderId'])
        return resp['orderId']

    @staticmethod
    def get_market_price():
        """
        Get market price
        """
        try:
            ticker = Trader.client.get_symbol_ticker(symbol=TRADING_PAIR)
        except Exception as e:
            Trader.logger.exception(e)
            raise
        return float(ticker['price'])

    @staticmethod
    def get_open_24h_price():
        """
        Get open price 24h
        """
        try:
            ticker = Trader.client.get_ticker(symbol=TRADING_PAIR)
        except Exception as e:
            Trader.logger.exception(e)
            raise
        return float(ticker['openPrice'])

    @staticmethod
    def get_last_close_price(limit=1):
        """
        Get recent close price
        """
        try:
            klines = Trader.client.get_klines(symbol=TRADING_PAIR,
                                              interval=KLINE_INTERVAL_1MINUTE,
                                              limit=limit)
        except Exception as e:
            Trader.logger.exception(e)
            raise
        close_prices = [float(kline[4]) for kline in klines]
        if len(close_prices) == 1:
            return close_prices[0]
        return close_prices

    @staticmethod
    def analyze(signal):
        """
        Analyze data
        """
        def calc_rsi(prices, n=14):
            deltas = np.diff(prices)
            seed = deltas[:n + 1]
            up = seed[seed >= 0].sum() / n
            down = -seed[seed < 0].sum() / n
            rs = up / down
            rsi = np.zeros_like(prices)
            rsi[:n] = 100. - 100. / (1. + rs)
            for i in range(n, len(prices)):
                delta = deltas[i - 1]  # cause the diff is 1 shorter
                if delta > 0:
                    upval = delta
                    downval = 0.
                else:
                    upval = 0.
                    downval = -delta
                up = (up * (n - 1) + upval) / n
                down = (down * (n - 1) + downval) / n
                rs = up / down
                rsi[i] = 100. - 100. / (1. + rs)
            return rsi

        def get_last_peak(data):
            np_data = np.array(data)
            peaks = (np_data >= np.roll(np_data, 1)) & (np_data > np.roll(
                np_data, -1))
            peaks = list(peaks[1:len(peaks) - 1])
            idx = len(peaks) - peaks[::-1].index(True)
            return DictMap({'index': idx, 'value': data[idx]})

        def get_last_trough(data):
            np_data = np.array(data)
            troughs = (np_data <= np.roll(np_data, 1)) & (np_data < np.roll(
                np_data, -1))
            troughs = list(troughs[1:len(troughs) - 1])
            idx = len(troughs) - troughs[::-1].index(True)
            return DictMap({'index': idx, 'value': data[idx]})

        data = list(signal)
        ema = exponential_moving_average(data[-EMA_PERIOD:], EMA_PERIOD)[-1]
        if Trader.selling_analyzed_data:
            hull_data = hull_moving_average(data[-(HULL_PERIOD + 30):],
                                            HULL_PERIOD)
        else:
            hull_data = hull_moving_average(data, HULL_PERIOD)

        # @TODO: clean up the code
        sell_now = False
        if not Trader.selling_analyzed_data:  # first time
            hd = [x for x in hull_data if x >= 0]
            last_peak = get_last_peak(hd)
            last_trough = get_last_trough(hd)
            if last_peak.index > last_trough.index:
                Trader.selling_analyzed_data.last_is_trough = False
            else:
                Trader.selling_analyzed_data.last_is_trough = True
            Trader.selling_analyzed_data.peak = last_peak.value
            Trader.selling_analyzed_data.trough = last_trough.value
            Trader.selling_analyzed_data.previous_peak = None
            Trader.selling_analyzed_data.previous_trough = None
            Trader.selling_analyzed_data.last = hull_data[-1]
        else:
            last = hull_data[-1]
            height = Trader.selling_analyzed_data.peak - Trader.selling_analyzed_data.trough
            if Trader.selling_analyzed_data.last_is_trough:
                retrace_height = last - Trader.selling_analyzed_data.trough
            else:
                retrace_height = Trader.selling_analyzed_data.peak - last

            retrace_perc = retrace_height / height * 100.0
            if Trader.selling_analyzed_data.last_is_trough:
                if retrace_perc < 0:
                    Trader.selling_analyzed_data.last_is_trough = False
                    if Trader.selling_analyzed_data.previous_trough:
                        Trader.selling_analyzed_data.trough = Trader.selling_analyzed_data.previous_trough
                if last < Trader.selling_analyzed_data.last:
                    if retrace_perc > IGNORE_SMALL_PEAK_PERCENTAGE:
                        Trader.selling_analyzed_data.last_is_trough = False
                        Trader.selling_analyzed_data.previous_peak = Trader.selling_analyzed_data.peak
                        Trader.selling_analyzed_data.peak = Trader.selling_analyzed_data.last
            else:
                if retrace_perc < 0:
                    Trader.selling_analyzed_data.last_is_trough = True
                    if Trader.selling_analyzed_data.previous_peak:
                        Trader.selling_analyzed_data.peak = Trader.selling_analyzed_data.previous_peak
                if last > Trader.selling_analyzed_data.last:  # got a new reversal
                    if retrace_perc > IGNORE_SMALL_PEAK_PERCENTAGE:
                        Trader.selling_analyzed_data.last_is_trough = True
                        Trader.selling_analyzed_data.previous_trough = Trader.selling_analyzed_data.trough
                        Trader.selling_analyzed_data.trough = Trader.selling_analyzed_data.last
                if retrace_perc >= SELL_MAX_RETRACEMENT_PERCENTAGE:
                    sell_now = True
            Trader.selling_analyzed_data.last = last
        Trader.logger.debug("selling analyze data: %s" %
                            str(Trader.selling_analyzed_data))

        rsi = calc_rsi(data[-(RSI_PERIOD + 1):], RSI_PERIOD)[-1]
        ma_spread = 100 * (ema / hull_data[-1] - 1)
        Trader.logger.debug("ema - rsi - ma_spread: %s - %s - %s" %
                            (str(ema), str(rsi), str(ma_spread)))
        buy_now = False

        if rsi < RSI_OVERSOLD_PERCENTAGE and ma_spread > MIN_MA_SPREAD and hull_data[
                -1] <= hull_data[-2]:
            Trader.buy_now_tracking = True
        else:
            if Trader.buy_now_tracking and hull_data[-1] > hull_data[
                    -2] and Trader.selling_analyzed_data.last_is_trough:
                height = Trader.selling_analyzed_data.peak - Trader.selling_analyzed_data.trough
                retrace_height = last - Trader.selling_analyzed_data.trough
                retrace_perc = retrace_height / height * 100.0
                if retrace_perc >= BUY_MAX_RETRACEMENT_PERCENTAGE:
                    buy_now = True
                    Trader.buy_now_tracking = False

        return DictMap({
            'buy_now': buy_now,
            'sell_now': sell_now,
            'ema': ema,
            'hull': hull_data[-1],
            'close': data[-1]
        })

    @staticmethod
    def analyze_market_data():
        """
        Analyze market data
        Start as daemon thread
        """
        server_time = Trader.client.get_server_time()
        server_time_offset = int(time.time() * 1000) - int(
            server_time['serverTime'])
        Trader.logger.debug("Time offset: %d" % server_time_offset)
        close_time = 0
        while True:
            Trader.logger.debug("RUNNING...")
            st = time.time()
            if len(Trader.close_prices) == 0:  # first time fetch
                data = Trader.client.get_klines(
                    symbol=TRADING_PAIR,
                    interval=KLINE_INTERVAL_1MINUTE,
                    limit=500)
                for point in data:
                    Trader.close_prices.append(float(point[4]))
                close_time = int(data[-1][6])
            else:
                current_time_with_offset = int(
                    time.time() * 1000) - server_time_offset
                Trader.logger.debug("close time: " + str(close_time))
                Trader.logger.debug("current time with offset: " +
                                    str(current_time_with_offset))
                if current_time_with_offset > close_time:
                    try:
                        data = Trader.client.get_klines(
                            symbol=TRADING_PAIR,
                            interval=KLINE_INTERVAL_1MINUTE,
                            limit=2)
                    except Exception as e:
                        Trader.logger.exception(e)
                        continue
                    close_time_new = int(data[-1][6])
                    if close_time != close_time_new:  # to avoid duplicate
                        close_time = close_time_new
                        Trader.close_prices.append(float(data[0][4]))
                        Trader.analyzed_data_lock.acquire()
                        Trader.analyzed_data = Trader.analyze(
                            Trader.close_prices)
                        Trader.logger.debug(str(Trader.analyzed_data))
                        Trader.analyzed_data_lock.release()
            et = time.time()
            if (et - st) < ANALYZE_WAIT:
                Trader.logger.debug("SLEEPING...")
                time.sleep(ANALYZE_WAIT - (et - st))

    @staticmethod
    def check_order():
        """
        Check status for orders in queue
        Start as daemon thread
        """
        while True:
            Trader.order_queue_lock.acquire()
            order_queue_empty = Trader.order_queue.empty()
            Trader.order_queue_lock.release()
            if not order_queue_empty:
                Trader.order_queue_lock.acquire()
                order_id = Trader.order_queue.get()
                Trader.order_queue_lock.release()
                Trader.logger.info("Checking for order #%d status..." %
                                   order_id)
                order_status = Trader.get_order_status(order_id)
                Trader.logger.info("Order #%s status: %s" %
                                   (order_id, order_status.status))
                Trader.db_lock.acquire()
                order_data = {
                    'order_id': str(order_id),
                    'price': order_status.price,
                    'orig_quantity': order_status.origQty,
                    'executed_quantity': order_status.executedQty,
                    'side': order_status.side,
                    'time': order_status.time,
                    'status': order_status.status
                }
                Trader.database.order_update(order_data)
                Trader.db_lock.release()
                Trader.logger.info("Checking done for order #%d" % order_id)
            else:
                Trader.logger.info(
                    "Order queue is empty. Waiting for new order...")
                time.sleep(CHECK_ORDER_WAIT_TIME)

    def update_balance(self,
                       name,
                       initial_amount=None,
                       initial_quantity=None,
                       executed_quantity=None,
                       price=None,
                       side=None,
                       first_time=False):
        """
        Update balance to database
        """
        Trader.logger.debug("Updating balance...")
        data = {'thread_name': name, 'pairs': {}}
        modifier = 1 - FEE / 100.0
        Trader.db_lock.acquire()
        if first_time:
            if not initial_amount:
                data['pairs']['initial_amount'] = '0.0'
                data['pairs']['current_amount'] = '0.0'
            else:
                data['pairs']['initial_amount'] = str(initial_amount)
                data['pairs']['current_amount'] = str(initial_amount)
            if not initial_quantity:
                data['pairs']['initial_quantity'] = '0.0'
                data['pairs']['current_quantity'] = '0.0'
            else:
                data['pairs']['initial_quantity'] = str(initial_quantity)
                data['pairs']['current_quantity'] = str(initial_quantity)
        else:
            executed_quantity = float(executed_quantity)
            price = float(price)
            current_amount = float(
                Trader.database.trader_read(
                    name, key='current_amount')['pairs']['current_amount'])
            current_quantity = float(
                Trader.database.trader_read(
                    name, key='current_quantity')['pairs']['current_quantity'])
            if executed_quantity > 0.0:
                if side == 'SELL':
                    current_quantity = current_quantity - executed_quantity
                    current_amount = current_amount + executed_quantity * price * modifier
                else:  #BUY
                    current_quantity = current_quantity + executed_quantity * modifier
                    current_amount = current_amount - executed_quantity * price
            else:
                return
            data['pairs']['current_amount'] = str(current_amount)
            data['pairs']['current_quantity'] = str(current_quantity)

        Trader.database.trader_update(data)
        Trader.db_lock.release()

    def validate(self, quantity, price):
        """
        Check validity of an order before sending it to the exchange
        """
        filters = Trader.symbol_info.filters
        price_filter = filters[0]
        lot_size_filter = filters[1]
        notional_filter = filters[2]
        min_price = float(price_filter['minPrice'])
        max_price = float(price_filter['maxPrice'])
        tick_size = float(price_filter['tickSize'])
        min_quantity = float(lot_size_filter['minQty'])
        max_quantity = float(lot_size_filter['maxQty'])
        step_size = float(lot_size_filter['stepSize'])
        min_notional = float(notional_filter['minNotional'])
        if price < min_price or price > max_price:
            raise Exception('PRICE_EXCEPTION')
        if quantity < min_quantity or quantity > max_quantity:
            raise Exception('QUANTITY_EXCEPTION')
        if price * quantity < min_notional:
            raise Exception('MIN_NOTIONAL')
        return True

    def amount_to_quantity(self, amount, price):
        """
        Calculate quantity
        """
        quantity = amount / price
        return self.format_quantity(quantity)

    def format_quantity(self, quantity):
        """
        Format quantity
        """
        step_size = float(Trader.symbol_info.filters[1]['stepSize'])
        return round(
            float(step_size * math.floor(float(quantity) / step_size)), 8)

    def format_price(self, price):
        """
        Format price
        """
        tick_size = float(Trader.symbol_info.filters[0]['tickSize'])
        return round(float(tick_size * math.floor(float(price) / tick_size)),
                     8)

    def calc_profit(self, price):
        """
        Calculate the profit
        """
        profit = (price / self.last_buy_price - 1) * 100
        return profit

    def is_profitable(self, price):
        """
        Check for profitability
        """
        if self.calc_profit(price) >= PREFERRED_PROFIT:
            return True
        return False

    def is_stoploss(self, price):
        """
        Check for loss
        """
        loss_perc = 100 * (1 - price / float(self.last_buy_price))
        if loss_perc >= STOPLOSS_TRIGGER_PERCENTAGE:
            return True
        return False

    def calc_profitable_price(self):
        """
        Calculate the profitable price
        """
        price = self.last_buy_price * (1 + PREFERRED_PROFIT / 100.0)

        return self.format_price(price)

    def calc_buy_price(self):
        """
        Calculate buy price
        """
        order_book = self.exchange_data.order_book
        orders = order_book.bids
        last_ask = float(order_book.asks[0][0])
        quantities = [float(order[1]) for order in orders]
        prices = [float(order[0]) for order in orders]
        for i in range(1, len(quantities)):
            if sum(quantities[:i]) >= (QUANTITY_COEFFICIENT * INITIAL_AMOUNT /
                                       prices[0]):
                break
        optimal_prices = prices[:i]
        tick_size = float(Trader.symbol_info.filters[0]['tickSize'])
        buy_price = optimal_prices[-1]
        while True:
            buy_price = buy_price + tick_size
            if buy_price not in optimal_prices:
                break
        buy_price = buy_price + BUY_PRICE_TICK_OFFSET * tick_size
        if buy_price > last_ask:
            buy_price = last_ask
        return self.format_price(buy_price)

    def calc_sell_price(self):
        """
        Calculate sell price
        """
        order_book = self.exchange_data.order_book
        orders = order_book.asks
        last_bid = float(order_book.bids[0][0])
        quantities = [float(order[1]) for order in orders]
        prices = [float(order[0]) for order in orders]
        for i in range(1, len(quantities)):
            if sum(quantities[:i]) >= (QUANTITY_COEFFICIENT * INITIAL_AMOUNT /
                                       prices[0]):
                break
        optimal_prices = prices[:i]
        tick_size = float(Trader.symbol_info.filters[0]['tickSize'])
        sell_price = optimal_prices[-1]
        while True:
            sell_price = sell_price - tick_size
            if sell_price not in optimal_prices:
                break
        sell_price = sell_price - SELL_PRICE_TICK_OFFSET * tick_size
        if sell_price < last_bid:
            sell_price = last_bid
        return self.format_price(sell_price)

    def calc_sell_quantity(self):
        """
        Calculate sell quantity
        """
        name = threading.currentThread().getName()
        Trader.db_lock.acquire()
        balance = float(
            Trader.database.trader_read(
                name, key='current_quantity')['pairs']['current_quantity'])
        Trader.db_lock.release()
        return self.format_quantity(balance)

    def calc_buy_quantity(self, price):
        """
        Calculate buy quantity
        """
        name = threading.currentThread().getName()
        Trader.db_lock.acquire()
        balance = float(
            Trader.database.trader_read(
                name, key='current_amount')['pairs']['current_amount'])
        Trader.db_lock.release()
        return self.amount_to_quantity(balance, price)

    def calc_price_range(self, price=None, side='buy'):
        """
        Calculate price range. 
        If the price of an open order is out of this range, cancel that order and place it again with new price.
        """
        order_book = self.exchange_data.order_book
        tick_size = float(Trader.symbol_info.filters[0]['tickSize'])
        if side == 'buy':
            orders = order_book.bids
        else:  #sell
            orders = order_book.asks
        lower_price = float(orders[0][0])
        if price:
            my_price = float(price)
            if my_price == float(orders[0][0]) and \
                           abs(my_price - float(orders[1][0])) > DIFF_TICKS * tick_size:
                lower_price = float(orders[1][0])
        quantities = [float(order[1]) for order in orders]
        for i in range(1, len(quantities)):
            if sum(quantities[:i]) >= (QUANTITY_COEFFICIENT * INITIAL_AMOUNT /
                                       lower_price):
                break
        upper_price = float(orders[i - 1][0])

        return [lower_price, upper_price]

    def buy_action(self, status=None):
        self.logger.info("*** BUY ACTION ***")
        if status == 'filled' or status == 'cancelled_partially_filled':
            if status == 'filled' and self.stoploss_triggered:
                self.stoploss_triggered = False
            self.partially_filled_wait_start_time = None
            self.order_wait_start_time = None
            Trader.buy_prices_lock.acquire()
            Trader.logger.debug("Removing price %s from buy_prices" %
                                (str(self.last_buy_price)))
            Trader.logger.debug("buy_prices: %s" % str(Trader.buy_prices))
            Trader.buy_prices = list(set(Trader.buy_prices))
            try:
                Trader.buy_prices.remove(self.last_buy_price)
            except Exception as e:
                Trader.logger.info(
                    "Probably the buy order was partially filled but not enough to sell."
                )
                Trader.logger.exception(e)
            Trader.logger.debug("buy_prices: %s" % str(Trader.buy_prices))
            Trader.buy_prices_lock.release()
        if not self.buying_lock_acquired:
            # Acquire the lock until the buying action is complete
            # It blocks other threads to avoid multiple buy orders at a time
            Trader.logger.debug("Acquiring buying lock...")
            Trader.buying_lock.acquire()
            self.buying_lock_acquired = True
            Trader.logger.debug("Buying lock acquired.")
        if not status or status == 'filled' or status == 'cancelled_partially_filled':
            self.order_id = 0
            buy_price = self.calc_buy_price()
            Trader.buy_prices_lock.acquire()
            buy_prices = Trader.buy_prices
            Trader.buy_prices_lock.release()

            Trader.analyzed_data_lock.acquire()
            buy_now = Trader.analyzed_data.buy_now
            ema = Trader.analyzed_data.ema
            Trader.analyzed_data_lock.release()

            if not ema:
                return
            perc = 100 * (ema / buy_price - 1)
            Trader.logger.info("ema - buy_price percentage: %.2lf -  buy: %s" %
                               (perc, str(buy_price)))
            if perc < EMA_TO_BUY_PRICE_PERCENTAGE:
                return
            if not buy_now:
                return
            if len(buy_prices) > 0:
                Trader.logger.debug("buy_prices: %s" % str(buy_prices))
                min_price = min(buy_prices)
                min_price_perc = (min_price / buy_price - 1) * 100
                if min_price_perc >= BUY_MORE_PRICE_PERCENTAGE:
                    pass
                else:
                    Trader.logger.info(
                        "There are incomplete actions. Waiting...")
                    return

            quantity = self.calc_buy_quantity(buy_price)
            try:
                self.validate(quantity, buy_price)
                self.order_id = self.buy(quantity, buy_price)
            except Exception as e:
                Trader.logger.exception(e)
                Trader.logger.info("An error occurred during buying.")
                Trader.logger.debug("Releasing the buying lock...")
                self.buying_lock_acquired = False
                Trader.buying_lock.release()

        elif status == 'new' or status == 'partially_filled':
            if status == 'new':
                if not self.order_wait_start_time:
                    self.order_wait_start_time = time.time()
                if not self.timeout(self.order_wait_start_time,
                                    order_type='new'):
                    return

            if status == 'partially_filled':
                if not self.partially_filled_wait_start_time:
                    self.partially_filled_wait_start_time = time.time()
                if not self.timeout(self.partially_filled_wait_start_time):
                    Trader.logger.info(
                        "Partially filled. Waiting for order to be filled...")
                    return
                else:
                    Trader.logger.info("Waiting for order timed out.")

            price_range = self.calc_price_range(side='buy',
                                                price=self.last_buy_price)
            self.logger.debug("BUY_ACTION: price_range: %s" % str(price_range))
            # if the price is not in range, cancel and try to place an order again
            if self.last_buy_price < price_range[
                    0] or self.last_buy_price > price_range[1]:
                try:
                    self.cancel(self.order_id)
                except Exception as e:
                    Trader.logger.exception(e)

    def sell_action(self, status=None):
        self.logger.info("*** SELL ACTION ***")
        sell_price = self.calc_sell_price()
        quantity = self.calc_sell_quantity()
        profitable_price = self.calc_profitable_price()

        if not status or status == 'filled' or status == 'cancelled' or status == 'cancelled_partially_filled':
            if status == 'filled' or status == 'cancelled_partially_filled':
                self.partially_filled_wait_start_time = None
                self.order_wait_start_time = None
                Trader.buy_prices_lock.acquire()
                Trader.logger.debug("Appending price %s to buy_prices" %
                                    (str(self.last_buy_price)))
                Trader.logger.debug("buy_prices: %s" % str(Trader.buy_prices))
                Trader.buy_prices.append(self.last_buy_price)
                Trader.logger.debug("buy_prices: %s" % str(Trader.buy_prices))
                Trader.buy_prices_lock.release()
                Trader.logger.debug("Releasing buying lock...")
                try:
                    Trader.buying_lock.release()
                except Exception as e:
                    Trader.logger.exception(e)
                else:
                    self.buying_lock_acquired = False
            self.order_id = -1
            Trader.analyzed_data_lock.acquire()
            sell_now = Trader.analyzed_data.sell_now
            Trader.analyzed_data_lock.release()

            if self.is_stoploss(sell_price):
                Trader.logger.info("Stop loss.")
                self.stoploss_triggered = True

            if not sell_now and not self.stoploss_triggered:
                Trader.logger.info("waiting for sell signal.")
                return

            if self.stoploss_triggered:
                loss_perc = 100 * (1 - sell_price / float(self.last_buy_price))
                if loss_perc <= STOPLOSS_PERCENTAGE and not sell_now:
                    Trader.logger.info("Stop loss: waiting for sell signal.")
                    return
                if loss_perc <= STOPLOSS_PERCENTAGE or loss_perc >= IMMEDIATELY_STOPLOSS_PERCENTAGE:
                    Trader.logger.info("Selling at %.2lf percent loss." %
                                       loss_perc)
                    quantity = self.calc_sell_quantity()
                else:
                    return
            elif self.is_profitable(sell_price):
                Trader.logger.info(
                    "The profit is %.2lf. Try to sell it. Least profitable_price is %.8lf."
                    % (self.calc_profit(sell_price), profitable_price))
            else:
                Trader.logger.info("Least profitable_price is %.8lf." %
                                   (profitable_price))
                return
            try:
                self.validate(quantity, sell_price)
                self.order_id = self.sell(quantity, sell_price)
            except Exception as e:
                Trader.logger.exception(e)
                if status == 'cancelled_partially_filled':
                    raise
                Trader.logger.error(
                    "Cannot sell. Please handle it manually. Exiting...")
                sys.exit(1)

        elif status == 'new' or status == 'partially_filled':
            if status == 'new':
                if not self.order_wait_start_time:
                    self.order_wait_start_time = time.time()
                if not self.timeout(self.order_wait_start_time,
                                    order_type='new'):
                    return

            if status == 'partially_filled':
                if not self.partially_filled_wait_start_time:
                    self.partially_filled_wait_start_time = time.time()
                if not self.timeout(self.partially_filled_wait_start_time):
                    Trader.logger.info("Waiting for order to be filled...")
                    return
                else:
                    Trader.logger.info("Waiting for filled order timed out.")

            price_range = self.calc_price_range(price=self.last_sell_price)
            self.logger.debug(
                "SELL_ACTION: last_sell: %s - sell_price: %s - price_range: %s"
                %
                (str(self.last_sell_price), str(sell_price), str(price_range)))
            if self.is_profitable(sell_price) or self.stoploss_triggered:
                if self.last_sell_price > price_range[
                        0] or self.last_sell_price < price_range[1]:
                    try:
                        self.cancel(self.order_id)
                    except Exception as e:
                        Trader.logger.exception(e)
                        Trader.logger.info(
                            "Cannot cancel order #%s. Maybe it has already fully filled."
                            % str(self.order_id))

    def trade(self):
        """
        Trading logic
        """
        name = threading.currentThread().getName()
        self.logger.info("%s starting...", name)
        self.update_balance(name,
                            initial_amount=INITIAL_AMOUNT,
                            first_time=True)
        while True:
            # make a copy of exchange data
            Trader.exchange_data_lock.acquire()
            self.exchange_data = Trader.exchange_data
            Trader.exchange_data_lock.release()
            if self.order_id == 0:
                self.buy_action()
            elif self.order_id == -1:
                self.sell_action()
            else:
                Trader.db_lock.acquire()
                order_data = Trader.database.order_read(self.order_id)
                Trader.db_lock.release()
                if not order_data:
                    Trader.logger.info(
                        "Waiting for order data to be available... Sleeping for a while..."
                    )
                    time.sleep(CHECK_ORDER_WAIT_TIME)
                else:
                    order_data = DictMap(order_data)
                    if order_data.status == 'NEW' and order_data.side == 'BUY':
                        self.buy_action(status='new')
                    elif order_data.status == 'NEW' and order_data.side == 'SELL':
                        self.sell_action(status='new')
                    elif order_data.status == 'FILLED' and order_data.side == 'BUY':
                        self.update_balance(
                            name,
                            executed_quantity=order_data.executed_quantity,
                            price=order_data.price,
                            side='BUY')
                        self.sell_action(status='filled')
                    elif order_data.status == 'FILLED' and order_data.side == 'SELL':
                        self.update_balance(
                            name,
                            executed_quantity=order_data.executed_quantity,
                            price=order_data.price,
                            side='SELL')
                        self.buy_action(status='filled')
                    elif order_data.status == 'PARTIALLY_FILLED' and order_data.side == 'BUY':
                        self.buy_action(status='partially_filled')
                    elif order_data.status == 'PARTIALLY_FILLED' and order_data.side == 'SELL':
                        self.sell_action(status='partially_filled')
                    elif order_data.status == 'CANCELED':
                        #if the order was cancelled and executed_quantity is 0, handle it as a normal case
                        if float(order_data.executed_quantity) == 0.0:
                            if order_data.side == 'BUY':
                                self.buy_action()
                            else:
                                self.sell_action()
                        # buy all with the current amount
                        # if the amount is not enough, sell more
                        else:
                            self.update_balance(
                                name,
                                executed_quantity=order_data.executed_quantity,
                                price=order_data.price,
                                side=order_data.side)
                            Trader.db_lock.acquire()
                            current_amount = float(
                                Trader.database.trader_read(
                                    name, key='current_amount')['pairs']
                                ['current_amount'])
                            current_quantity = float(
                                Trader.database.trader_read(
                                    name, key='current_quantity')['pairs']
                                ['current_quantity'])
                            Trader.db_lock.release()
                            if current_quantity * float(
                                    order_data.price) > float(
                                        Trader.symbol_info.filters[2]
                                        ['minNotional']):
                                if order_data.side == 'BUY':
                                    self.sell_action(
                                        status='cancelled_partially_filled')
                                else:  # sell more when the selling order was partially filled
                                    self.sell_action()
                            else:
                                try:
                                    self.buy_action(
                                        status='cancelled_partially_filled')
                                except:
                                    Trader.logger.info(
                                        'Order was partially filled. Unable to buy or sell. Please handle it manually.'
                                    )
                                    Trader.logger.info('%s exits now...' %
                                                       name)
                                    sys.exit(1)
            # Only put an order to the queue if its orderId > 0
            if int(self.order_id) > 0:
                Trader.order_queue_lock.acquire()
                Trader.order_queue.put(self.order_id)
                Trader.order_queue_lock.release()

            time.sleep(TRADER_WAIT_TIME)
Beispiel #10
0
def getTRXUSD(key, pwd):
    client = Client(key, pwd)
    ticker = client.get_symbol_ticker(symbol='TRXUSDT')
    return float(ticker["price"])
Beispiel #11
0
 def __init__(self, k, s):
     self.k, self.s = k, s
     self.client = Client(self.k, self.k)
     self.request_count = 0
import requests
import time
from pprint import pprint
import numpy
import sys
import os
import pickle
import gzip
import datetime
from binance.client import Client

while True:
    api_key = '41EwcPBxLxrwAw4a4W2cMRpXiQwaJ9Vibxt31pOWmWq8Hm3ZX2CBnJ80sIRJtbsI'
    api_secret = 'pnHoASmoe36q54DZOKsUujQqo4n5Ju25t5G0kBaioZZgGDOQPEHqgDDPA6s5dUiB'
    client = Client(api_key, api_secret)

    asset_balance = client.get_asset_balance(asset='BTC')
    # pprint(asset_balance)
    account_btc_balance = float(asset_balance['free']) + float(
        asset_balance['locked'])
    print('account_btc_balance', account_btc_balance)

    ryan_btc_before_bots = 1.76225309 + 2.00011051 + 2.26803360 + 1.75044720 + 1.44937472
    #9.23021912

    ryans_symbols = {
        'TRXBTC': 575806,
        'ADABTC': 0,
        'XRPBTC': 9734.518,
        'BNBBTC': 850.6494634,
Beispiel #13
0
 def __init__(self):
     self.client = Client(settings.api_key, settings.api_secret)
# Jason Bonilla
# Live sentiment analysis trading bot that handles cryptocurrencies specifically
# Bitcoin, based off the overall sentiment of live comments under r/bitcoin
import praw
import config
from textblob import TextBlob
from binance.client import Client
from binance.enums import *

# Passing API key and API secret
client = Client(config.BINANCE_KEY, config.BINANCE_SECRET, tld='us')

# configuring the python Reddit API wrapper
reddit = praw.Reddit(
    client_id=config.REDDIT_ID,
    client_secret=config.REDDIT_SECRET,
    password=config.REDDIT_PASS,
    user_agent="USERAGENT",
    username=config.REDDIT_USER,
)

sentimentList = []
neededSentiments = 300

TRADE_SYMBOL = 'BTCUSDT'
TRADE_QUANTIY = 0.0001

# ensures that the coin is not being bought repeatedly
# waits until a sell signal is recieved in order to proceed
in_position = False
Beispiel #15
0
#!/usr/bin/env python
# -*- coding: utf-8 -*- 
import requests
import json
import math
import datetime
import key
import telegram
import sys

from binance.client import Client
client = Client(key.api_key, key.api_secret)

from telegram import (Animation, Audio, Contact, Document, Chat, Location,
                      PhotoSize, Sticker, TelegramObject, User, Video, Voice,
                      Venue, MessageEntity, Game, Invoice, SuccessfulPayment,
                      VideoNote, PassportData)

bot = telegram.Bot(token=key.token)
bot.send_message(chat_id=key.chat_id, text="Start NuBot")

def RSI14(market, tick_interval):
  try:
    licznik = 1
    avaGain = 0
    avaLoss = 0
    #parms
    #market = 'GTOBTC'
    #tick_interval = '1h'
    url = 'https://api.binance.com/api/v1/klines?symbol=' + market + '&interval=' + tick_interval + '&limit=17'
    data = requests.get(url).json()
 def setKey(self):
     from binance.client import Client
     import config
     import sys
     client = Client(config.api_key, config.api_secret)
     return client
Beispiel #17
0
from tkinter import *
from binance.client import Client
from pprint import pprint
import time

api_key = '7'
api_secret = ''

client = Client(api_key, api_secret)

# Account endpoint / Account info
info = client.get_account()
# pprint(info)

doge = client.get_asset_balance(asset='DOGE')
usdt = client.get_asset_balance(asset='USDT')
print('DOGE', doge)
print('USDT', usdt)

try:
    print(doge['asset'])
except TypeError:
    textdoge = 'DOGE : None'
else:
    textdoge = '{} : {} (In order: {})'.format(doge['asset'], doge['free'],
                                               doge['locked'])

try:
    print(usdt['asset'])
except TypeError:
    textusdt = 'USDT : None'
Beispiel #18
0
class Bian(object):
    client = None
    action = None
    db = None
    cursor = None
    action = None

    use_conf = None
    cache_data = None
    proxies = {
        'http': 'http://127.0.0.1:1087',
        'https': 'http://127.0.0.1:1087',
    }

    def __init__(self):
        if len(sys.argv) < 2:
            print("your command is error")
            return

        self.action = sys.argv[1]
        self.use_conf = dict(conf_main.config)
        self.use_conf.update(conf_local.config)

        self.db = pymysql.connect(host="47.75.110.210",
                                  user="******",
                                  password=self.use_conf['db_password'],
                                  db="huobi",
                                  port=3306,
                                  charset="utf8")
        self.cursor = self.db.cursor()

        self.client = Client(
            'PBM4vgJTZ0aWKKaIeB720VqUm9TQDzcdW3yxnpdd0Urj9niLjT1D1YGpU65RUDaa',
            'aMDicDTNI7J0Qhzh2RDmNj2jc7Y2fjsTvLM8Np5Cft0uAeqa4ZVHbg8JG8UFJctK',
            {
                # "proxies": self.proxies,
                "verify": True,
                "timeout": 20
            })

    def test(self):
        # data = self.client.get_recent_trades(symbol='BNBBTC')
        # data = self.client.get_historical_klines("BNBBTC", Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC")
        data = self.client.get_klines(symbol='BTCUSDT',
                                      interval=Client.KLINE_INTERVAL_1MINUTE)
        print(data)

    def get_cache(self):
        cache_sql = '''select buy_code from bian_base_detail order by id desc limit 800 '''
        self.cursor.execute(cache_sql)
        data = self.cursor.fetchall()
        if data is not None:
            cache_data = [x[0] for x in data]
            return cache_data
        return []

    def get_trades(self):
        data = self.client.get_recent_trades(symbol='BTCUSDT')
        if data is not None:
            # 加载缓存
            self.cache_data = self.get_cache()
            for item in data:
                ts_time = time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.localtime(int(round(item['time'] / 1000))))
                # 进行去重
                if str(item['id']) in self.cache_data:
                    continue
                else:
                    now_time = time.strftime("%Y-%m-%d %H-%M-%S",
                                             time.localtime(time.time()))
                    if True == item['isBuyerMaker']:
                        item['isBuyerMaker'] = 1
                    elif False == item['isBuyerMaker']:
                        item['isBuyerMaker'] = 0

                    if True == item['isBestMatch']:
                        item['isBestMatch'] = 1
                    elif False == item['isBestMatch']:
                        item['isBestMatch'] = 0

                    use_sql = '''insert into bian_base_detail (symbol, qty, price, ts_id, isBuyerMaker, isBestMatch, 
buy_code, ts, created_at, updated_at) values ('%s', %f, %f, %d, %d, %d, '%s', '%s', '%s', '%s') ''' % (
                        'btc_usdt', float(item['qty']), float(item['price']),
                        int(item['time']), int(
                            item['isBuyerMaker']), int(item['isBestMatch']),
                        item['id'], ts_time, now_time, now_time)

                    try:
                        self.cursor.execute(use_sql)
                    except Exception:
                        print('this sql has some error ' + item['tid'])
                    else:
                        pass

            self.db.commit()
            self.cache_data = []
        return 'ok'

    def to_strip(self, params):
        if params == {}:
            print("need some params")
            return False
        if 'get_kline' == params['action']:
            sql = '''select id from bian_data_kline where opentime = '%s' and closetime = '%s' limit 1 ''' % (
                params['opentime'], params['closetime'])
        elif 'get_trades' == params['action']:
            sql = ''
        else:
            sql = ''

        self.cursor.execute(sql)
        data = self.cursor.fetchone()
        if data is None:
            return True
        else:
            return False

    def get_kline(self):
        data = self.client.get_klines(symbol='BTCUSDT',
                                      interval=Client.KLINE_INTERVAL_1MINUTE,
                                      limit=120)
        if data is not None:
            for item in data:
                open_time = time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.localtime(int(round(item[0] / 1000))))
                close_time = time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.localtime(int(round(item[6] / 1000))))
                # 进行去重
                if self.to_strip({
                        'opentime': open_time,
                        'closetime': close_time,
                        'action': 'get_kline'
                }):
                    now_time = time.strftime('%Y-%m-%d %H:%M:%S',
                                             time.localtime(time.time()))
                    use_sql = '''insert into bian_data_kline (symbol, period, opentime, open, high, low, close, volumn, closetime, 
quote_asset_volume, number_of_trades, buy_base_asset_volume, buy_quote_asset_volume, `ignore`, created_at, updated_at) values ('%s', '%s', '%s', 
%f, %f, %f, %f, %f, '%s', %f, %d, %f, %f, %f, '%s', '%s') ''' % (
                        'btc_usdt', '1min', open_time, float(item[1]),
                        float(item[2]), float(item[3]), float(item[4]),
                        float(item[5]), close_time, float(item[7]), int(
                            item[8]), float(item[9]), float(
                                item[10]), float(item[11]), now_time, now_time)

                    try:
                        self.cursor.execute(use_sql)
                    except Exception:
                        print("this sql has some error " + use_sql)
                    else:
                        pass

            self.db.commit()

        return 'ok'
Beispiel #19
0
class binanceThread(QThread):
    binance_data = pyqtSignal(dict)

    def __init__(self):
        QThread.__init__(self)
        self.mutex = QMutex()
        self.binance = Client()
        self.binanceList = list()
        self.exchange_rate = float(1100)
        self.isRun = True

    def delSymbol(self, symbol):
        if symbol + "BTC" in self.binanceList:
            self.binanceList.remove(symbol + "BTC")

    def _start(self):
        self.isRun = True
        self.start()

    def stop(self):
        self.isRun = False

    def get_symbol_list(self):
        binanceList = list()
        try:
            for i in self.binance.get_all_tickers():
                symbol = i['symbol']
                if symbol[-3:] == 'BTC':
                    binanceList.append(symbol[:-3])
                if symbol == 'BTCUSDT':
                    binanceList.append(symbol[:-4])
        except Exception as e:
            debuginfo(e)
            pass
        return binanceList

    def save_list(self, list):
        for i in list:
            if i == 'BTC':
                self.binanceList.append('BTCUSDT')
            else:
                self.binanceList.append(i + 'BTC')

    def get_dollor(self):
        try:
            res = requests.get('http://finance.naver.com/')
            text = res.text
            soup = BeautifulSoup(text, 'html.parser')
            td = soup.select_one(
                "#content > div.article2 > div.section1 > div.group1 > table > tbody > tr > td"
            )
            exchange_rate = ''
            for i in td.text:
                if i == ',':
                    pass
                else:
                    exchange_rate += i
            self.exchange_rate = float(exchange_rate)
        except Exception as e:
            debuginfo(e)

    def get_prices(self):
        prices = dict()
        try:
            for i in self.binance.get_all_tickers():
                prices[i['symbol']] = i['price']
        except Exception as e:
            debuginfo(e)
            pass
        return prices

    def get_orderbooks(self):
        orderbooks = dict()
        try:
            for i in self.binance.get_orderbook_tickers():
                orderbooks[i['symbol']] = dict()
                orderbooks[i['symbol']]['bidPrice'] = i['bidPrice']
                orderbooks[i['symbol']]['bidQty'] = i['bidQty']
                orderbooks[i['symbol']]['askPrice'] = i['askPrice']
                orderbooks[i['symbol']]['askQty'] = i['askQty']
        except Exception as e:
            debuginfo(e)
            pass
        return orderbooks

    def calculate_krw(self, price, BTCUSDT, exchange_rate):
        return str(round(float(price) * BTCUSDT * exchange_rate, 2))

    def run(self):
        while self.isRun:
            self.mutex.lock()
            binanceDict = dict()
            self.get_dollor()
            prices = self.get_prices()
            orderbooks = self.get_orderbooks()

            try:
                BTCUSDT = float(prices['BTCUSDT'])
                binanceDict['BTC'] = dict()
                binanceDict['BTC']['price'] = str(
                    round(BTCUSDT * self.exchange_rate, 2))
                binanceDict['BTC']['ask'] = str(
                    round(
                        float(orderbooks['BTCUSDT']['askPrice']) *
                        self.exchange_rate, 2)) + '/' + str(
                            round(float(orderbooks['BTCUSDT']['askQty']), 2))
                binanceDict['BTC']['bid'] = str(
                    round(
                        float(orderbooks['BTCUSDT']['bidPrice']) *
                        self.exchange_rate, 2)) + '/' + str(
                            round(float(orderbooks['BTCUSDT']['bidQty']), 2))

            except Exception as e:
                debuginfo(e)

            for i in self.binanceList:
                if i == 'BTCUSDT':
                    continue
                try:
                    symbol = i.replace('BTC', '')
                    binanceDict[symbol] = dict()
                    binanceDict[symbol]['price'] = self.calculate_krw(
                        prices[i], BTCUSDT, self.exchange_rate)
                    binanceDict[symbol]['ask'] = self.calculate_krw(
                        orderbooks[i]['askPrice'], BTCUSDT,
                        self.exchange_rate) + '/' + str(
                            round(float(orderbooks[i]['askQty']), 2))
                    binanceDict[symbol]['bid'] = self.calculate_krw(
                        orderbooks[i]['bidPrice'], BTCUSDT,
                        self.exchange_rate) + '/' + str(
                            round(float(orderbooks[i]['bidQty']), 2))
                except Exception as e:
                    debuginfo(e)
                    pass

            self.binance_data.emit(binanceDict)
            self.mutex.unlock()
def buy_alt(client: Client, alt: Coin, crypto: Coin):
    '''
    Buy altcoin
    '''
    trade_log = TradeLog(alt, crypto, False)
    alt_symbol = alt.symbol
    crypto_symbol = crypto.symbol
    ticks = {}
    for filt in client.get_symbol_info(alt_symbol + crypto_symbol)['filters']:
        if filt['filterType'] == 'LOT_SIZE':
            if filt['stepSize'].find('1') == 0:
                ticks[alt_symbol] = 1 - filt['stepSize'].find('.')
            else:
                ticks[alt_symbol] = filt['stepSize'].find('1') - 1
            break

    alt_balance = get_currency_balance(client, alt_symbol)
    crypto_balance = get_currency_balance(client, crypto_symbol)

    order_quantity = ((math.floor(
        crypto_balance * 10**ticks[alt_symbol] /
        get_market_ticker_price(client, alt_symbol + crypto_symbol)) /
                       float(10**ticks[alt_symbol])))
    logger.info('BUY QTY {0}'.format(order_quantity))

    # Try to buy until successful
    order = None
    while order is None:
        try:
            order = client.order_limit_buy(symbol=alt_symbol + crypto_symbol,
                                           quantity=order_quantity,
                                           price=get_market_ticker_price(
                                               client,
                                               alt_symbol + crypto_symbol))
            logger.info(order)
        except BinanceAPIException as e:
            logger.info(e)
            time.sleep(1)
        except Exception as e:
            logger.info("Unexpected Error: {0}".format(e))

    trade_log.set_ordered(alt_balance, crypto_balance, order_quantity)

    order_recorded = False
    while not order_recorded:
        try:
            time.sleep(3)
            stat = client.get_order(symbol=alt_symbol + crypto_symbol,
                                    orderId=order[u'orderId'])
            order_recorded = True
        except BinanceAPIException as e:
            logger.info(e)
            time.sleep(10)
        except Exception as e:
            logger.info("Unexpected Error: {0}".format(e))
    while stat[u'status'] != 'FILLED':
        try:
            stat = client.get_order(symbol=alt_symbol + crypto_symbol,
                                    orderId=order[u'orderId'])
            time.sleep(1)
        except BinanceAPIException as e:
            logger.info(e)
            time.sleep(2)
        except Exception as e:
            logger.info("Unexpected Error: {0}".format(e))

    logger.info('Bought {0}'.format(alt_symbol))

    trade_log.set_complete(stat['cummulativeQuoteQty'])

    return order
Beispiel #21
0
django.setup()

from decouple import config
from binance.client import Client

from django.forms.models import model_to_dict

from dashboard.models import PairStats, CointParams, Quotes
from dashboard.forms import PERIODOS_CALCULO
from dashboard.forms import BINANCE_FUTURES

from coint.cointegration import coint_model, beta_rotation, clean_timeseries
# TODO: Criar um arquivos com utils.py
from coint.b3_calc import create_cointparams, create_pairstats, gera_pares

client = Client(config('BINANCE_APIKEY'), config('BINANCE_SECRETKEY'))


def download_hquotes_binance():
    # Faz o calculo
    obj_buffer = []

    for idx, ticker in enumerate(BINANCE_FUTURES):
        print(idx, ticker)
        # fetch weekly klines since it listed
        klines = client.get_historical_klines(ticker,
                                              Client.KLINE_INTERVAL_1DAY,
                                              "1 Jan, 2017")

        ts_list, q_list = [], []
        for k in klines:
Beispiel #22
0
from binance.client import Client
from binance.enums import *

RSI_PERIOD = 14  # set RSI period
RSI_OVERBOUGHT = 70  # set RSI threshold
RSI_OVERSOLD = 30  # set RSI threshold
TRADE_SYMBOL = 'BTCUSD'  # set coin type
TRADE_QUANTITY = 0.05

# socket for getting candle stick data
SOCKET = "wss://stream.binance.com:9443/ws/btcusdt@kline_1m"

closes = []  # a list for storing the close prices
in_position = False  # a variable for checking if in position

client = Client(config.API_KEY, config.API_SECRET, tld='us')


def order(side, quantity, symbol, order_type=ORDER_TYPE_MARKET):
    try:
        print("sending order")
        order = client.create_order(symbol=symbol,
                                    side=side,
                                    type=order_type,
                                    quantity=quantity)
        print(order)

    except Exception as e:
        print("An exception occured - {}".format(e))
        return False
class Controller:
    def __init__(self, request, api_key, api_secret):
        self._request = request
        # init binance client
        self.__client = Client(api_key, api_secret)
        self.__api_key = api_key
        # create dir for templates
        self._env = Environment(loader=PackageLoader('main', 'templates'),
                                autoescape=select_autoescape(
                                    ['html', 'xml', 'tpl']))

    def __calc(self, symbol_ticker, in_amount):
        # get price from args
        price = symbol_ticker['price']
        # calculate excange result
        calculate_result = Decimal(price) * Decimal(in_amount.strip("'"))
        return calculate_result

    def _responce(self):
        # main view
        # get status and data
        status, data = self.__get_price()
        if status == 'OK':
            # return func that create tamplate, pass data into
            return self._get_template('index.html',
                                      title='Calc sanic',
                                      data=data)
        else:
            return self._get_template('index.html', title='Error', data=data)

    def _get_template(self, tpl, **kwargs):
        # get file .html with new from args
        template = self._env.get_template(tpl)
        # pass kwargs in template
        get_template = html(template.render(kwargs))
        return get_template

    def __generate_sign(self):
        # sort list by alphabet
        result = sorted(self.__strip_currency())
        # create part of sign
        # example: 2BTCUSDT
        prepare_sign = "{}{}{}".format(result[0], result[1], result[2])
        # encode strings
        api_key_bytes = self.__api_key.encode('UTF-8')
        prepare_sign_bytes = prepare_sign.encode('UTF-8')
        # create signature using hmac lib with alg sha256
        signature = hmac.new(api_key_bytes, prepare_sign_bytes,
                             hashlib.sha256).hexdigest()
        return signature

    def __check_sign(self):
        signature = self.__generate_sign()
        # check if sign in requests headers
        if 'sign' in self._request.headers:
            # check sign from request and real sign
            if self._request.headers['sign'] == signature:
                data = 'OK'
            else:
                data = 'Signature from header isnt valid'
        else:
            data = 'Not found signature in headers'
        return data, signature

    def __get_price(self):
        status = 'ERROR'
        # check if all nessesary params were pass
        if "in_currency" not in self._request.args:
            data = {
                "status": status,
                "msg": "The currency you want to exchange is not specified"
            }
        elif "out_currency" not in self._request.args:
            data = {"status": status, "msg": "Output currency not specified"}
        elif "in_amount" not in self._request.args:
            data = {
                "status": status,
                "msg": "The amount of currency is not specified"
            }
        else:
            # get request of check sign
            check_sign, signature = self.__check_sign()
            if check_sign == "OK":
                result_strip_currency = self.__strip_currency()
                symbol = "{}{}".format(result_strip_currency[0],
                                       result_strip_currency[1])
                try:
                    status = "OK"
                    # get data rate from binance api
                    symbol_ticker = self.__client.get_symbol_ticker(
                        params={'symbol': symbol})
                    data = {
                        "rate":
                        symbol_ticker,
                        "out_amount":
                        self.__calc(symbol_ticker, result_strip_currency[2])
                    }
                # if symbols arent exist
                except BinanceAPIException:
                    status = 'ERROR'
                    data = {
                        "status":
                        status,
                        "msg":
                        "Make sure the names of the currencies you entered are correct"
                    }
            else:
                data = {
                    "status":
                    status,
                    "msg":
                    check_sign,
                    "Example!!! Paste it in headers(its valid signature)":
                    signature
                }
        return status, data

    def __strip_currency(self):
        # format params from request
        strip_in_currency = str(self._request.args["in_currency"]).strip('[]"')
        strip_out_currency = str(
            self._request.args["out_currency"]).strip('[]"')
        in_amount = str(self._request.args["in_amount"]).strip('[]"')
        result = [
            strip_in_currency.strip("'"),
            strip_out_currency.strip("'"),
            in_amount.strip("'")
        ]
        return result
Beispiel #24
0
def session():
    with open("lib/settings.json", "r") as settings_json:
        settings = json.load(settings_json)
        account_settings = settings["BinanceSettings"]["Account"]
        filter_settings = settings["BinanceSettings"]["Filter"]

    print(datetime.now().strftime("%d-%m-%Y %H:%M:%S,%f"))
    client = Client(api_key=account_settings["API_Key"],
                    api_secret=account_settings["API_Secret"])

    ###############################################
    # ticker_df:        24h change stats per symbol
    # symbol_prices:    'BTCUSDT': xxxx.xx
    ###############################################
    ticker_df = pd.DataFrame(client.get_ticker())
    symbol_prices = {}
    for pair_price in client.get_all_tickers():
        symbol_prices[pair_price['symbol']] = float(pair_price['price'])

    #################################################################
    # -> only pairs with USDT (will be updated to work individually)
    # -> only pairs with volume > minimal volume of interest to trade
    # -> only pairs not containing other quote asset than USDT
    #################################################################

    # filter ticker data for specific quote asset (USDT is the quote asset of BTCUSDT)
    filter_ticker_df = ticker_df['symbol'].str.contains('USDT')
    ticker_df = ticker_df[filter_ticker_df]

    # filter ticker data for minimum 24 volume
    filter_ticker_df = ticker_df['quoteVolume'].astype(
        float) > filter_settings["Min_Volume_USDT"]
    ticker_df = ticker_df[filter_ticker_df]

    # filter ticker data to skip all pairs containing any of these coins
    # Note: somehow TKOUSDT had no close price in its Dataframe while testing
    ignore_coins = ['USDC', 'PAX', 'BUSD', 'TUSD', 'USDS', 'BNB', 'MTL'
                    ] + filter_settings["Coins_to_ignore"]
    for coin in ignore_coins:
        filter_ticker_df = ticker_df['symbol'].str.contains(coin)
        ticker_df = ticker_df[~filter_ticker_df]

    # filter all pairs to examine
    trade_pairs = ticker_df['symbol'].tolist()
    trade_pairs = [pair for pair in trade_pairs if pair[-4:] == 'USDT'
                   ]  # this needs to be checked for every quote asset
    for pair in filter_settings["Coins_to_include"]:
        if pair not in trade_pairs:
            trade_pairs.append(pair)

    #################################################
    # check if any pair meets conditions to be traded
    #################################################

    sell_signals = []  # list of pairs to sell (e.g. ["BTCUSDT", ...]
    buy_signals = []  # list of pairs to buy (e.g. ["BTCUSDT", ...]
    currencies = {}  # for the Charts generator

    #######################################
    # buy_dict:     symbol: Strategy_object
    #######################################
    buy_dict = {}
    for pair in trade_pairs:
        if any([ignore in pair for ignore in ignore_coins]):
            continue

        #########################################################
        # run checks and execute sell order if conditions are met
        #########################################################

        print(f"Checking {pair}...")

        # check pair in buy/sell strategy
        signal = Strategy(pair)
        currencies[pair] = signal.symbol

        # Note: maybe check only intersection set of criteria pairs and coins in possession for sell orders

        # close open position if criteria are met
        if signal.is_hot_sell:
            sell_signals.append(pair)
            try:
                binance_account = BinanceAccount("admin")
                market_order = MarketOrder(
                    symbol=pair,
                    acc_name="admin",
                    symbol_info=signal.symbol.symbol_info,
                    amount=binance_account.value_per_trade,
                    stoploss=
                    0.1,  # not necessary in sell order, parameter will be deleted
                    type="SELL")
                market_order.run_order()
            except BinanceAPIException as e:
                print(e.message)

        # save every pair to buy after all possible open positions are closed
        if signal.is_hot_buy:
            buy_signals.append(pair)
            buy_dict[pair] = signal

    ########################################################
    # run checks and execute buy order if conditions are met
    ########################################################
    buy_list = [(val.enough_data, key, val.symbol.lot_size)
                for key, val in buy_dict.items()]
    for buy_signal in buy_list:
        try:
            binance_account = BinanceAccount(account_settings["API_Key"],
                                             account_settings["API_Secret"])

            # update price again
            tickers_raw = binance_account.client.get_orderbook_tickers()

            # hardcoded name will be deleted later
            tickers_usdt = [
                tck_usdt for tck_usdt in tickers_raw
                if 'USDT' in tck_usdt['symbol']
                and not float(tck_usdt['bidPrice']) == 0
            ]

            # open new positions only if bid price and ask price differ less than 0.4%
            for ticker in tickers_usdt:
                if ticker['symbol'] == buy_signal[1]:
                    diff = (float(ticker['askPrice']) /
                            float(ticker['bidPrice']) - 1) * 100
                    if diff < 0.4:
                        market_order = MarketOrder(
                            symbol=buy_signal[1],
                            acc_name="admin",
                            symbol_info=buy_dict[
                                buy_signal[1]].symbol.symbol_info,
                            amount=binance_account.value_per_trade,
                            stoploss=0.1,
                            type="BUY")
                        market_order.run_order()

        except BinanceAPIException as e:
            print(e.message)
Beispiel #25
0
from binance.client import Client
from binance.enums import *
from env import API_KEY, API_SECRET

client = Client(API_KEY, API_SECRET)

# transaction = client.create_margin_loan(asset='USDT', amount=f'{0.01 * 1500}', isIsolated='TRUE', symbol='ETHUSDT')

# order = client.create_margin_order(
#     symbol='ETHUSDT',
#     side=SIDE_BUY,
#     type=ORDER_TYPE_LIMIT,
#     timeInForce=TIME_IN_FORCE_GTC,
#     quantity=0.01,
#     price='1500',
#     isIsolated='TRUE')
# orders = client.get_open_margin_orders(symbol='ETHUSDT', isIsolated='TRUE')
# print(orders)

# result = client.cancel_margin_order(
#     symbol='ETHUSDT',
#     orderId='3145302551',
#     isIsolated='TRUE')
# print(result)

info = client.get_isolated_margin_account()
borrowed = info['assets'][0]['quoteAsset']['borrowed']

transaction = client.repay_margin_loan(asset='USDT',
                                       amount=borrowed,
                                       isIsolated='TRUE',
Beispiel #26
0
from binance.client import Client
import pandas as pd
from stockstats import StockDataFrame as Sdf
from time import time
import numpy as np
import json
import collections
import pickle

secret = open("secret.txt", "r").read()
api_key = secret.split(",")[0]
api_secret = secret.split(",")[1]
client = Client(api_key, api_secret)


def getTradingSymbols():
    return client.get_all_tickers()


def getKlineData(symbol, interval, startTime=None, endTime=None):
    try:
        return client.get_klines(symbol=symbol,
                                 interval=interval,
                                 startTime=startTime,
                                 endTime=endTime)
    except json.decoder.JSONDecodeError:
        return getKlineData(symbol, interval)


def getKlines(symbol, interval, startTime=None, endTime=None):
    klineData = getKlineData(symbol, interval, startTime, endTime)
def get_historical_klines(symbol, interval, start_str, end_str=None):
    """Get Historical Klines from Binance

    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: Biannce 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

    """
    # create the Binance client, no need for api key
    client = Client("", "")

    # init our list
    output_data = []

    # setup the max limit
    limit = 500

    # convert interval to useful value in seconds
    timeframe = interval_to_milliseconds(interval)

    # convert our date strings to milliseconds
    start_ts = date_to_milliseconds(start_str)

    # if an end time was passed convert it
    end_ts = None
    if end_str:
        end_ts = date_to_milliseconds(end_str)

    idx = 0
    # it can be difficult to know when a symbol was listed on Binance so allow start time to be before list date
    symbol_existed = False
    while True:
        # fetch the klines from start_ts up to max 500 entries or the end_ts if set
        temp_data = client.get_klines(
            symbol=symbol,
            interval=interval,
            limit=limit,
            startTime=start_ts,
            endTime=end_ts
        )

        # handle the case where our start date is before the symbol pair listed on Binance
        if not symbol_existed and len(temp_data):
            symbol_existed = True

        if symbol_existed:
            # append this loops data to our output data
            output_data += temp_data

            # update our start timestamp using the last value in the array and add the interval timeframe
            start_ts = temp_data[len(temp_data) - 1][0] + timeframe
        else:
            # it wasn't listed yet, increment our start date
            start_ts += timeframe

        idx += 1
        # check if we received less than the required limit and exit the loop
        if len(temp_data) < limit:
            # exit the while loop
            break

        # sleep after every 3rd call to be kind to the API
        if idx % 3 == 0:
            time.sleep(1)

    return output_data
Beispiel #28
0
#!/usr/bin/env python3

from os import environ
from binance.client import Client
real_api_key = environ.get("BINANCE_API_KEY")
real_api_sec = environ.get("BINANCE_API_SEC")
client = Client(real_api_key, real_api_sec)


def parseKline(kline):
    newKline = []
    for candle in kline:
        newCandle = {
            "openTime": datetime.fromtimestamp(candle[0] / 1000),
            "open": Decimal(candle[1]),
            "high": Decimal(candle[2]),
            "low": Decimal(candle[3]),
            "close": Decimal(candle[4])
        }
        newKline.append(newCandle)
    return newKline
    #for line in newKline:
    #print(line)


class Checker:
    """Antigua clase ALGO. Esta clase engloba las comprobaciones de los
	datos de la clase AT y determina si un par cualifica o no para un trade.

	Por el momento, la comprobación se compone de 2 etapas.
	"""
Beispiel #29
0
class Aquisition(object):
    def __init__(self):
        self.client = Client('', '')
        self.df = pd.DataFrame(columns=[
            'Open_time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Close_time'
        ])

    def cast_to_dataframe(self, opentime, lopen, lhigh, llow, lclose, lvol,
                          closetime):
        self.df['Open_time'] = opentime
        self.df["date"] = opentime
        self.df['Open'] = np.array(lopen).astype(np.float)
        self.df['High'] = np.array(lhigh).astype(np.float)
        self.df['Low'] = np.array(llow).astype(np.float)
        self.df['Close'] = np.array(lclose).astype(np.float)
        self.df['Volume'] = np.array(lvol).astype(np.float)
        self.df['Close_time'] = closetime
        self.df["date"] = pd.to_datetime(self.df['date'], unit='ms')

    def parse(self, candles):
        opentime, lopen, lhigh, llow, lclose, lvol, closetime = [], [], [], [], [], [], []
        for candle in candles:
            opentime.append(candle[0])
            lopen.append(candle[1])
            lhigh.append(candle[2])
            llow.append(candle[3])
            lclose.append(candle[4])
            lvol.append(candle[5])
            closetime.append(candle[6])
        self.cast_to_dataframe(opentime, lopen, lhigh, llow, lclose, lvol,
                               closetime)

    def get_candles(self):
        candles = self.client.get_historical_klines(
            "BTCUSDT", Client.KLINE_INTERVAL_1HOUR, "1 Ago, 2018")
        #candles = self.client.get_klines(symbol='BTCUSDT', interval=Client.KLINE_INTERVAL_1DAY)
        self.parse(candles)
        return self.df

    def get_price_now(self):
        r = requests.get(
            "https://www.binance.com/api/v3/ticker/price?symbol=BTCUSDT")
        r = r.content
        jsonResponse = json.loads(r.decode('utf-8'))
        return float(jsonResponse['price'])

    def plot_candles(self):
        df = self.df[450:]
        df["date"] = df["Open_time"]
        df["date"] = pd.to_datetime(self.df['date'], unit='ms')
        inc = df.Close > df.Open
        dec = df.Open > df.Close
        w = 12 * 60 * 60 * 1000  # half day in ms
        TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
        p = figure(x_axis_type="datetime",
                   tools=TOOLS,
                   plot_width=1000,
                   title="BITCOIN Candlestick")
        p.xaxis.major_label_orientation = pi / 4
        p.grid.grid_line_alpha = 0.3
        p.segment(df.date, df.High, df.date, df.Low, color="black")
        p.vbar(df.date[inc],
               w,
               df.Open[inc],
               df.Close[inc],
               fill_color="#006400",
               line_color="black")
        p.vbar(df.date[dec],
               w,
               df.Open[dec],
               df.Close[dec],
               fill_color="#F2583E",
               line_color="black")
        output_notebook()
        return p
### Parámetros para cálculo RSI y órdenes Compra/Venta
RSI_PERIOD = 14
RSI_OVERBOUGHT = 70
RSI_OVERSOLD = 30
TRADE_SYMBOL = 'THETABNB'
TRADE_QUANTITY = 0.05

### Array de cierres closes
closes = []

### En posición de compra
in_posicion = True

### Client
client = Client(config.API_KEY, config.API_SECRET)


### Función para enviar orden (compra/venta)
def order(side, quantity, symbol, order_type=ORDER_TYPE_MARKET):
    try:
        print("Enviando Orden")
        order = client.create_order(symbol=symbol,
                                    side=side,
                                    type=order_type,
                                    quantity=quantity)
        print(order)
    except Exception as e:
        print("Ha ocurrido un error al enviar la orden - {}".format(e))
        return False
Beispiel #31
0
 def __init__(self):
     self.client = Client('', '')
     self.df = pd.DataFrame(columns=[
         'Open_time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Close_time'
     ])
Beispiel #32
0
def main():
    client = None
    #get the user api keys and check balance
    while True:
        try:
            api_secret = input("Enter your binance api secret: ")
            api_key = input("Enter your binance api key: ")

            client = Client(api_key, api_secret, {"timeout": 100})
            #test to see if client is valid
            eth = float(client.get_asset_balance(asset='ETH')['free'])
            break
        except:
            print("api secret and/or api key does not match existing user")

    print("Successfully logged into your binance account.")

    while True:
        option = input("enter '1' to check your balance. \n" +
                       "enter '2' to start trading ETHBTC pair. \n" +
                       "enter '3' to start trading XRPBTC pair. \n" +
                       "enter 'exit' to exit. \n")
        # checking account balance
        if (option == "1"):
            check_balance(client)
        # ETHBTC trading pair
        elif (option == "2"):
            while True:
                option2 = input(
                    "enter the starting coin and amount and the percent increase per cycle (ex: ETH 1.0 2) to continue or\n"
                    + "enter '2' to go back \n" + "enter 'exit' to exit \n")
                if (option2 == "2"):
                    break
                elif (option2 == "exit"):
                    exit()
                else:
                    starting_coin_amount = option2.split(" ")
                    if (len(starting_coin_amount) != 3):
                        print("invalid input")
                    elif (starting_coin_amount[0] != "ETH"
                          and starting_coin_amount[0] != "BTC"):
                        print("only support ETH or BTC")
                    elif (not check_coin_available(
                            client, starting_coin_amount[0],
                            float(starting_coin_amount[1]))):
                        print(
                            "trading amount cannot be larger than account balance"
                        )
                    elif (float(starting_coin_amount[2]) < 0.2):
                        print(
                            "trading percent increase should be > 0.2% to offset binance trading fees"
                        )
                    else:
                        ETHBTC_bot(client, starting_coin_amount[0],
                                   float(starting_coin_amount[1]),
                                   float(starting_coin_amount[2]) / 100)

        # XRPBTC trading pair
        elif (option == "3"):
            while True:
                option2 = input(
                    "enter the starting coin and amount and the percent increase per cycle (ex: XRP 1.0 2 or BTC 1.0 3) to continue or\n"
                    + "enter '2' to go back \n" + "enter 'exit' to exit \n")
                if (option2 == "2"):
                    break
                elif (option2 == "exit"):
                    exit()
                else:
                    starting_coin_amount = option2.split(" ")
                    if (len(starting_coin_amount) != 3):
                        print("invalid input")
                    elif (starting_coin_amount[0] != "XRP"
                          and starting_coin_amount[0] != "BTC"):
                        print("only support XRP or BTC")
                    elif (not check_coin_available(
                            client, starting_coin_amount[0],
                            float(starting_coin_amount[1]))):
                        print(
                            "trading amount cannot be larger than account balance"
                        )
                    elif (float(starting_coin_amount[2]) < 0.2):
                        print(
                            "trading percent increase should be > 0.2% to offset binance trading fees"
                        )
                    else:
                        XRPBTC_bot(client, starting_coin_amount[0],
                                   float(starting_coin_amount[1]),
                                   float(starting_coin_amount[2]) / 100)

        #exit
        elif (option == "exit"):
            exit()
        else:
            print("Not a valid option \n")
Beispiel #33
0
import numpy as np
import pandas as pd
import math
import ta
from datetime import datetime
from binance.client import Client

# Initialize the client
client = Client()

def fetchData(symbol, amount, timeframe):
    """
    Pandas DataFrame with the latest OHLCV data from Binance.

    Parameters
    --------------
    symbol : string, combine the coin you want to get with the pair. For instance "BTCUSDT" for BTC/USDT.
    amount : int, the amount of rows that should be returned divided by 500. For instance 2 will return 1000 rows.
    timeframe : string, the timeframe according to the Binance API. For instance "4h" for the 4 hour candles.
    All the timeframe options are: '1m', '3m', '5m', '15m', '30m', '1h', '2h', '4h', '6h', '8h', '12h', '1d', '3d', '1w', '1M'
    """
    # https://python-binance.readthedocs.io/en/latest/binance.html#binance.client.Client.get_klines

    # ms calculations based on: http://convertlive.com/nl/u/converteren/minuten/naar/milliseconden
    # 1m = 60000 ms
    if (timeframe == '1m'):
        diff = 60000
    if (timeframe == '3m'):
        diff = 3 * 60000
    if (timeframe == '5m'):
        diff = 5 * 60000