I have two classes of interest: priceLevel and orderBook.
orderBook is a global variable that holds a pointer to a dynamic array of priceLevel pointers. priceLevel is a queue data structure that holds a third class called orderElement.
I'm struggling with my order matching function. In particular, with priceLevel. Orders on the same price level are matched properly against an incoming order, but once the queue of orderElements for a given priceLevel is depleted, I am unable to continue to the next priceLevel. This is strange because incrementing/decrementing a pointer during the first half of my function works fine, but then doesn't work when applied similarly later (see below).
My Goal is to simply increment a pointer to the memory location of the exhausted priceLevel, such that I arrive at the next priceLevel
For instance,
priceLevel* plPointer;
plPointer = &OB.priceLevels[0][0]; // First price level, first orderElement
plPointer++ // Now on OB.priceLevels[1][0];
Classes
class priceLevel {
private:
int price;
int outstandingOrders{};
orderElement* priceHead{nullptr};
orderElement* priceTail{nullptr};
public:
priceLevel(int price);
};
class orderBook {
public:
priceLevel** priceLevels;
orderBook(int price);
};
Constructors
orderBook::orderBook(int price) {
priceLevels = new priceLevel*[MAX_OB_PRICE - MIN_OB_PRICE];
for (int i{MAX_OB_PRICE - MIN_OB_PRICE}; i >= 0; i--) {
priceLevels[i] = new priceLevel(price + i);
}
}
priceLevel::priceLevel(int p) : price{p} {
for (int i{ORDER_COUNT}; i >= 0; i--) {
orderSubmitted(randomCharacterGenerator()); //Queue orderElement
}
}
My placeOrder function works, until it needs to move to the next priceLevel.
Function
void trader::placeOrder(char side, int quantity, int price) {
priceLevel* plPointer;
if (side == 'B') { // Buy order.
plPointer = &OB.priceLevels[0][0];
while(plPointer->getPrice() != bestAsk) {
plPointer--; // WORKS HERE PERFECTLY
}
do {
while(plPointer->getHead() != NULL && quantity > 0) {
if (plPointer->getHead()->quantity <= orderSize) {
plPointer->getHead()->status = tradeStatus::Filled;
orderSize -= plPointer->getHead()->quantity;
plPointer->removeHead();
} else {
plPointer->getHead()->status = tradeStatus::partiallyFilled;
plPointer->getHead()->quantity -= orderSize;
quantity = 0;
}
executionID++ // Static global variable.
}
if (plPointer->getHead() == NULL) {
bestAsk++; // Static global variable.
plPointer++; // BREAKS HERE!
}
} while (price >= bestAsk && quantity > 0);
Results
... // 10 orders per price level. Hits the tenth and dies.
[LIMIT ORDER] (B) Order submitted for 5000 contracts at 8990.
[EXECUTION] 0: Order filled against CPTGM-COXNU-TQRAN-QZLVG-VSEQW
[EXECUTION] 1: Order filled against ZAKAH-ZJEIY-XTEZG-KKWHN-JEGUJ
[EXECUTION] 2: Order filled against ZDNMK-BOMDA-ZHBYF-STVTY-ORFTJ
[EXECUTION] 3: Order filled against IJTWQ-BDJFJ-SDXXX-MJMFW-ZEFKP
[EXECUTION] 4: Order filled against FMDUA-SWOJK-UFPLC-IVQLB-JQNKO
[EXECUTION] 5: Order filled against GJUOV-ITJVT-UJKSS-DQEFY-ZIQSL
[EXECUTION] 6: Order filled against WKELY-OXFVF-MDXIV-FZLWE-TEFMC
[EXECUTION] 7: Order filled against WACJS-XYYCG-CVACG-YIMDB-GMYSR
[EXECUTION] 8: Order filled against JYIPK-PTYRF-XEEMA-YJDLG-LVVML
[EXECUTION] 9: Order filled against NSIRG-RSQAJ-RJNPI-SDNCF-XGUVC
Segmentation fault (core dumped)