def buyer_strategy(order_book, open_orders, spreads):
    time.sleep(10)
    while True:
        time.sleep(0.001)
        if not open_orders.open_bid_order_id:
            open_bid_price = order_book.bids.price_tree.max_key() - spreads.bid_spread
            if 0.01 * float(open_bid_price) < float(open_orders.accounts['USD']['available']):
                order = {'size': '0.01',
                         'price': str(open_bid_price),
                         'side': 'buy',
                         'product_id': 'BTC-USD',
                         'post_only': True}
                response = requests.post(exchange_api_url + 'orders', json=order, auth=exchange_auth)
                try:
                    response = response.json()
                except ValueError:
                    file_logger.error('Unhandled response: {0}'.format(pformat(response)))
                if 'status' in response and response['status'] == 'pending':
                    open_orders.open_bid_order_id = response['id']
                    open_orders.open_bid_price = open_bid_price
                    open_orders.open_bid_rejections = Decimal('0.0')
                    file_logger.info('new bid @ {0}'.format(open_bid_price))
                elif 'status' in response and response['status'] == 'rejected':
                    open_orders.open_bid_order_id = None
                    open_orders.open_bid_price = None
                    open_orders.open_bid_rejections += Decimal('0.04')
                    file_logger.warn('rejected: new bid @ {0}'.format(open_bid_price))
                elif 'message' in response and response['message'] == 'Insufficient funds':
                    open_orders.open_bid_order_id = None
                    open_orders.open_bid_price = None
                    file_logger.warn('Insufficient USD')
                elif 'message' in response and response['message'] == 'request timestamp expired':
                    open_orders.open_bid_order_id = None
                    open_orders.open_bid_price = None
                    file_logger.warn('Request timestamp expired')
                else:
                    file_logger.error('Unhandled response: {0}'.format(pformat(response)))
                continue

        if open_orders.open_bid_order_id and not open_orders.open_bid_cancelled:
            bid_too_far_out = open_orders.open_bid_price < (order_book.bids.price_tree.max_key()
                                                            - spreads.bid_too_far_adjustment_spread)
            bid_too_close = open_orders.open_bid_price > (order_book.bids.price_tree.max_key()
                                                          - spreads.bid_too_close_adjustment_spread)
            cancel_bid = bid_too_far_out or bid_too_close
            if cancel_bid:
                if bid_too_far_out:
                    file_logger.info('CANCEL: open bid {0} too far from best bid: {1} spread: {2}'.format(
                        open_orders.open_bid_price,
                        order_book.bids.price_tree.max_key(),
                        order_book.bids.price_tree.max_key() - open_orders.open_bid_price))
                if bid_too_close:
                    file_logger.info('CANCEL: open bid {0} too close to best bid: {1} spread: {2}'.format(
                        open_orders.open_bid_price,
                        order_book.bids.price_tree.max_key(),
                        order_book.bids.price_tree.max_key() - open_orders.open_bid_price))
                open_orders.cancel('bid')
                continue
def market_maker_strategy(open_orders, order_book, spreads):
    time.sleep(10)
    open_orders.get_open_orders()
    open_orders.cancel_all()
    while True:
        time.sleep(0.005)
        if order_book.asks.price_tree.min_key() - order_book.bids.price_tree.max_key() < 0:
            file_logger.warn('Negative spread: {0}'.format(
                order_book.asks.price_tree.min_key() - order_book.bids.price_tree.max_key()))
            continue
        if not open_orders.open_bid_order_id:
            open_bid_price = order_book.asks.price_tree.min_key() - spreads.bid_spread - open_orders.open_bid_rejections
            if 0.01 * float(open_bid_price) < float(open_orders.accounts['USD']['available']):
                order = {'size': '0.01',
                         'price': str(open_bid_price),
                         'side': 'buy',
                         'product_id': 'BTC-USD',
                         'post_only': True}
                response = requests.post(exchange_api_url + 'orders', json=order, auth=exchange_auth)
                if 'status' in response.json() and response.json()['status'] == 'pending':
                    open_orders.open_bid_order_id = response.json()['id']
                    open_orders.open_bid_price = open_bid_price
                    open_orders.open_bid_rejections = Decimal('0.0')
                    file_logger.info('new bid @ {0}'.format(open_bid_price))
                elif 'status' in response.json() and response.json()['status'] == 'rejected':
                    open_orders.open_bid_order_id = None
                    open_orders.open_bid_price = None
                    open_orders.open_bid_rejections += Decimal('0.04')
                    file_logger.warn('rejected: new bid @ {0}'.format(open_bid_price))
                elif 'message' in response.json() and response.json()['message'] == 'Insufficient funds':
                    open_orders.open_bid_order_id = None
                    open_orders.open_bid_price = None
                    file_logger.warn('Insufficient USD')
                else:
                    file_logger.error('Unhandled response: {0}'.format(pformat(response.json())))
                continue

        if not open_orders.open_ask_order_id:
            open_ask_price = order_book.bids.price_tree.max_key() + spreads.ask_spread + open_orders.open_ask_rejections
            if 0.01 < float(open_orders.accounts['BTC']['available']):
                order = {'size': '0.01',
                         'price': str(open_ask_price),
                         'side': 'sell',
                         'product_id': 'BTC-USD',
                         'post_only': True}
                response = requests.post(exchange_api_url + 'orders', json=order, auth=exchange_auth)
                if 'status' in response.json() and response.json()['status'] == 'pending':
                    open_orders.open_ask_order_id = response.json()['id']
                    open_orders.open_ask_price = open_ask_price
                    file_logger.info('new ask @ {0}'.format(open_ask_price))
                    open_orders.open_ask_rejections = Decimal('0.0')
                elif 'status' in response.json() and response.json()['status'] == 'rejected':
                    open_orders.open_ask_order_id = None
                    open_orders.open_ask_price = None
                    open_orders.open_ask_rejections += Decimal('0.04')
                    file_logger.warn('rejected: new ask @ {0}'.format(open_ask_price))
                elif 'message' in response.json() and response.json()['message'] == 'Insufficient funds':
                    open_orders.open_ask_order_id = None
                    open_orders.open_ask_price = None
                    file_logger.warn('Insufficient BTC')
                else:
                    file_logger.error('Unhandled response: {0}'.format(pformat(response.json())))
                continue

        if open_orders.open_bid_order_id and not open_orders.open_bid_cancelled:
            bid_too_far_out = open_orders.open_bid_price < (order_book.asks.price_tree.min_key()
                                                            - spreads.bid_too_far_adjustment_spread)
            bid_too_close = open_orders.open_bid_price > (order_book.bids.price_tree.max_key()
                                                          - spreads.bid_too_close_adjustment_spread)
            cancel_bid = bid_too_far_out or bid_too_close
            if cancel_bid:
                if bid_too_far_out:
                    file_logger.info('CANCEL: open bid {0} too far from best ask: {1} spread: {2}'.format(
                        open_orders.open_bid_price,
                        order_book.asks.price_tree.min_key(),
                        open_orders.open_bid_price - order_book.asks.price_tree.min_key()))
                if bid_too_close:
                    file_logger.info('CANCEL: open bid {0} too close to best bid: {1} spread: {2}'.format(
                        open_orders.open_bid_price,
                        order_book.bids.price_tree.max_key(),
                        open_orders.open_bid_price - order_book.bids.price_tree.max_key()))
                open_orders.cancel('bid')
                continue

        if open_orders.open_ask_order_id and not open_orders.open_ask_cancelled:
            ask_too_far_out = open_orders.open_ask_price > (order_book.bids.price_tree.max_key() +
                                                            spreads.ask_too_far_adjustment_spread)

            ask_too_close = open_orders.open_ask_price < (order_book.asks.price_tree.min_key() -
                                                          spreads.ask_too_close_adjustment_spread)

            cancel_ask = ask_too_far_out or ask_too_close

            if cancel_ask:
                if ask_too_far_out:
                    file_logger.info('CANCEL: open ask {0} too far from best bid: {1} spread: {2}'.format(
                        open_orders.open_ask_price,
                        order_book.bids.price_tree.max_key(),
                        open_orders.open_ask_price - order_book.bids.price_tree.max_key()))
                if ask_too_close:
                    file_logger.info('CANCEL: open ask {0} too close to best ask: {1} spread: {2}'.format(
                        open_orders.open_ask_price,
                        order_book.asks.price_tree.min_key(),
                        open_orders.open_ask_price - order_book.asks.price_tree.min_key()))
                open_orders.cancel('ask')
                continue
def manage_orders():
    max_bid = Decimal(order_book.bids.price_tree.max_key())
    min_ask = Decimal(order_book.asks.price_tree.min_key())
    if min_ask - max_bid < 0:
        file_logger.warn('Negative spread: {0}'.format(min_ask - max_bid))
        return False
    if command_line:
        print('Latency: {0:.6f} secs, '
              'Min ask: {1:.2f}, Max bid: {2:.2f}, Spread: {3:.2f}, '
              'Your ask: {4:.2f}, Your bid: {5:.2f}, Your spread: {6:.2f}'.format(
            ((datetime.now(tzlocal()) - order_book.last_time).microseconds * 1e-6),
            min_ask, max_bid, min_ask - max_bid,
            open_orders.float_open_ask_price, open_orders.float_open_bid_price,
                              open_orders.float_open_ask_price - open_orders.float_open_bid_price), end='\r')

    if not open_orders.open_bid_order_id and not open_orders.insufficient_usd:
        if open_orders.insufficient_btc:
            size = 0.1
            open_bid_price = Decimal(round(max_bid + Decimal(open_orders.open_bid_rejections), 2))
        else:
            size = 0.01
            spreads.bid_spread = Decimal(round((random.randrange(15) + 6) / 100, 2))
            open_bid_price = Decimal(round(min_ask - Decimal(spreads.bid_spread)
                                           - Decimal(open_orders.open_bid_rejections), 2))
        order = {'size': size,
                 'price': str(open_bid_price),
                 'side': 'buy',
                 'product_id': 'BTC-USD',
                 'post_only': True}
        response = requests.post(exchange_api_url + 'orders', json=order, auth=exchange_auth)
        if 'status' in response.json() and response.json()['status'] == 'pending':
            open_orders.open_bid_order_id = response.json()['id']
            open_orders.open_bid_price = open_bid_price
            open_orders.open_bid_rejections = 0.0
            file_logger.info('new bid @ {0}'.format(open_bid_price))
        elif 'status' in response.json() and response.json()['status'] == 'rejected':
            open_orders.open_bid_order_id = None
            open_orders.open_bid_price = None
            open_orders.open_bid_rejections += 0.04
            file_logger.warn('rejected: new bid @ {0}'.format(open_bid_price))
        elif 'message' in response.json() and response.json()['message'] == 'Insufficient funds':
            open_orders.insufficient_usd = True
            open_orders.open_bid_order_id = None
            open_orders.open_bid_price = None
            file_logger.warn('Insufficient USD')
        else:
            file_logger.error('Unhandled response: {0}'.format(pformat(response.json())))
            return False
        return True

    if not open_orders.open_ask_order_id and not open_orders.insufficient_btc:
        if open_orders.insufficient_usd:
            size = 0.10
            open_ask_price = Decimal(round(min_ask + Decimal(open_orders.open_ask_rejections), 2))
        else:
            size = 0.01
            spreads.ask_spread = Decimal(round((random.randrange(15) + 6) / 100, 2))
            open_ask_price = Decimal(round(max_bid + Decimal(spreads.ask_spread)
                                           + Decimal(open_orders.open_ask_rejections), 2))
        order = {'size': size,
                 'price': str(open_ask_price),
                 'side': 'sell',
                 'product_id': 'BTC-USD',
                 'post_only': True}
        response = requests.post(exchange_api_url + 'orders', json=order, auth=exchange_auth)
        if 'status' in response.json() and response.json()['status'] == 'pending':
            open_orders.open_ask_order_id = response.json()['id']
            open_orders.open_ask_price = open_ask_price
            file_logger.info('new ask @ {0}'.format(open_ask_price))
            open_orders.open_ask_rejections = 0
        elif 'status' in response.json() and response.json()['status'] == 'rejected':
            open_orders.open_ask_order_id = None
            open_orders.open_ask_price = None
            open_orders.open_ask_rejections += 0.04
            file_logger.warn('rejected: new ask @ {0}'.format(open_ask_price))
        elif 'message' in response.json() and response.json()['message'] == 'Insufficient funds':
            open_orders.insufficient_btc = True
            open_orders.open_ask_order_id = None
            open_orders.open_ask_price = None
            file_logger.warn('Insufficient BTC')
        else:
            file_logger.error('Unhandled response: {0}'.format(pformat(response.json())))
            return False
        return True

    if open_orders.open_bid_order_id and Decimal(open_orders.open_bid_price) < round(
                    min_ask - Decimal(spreads.bid_adjustment_spread), 2):
        file_logger.info('CANCEL: open bid {0} threshold {1} diff {2}'.format(
            Decimal(open_orders.open_bid_price),
            round(min_ask - Decimal(spreads.bid_adjustment_spread), 2),
            Decimal(open_orders.open_bid_price) - round(min_ask - Decimal(spreads.bid_adjustment_spread), 2)))
        open_orders.cancel('bid')
        return True

    if open_orders.open_ask_order_id and Decimal(open_orders.open_ask_price) > round(
                    max_bid + Decimal(spreads.ask_adjustment_spread), 2):
        file_logger.info('CANCEL: open ask {0} threshold {1} diff {2}'.format(
            Decimal(open_orders.open_ask_price),
            round(max_bid - Decimal(spreads.ask_adjustment_spread), 2),
            Decimal(open_orders.open_ask_price) - round(max_bid + Decimal(spreads.ask_adjustment_spread), 2)))
        open_orders.cancel('ask')
        return True
    return True