Ejemplo n.º 1
0
    def __init__(self, **kwargs):

        self.path = os.path.dirname(__file__)
        ticker = kwargs.get('ticker')
        date = kwargs.get('date')
        year = date.year
        month = date.month
        day = date.day
        start_h = kwargs.get('start_h', 9)
        end_h = kwargs.get('end_h', 17.5)
        start_secs = int(start_h * 3600)
        end_secs = int(end_h * 3600)
        start_time = datetime(year, month, day) + timedelta(0, start_secs)
        end_time = datetime(year, month, day) + timedelta(0, end_secs)
        self.ob_time = start_time
        self.latency = kwargs.get('latency', 20000)
        self.my_queue = deque()
        self.ob_idx = 0
        self.ob = Orderbook(ticker=ticker)
        date = f'{year}-{month}-{day}'
        self.ob.date = ticker, date
        self.OrdTuple = namedtuple('Order',
                                   'ordtype uid is_buy qty price timestamp')
        self.my_last_uid = 0

        # load historical orders from csv file
        session = f'{self.path}/../data/historic_orders/orders-{ticker}-{date}.csv'
        csv = pd.read_csv(session, sep=';', float_precision='round_trip')
        csv['timestamp'] = pd.to_datetime(csv['timestamp'])

        # We will be working with ndarrays instead of DataFrames for speed
        self.hist_orders = csv.values
        self.ob_nord = csv.shape[0]

        # we store index positions of columns for array indexing
        columns = csv.columns
        self.col_idx = {}
        for col_name in csv.columns:
            self.col_idx.update({col_name: np.argmax(columns == col_name)})

        last_ord_time = self.hist_orders[-1][self.col_idx['timestamp']]
        self.end_time = min(last_ord_time, end_time)
        self.stop_time = self.end_time

        # book positions (bid+ask) available in historical data
        book_pos = 20
        # send first 20 orders that will compose first orderbook snapshot
        # this is the real orderbook that was present when the orderbook opened
        # right after the opening auction

        for ord_idx in range(book_pos):
            oborder = self.hist_orders[self.ob_idx]
            self._send_historical_order(oborder)

        self.move_historic_until(start_time)

        self.ob.reset_ob(reset_all=False)

        self.in_queue = dict()
        self.vol_in_queue = 0
Ejemplo n.º 2
0
    def test_new_pricelevel(self):
        """ Add new bid and ask orders and checks price-time priority
        
        """

        orderbook = Orderbook('san')
        bidprice = np.random.uniform(0.0001, 100000)
        o1uid = 1
        o2uid = 2
        o3uid = 3
        order = namedtuple('Order', 'is_buy, qty, price, uid')
        o1 = order(is_buy=True, qty=10, price=bidprice, uid=o1uid)
        o2 = order(is_buy=True, qty=5, price=bidprice, uid=o2uid)
        o3 = order(is_buy=True, qty=7, price=bidprice, uid=o3uid)

        # Check price level creation, heads and tails, uid & order active
        orderbook.send(*o1)
        self.assertIn(o1.price, orderbook._bids.book.keys())
        self.assertEqual(orderbook._bids.best.price, o1.price)
        self.assertEqual(orderbook._bids.best.head.uid, o1uid)
        self.assertEqual(orderbook._bids.best.tail.uid, o1uid)
        self.assertEqual(orderbook._orders[o1uid].uid, o1uid)
        self.assertEqual(orderbook.get(o1uid)['active'], True)
        orderbook.send(*o2)
        self.assertEqual(orderbook._bids.best.price, bidprice)
        # Check time priority inside PriceLevel
        self.assertEqual(orderbook._bids.best.head.uid, o1uid)
        orderbook.send(*o3)
        self.assertEqual(orderbook._bids.best.head.uid, o1uid)
        self.assertEqual(orderbook._bids.best.head.next.uid, o2uid)
        self.assertEqual(orderbook._bids.best.tail.uid, o3uid)
        # Check list of orders

        ### SAME FOR ASKS
        askprice = bidprice + 0.0001
        o4uid = 4
        o5uid = 5
        o6uid = 6
        o4 = order(is_buy=False, qty=10, price=askprice, uid=o4uid)
        o5 = order(is_buy=False, qty=5, price=askprice, uid=o5uid)
        o6 = order(is_buy=False, qty=7, price=askprice, uid=o6uid)

        # Check price level creation, heads and tails
        orderbook.send(*o4)
        self.assertIn(askprice, orderbook._asks.book.keys())
        self.assertEqual(orderbook._asks.best.price, o4.price)
        self.assertEqual(orderbook._asks.best.head.uid, o4uid)
        self.assertEqual(orderbook._asks.best.tail.uid, o4uid)
        self.assertEqual(orderbook._orders[o4uid].uid, o4uid)
        orderbook.send(*o5)

        # Check time priority inside PriceLevel
        self.assertIs(orderbook._asks.best.head.uid, o4uid)
        orderbook.send(*o6)
        self.assertEqual(orderbook._asks.best.head.uid, o4uid)
        self.assertEqual(orderbook._asks.best.head.next.uid, o5uid)
        self.assertEqual(orderbook._asks.best.tail.uid, o6uid)
Ejemplo n.º 3
0
    def test_send_bid_to_empty_book(self, bid1):
        orderbook = Orderbook('band6stock')
        orderbook.send(*bid1)

        assert orderbook._bids.best.price == bid1.price
        assert orderbook._bids.best.head.uid == bid1.uid
        assert orderbook._bids.best.tail.uid == bid1.uid
        assert orderbook._orders[bid1.uid].uid == bid1.uid
        assert orderbook.get(bid1.uid)['active']
Ejemplo n.º 4
0
    def test_send_ask_to_empty_book(self, ask1):
        orderbook = Orderbook('band6stock')
        orderbook.send(*ask1)

        assert orderbook._asks.best.price == ask1.price
        assert orderbook._asks.best.head.uid == ask1.uid
        assert orderbook._asks.best.tail.uid == ask1.uid
        assert orderbook._orders[ask1.uid].uid == ask1.uid
        assert orderbook.get(ask1.uid)['active']
Ejemplo n.º 5
0
 def test_band6_stock_get_new_price(self):
     # we test in the price boundary of tick size change 
     orderbook = Orderbook('band6stock') 
     assert orderbook.get_new_price(5, n_moves=-1) == 4.9995
     assert orderbook.get_new_price(5, n_moves=1) == 5.001
     assert orderbook.get_new_price(10, n_moves=-1) == 9.999
     assert orderbook.get_new_price(10, n_moves=1) == 10.002
     assert orderbook.get_new_price(20, n_moves=-1) == 19.998
     assert orderbook.get_new_price(20, n_moves=1) == 20.005
     assert orderbook.get_new_price(100, n_moves=-1) == 99.99
     assert orderbook.get_new_price(100, n_moves=1) == 100.02
Ejemplo n.º 6
0
    def test_aggressive_orders(self):
        orderbook = Orderbook('san')
        # alternate oders in PriceLevels
        order = namedtuple('Order', 'is_buy, qty, price, uid')
        o1uid = 1
        o2uid = 2
        o3uid = 3
        o4uid = 4
        o5uid = 5
        o1 = order(is_buy=True, qty=100, price=10.001, uid=o1uid)
        o2 = order(is_buy=True, qty=100, price=10.002, uid=o2uid)
        o3 = order(is_buy=True, qty=100, price=10.001, uid=o3uid)
        o4 = order(is_buy=True, qty=100, price=10.002, uid=o4uid)
        o5 = order(is_buy=True, qty=100, price=10.003, uid=o5uid)
        orderbook.send(*o1)
        orderbook.send(*o2)
        orderbook.send(*o3)
        orderbook.send(*o4)
        orderbook.send(*o5)

        # aggressive order to sweep all positions and place rest
        o6uid = 6
        o6 = order(is_buy=False, qty=100, price=9.999, uid=o6uid)
        orderbook.send(*o6)
        # check new top of book
        self.assertIs(orderbook.bbid[0], o2.price)
        # check best price
        self.assertEqual(orderbook.trades_px[0], 10.003)

        # send copy of o6 order
        o7uid = 7
        o7 = order(is_buy=False, qty=100, price=9.999, uid=o7uid)
        orderbook.send(*o7)
        self.assertIs(orderbook._bids.best.head.uid, o4uid)
        self.assertIs(orderbook.get(o5uid)['leavesqty'], 0)
        self.assertEqual(orderbook.trades_px[1], 10.002)

        # send order and sweep 4 positions and leave rest in book as ask
        o8uid = 8
        o8 = order(is_buy=False, qty=500, price=9.999, uid=o8uid)
        orderbook.send(*o8)

        # check worst price
        self.assertIs(len(orderbook.trades), 5)
        self.assertEqual(orderbook.trades_px[4], 10.001)
        # check empty bids book
        self.assertIs(len(orderbook._bids.book), 0)
        # check new pricelevel at o8 price
        self.assertIs(orderbook._asks.best.price, o8.price)
Ejemplo n.º 7
0
    def test_cancel_order(self):
        """ Cancels active orders and checks PriceLevel deletion,
            price-time priority of left resting orders, and doubly linked
            list of orders inside Price Level
        
        """

        orderbook = Orderbook('san')
        o1uid = 1
        o2uid = 2
        o3uid = 3
        o4uid = 4
        o5uid = 5
        order = namedtuple('Order', 'is_buy, qty, price, uid')
        o1 = order(is_buy=True, qty=1000, price=0.2, uid=o1uid)
        o2 = order(is_buy=True, qty=500, price=0.2, uid=o2uid)
        o3 = order(is_buy=True, qty=600, price=0.2, uid=o3uid)
        o4 = order(is_buy=True, qty=200, price=0.2, uid=o4uid)
        o5 = order(is_buy=True, qty=77, price=0.19, uid=o5uid)
        orderbook.send(*o1)
        orderbook.send(*o2)
        orderbook.send(*o3)
        orderbook.send(*o4)
        orderbook.send(*o5)

        # CANCEL MIDDLE ORDER IN QUEUE
        orderbook.cancel(o2uid)
        # Check order is not active & leavesqty is 0
        self.assertEqual(orderbook.get(o2uid)['active'], False)
        self.assertEqual(orderbook.get(o2uid)['leavesqty'], 0)

        # Check Doubly Linked List
        self.assertIs(orderbook._orders[o1uid].next.uid, o3uid)
        self.assertIs(orderbook._orders[o3uid].prev.uid, o1uid)
        self.assertIs(orderbook._orders[o3uid].next.uid, o4uid)
        self.assertIs(orderbook._orders[o4uid].prev.uid, o3uid)
        self.assertIs(orderbook.bbid[0], o1.price)
        self.assertIs(orderbook._bids.best.tail.uid, o4uid)

        # CANCEL TAIL
        orderbook.cancel(o4uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o4uid)['leavesqty'], 0)
        # Check Doubly Linked List
        self.assertIs(orderbook._orders[o1uid].next.uid, o3uid)
        self.assertIs(orderbook._orders[o3uid].prev.uid, o1uid)
        self.assertIsNone(orderbook._orders[o3uid].next)
        self.assertIs(orderbook._bids.best.head.uid, o1uid)
        self.assertIs(orderbook._bids.best.tail.uid, o3uid)

        # CANCEL HEAD
        # alternate oders in PriceLevels
        orderbook.cancel(o1uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o1uid)['leavesqty'], 0)
        # Check Doubly Linked List
        self.assertIsNone(orderbook._orders[o3uid].prev)
        self.assertIsNone(orderbook._orders[o3uid].next)
        self.assertIs(orderbook._bids.best.head.uid, o3uid)
        self.assertIs(orderbook._bids.best.tail.uid, o3uid)

        # CANCEL HEAD&TAIL ORDER => REMOVE PRICE_LEVEL
        orderbook.cancel(o3uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o3uid)['leavesqty'], 0)
        # Check PriceLevel removed
        self.assertNotIn(0.2, orderbook._bids.book)
        # Check new best bid
        self.assertIs(orderbook._bids.best.head.uid, o5uid)
        orderbook.cancel(o5uid)
        self.assertIs(len(orderbook._bids.book), 0)

        ########################
        #### SAME FOR ASKS #####
        ########################
        orderbook = Orderbook('san')
        o1uid = 1
        o2uid = 2
        o3uid = 3
        o4uid = 4
        o5uid = 5
        order = namedtuple('Order', 'is_buy, qty, price, uid')
        o1 = order(is_buy=False, qty=1000, price=0.2, uid=o1uid)
        o2 = order(is_buy=False, qty=500, price=0.2, uid=o2uid)
        o3 = order(is_buy=False, qty=600, price=0.2, uid=o3uid)
        o4 = order(is_buy=False, qty=200, price=0.2, uid=o4uid)
        o5 = order(is_buy=False, qty=77, price=0.21, uid=o5uid)
        orderbook.send(*o1)
        orderbook.send(*o2)
        orderbook.send(*o3)
        orderbook.send(*o4)
        orderbook.send(*o5)

        # CANCEL MIDDLE ORDER IN QUEUE
        orderbook.cancel(o2uid)
        # Check order is not active & leavesqty is 0
        self.assertEqual(orderbook.get(o2uid)['active'], False)
        self.assertEqual(orderbook.get(o2uid)['leavesqty'], 0)

        # Check Doubly Linked List
        self.assertIs(orderbook._orders[o1uid].next.uid, o3uid)
        self.assertIs(orderbook._orders[o3uid].prev.uid, o1uid)
        self.assertIs(orderbook._orders[o3uid].next.uid, o4uid)
        self.assertIs(orderbook._orders[o4uid].prev.uid, o3uid)
        self.assertIs(orderbook.bask[0], o1.price)
        self.assertIs(orderbook._asks.best.tail.uid, o4uid)

        # CANCEL TAIL ORDER
        orderbook.cancel(o4uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o4uid)['leavesqty'], 0)
        # Check Doubly Linked List
        self.assertIs(orderbook._orders[o1uid].next.uid, o3uid)
        self.assertIs(orderbook._orders[o3uid].prev.uid, o1uid)
        self.assertIsNone(orderbook._orders[o3uid].next)
        self.assertIs(orderbook._asks.best.head.uid, o1uid)
        self.assertIs(orderbook._asks.best.tail.uid, o3uid)

        # CANCEL HEAD
        # alternate oders in PriceLevels
        orderbook.cancel(o1uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o1uid)['leavesqty'], 0)
        # Check Doubly Linked List
        self.assertIsNone(orderbook._orders[o3uid].prev)
        self.assertIsNone(orderbook._orders[o3uid].next)
        self.assertIs(orderbook._asks.best.head.uid, o3uid)
        self.assertIs(orderbook._asks.best.tail.uid, o3uid)

        # CANCEL HEAD&TAIL ORDER => REMOVE PRICE_LEVEL
        orderbook.cancel(o3uid)
        # Check order is removed
        self.assertEqual(orderbook.get(o3uid)['leavesqty'], 0)
        # Check PriceLevel removed
        self.assertNotIn(0.2, orderbook._asks.book)
        # Check new best ask
        self.assertIs(orderbook._asks.best.head.uid, o5uid)
        orderbook.cancel(o5uid)
        self.assertIs(len(orderbook._asks.book), 0)
Ejemplo n.º 8
0
def ask_orderbook(ask_lmt_orders):
    orderbook = Orderbook('san')
    for order in ask_lmt_orders:
        orderbook.send(*order)
    return orderbook
Ejemplo n.º 9
0
def bid_orderbook(bid_lmt_orders):
    orderbook = Orderbook('san')
    for order in bid_lmt_orders:
        orderbook.send(*order)
    return orderbook