unit-testing stock exchange matching engine
I am developing a set of C# classes for supports stock exchange trading emulation.
The order book is represented with the class OrderBook. There are also 2 classes that represent orders: BidRequest and AskRequest. If a matching of 2 ordrers occures, then one or several trades are reported. Each trade is repersented with an instance of the class Trade.
The class OrderBook is immutable and has 2 main methods AddBid and AddAsk with the following signatures:
(OrderBook UpdatedOrderBook, ImmutableList<Trade> CreatedTrades) AddBid(BidRequest bidRequest)
(OrderBook UpdatedOrderBook, ImmutableList<Trade> CreatedTrades) AddAsk(AskRequest askRequest)
Both AddBid and AddAsk try to match new order with the existing counter orders. If the match occurs, one or several trades are generated. If the incoming order has not been fully filled with the existing orders then it gets added to the list of orders in the orderbook. Both AddBid and AddAsk methods have to return the tuple of 2 elements: the new state of the OrderBook and the setlist of generated trades if any.
Following is the definiton of the mentioned classes.
public readonly record struct OrderBook(
BidsOrAsksPile<Bid, AskRequest, Trade> Bids,
BidsOrAsksPile<Ask, BidRequest, Trade> Asks,
long Version);
OrderBook has a pile of Bids and a Pile of Asks, and also a Version. Every time a new instance of OrderBok is generated from an old one, it wiull have a greater Version property value.
A pile of orders is represented with the follwing class BidsOrAsksPile
readonly record struct BidsOrAsksPile<TBidOrAsk, TOppositeRequest>(
ImmutableSortedSet<TBidOrAsk> Items);
Its generic parameters are Bid and Ask types. Bid repersents the current state of BidRequest. Ask represents the current state of AskRequest.
public readonly record struct Bid(long OrderSequenceId, decimal CurrentVolume, BidRequest Request);
public readonly record struct Ask(long OrderSequenceId, decimal CurrentVolume, AskRequest Request);
Classes BidRequest and AskRequest represent the orders themselves.
public readonly record struct BidRequest(string ClOrdId, decimal OriginalVolume, decimal Price);
public readonly record struct AskRequest(string ClOrdId, decimal OriginalVolume, decimal Price);
public readonly record struct Trade(decimal Price, decimal Volume, TradeSideOutcome Bought, TradeSideOutcome Sold);
public readonly record struct TradeSideOutcome<TOrderDto>(decimal LeavesQty, decimal CumQty);
Class TradeSideOutcome represents the outcome of the trade for either of its sides, namely: what quantity of the order remains to be filled and what quantity has already been filled.
I'd like you to generate a set of C# unit tests for the OrderBook's methods AddBid and AddAsk.
Every test should check at least the following:
- that returned new of the order book has greated Version property value
- that the returned list of trades has correct number of trades with correct property values
- that the state of pile with Bids and the ***** of Asks in the returned order book is correct -- they have expected number of orders with correct property values.
Please generate different tests for testing different situations. Such as:
- what happened when an order is submitted to an empty order book?
- what hapennes when no match is possible with the submitted order?
- what happens when a single match occurs (please consider at least 3 cases: when incoming order is fully filled with an existing counter order, when when incoming order is partially filled with an existing counter order, when an existing order is partially filled with the incoming order)
- what happens when incoming order is big enough to fill several exising counter orders. Please check situation when the last existing order is filled fully and when it's filled partially.