def test_sequence2(self):
     """ test sequence 1: add ,add ,update, update, cancel"""
     obj = OrderBook()
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (0, 0))
     obj.process_order("1568390201|abbb11|a|AAPL|B|209.00000|100")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 0))
     obj.process_order("1568390202|abbb12|a|AAPL|S|210.00000|10")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 210.0))
     obj.process_order("1568390204|abbb11|u|10")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 210.0))
     obj.process_order("1568390203|abbb12|u|101")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 210.0))
     obj.process_order("1568390243|abbb11|c")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (0, 210.0))
Example #2
0
class test_order_book(unittest.TestCase):
    def setUp(self):
        self.completed_trades = []
        self.completed_orders = []
        self.orders = []
        self.order_book = OrderBook("KEQ")
        for i in range(1, 10):
            quote = test_quotes[str(i)]
            if "price" in quote:
                quote["price"] = Decimal(quote["price"])
            order = json.loads(self.order_book.process_order(quote))
            self.orders.append(order)
            for trades in self.order_book.completed_trades:
                self.completed_trades.append(trades)
            for orders in self.order_book.completed_orders:
                self.completed_orders.append(orders)

    def test_get_min_ask(self):
        self.assertEqual(self.order_book.get_min_ask(), 99.5)

    def test_get_max_bid(self):
        self.assertEqual(self.order_book.get_max_bid(), 99)

    def test_process_order(self):
        self.assertEqual(len(self.order_book.bids.keys()), 1)
        self.assertEqual(len(self.order_book.asks.keys()), 2)
        self.assertEqual(len(self.completed_trades), 6)
        self.assertEqual(len(self.order_book.ongoing_orders), 3)
        self.assertEqual(len(self.completed_orders), 6)

    def test_modify_order(self):
        quote = test_quotes[str(10)]
        if "price" in quote:
            quote["price"] = Decimal(quote["price"])
        new_order = json.loads(
            self.order_book.modify_order(self.orders[8]["order_id"], quote))
        self.assertEqual(new_order["price"], '75')

    def test_cancel_order(self):
        quote = test_quotes[str(10)]
        if "price" in quote:
            quote["price"] = Decimal(quote["price"])
        new_order = json.loads(self.order_book.process_order(quote))
        self.order_book.cancel_order(new_order["order_id"])
        self.assertEqual(len(self.order_book.bids.keys()), 1)
Example #3
0
class OnlineDA(object):
    def __init__(self):
        self.ob=OrderBook()
        self.day=0
        self.trades=[]
    
    def nextDay(self):
        self.day+=1
        self.trades=[]
        self.ob.asks=OrderTree()
        self.ob.bids=OrderTree()
    
    def submitOrder(self, order):
        trades, remOrder=self.ob.process_order(order, False, False)
        if len(trades)>0:
            self.trades.extend(trades)
        
        if not remOrder:
            order['isFilled']=True
            return trades, order
            
        if remOrder['quantity']<order['quantity']:
            order['isFilled']=True
            return trades, order
        
        order['isFilled']=False
        return trades, order
        
    def getOpenPrice(self):
        if len(self.trades)>0: 
            return self.trades[0]['price']
        return 0
    
    def getClosePrice(self):
        if len(self.trades)>0: 
            return self.trades[-1]['price']
        return 0
    
    def getHighPrice(self):
        if len(self.trades)>0: 
            return np.max([t['price'] for t in self.trades])
        return 0

    def getLowPrice(self):
        if len(self.trades)>0: 
            return np.min([t['price'] for t in self.trades])
        return 0
    
    def getVolume(self):
        return np.sum([t['quantity'] for t in self.trades])
Example #4
0
def main():

    # TODO: Create three agents:
    order_book = OrderBook()
    agents = [101, 102, 103]

    # TODO: Agents send in buy/sell orders randomly with some probablility
    for i in range(30):
        print '\nTimestep# {}: '.format(i)
        for a in agents:
            if (random.random() > 0.5):
                # make an order
                # buy or sell?
                # TO BE REPLACED WITH TRADING STRATEGIES
                tradedir = random.choice(['bid', 'ask'])
                # how many?
                ordqty = random.randint(1, 20)
                # market or limit?
                tradetype = random.choice(['market', 'limit'])
                # if limit, what is your bid/ask price
                if tradetype == 'limit':
                    # TO BE REPLACED WITH TRADING STRATEGIES
                    limitprice = random.uniform(90, 100)
                # send in the order
                if tradetype == 'market':
                    agent_order = {
                        'type': 'market',
                        'side': tradedir,
                        'quantity': ordqty,
                        'trade_id': a
                    }
                    print 'agent {} made a market order to {} {} shares'.format(
                        a, tradedir, ordqty)
                else:
                    agent_order = {
                        'type': 'limit',
                        'side': tradedir,
                        'quantity': ordqty,
                        'price': limitprice,
                        'trade_id': a
                    }
                    print 'agent {} made a limit order at {} to {} {} shares'.format(
                        a, limitprice, tradedir, ordqty)

                trades, order_in_book = order_book.process_order(
                    agent_order, False, False)
            else:
                print 'agent {} did not trade'.format(a)
    # plot how the stock changes
    print order_book
def main():
    
    # TODO: Create three agents:
    order_book = OrderBook()
    agents = [101, 102, 103]

    # TODO: Agents send in buy/sell orders randomly with some probablility
    for i in range(30):
        print '\nTimestep# {}: '.format(i)
        for a in agents:
            if (random.random() > 0.5):
                # make an order
                # buy or sell?
                # TO BE REPLACED WITH TRADING STRATEGIES
                tradedir = random.choice(['bid','ask'])
                # how many?
                ordqty = random.randint(1,20)
                # market or limit?
                tradetype = random.choice(['market', 'limit'])
                # if limit, what is your bid/ask price
                if tradetype == 'limit':
                # TO BE REPLACED WITH TRADING STRATEGIES
                    limitprice = random.uniform(90,100)
                # send in the order
                if tradetype == 'market':
                    agent_order = {'type':'market', 'side':tradedir, 'quantity':ordqty, 'trade_id':a}
                    print 'agent {} made a market order to {} {} shares'.format(a, tradedir, ordqty)
                else:
                    agent_order = {'type':'limit', 'side':tradedir, 'quantity':ordqty, 'price':limitprice, 'trade_id':a}
                    print 'agent {} made a limit order at {} to {} {} shares'.format(a, limitprice, tradedir, ordqty)
                
                trades, order_in_book = order_book.process_order(agent_order, False, False)
            else:
                print 'agent {} did not trade'.format(a)
    # plot how the stock changes
    print order_book
Example #6
0
        'quantity': 5,
        'price': 99,
        'trade_id': 102
    },
    {
        'type': 'limit',
        'side': 'bid',
        'quantity': 5,
        'price': 97,
        'trade_id': 103
    },
]

# Add orders to order book
for order in limit_orders:
    trades, order_id = order_book.process_order(order, False, False)

# The current book may be viewed using a print
print order_book

# Submitting a limit order that crosses the opposing best price will result in a trade
crossing_limit_order = {
    'type': 'limit',
    'side': 'bid',
    'quantity': 2,
    'price': 102,
    'trade_id': 109
}

print crossing_limit_order
trades, order_in_book = order_book.process_order(crossing_limit_order, False,
class MarketSim(object):
    def __init__(self, order_arrival_lambda=2, initial_price=100., price_sigma=.2, quantity_mu=2, quantity_sigma=1,
                 periods=None, traders=50, tick_size=.0001, purge_after_vol=100,
                 open_time=dt.datetime(2017, 1, 1, 8, 0, 0), close_time=dt.datetime(2017, 1, 1, 15, 0, 0)):
        self.p0 = initial_price
        self.p = initial_price
        self.tick_size = tick_size
        self.purge_after_vol = purge_after_vol
        self.order_arrival_lambda = order_arrival_lambda
        self.price_sigma = price_sigma
        self.quantity_mu = quantity_mu
        self.quantity_sigma = quantity_sigma
        if periods:
            self.periods = periods
        else:
            self.periods = (close_time-open_time).total_seconds()
        if type(traders) == int:
            traders = range(traders)
        self.traders = traders

        self.orderbook = OrderBook()
        self.total_orders_submitted = 0
        self.sides = np.array(['ask', 'bid'])
        self.sign = np.array([1., -1.])
        self.time = 0
        self.orders_by_vol = deque(maxlen=None)

    def simulate_batch(self, size=10000, verbose=False):
        # number of orders that arrive
        inter_arrival_times = np.random.exponential(self.order_arrival_lambda, size=size)
        timestamps = inter_arrival_times.cumsum() + self.time
        self.process_orders(timestamps, verbose)
        self.purge_stale_orders()
        self.time = timestamps[-1]

    def simulate_periods(self, periods=None, verbose=False):
        if not periods:
            periods = self.periods
        while self.time < periods:
            self.simulate_batch(size=min(10000, periods/10), verbose=verbose)

    def process_orders(self, timestamps, verbose=False):
        # if new orders arrived--add them to the book
        n_orders = len(timestamps)
        # draw side (buy/sell) distribution is binomial, p=.5
        order_side = np.random.choice([0, 1], size=n_orders, replace=True)
        # randomly assign traders to each slot
        order_trader = np.random.choice(self.traders, size=n_orders, replace=True)
        order_price_shocks = np.random.lognormal(0, self.price_sigma, size=n_orders)
        order_quantity = np.ceil(np.random.lognormal(self.quantity_mu, self.quantity_sigma, size=n_orders))

        for i in xrange(n_orders):
            if timestamps[i] > self.periods:
                break
            side = self.sides[order_side][i]
            order_price = self.p * order_price_shocks[i] + self.sign[order_side][i] * self.tick_size * self.p
            quote = {
               "type": "limit",
               "side": side,
               "timestamp": timestamps[i],
               "trade_id": order_trader[i],
               "order_id": self.total_orders_submitted,
               "price": order_price,
               'quantity': int(order_quantity[i])
            }
            self.orderbook.process_order(quote, from_data=True, verbose=verbose)
            self.log_order_type(side)
            self.total_orders_submitted += 1
            self.sync_book_price()

    def purge_stale_orders(self):
        if len(self.orders_by_vol) > 0 & len(self.orderbook.tape) >= 100:
            current_vol = len(self.orderbook.tape)
            while current_vol-self.purge_after_vol >= self.orders_by_vol[0][0]:
                _, side, order_id = self.orders_by_vol.popleft()
                self.orderbook.cancel_order(side=side, order_id=order_id)
                if len(self.orders_by_vol) == 0:
                    break

    def sync_book_price(self):
        if len(self.orderbook.tape) > 0:
            self.p = float(self.orderbook.tape[-1]['price'])

    def plot_prices(self, time_scale=1.,plot_params={}):
        interval_trades = self.get_transactions(time_scale=time_scale)
        interval_trades.set_index('time')['price'].apply(lambda x: float(x)).plot(**plot_params)

    def get_tape_dataframe(self):
        return pd.DataFrame(list(self.orderbook.tape))

    def show_stats(self):
        n_trades = len(self.orderbook.tape)
        mean_quantity = self.get_tape_dataframe()['quantity'].apply(lambda x: float(x)).mean()
        print("trades per second: %3.3f" % (n_trades / self.time))
        print("quantity per 600: %3.3f" % (mean_quantity * 600))

    def log_order_type(self, side):
        order_id = self.total_orders_submitted
        current_vol = len(self.orderbook.tape)
        self.orders_by_vol.append((current_vol, str(side), int(order_id)))

    @staticmethod
    def get_side_id(side, party1, party2):
        if party1[1] == side:
            return party1[0]
        else:
            return party2[0]

    def get_transactions(self, time_scale=1):
        tape = self.get_tape_dataframe()
        tape['price'] = tape['price'].apply(float)
        tape['quantity'] = tape['quantity'].apply(int)
        tape['time'] = tape['timestamp'].apply(lambda x: np.floor(x/time_scale))
        tape['quantity'] = (tape.groupby('time')['quantity'].transform('sum'))
        agg = tape.groupby('time').last().reset_index()
        agg['ask_id'] = agg.apply(lambda row: MarketSim.get_side_id('ask', row['party1'], row['party2']), axis=1)
        agg['bid_id'] = agg.apply(lambda row: MarketSim.get_side_id('bid', row['party1'], row['party2']), axis=1)
        return agg[['time', 'ask_id', 'bid_id', 'quantity', 'price']]

    def export_transactions(self, filename):
        self.get_transactions().to_csv(filename, index=False)
Example #8
0
from orderbook import OrderBook

# Create an order book

order_book = OrderBook()

# Create some limit orders

limit_orders = [
                {'type' : 'limit',  'side' : 'bid', 'quantity' : 200,'price' : 161, 'trade_id' : 100, 'order_id' : 100, 'timestamp' : 1},
                {'type' : 'limit',  'side' : 'bid', 'quantity' : 300,'price' : 162, 'trade_id' : 101, 'order_id' : 101, 'timestamp' : 2},
                {'type' : 'limit',  'side' : 'bid', 'quantity' : 500,'price' : 163, 'trade_id' : 102, 'order_id' : 102, 'timestamp' : 3},
                {'type' : 'limit',  'side' : 'bid', 'quantity' : 200,'price' : 164, 'trade_id' : 103, 'order_id' : 103, 'timestamp' : 4},
                {'type' : 'limit',  'side' : 'ask', 'quantity' : 400,'price' : 160, 'trade_id' : 200, 'order_id' : 200, 'timestamp' : 5},
                {'type' : 'limit',  'side' : 'ask', 'quantity' : 400,'price' : 161, 'trade_id' : 201, 'order_id' : 201, 'timestamp' : 6},
                {'type' : 'limit',  'side' : 'ask', 'quantity' : 100,'price' : 162, 'trade_id' : 202, 'order_id' : 202, 'timestamp' : 7},
                {'type' : 'limit',  'side' : 'ask', 'quantity' : 300,'price' : 163, 'trade_id' : 203, 'order_id' : 203, 'timestamp' : 8},
                {'type' : 'limit',  'side' : 'ask', 'quantity' : 300,'price' : 164, 'trade_id' : 204, 'order_id' : 204, 'timestamp' : 9},
               ]

# Add orders to order book
for order in limit_orders:
    trades, order_id = order_book.process_order(order, True, False)
    #print(trades, order_id)


# The current book may be viewed using a print
print(order_book)


Example #9
0
                         q = order_book.asks
                     else:
                         sys.exit('not given bid or ask')
                     for order in q.price_tree.get(Decimal(line['price']),
                                                   []):
                         if order.trade_id == line['trade_id']:
                             order_book.cancel_order(line['side'],
                                                     order.order_id)
                 elif line['type'] == 'modify':
                     order_book.modify_order(line['order_id'], {
                         'side': line['side'],
                         'price': line['price'],
                         'quantity': line['quantity']})
                 else:
                     (trade, order) = order_book.process_order(line,
                                                               False,
                                                               False)
                     myalgo.process_trade(trade, mode)
             if len(algo_orders) > 0:
                 printme("\n")
                 printme("After algo")
                 print_orderbook(order_book, old_orderbook)
                 stats=myalgo.stats()
                 printme ("total volume=", stats[0])
                 printme ("my volume=", stats[1])
                 printme ("participation=", stats[3])
             else:
                 printme("No action by algo")
             printme("--------- END -------")
     reader.close()
 except IOError:
Example #10
0
                    'trade_id' : 101},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 99,
                    'trade_id' : 102},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 97,
                    'trade_id' : 103},
                   ]

# Add orders to order book
for order in limit_orders:
    trades, order_id = order_book.process_order(order, False, False)

# The current book may be viewed using a print
print order_book

# Submitting a limit order that crosses the opposing best price will result in a trade
crossing_limit_order = {'type': 'limit',
                        'side': 'bid',
                        'quantity': 2,
                        'price': 102,
                        'trade_id': 109}

print crossing_limit_order
trades, order_in_book = order_book.process_order(crossing_limit_order, False, False)
print "Trade occurs as incoming bid limit crosses best ask"
print trades
 def test_sequence3(self):
     """ test sequence 1: add ,add ,add,add,cancel,cancel """
     obj = OrderBook()
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (0, 0))
     obj.process_order("1568390201|abbb11|a|AAPL|B|209.00000|100")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 0))
     obj.process_order("1568390201|abbb12|a|AAPL|B|209.50000|100")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.5, 0))
     obj.process_order("1568390203|abbb13|a|AAPL|S|210.00000|10")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.5, 210.0))
     obj.process_order("1568390204|abbb14|a|AAPL|S|209.90000|10")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.5, 209.9))
     obj.process_order("1568390243|abbb12|c")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 209.9))
     obj.process_order("1568390244|abbb14|c")
     self.assertEqual(obj.get_best_bid_and_ask('AAPL'), (209.0, 210.0))
Example #12
0
             printme('')
             printme("RUNNING ALGO WITH MODE=", mode)
             old_orderbook = copy.deepcopy(order_book)
             for line in algo_orders:
                 printme(pprint.pformat(line))
                 if line['type'] == 'cancel':
                     order_book.cancel_order(line['side'],
                                             line['order_id'])
                 elif line['type'] == 'modify':
                     order_book.modify_order(line['order_id'], {
                         'side': line['side'],
                         'price': line['price'],
                         'quantity': line['quantity']})
                 else:
                     (trade, order) = order_book.process_order(line,
                                                               False,
                                                               False)
                     myalgo.process_trade(trade, mode)
             if len(algo_orders) > 0:
                 printme("\n")
                 printme("After algo")
                 print_orderbook(order_book, old_orderbook)
                 stats=myalgo.stats()
                 printme ("total volume=", stats[0])
                 printme ("my volume=", stats[1])
                 printme ("participation=", stats[3])
             else:
                 printme("No action by algo")
             printme("--------- END -------")
     reader.close()
 except IOError:
class OrderBookTestCase(unittest.TestCase):
    ''' Unittest for the OrderBook module '''
    def setUp(self):
        self.order_book = OrderBook()
        self.limit_orders = [{'type' : 'limit', 
                   'side' : 'ask', 
                    'quantity' : 5, 
                    'price' : 101},
                   {'type' : 'limit', 
                    'side' : 'ask', 
                    'quantity' : 5, 
                    'price' : 103},
                   {'type' : 'limit', 
                    'side' : 'ask', 
                    'quantity' : 5, 
                    'price' : 101},
                   {'type' : 'limit', 
                    'side' : 'ask', 
                    'quantity' : 5, 
                    'price' : 101},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 99},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 98},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 99},
                   {'type' : 'limit', 
                    'side' : 'bid', 
                    'quantity' : 5, 
                    'price' : 97},
                   ]
        for order in self.limit_orders:
            trades, order_id = self.order_book.process_order(order)

    def test_process_asks_order(self):
        ''' set up asks orders for unittests '''
        self.assertEquals(self.order_book.asks.order_map[1].price, 101.0)
        self.assertEquals(self.order_book.asks.order_map[2].price, 103.0)
        self.assertEquals(self.order_book.asks.order_map[3].price, 101.0)
        self.assertEquals(self.order_book.asks.order_map[4].price, 101.0)

    def test_process_bids_order(self):
        ''' set up bids orders for unittests '''
        self.assertEquals(self.order_book.bids.order_map[5].price, 99.0)
        self.assertEquals(self.order_book.bids.order_map[6].price, 98.0)
        self.assertEquals(self.order_book.bids.order_map[7].price, 99.0)
        self.assertEquals(self.order_book.bids.order_map[8].price, 97.0)

    def test_trades(self):
        ''' Submitting a limit order that crosses the opposing best price 
        will result in a trade '''
        crossing_limit_order = {'type': 'limit',
                                'side': 'bid',
                                'quantity': 2,
                                'price': 102}
        trades, order_in_book = self.order_book.process_order(\
            crossing_limit_order)
        self.assertEquals(trades[0]['price'], 101)
        self.assertEquals(trades[0]['quantity'],2)

    def test_large_trades(self):
        ''' If a limit crosses but is only partially matched, the remaning 
        volume will be placed in the book as an outstanding order '''
        big_crossing_limit_order = {'type': 'limit',
                                    'side': 'bid',
                                    'quantity': 50,
                                    'price': 102}
        trades, order_in_book = self.order_book.process_order(\
            big_crossing_limit_order)
        self.assertEquals(order_in_book['price'], 102) 
        self.assertEquals(order_in_book['quantity'], 35)
class OrderBookTestCase(unittest.TestCase):
    ''' Unittest for the OrderBook module '''
    def setUp(self):
        self.order_book = OrderBook()
        self.limit_orders = [
            {
                'type': 'limit',
                'side': 'ask',
                'quantity': 5,
                'price': 101
            },
            {
                'type': 'limit',
                'side': 'ask',
                'quantity': 5,
                'price': 103
            },
            {
                'type': 'limit',
                'side': 'ask',
                'quantity': 5,
                'price': 101
            },
            {
                'type': 'limit',
                'side': 'ask',
                'quantity': 5,
                'price': 101
            },
            {
                'type': 'limit',
                'side': 'bid',
                'quantity': 5,
                'price': 99
            },
            {
                'type': 'limit',
                'side': 'bid',
                'quantity': 5,
                'price': 98
            },
            {
                'type': 'limit',
                'side': 'bid',
                'quantity': 5,
                'price': 99
            },
            {
                'type': 'limit',
                'side': 'bid',
                'quantity': 5,
                'price': 97
            },
        ]
        for order in self.limit_orders:
            trades, order_id = self.order_book.process_order(order)

    def test_process_asks_order(self):
        ''' set up asks orders for unittests '''
        self.assertEquals(self.order_book.asks.order_map[1].price, 101.0)
        self.assertEquals(self.order_book.asks.order_map[2].price, 103.0)
        self.assertEquals(self.order_book.asks.order_map[3].price, 101.0)
        self.assertEquals(self.order_book.asks.order_map[4].price, 101.0)

    def test_process_bids_order(self):
        ''' set up bids orders for unittests '''
        self.assertEquals(self.order_book.bids.order_map[5].price, 99.0)
        self.assertEquals(self.order_book.bids.order_map[6].price, 98.0)
        self.assertEquals(self.order_book.bids.order_map[7].price, 99.0)
        self.assertEquals(self.order_book.bids.order_map[8].price, 97.0)

    def test_trades(self):
        ''' Submitting a limit order that crosses the opposing best price 
        will result in a trade '''
        crossing_limit_order = {
            'type': 'limit',
            'side': 'bid',
            'quantity': 2,
            'price': 102
        }
        trades, order_in_book = self.order_book.process_order(\
            crossing_limit_order)
        self.assertEquals(trades[0]['price'], 101)
        self.assertEquals(trades[0]['quantity'], 2)

    def test_large_trades(self):
        ''' If a limit crosses but is only partially matched, the remaning 
        volume will be placed in the book as an outstanding order '''
        big_crossing_limit_order = {
            'type': 'limit',
            'side': 'bid',
            'quantity': 50,
            'price': 102
        }
        trades, order_in_book = self.order_book.process_order(\
            big_crossing_limit_order)
        self.assertEquals(order_in_book['price'], 102)
        self.assertEquals(order_in_book['quantity'], 35)