Exemplo n.º 1
0
    def update(self):
        # Get current state of trade history before placing orders
        log.info("Update entered")
        
        now = str(datetime.datetime.now().isoformat()[:-7].replace("T", " "))
        last_trade_price = self.exchange.get_last_trade_price()

        first_order = get_first_order(self.mutex_UUID)
        current_history = self.exchange.get_my_trade_history(first_order)
        last_order = get_last_order(self.mutex_UUID)
        new_history = get_new_history(current_history, last_order)
        print('first_order', first_order)
        print('last_order', last_order)
        print('new_history', new_history)
        new_transactions = []
        
        if len(new_history) > 0:
            # We have new transactions
            log.info('we have new history')
            log.debug("New transactions: {}".format(new_history))
            new_transactions = self.rebalance_orders(new_history)
            #self.merge_orders()
            
        # context to be used for GUI plotting
        context = {"price": (now, last_trade_price),
                   "filled_orders": new_transactions,
                   "open_orders": self.exchange.get_my_open_orders(context_formatted=True),
                   "balances": self.exchange.get_balances(),
                   "orderbook": self.exchange.get_all_orders()
                   }
        
        return context
Exemplo n.º 2
0
    def update(self):
        ''' TODO: Function comment
        '''
        log.info("Update entered\n")

        now = str(datetime.datetime.now().isoformat()[:-7].replace("T", " "))
        last_trade_price = self.exchange.get_last_trade_price()
        if last_trade_price == "EOF":
            # Test merkato datastream ended
            print("test datastream ended")
            return "stuffs"

        first_order = get_first_order(self.mutex_UUID)
        last_order = get_last_order(self.mutex_UUID)

        current_history = self.exchange.get_my_trade_history()
        new_history = get_new_history(current_history, last_order)
        log.info(
            'update new_history: {} first_order: {} last_order: {} \n'.format(
                new_history, first_order, last_order))
        new_transactions = []

        if len(new_history) > 0:
            log.info('we have new history')
            log.debug("New transactions: {} \n".format(new_history))

            new_transactions = self.rebalance_orders(new_history)
            #self.merge_orders()
            # todo: Talk about whether merging 'close enough' orders is reasonable.

        # context to be used for GUI plotting
        context = {
            "price": (now, last_trade_price),
            "filled_orders": new_transactions,
            "open_orders":
            self.exchange.get_my_open_orders(context_formatted=True),
            "balances": self.exchange.get_balances(),
            "orderbook": self.exchange.get_all_orders(),
            "starting_price": self.starting_price,
            "starting_base": self.bid_reserved_balance * 4,
            "starting_quote": self.ask_reserved_balance * 4,
            "spread": self.spread,
            "step": self.step
        }

        return context
Exemplo n.º 3
0
    def __init__(self, configuration, coin, base, spread,
                 bid_reserved_balance, ask_reserved_balance,
                 user_interface=None, profit_margin=0, first_order=''):

        validate_merkato_initialization(configuration, coin, base, spread)
        self.initialized = False
        UUID = configuration[EXCHANGE] + "coin={}_base={}".format(coin,base)
        self.mutex_UUID = UUID
        self.distribution_strategy = 1
        self.spread = float(spread)
        self.profit_margin = profit_margin
        # Create ladders from the bid and ask bidget here
        self.bid_reserved_balance = bid_reserved_balance
        self.ask_reserved_balance = ask_reserved_balance
        self.user_interface = user_interface
        exchange_class = get_relevant_exchange(configuration[EXCHANGE])
        self.exchange = exchange_class(configuration, coin=coin, base=base)
        merkato_does_exist = merkato_exists(UUID)

        if not merkato_does_exist:
            log.info("Creating New Merkato")
            self.cancelrange(ONE_SATOSHI, ONE_BITCOIN)
            total_pair_balances = self.exchange.get_balances()
            log.info("total pair balances", total_pair_balances)
            allocated_pair_balances = get_allocated_pair_balances(configuration['exchange'], base, coin)
            check_reserve_balances(total_pair_balances, allocated_pair_balances, coin_reserve=ask_reserved_balance, base_reserve=bid_reserved_balance)
            insert_merkato(configuration[EXCHANGE], UUID, base, coin, spread, bid_reserved_balance, ask_reserved_balance, first_order)
            history = self.exchange.get_my_trade_history()
            print('initial history', history)
            if len(history) > 0:
                print('updating history', history[0]['orderId'])
                new_last_order = history[0]['orderId']
                update_merkato(self.mutex_UUID, LAST_ORDER, new_last_order)
            self.distribute_initial_orders(total_base=bid_reserved_balance, total_alt=ask_reserved_balance)

        else:
            #self.history = get_old_history(self.exchange.get_my_trade_history(), self.mutex_UUID)
            first_order = get_first_order(self.mutex_UUID)
            current_history = self.exchange.get_my_trade_history(first_order)
            last_order = get_last_order(self.mutex_UUID)
            new_history = get_new_history(current_history, last_order)
            self.rebalance_orders(new_history)
        self.initialized = True  # to avoid being updated before orders placed
Exemplo n.º 4
0
    def get_context_history(self):
        now = str(datetime.datetime.now().isoformat()[:-7].replace("T", " "))
        last_trade_price = self.exchange.get_last_trade_price()
        current_history = self.exchange.get_my_trade_history()
        first_order = get_first_order(self.mutex_UUID)
        new_history = get_new_history(current_history, first_order)

        self.exchange.process_new_transactions(new_history, context_only=True)

        context = {
            "price": (now, last_trade_price),
            "filled_orders": new_history,
            "open_orders":
            self.exchange.get_my_open_orders(context_formatted=True),
            "balances": self.exchange.get_balances(),
            "orderbook": self.exchange.get_all_orders(),
            "starting_price": self.starting_price,
            "starting_base": self.base_quote_balance,
            "starting_quote": self.init_quote_balance,
            "spread": self.spread,
            "step": self.step
        }

        return context
Exemplo n.º 5
0
    def __init__(self,
                 configuration,
                 coin,
                 base,
                 spread,
                 bid_reserved_balance,
                 ask_reserved_balance,
                 user_interface=None,
                 profit_margin=0,
                 first_order='',
                 starting_price=.018,
                 increased_orders=0,
                 step=1.0033,
                 distribution_strategy=1,
                 init_base_balance=0,
                 init_quote_balance=0,
                 base_profit=0,
                 quote_profit=0,
                 buy_volume=0,
                 sell_volume=0):

        validate_merkato_initialization(configuration, coin, base, spread)
        self.initialized = False
        UUID = configuration[EXCHANGE] + "coin={}_base={}".format(coin, base)
        self.mutex_UUID = UUID
        self.distribution_strategy = distribution_strategy
        self.spread = Decimal(spread)
        self.profit_margin = Decimal(profit_margin)
        self.starting_price = starting_price
        self.step = step
        self.increased_orders = increased_orders
        self.quote_profit = Decimal(quote_profit)
        self.base_profit = Decimal(base_profit)
        self.bid_reserved_balance = Decimal(float(bid_reserved_balance))
        self.ask_reserved_balance = Decimal(float(ask_reserved_balance))
        self.init_base_balance = init_base_balance
        self.init_quote_balance = init_quote_balance
        # The current sum of all partially filled orders
        self.base_partials_balance = 0
        self.quote_partials_balance = 0
        self.buy_volume = buy_volume
        self.sell_volume = sell_volume
        self.last_placed_UUID = ''  #this assures that no faulty doubled up orders will be placed sequentially

        self.user_interface = user_interface

        exchange_class = get_relevant_exchange(configuration[EXCHANGE])
        self.exchange = exchange_class(configuration, coin=coin, base=base)

        merkato_does_exist = merkato_exists(self.mutex_UUID)

        if not merkato_does_exist:
            log.info("Creating New Merkato")

            self.cancelrange(ONE_SATOSHI, ONE_BITCOIN)

            total_pair_balances = self.exchange.get_balances()

            log.info("total pair balances: {}".format(total_pair_balances))

            allocated_pair_balances = get_allocated_pair_balances(
                configuration['exchange'], base, coin)
            check_reserve_balances(total_pair_balances,
                                   allocated_pair_balances,
                                   coin_reserve=ask_reserved_balance,
                                   base_reserve=bid_reserved_balance)

            insert_merkato(configuration[EXCHANGE],
                           self.mutex_UUID,
                           base,
                           coin,
                           spread,
                           bid_reserved_balance,
                           ask_reserved_balance,
                           first_order,
                           starting_price,
                           init_base_balance=bid_reserved_balance,
                           init_quote_balance=ask_reserved_balance,
                           step=step)
            history = self.exchange.get_my_trade_history()

            log.debug('initial history: {}'.format(history))

            if len(history) > 0:
                log.debug('updating history first ID: {}'.format(
                    history[0][ID]))
                new_last_order = history[0][ID]
                update_merkato(self.mutex_UUID, LAST_ORDER, new_last_order)
            self.distribute_initial_orders(total_base=bid_reserved_balance,
                                           total_alt=ask_reserved_balance)

        else:
            first_order = get_first_order(self.mutex_UUID)
            current_history = self.exchange.get_my_trade_history()
            last_order = get_last_order(self.mutex_UUID)
            new_history = get_new_history(current_history, last_order)
            self.rebalance_orders(new_history)

        self.initialized = True  # to avoid being updated before orders placed
Exemplo n.º 6
0
    def rebalance_orders(self, new_txes):
        # This function places matching orders for all orders that filled fully since last

        factor = self.spread * self.profit_margin / 2
        ordered_transactions = new_txes

        log.info(
            'ordered transactions rebalanced: {}'.format(ordered_transactions))

        filled_orders = []
        market_orders = []

        if self.exchange.name != 'tux':
            self.exchange.process_new_transactions(ordered_transactions)

        for tx in ordered_transactions:
            log.info('Checking Transaction: {}'.format(tx))
            orderid = tx['orderId']
            tx_id = tx[ID]
            price = tx[PRICE]

            filled_amount = Decimal(tx['amount'])
            init_amount = Decimal(tx['initamount'])

            if self.exchange.name == 'tux':
                partial_fill_info = self.exchange.get_my_order_info(orderid)
                init_amount = partial_fill_info['initamount']
                partial_fill = (partial_fill_info['state'] == 'closed')
            else:
                partial_fill = self.exchange.is_partial_fill(
                    orderid)  # todo implement for tux (binance done)

            total_amount = self.get_total_amount(init_amount, orderid)
            amount = Decimal(total_amount) * Decimal((1 - factor))

            if partial_fill:
                self.handle_partial_fill(tx[TYPE], filled_amount, tx_id)
                continue

            if orderid in filled_orders:
                self.handle_is_in_filled_orders(tx)
                continue

            if tx[TYPE] == SELL:
                buy_price = Decimal(price) * (1 - self.spread)

                # Convert from the coin amount into base at the executed price
                base_amt = Decimal(price) * amount
                # Convert the base amount into coin at the final price
                coin_amt = base_amt / buy_price
                # This is the actual number we want to apply, not the original executed amount.
                amount = coin_amt

                if self.last_placed_UUID != buy_price + amount:
                    log.info(
                        "Found sell {} corresponding buy price: {} amount: {}".
                        format(tx, buy_price, amount))
                    order_response = self.exchange.buy(amount, buy_price)
                else:
                    order_response = None

                self.update_sell_volume(filled_amount)

                if order_response == MARKET:
                    log.info('MARKET ORDER buy {}'.format(order_response))
                    market_orders.append((
                        amount,
                        buy_price,
                        BUY,
                        tx_id,
                    ))

                self.apply_filled_difference(tx, total_amount)

                is_round_trip = float(price) <= (float(self.starting_price) *
                                                 float(1 + (self.spread / 2)))
                if is_round_trip:
                    log.info('Is round trip sell price: {}'.format(price))
                    self.base_profit += total_amount * Decimal(
                        float(price)) * (self.spread -
                                         Decimal(self.exchange.fee * 2))
                    update_merkato(self.mutex_UUID, BASE_PROFIT,
                                   float(self.base_profit))
                order_price = buy_price

            if tx[TYPE] == BUY:
                sell_price = Decimal(price) * (1 + self.spread)

                if self.last_placed_UUID != sell_price + amount:
                    log.info(
                        "Found buy {} corresponding sell price: {} amount: {}".
                        format(tx, sell_price, amount))
                    order_response = self.exchange.sell(amount, sell_price)
                else:
                    order_response = None

                self.update_buy_volume(filled_amount, price)

                if order_response == MARKET:
                    log.info('MARKET ORDER sell {}'.format(order_response))
                    market_orders.append((amount, sell_price, SELL, tx_id))

                self.apply_filled_difference(tx, total_amount)

                is_round_trip = float(price) >= (float(self.starting_price) *
                                                 float(1 - (self.spread / 2)))
                if is_round_trip:
                    log.info('Is round trip buy price: {}'.format(price))
                    self.quote_profit += total_amount * Decimal(
                        self.spread - Decimal(self.exchange.fee * 2))
                    update_merkato(self.mutex_UUID, QUOTE_PROFIT,
                                   float(self.quote_profit))
                order_price = sell_price

            if order_response != MARKET:
                log.info('NOT MARKET ORDER')
                update_merkato(self.mutex_UUID, LAST_ORDER, tx[ID])

            filled_orders.append(orderid)

            first_order = get_first_order(self.mutex_UUID)
            no_first_order = first_order == ''

            if no_first_order:
                update_merkato(self.mutex_UUID, FIRST_ORDER, tx_id)
            self.last_placed_UUID = order_price + amount

        for order in market_orders:
            self.handle_market_order(*order)
        log.info('ending partials base: {} quote: {}'.format(
            self.base_partials_balance, self.quote_partials_balance))
        return ordered_transactions
Exemplo n.º 7
0
    def rebalance_orders(self, new_txes):
        # This function places matching orders for all orders that filled fully since last

        factor = self.spread * self.profit_margin / 2
        ordered_transactions = new_txes

        log.info(
            'ordered transactions rebalanced: {}'.format(ordered_transactions))

        filled_orders = []
        market_orders = []

        if self.exchange.name != 'tux':
            self.exchange.process_new_transactions(ordered_transactions)

        for tx in ordered_transactions:
            log.info('Checking Transaction: {}\n'.format(tx))
            orderid = tx['orderId']
            tx_id = tx[ID]
            price = tx[PRICE]

            filled_amount = Decimal(tx['amount'])
            init_amount = Decimal(tx['initamount'])

            if self.exchange.name == 'tux':
                partial_fill_info = self.exchange.get_my_order_info(orderid)
                init_amount = partial_fill_info['initamount']
                partial_fill = (partial_fill_info['state'] == 'closed')
            else:
                partial_fill = self.exchange.is_partial_fill(
                    orderid)  # todo implement for tux (binance done)

            total_amount = self.get_total_amount(init_amount, orderid)
            amount = Decimal(total_amount) * Decimal((1 - factor))

            if partial_fill:
                self.handle_partial_fill(tx[TYPE], filled_amount, tx_id)
                continue

            if orderid in filled_orders:
                self.handle_is_in_filled_orders(tx)
                continue

            if tx[TYPE] == SELL:
                buy_price = Decimal(price) * (1 - self.spread)
                log.info(
                    "Found sell {} corresponding buy price: {} amount: {}".
                    format(tx, buy_price, amount))

                market = self.exchange.buy(amount, buy_price)
                # A lock is probably needed somewhere near here in case of unexpected shutdowns

                if market == MARKET:
                    log.info('MARKET ORDER buy {}'.format(market))
                    market_orders.append((
                        amount,
                        buy_price,
                        BUY,
                        tx_id,
                    ))

                self.apply_filled_difference(tx, total_amount)

                is_round_trip = float(price) <= (float(self.starting_price) *
                                                 float(1 + (self.spread / 2)))
                if is_round_trip:
                    log.info('Is round trip sell price: {}'.format(price))
                    self.base_volume += total_amount * Decimal(float(price))
                    update_merkato(self.mutex_UUID, BASE_VOLUME,
                                   float(self.base_volume))

            if tx[TYPE] == BUY:
                sell_price = Decimal(price) * (1 + self.spread)

                log.info(
                    "Found buy {} corresponding sell price: {} amount: {}".
                    format(tx, sell_price, amount))

                market = self.exchange.sell(amount, sell_price)

                if market == MARKET:
                    log.info('MARKET ORDER sell {}'.format(market))
                    market_orders.append((amount, sell_price, SELL, tx_id))

                self.apply_filled_difference(tx, total_amount)

                is_round_trip = float(price) >= (float(self.starting_price) *
                                                 float(
                                                     (1 - (self.spread / 2))))

                if is_round_trip:
                    log.info('Is round trip buy price: {}'.format(price))
                    self.quote_volume += total_amount
                    update_merkato(self.mutex_UUID, QUOTE_VOLUME,
                                   float(self.quote_volume))

            insert_transaction(self.mutex_UUID,
                               self.exchange.base, self.exchange.coin,
                               float(self.spread), tx_id, orderid,
                               float(price), float(filled_amount), tx['time'])

            if market != MARKET:
                log.info('NOT MARKET ORDER')
                update_merkato(self.mutex_UUID, LAST_ORDER, tx[ID])

            filled_orders.append(orderid)

            first_order = get_first_order(self.mutex_UUID)
            no_first_order = first_order == ''

            if no_first_order:
                update_merkato(self.mutex_UUID, FIRST_ORDER, tx_id)

        for order in market_orders:
            self.handle_market_order(*order)

        self.log_new_cointrackr_transactions(ordered_transactions)
        log.info('ending partials base: {} quote: {}'.format(
            self.base_partials_balance, self.quote_partials_balance))
        return ordered_transactions
Exemplo n.º 8
0
    def rebalance_orders(self, new_txes):
        # This function places a matching order for every new transaction since last run
        #
        # profit_margin is a number from 0 to 1 representing the percent of the spread to return
        # to the user's balance before placing the matching order.
        #
        # TODO: Modify so that the parent function only passes in the new transactions, don't
        # do the index check internally.

        # new_history is an array of transactions
        # new_txes is the number of new transactions contained in new_history
        factor = self.spread*self.profit_margin/2
        ordered_transactions = new_txes
        log.info('ordered transactions rebalanced: {}'.format(ordered_transactions))
        for tx in ordered_transactions:
            log.info('length of ordered_transactions length length: {}'.format(len(ordered_transactions)))
            if tx['type'] == SELL:
                log.info("Found sell {} corresponding buy {}".format(tx, sell_price))
                
                amount = float(tx['amount']) * float(tx[PRICE])*(1-factor)
                price = float(tx[PRICE])
                buy_price = price * ( 1  - self.spread)
                log.info("found sell {}; corresponding buy {}".format(tx, buy_price))
                market = self.exchange.buy(amount, buy_price)
                if market == MARKET:
                    log.info('market sell', market)
                    last_order_time = str(int(time.time()))
                    self.exchange.market_buy(amount, buy_price)
                    market_history = self.exchange.get_my_trade_history(start=last_order_time)
                    market_data = get_market_results(market_history)

                    # We have a sell executed. We want to place a matching buy order.
                    # If the whole order is executed, no edge case.
                    # If the order has a remainder, the remainder will be on the books at
                    # the appropriate price. So no problem. 
                    # If the remainder is too small to have a matching order, it could 
                    # disappear, but this is such a minor edge case we can ignore it.
                    # 
                    # The sell gave us some BTC. The buy is executed with that BTC.
                    # The market buy will get us X xmr in return. All of that xmr
                    # should be placed at the original order's matching price.
                    amount_executed = float(market_data['amount_executed'])
                    last_orderid    = market_data['last_orderid']
                    log.info('market data: {}'.format(market_data))

                    self.exchange.sell(amount_executed, price) # Should never market order

                    # A market buy occurred, so we need to update the db with the latest tx
                    update_merkato(self.mutex_UUID, LAST_ORDER, last_orderid)

            if tx['type'] == BUY:
                amount = float(tx['amount'])*float((1-factor))
                price = tx[PRICE]
                sell_price = float(price) * ( 1  + self.spread)
                log.info("Found buy {} corresponding sell {}".format(tx, sell_price))
                market = self.exchange.sell(amount, sell_price)
                if market == MARKET:
                    log.info('market buy {}'.format(market))
                    last_order_time = str(int(time.time()))
                    self.exchange.market_sell(amount, sell_price)
                    market_history = self.exchange.get_my_trade_history(start=last_order_time)
                    market_data = get_market_results(market_history)

                    # We have a buy executed. We want to place a matching sell order.
                    # If the whole order is executed, no edge case.
                    # If the order has a remainder, the remainder will be on the books at
                    # the appropriate price. So no problem. 
                    # If the remainder is too small to have a matching order, it could 
                    # disappear, but this is such a minor edge case we can ignore it.
                    # 
                    # The buy gave us some alt. The sell is executed with that alt.
                    # The market sell will get us X btc in return. All of that btc
                    # should be placed at the original order's matching price.
                    amount_executed = float(market_data['total_gotten'])
                    last_orderid    = market_data['last_orderid']
                    log.info('market data {}'.format(market_data))
                    self.exchange.buy(amount_executed, float(price)) # Should never market order

                    # A market buy occurred, so we need to update the db with the latest tx
                    update_merkato(self.mutex_UUID, LAST_ORDER, last_orderid)

            if market != MARKET: 
                log.info('market != MARKET market != MARKET')
                update_merkato(self.mutex_UUID, LAST_ORDER, tx['orderId'])
            
            first_order = get_first_order(self.mutex_UUID)
            no_first_order = first_order == ''
            if no_first_order:
                update_merkato(self.mutex_UUID, FIRST_ORDER, tx['orderId'])

        self.log_new_transactions(ordered_transactions)
        
        return ordered_transactions
Exemplo n.º 9
0
    def __init__(self,
                 configuration,
                 coin,
                 base,
                 spread,
                 bid_reserved_balance,
                 ask_reserved_balance,
                 user_interface=None,
                 profit_margin=0,
                 first_order='',
                 starting_price=.018,
                 quote_volume=0,
                 base_volume=0):

        validate_merkato_initialization(configuration, coin, base, spread)
        self.initialized = False
        UUID = configuration[EXCHANGE] + "coin={}_base={}".format(coin, base)
        self.mutex_UUID = UUID
        self.distribution_strategy = 1
        self.spread = Decimal(spread)
        self.profit_margin = Decimal(profit_margin)
        self.starting_price = starting_price
        self.quote_volume = Decimal(quote_volume)
        self.base_volume = Decimal(base_volume)
        self.step = 1.0033
        # Exchanges have a maximum number of orders every user can place. Due
        # to this, every Merkato has a reserve of coins that are not currently
        # allocated. As the price approaches unallocated regions, the reserves
        # are deployed.
        self.bid_reserved_balance = Decimal(float(bid_reserved_balance))
        self.ask_reserved_balance = Decimal(float(ask_reserved_balance))

        # The current sum of all partially filled orders
        self.base_partials_balance = 0
        self.quote_partials_balance = 0

        self.user_interface = user_interface

        exchange_class = get_relevant_exchange(configuration[EXCHANGE])
        self.exchange = exchange_class(configuration, coin=coin, base=base)

        merkato_does_exist = merkato_exists(self.mutex_UUID)

        if not merkato_does_exist:
            log.info("Creating New Merkato")

            self.cancelrange(ONE_SATOSHI, ONE_BITCOIN)

            total_pair_balances = self.exchange.get_balances()

            log.info("total pair balances: {}".format(total_pair_balances))

            allocated_pair_balances = get_allocated_pair_balances(
                configuration['exchange'], base, coin)
            check_reserve_balances(total_pair_balances,
                                   allocated_pair_balances,
                                   coin_reserve=ask_reserved_balance,
                                   base_reserve=bid_reserved_balance)

            insert_merkato(configuration[EXCHANGE], self.mutex_UUID, base,
                           coin, spread, bid_reserved_balance,
                           ask_reserved_balance, first_order, starting_price)
            history = self.exchange.get_my_trade_history()

            log.debug('initial history: {}'.format(history))

            if len(history) > 0:
                log.debug('updating history first ID: {}'.format(
                    history[0][ID]))
                new_last_order = history[0][ID]
                update_merkato(self.mutex_UUID, LAST_ORDER, new_last_order)
            self.distribute_initial_orders(total_base=bid_reserved_balance,
                                           total_alt=ask_reserved_balance)

        else:
            first_order = get_first_order(self.mutex_UUID)
            current_history = self.exchange.get_my_trade_history(first_order)
            last_order = get_last_order(self.mutex_UUID)
            new_history = get_new_history(current_history, last_order)
            self.rebalance_orders(new_history)

        self.initialized = True  # to avoid being updated before orders placed