HelloWorldAgainAndAgain / Stock_market

Another implementation of stock matching engine which uses binary heaps to store prices in bid/ask order books, and balances the orders recursively.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Stock_market

Another implementation of stock matching engine which uses binary heaps to store prices in bid/ask order books, and balances the orders recursively.

******************************* Exchange ********************************

The value of 'order_id' reflects the order of arrival to the exchange. Orders are executed in the priority of the 'order_id'. Orders with a smaller 'order_id', other conditions being equal, get to be executed first, because these are the orders which arrived earlier.

Both of binary heaps, 'buys_prices' and 'sells_prices', are min-heaps. 'buys_prices' heap contains minus of submitted buy prices. The binary heaps here contain unique entries. When we store information about new orders at each price level in the 'buys_info' and 'sells_info' we check first whether that price is already there. We can use that check to also see whether we need to push that price into the corresponding heap, and avoid duplicates.

Exchange class attributes:

Binary heaps with unique (negative) limit prices for (buys) sells:
    buys_prices (list)
    sells_prices (list)
Order ID and size information for orders at given prices:
    buys_info (dict)
    sells_info (dict)
        An entry in the dictionary contains the list of order IDs
        in the order of arrival, dictionary of sizes of the orders
        (map between order IDs and order sizes), and the total
        current volume of orders at the given price level.
Bid and ask prices time series:
    bids (list)
    asks (list)
Self-incremented order ID:
    order_id
Instantaneous stored information on filled orders:
    buys_filled (dict)
    sells_filled (dict)

Exchange class methods:

start_price. Seed price. An artifact of the specific model example
considered here, used for the consitent recording of the bid and ask
prices time series. Can be altered for a different simulation purposes,
but make sure to take it into account in the savePrices, which might be
pathological if the buys and/or the sells have been completely filled
so that now best buys and/or best sells could be added to the time series.
In that case we need to add the price from the previous time step,
which in the most straightforward implementation requires an initial
seed price to start with.

reset. Reset the order_id count to -1. 

addOrder. Arguments: side of the order ('B' or 'S'), limit price, size.
    Increments the order_id count by one and assigns it to the current
    order. Returns the order_id.
    When the new order arrives, check whether the price level (as
    defined by the limit price) for that order already exists in the
    heap. Since we will need to prepare an entry for the order info
    dictionary, we combine these two checks, by checking whether the
    order info dictionary contains that limit price among its keys.
    
prepareMatch. Ancillary method for the matchOrders method (see below).
    Clears up buys_filled and sells_filled dictionaries of the orders,
    which will then be populated during the process of the matchOrders
    filling out the orders.
    
matchOrders. Recursive filling of all the orders. Calls itself until
    the buy and the sell books are balanced. Doesn't return any output,
    but acts on the class attributes buys_filled, sells_filled, storing
    there the orderID:(size,price) for the orders filled during its
    execution. Here is how it works:
        1. Check whether the current best prices in the buy and sell
        books actually have zero volume. This might be a leftover of
        the orders that already got executed. If true, clean those price
        levels from the heaps and from the order info books.
        2. Check whether the books are balanced. This will happen if
        either any of the books is empty, or the best buy is lower
        than the best sell.
        3. Update the best buy and the best sell prices, because we
        might have removed the previous best ones from the heaps, if the
        corresponding orders have already been filled.
        4. Take the earliest orders from the best buy and the best sell
        orders. Record their order IDs and sizes.
        5. Fill the smaller sized order in 'filled'.
        6. Record the executed orders in the buys_filled and sells_filled.
        The orders will be executed at the price which is the mean of the
        submitted limit price and the best limit price from the opposite
        order book. Therefore each order might get executed in different
        portions and at different sizes (we assume that no orders are of
        the 'all or none' condition). Record the prices and sizes tuples
        each time the order gets executed.
        7. Removed the 'filled' volume from the total volumes of the buy
        and sell books.
        8. Subtract the filled size from the orders volumes.
        9. Clean up the orders which have been totally filled.
        10. Recurrently call itself.
        
savePrices. Save the current best prices in the buy and the sell books.
    To be called after the matchOrders.

******************************* Test1 *********************************

Add random orders to the exchange and try to fill the orders (match with the orders on the opposite side). Plot the balanced buy and sell order books, and the bid and ask prices time series.

******************************* Test2 *********************************

Simulate a random stock market activity over several trading session. Each trading session is defined by a new exchange, and therefore unfilled orders from the previous trading sessions are emptied (this restriction can be relaxed). At each trading session each agent participates in the trade with the probability 10%

Each Agent is originally endowed with (almost) the same number of shares of stock and amount of cash; up to small normal variability. The agents trade randomly, submitting buy/sell orders with 50/50% probability, and choose the size of the trade according to a uniform distribution (Genoa Stock Market, see https://arxiv.org/pdf/cond-mat/0103600.pdf and references therein). The agents choose limit price as a gaussian variable centered around the last price.

Plot the resulting stock price time series (stock price is chosen as the mean between the best bid and the best ask), the QQ plot of the stock returns, and the final wealth distribution. Notice the Pareto tail of the final wealth distribution. Stock price exhibits a mean-reversing beahavior around the equilibrium price (which under the current conditions is equal to the total amount of cash divided by the total amount of shares), which is approximately equal to the starting price, as specified here. Stock returns are distributed normally, due to the passive trading of the agents.

About

Another implementation of stock matching engine which uses binary heaps to store prices in bid/ask order books, and balances the orders recursively.

License:Other


Languages

Language:Python 100.0%