Esempio n. 1
0
def configure_poloniex():
    api_key = config.API_KEY
    api_secret = config.API_SECRET
    polo = Poloniex(api_key, api_secret)

    _timing = time.time()

    def _arc(f):
        def decorator(*args, **kwargs):
            logging.info(('request', f.__name__, str(args), str(kwargs)))
            while time.time() - _timing < 0.5:
                time.sleep(0.01)
            return f(*args, **kwargs)

        return decorator

    polo.buy = _arc(polo.buy)
    polo.sell = _arc(polo.sell)
    polo.returnCompleteBalances = _arc(polo.returnCompleteBalances)
    polo.returnOpenOrders = _arc(polo.returnOpenOrders)
    polo.cancelOrder = _arc(polo.cancelOrder)
    polo.moveOrder = _arc(polo.moveOrder)
    polo.returnTradeHistory = _arc(polo.returnTradeHistory)
    return polo
Esempio n. 2
0
class Polo(Base):
    """
    Poloniex interface
    """
    arg_parser = configargparse.get_argument_parser()
    arg_parser.add('--polo_api_key', help='polo_api_key')
    arg_parser.add("--polo_secret", help='polo_secret')
    arg_parser.add("--polo_txn_fee", help='Poloniex txn. fee')
    arg_parser.add("--polo_buy_order", help='Poloniex buy order type')
    arg_parser.add("--polo_sell_order", help='Poloniex sell order type')
    valid_candle_intervals = [300, 900, 1800, 7200, 14400, 86400]

    def __init__(self):
        args = self.arg_parser.parse_known_args()[0]
        super(Polo, self).__init__()
        api_key = args.polo_api_key
        secret = args.polo_secret
        self.transaction_fee = float(args.polo_txn_fee)
        self.polo = Poloniex(api_key, secret)
        self.buy_order_type = args.polo_buy_order
        self.sell_order_type = args.polo_sell_order
        self.verbosity = args.verbosity
        self.pair_delimiter = '_'
        self.tickers_cache_refresh_interval = 50  # If the ticker request is within the interval, get data from cache
        self.last_tickers_fetch_epoch = 0  #
        self.last_tickers_cache = None  # Cache for storing immediate tickers

    def get_balances(self):
        """
        Return available account balances (function returns ONLY currencies > 0)
        """
        try:
            balances = self.polo.returnBalances()
            only_non_zeros = {
                k: float(v)
                for k, v in balances.items() if float(v) > 0.0
            }
        except PoloniexError as e:
            print(
                colored('!!! Got exception (polo.get_balances): ' + str(e),
                        'red'))
            only_non_zeros = dict()

        return only_non_zeros

    def get_symbol_ticker(self, symbol, candle_size=5):
        """
        Returns real-time ticker Data-Frame for given symbol/pair
        Info: Currently Poloniex returns tickers for ALL pairs. To speed the queries and avoid
              unnecessary API calls, this method implements temporary cache
        """
        epoch_now = int(time.time())
        if epoch_now < (self.last_tickers_fetch_epoch +
                        self.tickers_cache_refresh_interval):
            # If the ticker request is within cache_fetch_interval, try to get data from cache
            pair_ticker = self.last_tickers_cache[symbol].copy()
        else:
            # If cache is too old fetch data from Poloniex API
            try:
                ticker = self.polo.returnTicker()
                pair_ticker = ticker[symbol]
                self.last_tickers_fetch_epoch = int(time.time())
                self.last_tickers_cache = ticker.copy()
            except (PoloniexError | JSONDecodeError) as e:
                print(
                    colored(
                        '!!! Got exception in get_symbol_ticker. Details: ' +
                        str(e), 'red'))
                pair_ticker = self.last_tickers_cache[symbol].copy()
                pair_ticker = dict.fromkeys(pair_ticker, None)

        df = pd.DataFrame.from_dict(pair_ticker, orient="index")
        df = df.T
        # We will use 'last' price as closing one
        df = df.rename(columns={'last': 'close', 'baseVolume': 'volume'})
        df['close'] = df['close'].astype(float)
        df['volume'] = df['volume'].astype(float)
        df['pair'] = symbol
        df['date'] = int(datetime.datetime.utcnow().timestamp())
        return df

    def return_ticker(self):
        """
        Returns ticker for all currencies
        """
        return self.polo.returnTicker()

    def cancel_order(self, order_number):
        """
        Cancels order for given order number
        """
        return self.polo.cancelOrder(order_number)

    def return_open_orders(self, currency_pair='all'):
        """
        Returns your open orders
        """
        return self.polo.returnOpenOrders(currency_pair)

    def get_pairs(self):
        """
        Returns ticker pairs for all currencies
        """
        ticker = self.polo.returnTicker()
        return list(ticker)

    def get_candles_df(self,
                       currency_pair,
                       epoch_start,
                       epoch_end,
                       period=False):
        """
        Returns candlestick chart data in pandas dataframe
        """
        try:
            data = self.get_candles(currency_pair, epoch_start, epoch_end,
                                    period)
            df = pd.DataFrame(data)
            df = df.tail(1)
            df['close'] = df['close'].astype(float)
            df['volume'] = df['volume'].astype(float)
            df['pair'] = currency_pair
            return df
        except (PoloniexError, JSONDecodeError) as e:
            print()
            print(
                colored(
                    '!!! Got exception while retrieving polo data:' + str(e) +
                    ', pair: ' + currency_pair, 'red'))
        return pd.DataFrame()

    def get_candles(self,
                    currency_pair,
                    epoch_start,
                    epoch_end,
                    interval_in_sec=False):
        """
        Returns candlestick chart data
        """
        candle_interval = self.get_valid_candle_interval(interval_in_sec)
        data = []
        try:
            data = self.polo.returnChartData(currency_pair, candle_interval,
                                             epoch_start, epoch_end)
        except (PoloniexError, JSONDecodeError) as e:
            print()
            print(
                colored(
                    '!!! Got exception while retrieving polo data:' + str(e) +
                    ', pair: ' + currency_pair, 'red'))
        return data

    def get_valid_candle_interval(self, period_in_sec):
        """
        Returns closest value from valid candle intervals
        """
        if not period_in_sec:
            return period_in_sec

        if period_in_sec in self.valid_candle_intervals:
            return period_in_sec
        # Find the closest valid interval
        return min(self.valid_candle_intervals,
                   key=lambda x: abs(x - period_in_sec))

    def trade(self, actions, wallet, trade_mode):
        if trade_mode == TradeMode.backtest:
            return Base.trade(actions, wallet, trade_mode)
        else:
            actions = self.life_trade(actions)
            return actions

    def life_trade(self, actions):
        """
        Places orders and returns order number
        !!! For now we are NOT handling postOnly type of orders !!!
        """
        for action in actions:

            if action.action == TradeState.none:
                actions.remove(action)
                continue

            # Handle buy_sell mode
            wallet = self.get_balances()
            if action.buy_sell_mode == BuySellMode.all:
                action.amount = self.get_buy_sell_all_amount(wallet, action)
            elif action.buy_sell_mode == BuySellMode.fixed:
                action.amount = self.get_fixed_trade_amount(wallet, action)

            if self.verbosity:
                print(
                    'Processing live-action: ' + str(action.action) +
                    ', amount:',
                    str(action.amount) + ', pair:', action.pair + ', rate:',
                    str(action.rate) + ', buy_sell_mode:',
                    action.buy_sell_mode)

            # If we don't have enough assets, just skip/remove the action
            if action.amount == 0.0:
                print(
                    colored(
                        'No assets to buy/sell, ...skipping: ' +
                        str(action.amount) + ' ' + action.pair, 'green'))
                actions.remove(action)
                continue

            # ** Buy Action **
            if action.action == TradeState.buy:
                try:
                    print(
                        colored(
                            'Setting buy order: ' + str(action.amount) + '' +
                            action.pair, 'green'))
                    action.order_number = self.polo.buy(
                        action.pair, action.rate, action.amount,
                        self.buy_order_type)
                except PoloniexError as e:
                    print(
                        colored(
                            'Got exception: ' + str(e) + ' Txn: buy-' +
                            action.pair, 'red'))
                    continue
                amount_unfilled = action.order_number.get('amountUnfilled')
                if float(amount_unfilled) == 0.0:
                    actions.remove(action)
                    print(
                        colored(
                            'Bought: ' + str(action.amount) + '' + action.pair,
                            'green'))
                else:
                    action.amount = amount_unfilled
                    print(
                        colored(
                            'Not filled 100% buy txn. Unfilled amount: ' +
                            str(amount_unfilled) + '' + action.pair, 'red'))

            # ** Sell Action **
            elif action.action == TradeState.sell:
                try:
                    print(
                        colored(
                            'Setting sell order: ' + str(action.amount) + '' +
                            action.pair, 'yellow'))
                    action.order_number = self.polo.sell(
                        action.pair, action.rate, action.amount,
                        self.buy_order_type)
                except PoloniexError as e:
                    print(
                        colored(
                            'Got exception: ' + str(e) + ' Txn: sell-' +
                            action.pair, 'red'))
                    continue
                amount_unfilled = action.order_number.get('amountUnfilled')
                if float(amount_unfilled) == 0.0:
                    actions.remove(action)
                    print(
                        colored(
                            'Sold: ' + str(action.amount) + '' + action.pair,
                            'yellow'))
                else:
                    action.amount = amount_unfilled
                    print(
                        colored(
                            'Not filled 100% sell txn. Unfilled amount: ' +
                            str(amount_unfilled) + '' + action.pair, 'red'))
        return actions
Esempio n. 3
0
class LiveTrader:
    params = {
        "initial_depth": 3,
        "max_depth": 4,
        "variance_threshold": 0.00013,
        "band_threshold": 0.00013,
        "iteration_level": 3,
        "division_threshold": 0.00013,
        "max_weight": 8.0,
        "activation": "tanh"
    }

    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome,
                                neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet,
                                neat.stagnation.DefaultStagnation,
                                'config_trader')

    def __init__(self, ticker_len, target_percent, hd, base_sym="BTC"):
        self.base_sym = base_sym
        self.load_polo_client()
        self.hd = hd
        self.target_percent = target_percent
        self.ticker_len = ticker_len
        self.end_ts = datetime.now() + timedelta(seconds=(ticker_len * 55))
        self.hs = HistWorker()
        self.refresh_data()
        self.tickers = self.polo.returnTicker()
        self.refresh_balances()
        self.sellCoins()
        self.set_target()
        self.inputs = self.hs.hist_shaped.shape[0] * (
            self.hs.hist_shaped[0].shape[1])
        self.outputs = self.hs.hist_shaped.shape[0]
        self.end_idx = len(self.hs.hist_shaped[0]) - 1
        self.make_shapes()
        self.load_net()
        self.poloTrader()

    def load_polo_client(self):
        keys = self.get_keys()
        self.polo = Poloniex(keys[0], keys[1])

    def purge_polo_client(self):
        self.polo = None

    def load_net(self):
        champ_file = open("./champ_data/latest_greatest.pkl", 'rb')
        g = pickle.load(champ_file)
        #file.close()
        the_cppn = neat.nn.FeedForwardNetwork.create(g, self.config)
        self.cppn = the_cppn

    def refresh_data(self):
        try:
            self.hs.pull_polo_usd_live(21)
            self.hs.combine_live_usd_frames()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.refresh_data()

    def refresh_balances(self):
        try:
            self.bal = self.polo.returnCompleteBalances()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.refresh_balances()

    def get_one_bar_input_2d(self):
        master_active = []
        try:
            for x in range(0, self.hd):
                active = []
                #print(self.outputs)
                for y in range(0, self.outputs):
                    sym_data = self.hs.hist_shaped[y][self.end_idx - x]
                    #print(len(sym_data))
                    active += sym_data.tolist()
                master_active.append(active)
        except:
            print("error getting look back data")
            self.refresh_data()
            self.get_one_bar_input_2d()
        #print(active)
        return master_active

    def closeOrders(self):
        try:
            orders = self.polo.returnOpenOrders()
        except Exception as e:
            print(e)
            print('error getting open orers')
            time.sleep(360)
            self.closeOrders()
        for o in orders:
            if orders[o] != []:
                try:
                    ordnum = orders[o][0]['orderNumber']
                    self.polo.cancelOrder(ordnum)
                except Exception as e:
                    print(e)
                    print('error closing')

    def sellCoins(self):
        for b in self.tickers:
            if (b.split("_")[0] == self.base_sym):
                price = self.get_price(b)
                price = price - (price * .005)
                self.sell_coin(b, price)

    def buy_coin(self, coin, price):
        amt = self.target / price
        if (self.bal[self.base_sym]["available"] > self.target):
            try:
                self.polo.buy(coin, price, amt)
                print("buying: ", coin)
            except Exception as e:
                print("error buying ", coin)
                print(e)
        return

    def sell_coin(self, coin, price):
        if (self.base_sym != "BTC"):
            amt = self.bal[coin.split("_")[1]]["available"]
        else:
            amt = self.bal[coin.split("_")[1]]["btcValue"]
        if (amt * price > .0001):
            try:
                self.polo.sell(coin, price, amt)
                print("selling this shit: ", coin)
            except Exception as e:
                print("error selling ", coin)
                print(e)
        return

    def reset_tickers(self):
        try:
            self.tickers = self.polo.returnTicker()
            self.bal = self.polo.returnCompleteBalances()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.reset_tickers()
        return

    def get_keys(self):
        with open("./godsplan.txt") as f:
            content = f.readlines()
            content[0] = content[0][:-1]
            if (content[1][-1:] == "\n"):
                content[1] = content[1][:-1]
            return content

    def make_shapes(self):
        sign = 1
        self.out_shapes = []
        self.in_shapes = []
        for ix in range(1, self.outputs + 1):
            sign = sign * -1
            self.out_shapes.append((0.0 - (sign * .005 * ix), 0.0, -1.0))
            for ix2 in range(1, (self.inputs // self.outputs) + 1):
                self.in_shapes.append(
                    (0.0 + (sign * .01 * ix2), 0.0 - (sign * .01 * ix2), 0.0))
        self.subStrate = Substrate(self.in_shapes, self.out_shapes)

    def get_price(self, coin):
        return self.tickers[coin]['last']

    def set_target(self):
        total = 0
        full_bal = self.polo.returnCompleteBalances()
        for x in full_bal:
            total += full_bal[x]["btcValue"]
        if (self.base_sym != "BTC"):
            total = total * self.get_price(self.base_sym + "_" +
                                           "BTC") * self.target_percent
        print(total)
        self.target = total

    def poloTrader(self):
        self.refresh_balances()
        end_prices = {}
        active = self.get_one_bar_input_2d()
        self.load_net()
        network = ESNetwork(self.subStrate, self.cppn, self.params, self.hd)
        net = network.create_phenotype_network_nd('paper_net.png')
        net.reset()
        sell_syms = []
        buy_syms = []
        buy_signals = []
        sell_signals = []
        self.closeOrders()
        for n in range(1, self.hd):
            net.activate(active[self.hd - n])
        out = net.activate(active[0])
        for x in range(len(out)):
            sym = self.hs.coin_dict[x]
            end_prices[sym] = self.get_price(self.base_sym + "_" + sym)
            if (out[x] > .5):
                buy_signals.append(out[x])
                buy_syms.append(sym)
            if (out[x] < -.5):
                sell_signals.append(out[x])
                sell_syms.append(sym)
        #rng = iter(shuffle(rng))
        sorted_buys = np.argsort(buy_signals)[::-1]
        sorted_sells = np.argsort(sell_signals)
        self.reset_tickers()
        for x in sorted_sells:
            sym = sell_syms[x]
            p = self.get_price(self.base_sym + "_" + sym)
            price = p - (p * .005)
            self.sell_coin(self.base_sym + "_" + sym, price)
        for x in sorted_buys:
            sym = buy_syms[x]
            self.target_percent = .1 + out[x] - .45
            p = self.get_price(self.base_sym + "_" + sym)
            price = p * 1.005
            self.buy_coin(self.base_sym + "_" + sym, price)
        if datetime.now() >= self.end_ts:
            return
        else:
            self.purge_polo_client()
            time.sleep(self.ticker_len)
            self.load_polo_client()
        self.refresh_data()
        self.make_shapes()
        #self.closeOrders()
        self.poloTrader()
Esempio n. 4
0
class Polo(Base):
    """
    Poloniex interface
    """
    def __init__(self, config, verbosity=2):
        super(Polo, self).__init__()
        api_key = config['api_key']
        secret = config['secret']
        self.transaction_fee = float(config['transaction_fee'])
        self.polo = Poloniex(api_key, secret)
        self.buy_order_type = config['buy_order_type']
        self.sell_order_type = config['sell_order_type']
        self.verbosity = verbosity
        self.pair_delimiter = '_'

    def get_balances(self):
        """
        Return available account balances (function returns ONLY currencies > 0)
        """
        try:
            balances = self.polo.returnBalances()
            only_non_zeros = {
                k: float(v)
                for k, v in balances.items() if float(v) > 0.0
            }
        except PoloniexError as e:
            print(
                colored('!!! Got exception (polo.get_balances): ' + str(e),
                        'red'))
            only_non_zeros = dict()

        return only_non_zeros

    def get_symbol_ticker(self, symbol, candle_size=5):
        """
        Returns real-time ticker Data-Frame
        """
        ticker = self.polo.returnTicker()[symbol]
        df = pd.DataFrame.from_dict(ticker, orient="index")
        df = df.T
        # We will use 'last' price as closing one
        df = df.rename(columns={'last': 'close', 'baseVolume': 'volume'})
        df['close'] = df['close'].astype(float)
        df['volume'] = df['volume'].astype(float)
        df['pair'] = symbol
        df['date'] = int(datetime.datetime.utcnow().timestamp())
        return df

    def return_ticker(self):
        """
        Returns ticker for all currencies
        """
        return self.polo.returnTicker()

    def cancel_order(self, order_number):
        """
        Cancels order for given order number
        """
        return self.polo.cancelOrder(order_number)

    def return_open_orders(self, currency_pair='all'):
        """
        Returns your open orders
        """
        return self.polo.returnOpenOrders(currency_pair)

    def get_pairs(self):
        """
        Returns ticker pairs for all currencies
        """
        ticker = self.polo.returnTicker()
        return list(ticker)

    def return_candles(self,
                       currency_pair,
                       epoch_start,
                       epoch_end,
                       period=False):
        """
        Returns candlestick chart data
        """
        data = []
        try:
            data = self.polo.returnChartData(currency_pair, period,
                                             epoch_start, epoch_end)
        except (PoloniexError, JSONDecodeError) as e:
            print()
            print(
                colored(
                    '!!! Got exception while retrieving polo data:' + str(e) +
                    ', pair: ' + currency_pair, 'red'))
        return data

    def trade(self, actions, wallet, trade_mode):
        if trade_mode == TradeMode.backtest:
            return Base.trade(actions, wallet, trade_mode)
        else:
            actions = self.life_trade(actions)
            return actions

    def life_trade(self, actions):
        """
        Places orders and returns order number
        !!! For now we are NOT handling postOnly type of orders !!!
        """
        for action in actions:

            if action.action == TradeState.none:
                actions.remove(action)
                continue

            # Handle buy_sell_all cases
            wallet = self.get_balances()
            if action.buy_sell_all:
                action.amount = self.get_buy_sell_all_amount(wallet, action)

            if self.verbosity > 0:
                print(
                    'Processing live-action: ' + str(action.action) +
                    ', amount:',
                    str(action.amount) + ', pair:', action.pair + ', rate:',
                    str(action.rate) + ', buy_sell_all:', action.buy_sell_all)

            # If we don't have enough assets, just skip/remove the action
            if action.amount == 0.0:
                print(
                    colored(
                        'No assets to buy/sell, ...skipping: ' +
                        str(action.amount) + ' ' + action.pair, 'green'))
                actions.remove(action)
                continue

            # ** Buy Action **
            if action.action == TradeState.buy:
                try:
                    print(
                        colored(
                            'Setting buy order: ' + str(action.amount) + '' +
                            action.pair, 'green'))
                    action.order_number = self.polo.buy(
                        action.pair, action.rate, action.amount,
                        self.buy_order_type)
                except PoloniexError as e:
                    print(
                        colored(
                            'Got exception: ' + str(e) + ' Txn: buy-' +
                            action.pair, 'red'))
                    continue
                amount_unfilled = action.order_number.get('amountUnfilled')
                if float(amount_unfilled) == 0.0:
                    actions.remove(action)
                    print(
                        colored(
                            'Bought: ' + str(action.amount) + '' + action.pair,
                            'green'))
                else:
                    action.amount = amount_unfilled
                    print(
                        colored(
                            'Not filled 100% buy txn. Unfilled amount: ' +
                            str(amount_unfilled) + '' + action.pair, 'red'))

            # ** Sell Action **
            elif action.action == TradeState.sell:
                try:
                    print(
                        colored(
                            'Setting sell order: ' + str(action.amount) + '' +
                            action.pair, 'yellow'))
                    action.order_number = self.polo.sell(
                        action.pair, action.rate, action.amount,
                        self.buy_order_type)
                except PoloniexError as e:
                    print(
                        colored(
                            'Got exception: ' + str(e) + ' Txn: sell-' +
                            action.pair, 'red'))
                    continue
                amount_unfilled = action.order_number.get('amountUnfilled')
                if float(amount_unfilled) == 0.0:
                    actions.remove(action)
                    print(
                        colored(
                            'Sold: ' + str(action.amount) + '' + action.pair,
                            'yellow'))
                else:
                    action.amount = amount_unfilled
                    print(
                        colored(
                            'Not filled 100% sell txn. Unfilled amount: ' +
                            str(amount_unfilled) + '' + action.pair, 'red'))
        return actions
	counter = 0 # Where to start in list (0=AMP, 1=ARDR, 2=BAT...)
	max_index = len(PoloniexCoins) - 1 # Length PoloniexCoins List - 1  List start at 0 not 1 
	print("Total amount of Altcoins on Poloniex BTC Market = " , max_index)
	while counter <= max_index: # while = loop through PoloniexCoins List until max_index
		AltCoin = PoloniexCoins[counter] # Every loop change variable AltCoin to counter (0=AMP, 1=ARDR, 2=BAT...)
		pair = "BTC_" + AltCoin # Market: BTC_ + AltCoin to create coinpairs (BTC_AMP , BTC_ARDR, BTC_BAT...)
		print_pair();

		while True: #0 First check if the coinpair already has a Open Order & Cancel it
			try:
				returnOpenOrders = polo.returnOpenOrders()[pair] # Collect the open orders of the coinpair			
				if returnOpenOrders != []: # if the openorders are not empty Cancel the Order
					returnOrderNumber = polo.returnOpenOrders()[pair][0]['orderNumber'] # Collect last orderNumber	
					returnOrderAmount = polo.returnOpenOrders()[pair][0]['amount'] # Collect OrderAmount
					print("Open Order: ", returnOrderNumber, "Total Amount in BTC: " , returnOrderAmount ) # OpenOrder Info
					cancelOrder = polo.cancelOrder(returnOrderNumber)# cancel order with latest orderNumber
					print("---!CANCEL Complete!---") # Reloop the OpenOrder Check						
				else: # if the openorders are not empty
					#print("---!No OpenOrders!---")
					break				
			except: # Print an Exeption (error) if script can't collect Orders
				backoff("Can not get the OpenOrder")
				exit(1) # Exit the entire script
		
		while True: #1 get the ticker of the coinpair (LowestAsk & HighestBid Price)
			try:
				Ask = polo.returnTicker()[pair]['lowestAsk'] # Collect latest Sell(ask) & Buy (bid) prices
				Bid = polo.returnTicker()[pair]['highestBid']
				#print("Sell price in BTC = " , Ask)
				#print("Buy  price in BTC = " , Bid)
				break
class LiveTrader:
    params = {"initial_depth": 4,
            "max_depth": 4,
            "variance_threshold": 0.00013,
            "band_threshold": 0.00013,
            "iteration_level": 3,
            "division_threshold": 0.00013,
            "max_weight": 8.0,
            "activation": "tanh"}


    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome, neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet, neat.stagnation.DefaultStagnation,
                                'config_trader')
    def __init__(self, ticker_len, target_percent, hd):
        self.polo = Poloniex(key, secret)
        self.hist_depth = hd
        self.target_percent = target_percent
        self.ticker_len = ticker_len
        self.end_ts = datetime.now()+timedelta(seconds=(ticker_len*55))
        self.hs = HistWorker()
        self.refresh_data()
        self.tickers = self.polo.returnTicker()
        self.bal = self.polo.returnBalances()
        self.sellCoins()
        self.set_target()
        self.inputs = self.hs.hist_shaped.shape[0]*(self.hs.hist_shaped[0].shape[1])
        self.outputs = self.hs.hist_shaped.shape[0]
        self.make_shapes()
        self.leaf_names = []
        self.db = tinydb.database("live_hist/memories.json")
        for l in range(len(self.in_shapes[0])):
            self.leaf_names.append('leaf_one_'+str(l))
            self.leaf_names.append('leaf_two_'+str(l))
        #self.load_net()
        self.poloTrader()

    def load_net(self):
        #file = open("./champ_gens/thot-checkpoint-13",'rb')
        g = neat.Checkpointer.restore_checkpoint("./champ_gens/thot-checkpoint-25")
        best_fit = 0.0
        for gx in g.population:
            if g.population[gx].fitness != None:
                if g.population[gx].fitness > best_fit:
                    bestg = g.population[gx]
        g = bestg
        #file.close()
        [the_cppn] = create_cppn(g, self.config, self.leaf_names, ['cppn_out'])
        self.cppn = the_cppn

    def refresh_data(self):
        self.hs.pull_polo_live(20)
        self.hs.combine_live_frames(self.hist_depth)

    def make_shapes(self):
        self.in_shapes = []
        self.out_shapes = []
        sign = 1
        for ix in range(1,self.outputs+1):
            sign = sign *-1
            self.out_shapes.append((0.0-(sign*.005*ix), -1.0, -1.0))
            for ix2 in range(1,(self.inputs//self.outputs)+1):
                self.in_shapes.append((0.0+(sign*.01*ix2), 0.0-(sign*.01*ix2), 1.0))


    def get_one_bar_input_2d(self,end_idx=10):
        master_active = []
        for x in range(0, self.hist_depth):
            active = []
            #print(self.outputs)
            for y in range(0, self.outputs):
                sym_data = self.hs.hist_shaped[y][self.hist_depth-x]
                #print(len(sym_data))
                active += sym_data.tolist()
            master_active.append(active)
        #print(active)
        return master_active


    def closeOrders(self):
        try:
            orders = self.polo.returnOpenOrders()
        except:
            print('error getting open orers')
            time.sleep(360)
            self.closeOrder()
        for o in orders:
            if orders[o] != []:
                try:
                    ordnum = orders[o][0]['orderNumber']
                    self.polo.cancelOrder(ordnum)
                except:
                    print('error closing')



    def sellCoins(self):
        for b in self.tickers:
            if(b[:3] == "BTC"):
                price = self.get_price(b)
                price = price - (price * .005)
                self.sell_coin(b, price)

    def buy_coin(self, coin, price):
        amt = self.target / price
        if(self.bal['BTC'] > self.target):
            self.polo.buy(coin, price, amt, fillOrKill=1)
            print("buying: ", coin)
        return

    def sell_coin(self, coin, price):
        amt = self.bal[coin[4:]]
        if (amt*price > .0001):
            try:
                self.polo.sell(coin, price, amt,fillOrKill=1)
                print("selling this shit: ", coin)
            except:
                print('error selling', coin)
        return


    def reset_tickers(self):
        try:
            self.tickers = self.polo.returnTicker()
            self.bal = self.polo.returnBalances()
        except:
            time.sleep(360)
            self.reset_tickers()
        return



    def get_price(self, coin):
        return self.tickers[coin]['last']

    def set_target(self):
        total = 0
        full_bal = self.polo.returnCompleteBalances()
        for x in full_bal:
            total += full_bal[x]["btcValue"]
        self.target = total*self.target_percent

    def poloTrader(self):
        end_prices = {}
        active = self.get_one_bar_input_2d()
        self.load_net()
        sub = Substrate(self.in_shapes, self.out_shapes)
        network = ESNetwork(sub, self.cppn, self.params)
        net = network.create_phenotype_network_nd('paper_net.png')
        net.reset()
        for n in range(1, self.hist_depth+1):
            out = net.activate(active[self.hist_depth-n])
        #print(len(out))
        rng = len(out)
        #rng = iter(shuffle(rng))
        self.reset_tickers()
        for x in np.random.permutation(rng):
            sym = self.hs.coin_dict[x]
            #print(out[x])
            try:
                if(out[x] < -.5):
                    print("selling: ", sym)
                    p = self.get_price('BTC_'+sym)
                    price = p -(p*.01)
                    self.sell_coin('BTC_'+sym, price)
                elif(out[x] > .5):
                    print("buying: ", sym)
                    self.target_percent = .1 + out[x] - .45
                    p = self.get_price('BTC_'+sym)
                    price = p*1.01
                    self.buy_coin('BTC_'+sym, price)
            except:
                print('error', sym)
            #skip the hold case because we just dont buy or sell hehe

        if datetime.now() >= self.end_ts:
            return
        else:
            time.sleep(self.ticker_len)
        self.refresh_data()
        #self.closeOrders()
        self.poloTrader()
class LiveTrader:
    params = {
        "initial_depth": 0,
        "max_depth": 4,
        "variance_threshold": 0.03,
        "band_threshold": 0.3,
        "iteration_level": 1,
        "division_threshold": 0.3,
        "max_weight": 5.0,
        "activation": "tanh"
    }

    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome,
                                neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet,
                                neat.stagnation.DefaultStagnation,
                                'config_trader')

    def __init__(self, ticker_len, target_percent):
        self.polo = Poloniex(key, secret)
        self.currentHists = {}
        self.hist_shaped = {}
        self.coin_dict = {}
        self.ticker_len = ticker_len
        self.end_ts = datetime.now() + timedelta(seconds=(ticker_len * 55))
        file = open("es_trade_god_cppn.pkl", 'rb')
        self.cppn = pickle.load(file)
        file.close()
        self.tickers = self.polo.returnTicker()
        self.bal = self.polo.returnBalances()
        self.target = self.bal['BTC'] * target_percent
        self.pull_polo()
        self.inputs = self.hist_shaped.shape[0] * (
            self.hist_shaped[0].shape[1] - 1)
        self.outputs = self.hist_shaped.shape[0]
        self.multiplier = self.inputs / self.outputs

    def make_shapes(self):
        self.in_shapes = []
        self.out_shapes = []
        sign = 1
        for ix in range(self.outputs):
            sign = sign * -1
            self.out_shapes.append((sign * ix, 1))
            for ix2 in range(len(self.hist_shaped[0][0]) - 1):
                self.in_shapes.append((sign * ix, (1 + ix2) * .1))

    def pull_polo(self):
        tickLen = '7200'
        start = datetime.today() - timedelta(1)
        start = str(int(start.timestamp()))
        ix = 0
        for coin in self.tickers:
            if coin[:3] == 'BTC':
                hist = requests.get(
                    'https://poloniex.com/public?command=returnChartData&currencyPair='
                    + coin + '&start=' + start + '&end=9999999999&period=' +
                    tickLen)
                try:
                    df = pd.DataFrame(hist.json())
                    #df.rename(columns = lambda x: col_prefix+'_'+x, inplace=True)
                    as_array = np.array(df)
                    #print(len(as_array))
                    self.currentHists[coin] = df
                    self.hist_shaped[ix] = as_array
                    self.coin_dict[ix] = coin
                    ix += 1
                except:
                    print("error reading json")
        self.hist_shaped = pd.Series(self.hist_shaped)
        self.end_idx = len(self.hist_shaped[0]) - 1

    def get_one_bar_input_2d(self):
        active = []
        misses = 0
        for x in range(0, self.outputs):
            try:
                sym_data = self.hist_shaped[x][self.end_idx]
                for i in range(len(sym_data)):
                    if (i != 1):
                        active.append(sym_data[i].tolist())
            except:
                self.outputs -= 1
                self.inputs -= self.multiplier
                print('error')
        #print(active)
        self.make_shapes()
        return active

    def closeOrders(self):
        orders = self.polo.returnOpenOrders()
        for o in orders:
            if orders[o] != []:
                try:
                    ordnum = orders[o][0]['orderNumber']
                    self.polo.cancelOrder(ordnum)
                except:
                    print('error closing')

    def sellCoins(self, coinlist, currency):
        balances = self.polo.returnBalances()
        for b in balances:
            bal = balances[b] * .99

    def buy_coin(self, coin, price):
        amt = self.target
        if (self.bal['BTC'] > self.target):
            try:
                self.polo.buy(coin, price, amt, fillOrKill=1)
                print("buying: ", coin)
            except:
                print('error buying', coin)
        return

    def sell_coin(self, coin, price):
        amt = self.bal[coin[4:]]
        try:
            self.polo.sell(coin, price, amt, fillOrKill=1)
        except:
            print('error selling: ', coin)
        return

    def reset_tickers(self):
        self.tickers = self.polo.returnTicker()
        return

    def get_price(self, coin):
        return self.tickers[coin]['last']

    def poloTrader(self):
        end_prices = {}
        active = self.get_one_bar_input_2d()
        sub = Substrate(self.in_shapes, self.out_shapes)
        network = ESNetwork(sub, self.cppn, self.params)
        net = network.create_phenotype_network()
        net.reset()
        for n in range(network.activations):
            out = net.activate(active)
        #print(len(out))
        rng = len(out)
        #rng = iter(shuffle(rng))
        for x in np.random.permutation(rng):
            sym = self.coin_dict[x]
            #print(out[x])
            try:
                if (out[x] < -.5):
                    print("selling: ", sym)
                    self.sell_coin(
                        sym,
                        self.get_price(sym),
                    )
                elif (out[x] > .5):
                    print("buying: ", sym)
                    self.buy_coin(sym, self.get_price(sym))
            except:
                print('error', sym)
            #skip the hold case because we just dont buy or sell hehe
            end_prices[sym] = self.get_price(sym)

        if datetime.now() >= self.end_ts:
            return
        else:
            time.sleep(self.ticker_len)
        self.reset_tickers
        self.pull_polo()
        self.poloTrader()
Esempio n. 8
0
class Trader(object):
    def __init__(self,
                 api_key,
                 api_secret,
                 coin,
                 currency,
                 dust_total=10,
                 dust_amount=100.0,
                 min_spread=0.0001,
                 max_trading_amount=1):
        # set currency pair
        self.coin = coin
        self.currency = currency
        self.my_pair = '%s_%s' % (currency, coin)

        # we'll need this while finding buy/sell prices
        self.dust_total = self.make_satoshi(dust_total)
        self.dust_amount = self.make_satoshi(dust_amount)
        self.min_spread = self.make_satoshi(min_spread)
        self.max_trading_amount = self.make_satoshi(max_trading_amount)

        # initialize the poloniex api
        self.api_key = api_key
        self.api_secret = api_secret
        self.polo = Poloniex(api_key, api_secret)

        # initialize other variables
        self.coin_balance = self.make_satoshi('0.0')
        self.currency_balance = self.make_satoshi('0.0')
        self.total_coin_balance = self.make_satoshi('0.0')
        self.total_currency_balance = self.make_satoshi('0.0')

        self.open_orders_raw = []
        self.open_orders = []
        self.open_orders_sell = []
        self.open_orders_buy = []

        self.order_book_raw = []
        self.order_book = {}
        self.order_book["buy"] = []
        self.order_book["sell"] = []

        self.sell_price = self.make_satoshi('0.0')
        self.buy_price = self.make_satoshi('0.0')
        self.price_spread = self.make_satoshi('0.0')
        self.sell_amount = self.make_satoshi('0.0')
        self.buy_amount = self.make_satoshi('0.0')
        self.trade = False

        # those are hardcoded. may be added to settings later.
        self.min_currency_balance = self.make_satoshi('0.00100000')
        # seconds to wait for exchange rate limits.
        self.exchange_wait_time = 0.8

    def make_satoshi(self, num):
        return decimal.Decimal(num).quantize(decimal.Decimal('1.00000000'))

    def load_open_orders(self):
        # loads open orders. Resets the balances so load_balances method should be called after.
        self.total_coin_balance = self.make_satoshi('0.0')
        self.total_currency_balance = self.make_satoshi('0.0')
        self.open_orders_raw = self.polo.returnOpenOrders(
            currencyPair=self.my_pair)
        self.open_orders = []
        self.open_orders_sell = []
        self.open_orders_buy = []
        for item in self.open_orders_raw:
            order = {}
            order['type'] = item['type']
            order["order_number"] = item['orderNumber']
            order["price"] = self.make_satoshi(item['rate'])
            order["amount"] = self.make_satoshi(item['amount'])
            order["total"] = self.make_satoshi(order['price'] *
                                               order['amount'])
            order["starting_amount"] = self.make_satoshi(
                item['startingAmount'])

            self.open_orders.append(order)
            if order['type'] == 'sell':
                self.open_orders_sell.append(order)
                self.total_coin_balance = self.total_coin_balance + order[
                    "amount"]
            else:
                self.open_orders_buy.append(order)
                self.total_currency_balance = self.total_currency_balance + order[
                    "total"]

        return self.open_orders

    def load_balances(self):
        # first load the open orders to get the balances in open orders.
        self.load_open_orders()
        # request from exchange
        self.balances = self.polo.returnBalances()
        # set the coin balance
        self.coin_balance = self.make_satoshi(self.balances[self.coin])
        self.total_coin_balance = self.total_coin_balance + self.coin_balance
        # '0.00000001' makes things complicated. get rid of it.
        if self.coin_balance <= self.make_satoshi('0.00000001'):
            self.coin_balance = self.make_satoshi('0.0')
        if self.total_coin_balance <= self.make_satoshi('0.00000001'):
            self.total_coin_balance = self.make_satoshi('0.0')
        # set the main currency balance
        self.currency_balance = self.make_satoshi(self.balances[self.currency])
        self.total_currency_balance = self.total_currency_balance + self.currency_balance
        # '0.00000001' makes things complicated. get rid of it.
        if self.currency_balance <= self.make_satoshi('0.00000001'):
            self.currency_balance = self.make_satoshi('0.0')
        if self.total_currency_balance <= self.make_satoshi('0.00000001'):
            self.total_currency_balance = self.make_satoshi('0.0')
        # added for debugging. make the BTC amount > 0 so we can test buying.
        # self.total_currency_balance = self.make_satoshi('0.10000000')

    def load_order_book(self):
        self.order_book_raw = self.polo.returnOrderBook(
            currencyPair=self.my_pair, depth='200')
        self.order_book["buy"] = []
        self.order_book["sell"] = []
        self.process_order_book('buy', self.order_book_raw["bids"])
        self.process_order_book('sell', self.order_book_raw["asks"])
        return self.order_book

    def process_order_book(self, order_type, order_book_raw):
        self.order_book[order_type] = []
        total = self.make_satoshi("0.0")
        for item in order_book_raw:
            order = {}
            order['type'] = order_type
            order["price"] = self.make_satoshi(item[0])
            order["amount"] = self.make_satoshi(item[1])
            order["cur"] = self.make_satoshi(order["price"] * order["amount"])
            total = self.make_satoshi(total + order["cur"])
            order["total"] = total
            # mark the order if its my order. put order number from open_orders
            order['order_number'] = None
            for open_order in self.open_orders:
                if (open_order['type']
                        == order['type']) and (open_order["price"]
                                               == order["price"]):
                    order["order_number"] = open_order['order_number']
                    print "order:", order

            self.order_book[order_type].append(order)

        return self.order_book[order_type]

    def find_sell_price(self):
        total = self.make_satoshi("0.0")
        for order in self.order_book['sell']:
            if order['order_number'] is None:
                total = self.make_satoshi(total + order["cur"])
                if (order["amount"] >= dust_amount) or (total >= dust_total):
                    return self.make_satoshi(order["price"] -
                                             self.make_satoshi("0.00000003"))

        return False

    def find_buy_price(self):
        total = self.make_satoshi("0.0")
        for order in self.order_book['buy']:
            if order['order_number'] is None:
                total = self.make_satoshi(total + order["cur"])
                if (order["amount"] >= dust_amount) or (total >= dust_total):
                    return self.make_satoshi(order["price"] +
                                             self.make_satoshi("0.00000003"))

        return False

    def decide_to_trade(self):
        self.sell_price = self.find_sell_price()
        self.buy_price = self.find_buy_price()
        self.price_spread = self.sell_price - self.buy_price

        print "Sell Price:", self.sell_price
        print "Buy Price:", self.buy_price
        print "Price Spread:", self.price_spread

        if (not self.sell_price) or (not self.buy_price):
            print "Something is wrong with sell and buy prices. Will not trade!"
            self.trade = False
            return False

        if self.total_currency_balance > self.min_currency_balance:
            print 'I have %s %s, will try to buy %s.' % (
                self.total_currency_balance, self.currency, self.coin)
            self.trade = 'buy'
            return True
        else:
            if self.price_spread >= self.min_spread:
                print 'Spread is good. Will trade'
                # sell or buy?
                if self.total_coin_balance > 0:
                    print 'I have %s %s, will try to sell %s for %s.' % (
                        self.total_coin_balance, self.coin, self.coin,
                        self.currency)
                    self.trade = 'sell'
                    return True
                else:
                    print 'I have nothing to trade.'
                    self.trade = False
            else:
                print 'Price Spread is not good. Stop trading.'
                self.trade = False

        return False

    def cancel_open_orders(self, buy_sell):
        for order in self.open_orders:
            if order['type'] == buy_sell:
                print "canceling order:", order
                try:
                    retval = self.polo.cancelOrder(order["order_number"])
                except:
                    retval = False
                    print 'ERROR canceling order.'
                print "cancel order retval:", retval
                self.open_orders.remove(order)
                if buy_sell == 'sell':
                    self.open_orders_sell.remove(order)
                else:
                    self.open_orders_buy.remove(order)

    def cancel_open_order(self, order):
        print "canceling order:", order
        try:
            retval = self.polo.cancelOrder(order["order_number"])
        except:
            retval = False
            print 'ERROR canceling order.'
        time.sleep(0.2)
        print "cancel order retval:", retval
        self.open_orders.remove(order)
        if order['type'] == 'sell':
            self.open_orders_sell.remove(order)
        else:
            self.open_orders_buy.remove(order)

    def add_sell_order(self):
        # compute the amount
        if self.total_coin_balance > self.max_trading_amount:
            self.sell_amount = self.max_trading_amount
        else:
            self.sell_amount = self.total_coin_balance

        print "self.sell_amount:", self.sell_amount
        # send order to exchange
        try:
            retval = self.polo.sell(currencyPair=self.my_pair,
                                    rate=self.sell_price,
                                    amount=self.sell_amount)
        except:
            print 'ERROR adding SELL order.'
            retval = False

        print retval

        return retval

    def sell(self):
        # cancel all buy orders first.
        self.cancel_open_orders('buy')
        # check open sell orders if the sell price is ok.
        for order in self.open_orders_sell:
            if order['price'] == self.sell_price:
                print "order is ok:", order
            else:
                # cancel the order.
                retval = self.cancel_open_order(order)

        print 'self.open_orders_sell:', len(self.open_orders_sell)
        if len(self.open_orders_sell) == 0:
            print 'adding a new sell order'
            retval = self.add_sell_order()

    def add_buy_order(self):
        # compute the amount
        if self.total_currency_balance > self.make_satoshi('0.00001000'):
            self.buy_amount = self.make_satoshi(
                self.total_currency_balance /
                self.buy_price) - self.make_satoshi('0.00000001')
            print "Buying amount:", self.buy_amount
        else:
            print "Buying amount is low. not buying:"
            return False

        # send order to exchange
        try:
            retval = self.polo.buy(currencyPair=self.my_pair,
                                   rate=self.buy_price,
                                   amount=self.buy_amount)
        except:
            print 'ERROR adding BUY order.'
            retval = False

        print retval

        return retval

    def buy(self):
        # cancel all buy orders first.
        self.cancel_open_orders('sell')
        # check open sell orders if the sell price is ok.
        for order in self.open_orders_buy:
            if order['price'] == self.buy_price:
                print "order is ok:", order
            else:
                # cancel the order.
                retval = self.cancel_open_order(order)

        print 'self.open_orders_buy:', len(self.open_orders_buy)
        if len(self.open_orders_buy) == 0:
            print 'adding a new buy order'
            retval = self.add_buy_order()

    def run_scalping(self):
        while True:
            now = datetime.datetime.now()
            print str(now)

            self.load_balances()
            self.load_order_book()

            print '%s Balance: %s' % (self.currency,
                                      self.total_currency_balance)
            print '%s Balance: %s' % (self.coin, self.total_coin_balance)

            # trade or not trade?
            trade = self.decide_to_trade()

            print "Trade?", trade

            if self.trade == 'sell':
                self.sell()
            elif self.trade == 'buy':
                self.buy()
            else:
                #Will not trade. Cancel all orders.
                self.cancel_open_orders('buy')
                self.cancel_open_orders('sell')

            print "."
            print "open orders:", self.open_orders
            print "."
            now = datetime.datetime.now()
            print str(now)

            print "Will wait a little bit for not to flood the exchange..."
            time.sleep(self.exchange_wait_time)

    def add_sell_all_order(self):
        # compute the amount
        self.sell_amount = self.total_coin_balance

        print "self.sell_amount:", self.sell_amount
        if self.sell_amount:
            # send order to exchange
            try:
                retval = self.polo.sell(currencyPair=self.my_pair,
                                        rate=self.sell_price,
                                        amount=self.sell_amount)
            except:
                print 'ERROR adding SELL ALL order.'
                retval = False

            print retval

            return retval
        else:
            return False

    def sell_all(self):
        # cancel all buy orders first.
        self.cancel_open_orders('buy')
        # check open sell orders if the sell price is ok.
        for order in self.open_orders_sell:
            if order['price'] == self.sell_price:
                print "order is ok:", order
            else:
                # cancel the order.
                retval = self.cancel_open_order(order)

        print 'self.open_orders_sell:', len(self.open_orders_sell)
        if len(self.open_orders_sell) == 0:
            print 'adding a new sell all order'
            retval = self.add_sell_all_order()

    def run_sell_all(self):
        self.trade = 'sell'
        while self.trade == 'sell':
            now = datetime.datetime.now()
            print str(now)

            self.load_balances()
            self.load_order_book()

            print '%s Balance: %s' % (self.currency,
                                      self.total_currency_balance)
            print '%s Balance: %s' % (self.coin, self.total_coin_balance)

            self.sell_price = self.find_sell_price()
            print "Sell Price:", self.sell_price

            if self.total_coin_balance > 0.0:
                print 'I have %s %s, will try to sell %s for %s.' % (
                    self.total_coin_balance, self.coin, self.coin,
                    self.currency)
                self.trade = 'sell'
            else:
                print 'I have nothing to trade.'
                self.trade = False

            if self.trade == 'sell':
                self.sell_all()
            else:
                #Will not trade. Cancel all orders.
                self.cancel_open_orders('buy')
                self.cancel_open_orders('sell')

            print "."
            print "open orders:", self.open_orders
            print "."
            now = datetime.datetime.now()
            print str(now)

            print "Will wait a little bit for not to flood the exchange..."
            time.sleep(self.exchange_wait_time)

    def add_buy_all_order(self):
        # compute the amount
        if self.total_currency_balance > self.make_satoshi('0.00001000'):
            self.buy_amount = self.make_satoshi(
                self.total_currency_balance /
                self.buy_price) - self.make_satoshi('0.00000001')
            print "Buying amount:", self.buy_amount
        else:
            print "Buying amount is low. not buying:"
            return False

        # send order to exchange
        try:
            retval = self.polo.buy(currencyPair=self.my_pair,
                                   rate=self.buy_price,
                                   amount=self.buy_amount)
        except:
            print 'ERROR adding BUY ALL order.'
            retval = False

        print retval

        return retval

    def buy_all(self):
        # cancel all buy orders first.
        self.cancel_open_orders('sell')
        # check open sell orders if the sell price is ok.
        for order in self.open_orders_buy:
            if order['price'] == self.buy_price:
                print "order is ok:", order
            else:
                # cancel the order.
                retval = self.cancel_open_order(order)

        print 'self.open_orders_buy:', len(self.open_orders_buy)
        if len(self.open_orders_buy) == 0:
            print 'adding a new buy all order'
            retval = self.add_buy_all_order()

    def run_buy_all(self):
        self.trade = 'buy'
        while self.trade == 'buy':
            now = datetime.datetime.now()
            print str(now)

            self.load_balances()
            self.load_order_book()

            print '%s Balance: %s' % (self.currency,
                                      self.total_currency_balance)
            print '%s Balance: %s' % (self.coin, self.total_coin_balance)

            self.buy_price = self.find_buy_price()
            print "Buy Price:", self.buy_price

            if self.total_currency_balance > self.min_currency_balance:
                print 'I have %s %s, will try to buy %s.' % (
                    self.total_currency_balance, self.currency, self.coin)
                self.trade = 'buy'
            else:
                print 'I have nothing to trade.'
                self.trade = False

            if self.trade == 'buy':
                self.buy_all()
            else:
                #Will not trade. Cancel all orders.
                self.cancel_open_orders('buy')
                self.cancel_open_orders('sell')

            print "."
            print "open orders:", self.open_orders
            print "."
            now = datetime.datetime.now()
            print str(now)

            print "Will wait a little bit for not to flood the exchange..."
            time.sleep(self.exchange_wait_time)
Esempio n. 9
0
class poloniex_functions(object):
    def __init__(self):
        self.output = BotLog()
        self.conn = Poloniex('secret', 'key')

    def getBalance(self):
        while True:
            try:
                balData = {
                    k: v
                    for k, v in self.conn.returnBalances().items()
                    if float(v) != 0
                }
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return balData

    def getCurrencies(self):
        while True:
            try:
                tickData = [k for k, v in self.conn.returnTicker().items()]
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return tickData

    def getNextTick(self, pair):
        while True:
            try:
                tickData = self.conn.returnTicker()[pair]
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return tickData

    def getHistoricTicks(self, pair, startTime, endTime, period):
        while True:
            try:
                result = self.conn.returnChartData(currencyPair=pair,
                                                   start=startTime,
                                                   end=endTime,
                                                   period=period)
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return result

    def sell(self, pair, rate, amount):
        try:
            result = self.conn.sell(currencyPair=pair,
                                    rate=rate,
                                    amount=amount)
        except Exception as e:
            self.output.log("Error: " + str(e))
            time.sleep(20)
        return result

    def buy(self, pair, rate, amount):
        try:
            result = self.conn.buy(currencyPair=pair, rate=rate, amount=amount)
        except Exception as e:
            self.output.log("Error: " + str(e))
            time.sleep(20)
        return result

    def returnOrderTrades(self, orderId):
        while True:
            try:
                result = self.conn.returnOrderTrades(orderId)
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return result

#==============================================================================
#     Returns your open orders for a given market, specified by the "currencyPair" POST parameter,
#     e.g. "BTC_XCP". Set "currencyPair" to "all" to return open orders for all markets. Sample output for single market:
#==============================================================================

    def returnOpenOrders(self, currencyPair='All'):
        while True:
            try:
                result = self.conn.returnOpenOrders(currencyPair)
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return result

#==============================================================================
#     Cancels an order you have placed in a given market. Required POST parameter is "orderNumber". If successful, the method will return:
#==============================================================================

    def cancelOrder(self, orderNumber):
        while True:
            try:
                result = self.conn.cancelOrder(orderNumber)
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return result

#==============================================================================
#     Cancels an order and places a new one of the same type in a single atomic transaction, meaning either both operations will succeed or both will fail.
#     Required POST parameters are "orderNumber" and "rate"; you may optionally specify "amount" if you wish to change
#     the amount of the new order. "postOnly" or "immediateOrCancel" may be specified for exchange orders, but will have no effect on margin orders.
#==============================================================================

    def moveOrder(self, orderNumber, rate, amount):
        while True:
            try:
                result = self.conn.moveOrder(orderNumber, rate, amount)
                break
            except Exception as e:
                self.output.log("Error: " + str(e))
                time.sleep(20)
                continue
        return result
Esempio n. 10
0
class Checker:
    def __init__(self, ex_ev):
        self.ex_ev = ex_ev
        self.log = None
        self.loop = asyncio.new_event_loop()
        self.polo = Poloniex(POLONIEX_API_KEY, POLONIEX_API_SECRET)

    async def eternity(self, timeout):
        while not self.ex_ev.is_set():
            await asyncio.sleep(timeout)

    async def get_balance(self, balances, user_exchange):

        total_btc = float(0)
        for coin, balance in balances.items():
            total_balance = float(balance['available']) + \
                            float(balance['onOrders'])

            total_btc += float(balance['btcValue'])
            try:
                coin_balance = await get_first_by_filter(session=session,
                                                         model=UserBalance,
                                                         ue=user_exchange,
                                                         coin=coin.lower())
            except Exception as e:
                self.log.error(f'Error getting coin balance: {e}')
                send_telegram(title='ERROR',
                              text=f'Error getting coin balance: {e}')
                coin_balance = None
            if coin_balance:
                data = {
                    'total': total_balance,
                    'btc_value': balance['btcValue'],
                    'conversions': '',
                    'used': balance['onOrders'],
                    'free': balance['available'],
                    'last_update': datetime.now(timezone.utc)
                }
                await update_model(session=session,
                                   model=UserBalance,
                                   pk=coin_balance.id,
                                   data=data)
            else:
                data = {
                    'ue_id': user_exchange.id,
                    'coin': coin,
                    'total': total_balance,
                    'btc_value': balance['btcValue'],
                    'conversions': '',
                    'used': balance['onOrders'],
                    'free': balance['available'],
                    'last_update': datetime.now(timezone.utc)
                }
                await create(session=session, model=UserBalance, **data)
        # =================================================
        data = {
            'total_btc': total_btc,
            'total_usd': get_usd_value('btc', total_btc),
            'error': '',
        }
        await update_model(session=session,
                           model=UserExchange,
                           pk=user_exchange.id,
                           data=data)

    async def pull_exchanges_balances(self, ue_pk=None):
        while not self.ex_ev.is_set():
            # print("=========CHECKER PULL EXCHANGE BALANCE========")
            try:
                if ue_pk is None:
                    user_exchanges = await get_by_filter(session=session,
                                                         model=UserExchange)
                else:
                    user_exchanges = await get_by_filter(session=session,
                                                         model=UserExchange,
                                                         id=ue_pk)
            except Exception as e:
                self.log.error(f'Get Exchange Error: {e}')
                return
            if not user_exchanges:
                self.log.error('No Active Exchanges!')
            for user_exchange in user_exchanges:
                try:
                    balances = self.polo.returnCompleteBalances()
                    try:
                        await self.get_balance(balances, user_exchange)
                    except Exception as e:
                        self.log.error(f'Get Balance Error: {e}')
                        send_telegram(title='ERROR',
                                      text=f'Get Balance Error: {e}')

                    data = {'error': '', 'is_correct': True, 'is_active': True}
                    await update_model(session=session,
                                       model=UserExchange,
                                       pk=user_exchange.id,
                                       data=data)
                except Exception as e:
                    self.log.error(f'Get Balance From Poloniex Error: {e}')
                    send_telegram(title='ERROR',
                                  text='Incorrect apikey or secret')
                    data = {
                        'error': 'Incorrect apikey or secret',
                        'is_correct': False,
                        'is_active': False
                    }
                    await update_model(session=session,
                                       model=UserExchange,
                                       pk=user_exchange.id,
                                       data=data)
            if self.ex_ev.is_set():
                break
            try:
                await asyncio.wait_for(self.eternity(10), timeout=60.0)
            except asyncio.TimeoutError:
                ...

            if ue_pk:
                break
        if self.ex_ev.is_set():
            self.log.info('=========EXIT EVENT PULL EXCHANGE BALANCE========')

    async def check_open(self, uo, orders_to_close):
        if uo in orders_to_close:
            self.log.info(f'Time to close for order # '
                          f'{uo.order_number} {uo.pair}')
            canceled = {}
            i = 3
            if uo.is_fake:
                canceled['success'] = 1
            else:
                while not self.ex_ev.is_set():
                    try:
                        self.log.info(f'Trying to cancel order '
                                      f'{uo.order_number} {uo.pair}')
                        canceled = self.polo.cancelOrder(str(uo.order_number))
                    except Exception as e:
                        self.log.error(f'Cancel order error: {e}')
                        await asyncio.sleep(.5)
                        self.polo = Poloniex(POLONIEX_API_KEY,
                                             POLONIEX_API_SECRET)
                        if 'success' in e:
                            canceled['success'] = 1
                    if canceled or i == 0:
                        break
                    i -= 1
            if canceled['success'] == 1:
                data = {
                    'date_cancel': datetime.now(timezone.utc),
                    'date_updated': datetime.now(timezone.utc),
                    'cancel_desc': 'TTL'
                }
                try:
                    await update_model(session=session,
                                       model=UserOrder,
                                       pk=uo.id,
                                       data=data)
                    self.log.info(f'Order # {uo.order_number}({uo.pair}) '
                                  f'was canceled')
                    send_telegram(title='Order was canceled',
                                  text=f'Order # {uo.order_number}({uo.pair}) '
                                  f'was canceled')
                except Exception as e:
                    self.log.error(
                        f'Order # {uo.order_number} update error {e}')
                    send_telegram(
                        title='ERROR',
                        text=f'Order # {uo.order_number} update error {e}')
        else:
            balance_main_coin = await get_first_by_filter(
                session=session,
                model=UserBalance,
                ue=uo.ue,
                coin=uo.pair.main_coin.symbol.lower())
            if balance_main_coin:
                try:
                    data = {
                        'interim_main_coin': balance_main_coin.total,
                        'date_updated': datetime.now(timezone.utc),
                    }
                    await update_model(session=session,
                                       model=UserOrder,
                                       pk=uo.id,
                                       data=data)
                except Exception as e:
                    self.log.error(
                        f'Order # {uo.order_number} update error {e}')
                    send_telegram(
                        title='ERROR',
                        text=f'Order # {uo.order_number} update error {e}')

    async def check_close(self, uo):

        current_balance_main_coin = await get_first_by_filter(
            session=session,
            model=UserBalance,
            ue=uo.ue,
            coin=uo.pair.main_coin.symbol.lower())
        fact_total = 0
        data = {}

        if current_balance_main_coin:
            data['main_coin_after_total'] = current_balance_main_coin.total
            data['main_coin_after_free'] = current_balance_main_coin.free
            data['main_coin_after_used'] = current_balance_main_coin.used
        else:
            data['main_coin_after_total'] = '-1'
            data['main_coin_after_free'] = '-1'
            data['main_coin_after_used'] = '-1'

        current_balance_second_coin = await get_first_by_filter(
            session=session,
            model=UserBalance,
            ue=uo.ue,
            coin=uo.pair.second_coin.symbol.lower())
        if current_balance_second_coin:
            data['second_coin_after_total'] = current_balance_second_coin.total
            data['second_coin_after_used'] = current_balance_second_coin.free
            data['second_coin_after_free'] = current_balance_second_coin.used
        else:
            data['second_coin_after_total'] = '-1'
            data['second_coin_after_used'] = '-1'
            data['second_coin_after_free'] = '-1'

        if uo.order_type == 'buy':
            fact_total = float(uo.interim_main_coin) - float(
                current_balance_main_coin.total)
        if uo.order_type == 'sell':
            fact_total = float(current_balance_main_coin.total) - float(
                uo.interim_main_coin)

        data['fact_total'] = fact_total
        if fact_total != 0:
            fact_fee = 100.0 * float(uo.total) / float(fact_total) - 100.0
            data['fact_fee'] = fact_fee
            if fact_fee > 0.2:
                data['is_ok'] = False
        try:
            data['to_close'] = False
            data['cancel_desc'] = 'Worked'
            data['date_updated'] = datetime.now(timezone.utc)
            data['date_cancel'] = datetime.now(timezone.utc)
            await update_model(session=session,
                               model=UserOrder,
                               pk=uo.id,
                               data=data)

            self.log.warning(f'[!!!!!] Order # {uo.order_number}, '
                             f'Pair {uo.pair} saved [!!!!!]')
            send_telegram(title='!!! Order saved',
                          text=f'Order # {uo.order_number}, '
                          f'Pair {uo.pair} saved')
        except Exception as e:
            self.log.error(f'Save Order Error: {e}')
            send_telegram(title='ERROR', text=f'Save Order Error: {e}')

    async def group_check_orders(self, uo, orders_to_close):
        try:
            order_status = self.polo.returnOrderStatus(uo.order_number)
            if order_status.get('success') == 1:
                await self.check_open(uo, orders_to_close)
            if order_status.get('success') == 0:
                await self.check_close(uo)
        except Exception as e:
            self.log.error(f'Error getting orders for {uo.order_number}: {e}')
            send_telegram(
                title='ERROR',
                text=f'Error getting orders for {uo.order_number}: {e}')

    async def check_orders(self):
        while not self.ex_ev.is_set():
            # print('===========CHECKER CHECK ORDERS================')
            user_orders = None
            try:
                user_orders = await get_by_filter(session=session,
                                                  model=UserOrder,
                                                  cancel_desc='')
            except Exception as e:
                self.log.error(f'Error getting user orders to close: {e}')

            if user_orders:
                try:
                    orders_to_close = session.query(UserOrder).filter(
                        UserOrder.date_created <= datetime.now(timezone.utc) -
                        timedelta(minutes=ORDER_TTL),
                        UserOrder.cancel_desc == '',
                        UserOrder.to_close.is_(False)).all()
                    [
                        asyncio.ensure_future(self.group_check_orders(
                            uo, orders_to_close),
                                              loop=self.loop)
                        for uo in user_orders
                    ]

                except Exception as e:
                    self.log.error(f'Check orders error: {e}')
                    send_telegram(title='ERROR',
                                  text=f'Check orders error: {e}')

            await asyncio.sleep(1)

        if self.ex_ev.is_set():
            self.log.info('==========CHECKER EXIT EVENT check_orders=======')

    async def open_real_order(self, to_trade):
        pair = f'{to_trade.user_pair.main_coin}_' \
               f'{to_trade.user_pair.second_coin}'
        order_id = None
        try:
            if to_trade.type == 'buy':
                order = self.polo.buy(currencyPair=pair,
                                      rate=to_trade.price,
                                      amount=to_trade.amount,
                                      postOnly=1)
                self.log.warning(f'Answer (buy): {order}')
                order_id = order.get('orderNumber')
                send_telegram(title=f'Order open: {pair}, '
                              f'price: {to_trade.price: .8f}, '
                              f'amount: {to_trade.amount}',
                              text=f'Answer (buy): {order}')
            elif to_trade.type == 'sell':
                order = self.polo.sell(currencyPair=pair,
                                       rate=to_trade.price,
                                       amount=to_trade.amount,
                                       postOnly=1)
                self.log.warning(f'Answer (sell): {order}')
                order_id = order.get('orderNumber')
                send_telegram(title=f'Order open: {pair}, '
                              f'price: {to_trade.price: .8f}, '
                              f'amount: {to_trade.amount}',
                              text=f'Answer (sell): {order}')
        except Exception as e:
            self.log.error(f'Open order {pair}, {to_trade.amount}, '
                           f'{to_trade.price}. Error: {e}')
            send_telegram(
                title='ERROR',
                text=f'Open order for: {pair}, amount: {to_trade.amount}, '
                f'price: {to_trade.price: .8f}. Error: {e}')
            await asyncio.sleep(1)

        return order_id

    async def check_to_trade(self):

        while not self.ex_ev.is_set():
            # print('================CHECK TO TRADE===================')
            try:
                to_trade = session.query(ToTrade).filter(
                    ToTrade.date_updated >= datetime.now(timezone.utc) -
                    timedelta(minutes=5)).order_by(
                        ToTrade.date_updated).first()
                if not to_trade:
                    await asyncio.sleep(5)
                    continue
                self.log.info(f'Found order to trade: {to_trade}')
                already_in_orders = await get_by_filter(
                    session=session,
                    model=UserOrder,
                    pair_id=to_trade.user_pair.pair.id,
                    date_cancel=None)

                self.log.info(f'Already in orders: {already_in_orders}')
                if len(already_in_orders) > 0:
                    to_delete = session.query(ToTrade).filter(
                        ToTrade.id == to_trade.id)
                    _ = to_delete.delete()
                    session.commit()
                else:
                    self.log.info('Trying to open order...')
                    order_id = await self.open_real_order(to_trade)
                    if not order_id:
                        await asyncio.sleep(5)
                        continue

                    await self.pull_exchanges_balances(
                        to_trade.user_pair.user_exchange.id)
                    self.log.info('Balance Checked')
                    main_coin_balance = await get_first_by_filter(
                        session=session,
                        model=UserBalance,
                        ue=to_trade.user_pair.user_exchange,
                        coin=to_trade.user_pair.pair.main_coin.symbol)
                    second_coin_balance = await get_first_by_filter(
                        session=session,
                        model=UserBalance,
                        ue=to_trade.user_pair.user_exchange,
                        coin=to_trade.user_pair.pair.second_coin.symbol)
                    self.log.info(f'Main coin: {main_coin_balance}, '
                                  f'Second coin: {second_coin_balance}')

                    data = {
                        'ue_id': to_trade.user_pair.user_exchange.id,
                        'pair_id': to_trade.user_pair.pair.id,
                        'order_type': to_trade.type,
                        'order_number': order_id,
                        'interim_main_coin': main_coin_balance.total,
                        'main_coin_before_total': main_coin_balance.total,
                        'main_coin_before_free': main_coin_balance.free,
                        'main_coin_before_used': main_coin_balance.used,
                        'second_coin_before_total': second_coin_balance.total,
                        'second_coin_before_free': second_coin_balance.free,
                        'second_coin_before_used': second_coin_balance.used,
                        'price': to_trade.price,
                        'amount': to_trade.amount,
                        'total': to_trade.price * to_trade.amount,
                        'date_created': datetime.now(timezone.utc),
                        'date_updated': datetime.now(timezone.utc),
                        'fee': FEE,
                    }
                    self.log.info('Create order')
                    try:
                        await create(session=session, model=UserOrder, **data)
                        self.log.warning(f"Order {order_id} added. "
                                         f"Type {to_trade.type}, "
                                         f"Pair {to_trade.user_pair.pair}, "
                                         f"Price {to_trade.price: .8f}")
                        to_delete = session.query(ToTrade).filter(
                            ToTrade.id == to_trade.id)
                        _ = to_delete.delete()
                        session.commit()
                    except Exception as e:
                        self.log.exception(f'Create Order Error: {e}')
                        send_telegram(title='ERROR',
                                      text=f'Error write order to DB: {e}')
            except Exception as e:
                self.log.error(f'check_to_trade error: {e}')
            await asyncio.sleep(5)

        if self.ex_ev.is_set():
            self.log.info('============CHECK TO TRADE EXIT EVENT===========')

    def run(self):
        self.log = get_logger('checker')
        self.log.info('Start Checker')
        asyncio.set_event_loop(self.loop)
        tasks = [
            self.pull_exchanges_balances(),
            self.check_orders(),
            self.check_to_trade()
        ]

        group = asyncio.gather(*tasks)
        self.loop.run_until_complete(group)
        if self.ex_ev.is_set():
            self.log.info('=======CHECKER RUN EXIT EVENT=================')
            self.loop.stop()
            self.loop.close()