I have compiled a shared library and a testprogram for that library. Originally, the testprogram was the main() of the library, but since I want to separate them, I divided into a library and a testprogram. This is not the only reason however, in the final program, the library will actually be a library and function as such.
When I run the program with the main() in the original file, all works well. If I separate stuff into the files matchingEngine.c, matchingEngine.h and testMatchingEngine.c, and I compile and run testMatchingEngine (which contains the original main() ), I get unexpected results. It is rather a lengthy post, but it will turn out to be needed anyway, so I will just get right at it. Below you will find:
- the sourcecode of the original file
- my command line mingw (windows gcc clone) compiler commands
- the output of the original program
- the sourcecode of the original file split up in matchingEngine.c, matchingEngine.h and testMatchingEngine.c
- my command line mingw (windows gcc clone) compiler commands
- output of the modified program
Once again, I suspect the mistake is somewhere in the headers, but I put the code here because in the end everybody asks for it anyway. So before you start digging in: this is probably about separating a program into a library and a working program in a wrong way (before you start didding into the code right away)
QUESTION: Why do the results of the modified program differ from the original program?
SOURCE CODE ORIGINAL PROGRAM
Code:
matchingEngineOriginal.c
-----------------------
#include <stdio.h>
#include <stdlib.h>
struct order {
char dir;
float price;
int actualSize;
int filledSize;
char instr[5];
};
struct bookOrder {
struct bookOrder *next;
struct order *order;
};
struct bookOrder *sellBook;
struct bookOrder *buyBook;
void printBook(char *message) {
struct bookOrder *sellWalker = sellBook;
struct bookOrder *buyWalker = buyBook;
printf("\n%s\n", message);
printf("--------BUY---------|---------SELL---------\n");
while ((buyWalker != NULL) || (sellWalker !=NULL)){
//stuff to help with printing in the right place
char *marker = "";
int margin = 4;
if (buyWalker != NULL) {
printf("%10i %10.3f",(buyWalker->order)->actualSize, (buyWalker->order)->price);
buyWalker = buyWalker->next;
}
else
margin = 15;
if (sellWalker != NULL){
printf("%*s %7.3f %5i",margin, marker, (sellWalker->order)->price, (sellWalker->order)->actualSize);
sellWalker = sellWalker->next;
}
printf("\n");
}
printf("------------------------------------\n");
}
void addBuyOrder(struct bookOrder **book, struct order buyOrder) {
struct bookOrder *walker = *book;
struct bookOrder *follower = *book;
struct bookOrder *newBook = malloc(sizeof(**book));
struct order *newOrder = malloc(sizeof(buyOrder));
//make new node
newOrder->price = buyOrder.price;
newOrder->actualSize = buyOrder.actualSize;
newBook->order = newOrder;
newBook->next = NULL;
if (*book == NULL) {
*book = newBook;
}
else {
//go on till walker is at first price that is lower
while ((walker->order->price >= newOrder->price) && (walker->next != NULL)) {
follower = walker;
walker = walker->next;
}
//insert before walker if walkerprice is lower
if (walker->order->price < newOrder->price) {
//insert before walker
//we are placing record as the first record
if (walker == follower) {
newBook->next = *book;
*book = newBook;
}
//more records
else {
follower->next = newBook;
newBook->next = walker;
}
}
else {
//insert after walker
follower = walker->next;
walker->next = newBook;
newBook->next = follower;
}
}
}
void addSellOrder(struct bookOrder **book, struct order sellOrder) {
struct bookOrder *walker = *book;
struct bookOrder *follower = *book;
struct bookOrder *newBook = malloc(sizeof(**book));
struct order *newOrder = malloc(sizeof(sellOrder));
//make new node
newOrder->price = sellOrder.price;
newOrder->actualSize = sellOrder.actualSize;
newBook->order = newOrder;
newBook->next = NULL;
if (*book == NULL) {
*book = newBook;
}
else {
while ((walker->order->price <= sellOrder.price) && (walker->next != NULL)) {
follower = walker;
walker = walker->next;
}
if (walker->order->price > sellOrder.price)
//insert before walker
if (walker == follower) {
newBook->next = *book;
*book = newBook;
}
else {
follower->next = newBook;
newBook->next = walker;
}
else {
//insert after walker
follower = walker->next;
walker->next = newBook;
newBook->next = follower;
}
}
}
//deletes the first row in a book
void deleteOrder(struct bookOrder **orderBook) {
if (*orderBook != NULL) {
struct bookOrder *tmp = *orderBook;
*orderBook = (*orderBook)->next;
tmp->next = NULL;
free(tmp);
}
}
//returns number of matches
int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches) {
int noMatches = numbOfMatches;
int size;
if (*sellOrderBook == NULL)
return noMatches;
if (buyOrder.price >= (*sellOrderBook)->order->price) {
size = buyOrder.actualSize - (*sellOrderBook)->order->actualSize;
++noMatches;
if (size == 0) {
// sendReport(createTransactionReport());
deleteOrder(sellOrderBook);
}
else if(size > 0) {
// sendReport(createTransactionReport());
buyOrder.filledSize = buyOrder.actualSize - size;
buyOrder.actualSize = size;
deleteOrder(sellOrderBook);
matchBuyOrder(sellOrderBook, buyOrder, noMatches);
}
else {
// sendReport(createTransactionReport());
(*sellOrderBook)->order->filledSize += buyOrder.actualSize;
(*sellOrderBook)->order->actualSize = -size;
}
}
else
addBuyOrder(&buyBook, buyOrder);
return noMatches;
}
//returns number of matches
int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches) {
int noMatches = numbOfMatches;
int size;
if (*buyOrderBook == NULL) {
addSellOrder(&sellBook, sellOrder);
return noMatches;
}
//
if (sellOrder.price <= (*buyOrderBook)->order->price) {
size = sellOrder.actualSize - (*buyOrderBook)->order->actualSize;
++noMatches;
if (size == 0) {
// sendReport(createTransactionReport());
deleteOrder(buyOrderBook);
}
else if(size > 0) {
// sendReport(createTransactionReport());
sellOrder.filledSize = sellOrder.actualSize - size;
sellOrder.actualSize = size;
deleteOrder(buyOrderBook);
matchSellOrder(buyOrderBook, sellOrder, noMatches);
}
else {
// sendReport(createTransactionReport());
(*buyOrderBook)->order->filledSize += sellOrder.actualSize;
(*buyOrderBook)->order->actualSize = -size;
}
}
else {
printf("here?\n");
addSellOrder(&sellBook, sellOrder);
}
return noMatches;
}
int main(void) {
//insert order and print
struct order inpOrder;
inpOrder.price = 29.88888;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
inpOrder.price = 30;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
inpOrder.price = 100;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
printBook("Initial");
inpOrder.price = 300;
inpOrder.actualSize = 600;
addBuyOrder(&buyBook, inpOrder);
printBook("Initial");
inpOrder.price = 300;
inpOrder.actualSize = 600;
addBuyOrder(&buyBook, inpOrder);
//insert order and print
inpOrder.price = 67;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 57;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 20;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 67;
inpOrder.actualSize = 380;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 59;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 10;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//buyorders
inpOrder.price = 10;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 90;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 45.9;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 100.8;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 8.0331;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 600;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 90;
inpOrder.actualSize = 100;
addBuyOrder(&buyBook, inpOrder);
printBook("Initial");
//match order and print
getchar();
inpOrder.price = 58;
inpOrder.actualSize = 200;
matchBuyOrder(&sellBook, inpOrder, 0);
printBook("match buy 200@58");
//match order and print
getchar();
inpOrder.price = 69;
inpOrder.actualSize = 100000;
matchBuyOrder(&sellBook, inpOrder, 0);
printBook("match buy 100000@69");
//match order and print
getchar();
inpOrder.price = 100;
inpOrder.actualSize = 440;
matchSellOrder(&buyBook, inpOrder, 0);
printBook("match sell 440@100");
//match order and print
getchar();
inpOrder.price = 8;
inpOrder.actualSize = 100000;
matchSellOrder(&buyBook, inpOrder, 0);
printBook("match sell 100000@8");
return 0;
}
COMPILER COMMANDS ORIGINAL PROGRAM
gcc ..\source\matchingEngineOriginal.c
OUTPUT ORIGINAL PROGRAM
Initial
--------BUY---------|---------SELL---------
29.889 600
30.000 600
100.000 600
------------------------------------
Initial
--------BUY---------|---------SELL---------
600 300.000 29.889 600
30.000 600
100.000 600
------------------------------------
Initial
--------BUY---------|---------SELL---------
340 600.000 10.000 340
600 300.000 20.000 340
600 300.000 29.889 600
340 100.800 30.000 600
340 90.000 57.000 340
100 90.000 59.000 340
340 45.900 67.000 340
340 10.000 67.000 380
340 8.033 100.000 600
------------------------------------
match buy 200@58
--------BUY---------|---------SELL---------
340 600.000 10.000 140
600 300.000 20.000 340
600 300.000 29.889 600
340 100.800 30.000 600
340 90.000 57.000 340
100 90.000 59.000 340
340 45.900 67.000 340
340 10.000 67.000 380
340 8.033 100.000 600
------------------------------------
match buy 100000@69
--------BUY---------|---------SELL---------
340 600.000 100.000 600
600 300.000
600 300.000
340 100.800
340 90.000
100 90.000
96920 69.000
340 45.900
340 10.000
340 8.033
------------------------------------
match sell 440@100
--------BUY---------|---------SELL---------
500 300.000 100.000 600
600 300.000
340 100.800
340 90.000
100 90.000
96920 69.000
340 45.900
340 10.000
340 8.033
------------------------------------
match sell 100000@8
--------BUY---------|---------SELL---------
8.000 180
100.000 600
------------------------------------
SOURCE CODE MODIFIED PROGRAM
Code:
matchingEngine.c
-----------------
#include <stdio.h>
#include <stdlib.h>
#include "matchingEngine.h"
/*
struct order {
char dir;
float price;
int actualSize;
int filledSize;
char instr[5];
};
struct bookOrder {
struct bookOrder *next;
struct order *order;
};
struct bookOrder *sellBook;
struct bookOrder *buyBook;
*/
void printBook(char *message) {
struct bookOrder *sellWalker = sellBook;
struct bookOrder *buyWalker = buyBook;
printf("\n%s\n", message);
printf("--------BUY---------|---------SELL---------\n");
while ((buyWalker != NULL) || (sellWalker !=NULL)){
//stuff to help with printing in the right place
char *marker = "";
int margin = 4;
if (buyWalker != NULL) {
printf("%10i %10.3f",(buyWalker->order)->actualSize, (buyWalker->order)->price);
buyWalker = buyWalker->next;
}
else
margin = 15;
if (sellWalker != NULL){
printf("%*s %7.3f %5i",margin, marker, (sellWalker->order)->price, (sellWalker->order)->actualSize);
sellWalker = sellWalker->next;
}
printf("\n");
}
printf("------------------------------------\n");
}
void addBuyOrder(struct bookOrder **book, struct order buyOrder) {
struct bookOrder *walker = *book;
struct bookOrder *follower = *book;
struct bookOrder *newBook = malloc(sizeof(**book));
struct order *newOrder = malloc(sizeof(buyOrder));
//make new node
newOrder->price = buyOrder.price;
newOrder->actualSize = buyOrder.actualSize;
newBook->order = newOrder;
newBook->next = NULL;
if (*book == NULL) {
*book = newBook;
}
else {
//go on till walker is at first price that is lower
while ((walker->order->price >= newOrder->price) && (walker->next != NULL)) {
follower = walker;
walker = walker->next;
}
//insert before walker if walkerprice is lower
if (walker->order->price < newOrder->price) {
//insert before walker
//we are placing record as the first record
if (walker == follower) {
newBook->next = *book;
*book = newBook;
}
//more records
else {
follower->next = newBook;
newBook->next = walker;
}
}
else {
//insert after walker
follower = walker->next;
walker->next = newBook;
newBook->next = follower;
}
}
}
void addSellOrder(struct bookOrder **book, struct order sellOrder) {
struct bookOrder *walker = *book;
struct bookOrder *follower = *book;
struct bookOrder *newBook = malloc(sizeof(**book));
struct order *newOrder = malloc(sizeof(sellOrder));
//make new node
newOrder->price = sellOrder.price;
newOrder->actualSize = sellOrder.actualSize;
newBook->order = newOrder;
newBook->next = NULL;
if (*book == NULL) {
*book = newBook;
}
else {
while ((walker->order->price <= sellOrder.price) && (walker->next != NULL)) {
follower = walker;
walker = walker->next;
}
if (walker->order->price > sellOrder.price)
//insert before walker
if (walker == follower) {
newBook->next = *book;
*book = newBook;
}
else {
follower->next = newBook;
newBook->next = walker;
}
else {
//insert after walker
follower = walker->next;
walker->next = newBook;
newBook->next = follower;
}
}
}
//deletes the first row in a book
void deleteOrder(struct bookOrder **orderBook) {
if (*orderBook != NULL) {
struct bookOrder *tmp = *orderBook;
*orderBook = (*orderBook)->next;
tmp->next = NULL;
free(tmp);
}
}
//returns number of matches
int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches) {
int noMatches = numbOfMatches;
int size;
if (*sellOrderBook == NULL)
return noMatches;
if (buyOrder.price >= (*sellOrderBook)->order->price) {
size = buyOrder.actualSize - (*sellOrderBook)->order->actualSize;
++noMatches;
if (size == 0) {
// sendReport(createTransactionReport());
deleteOrder(sellOrderBook);
}
else if(size > 0) {
// sendReport(createTransactionReport());
buyOrder.filledSize = buyOrder.actualSize - size;
buyOrder.actualSize = size;
deleteOrder(sellOrderBook);
matchBuyOrder(sellOrderBook, buyOrder, noMatches);
}
else {
// sendReport(createTransactionReport());
(*sellOrderBook)->order->filledSize += buyOrder.actualSize;
(*sellOrderBook)->order->actualSize = -size;
}
}
else
addBuyOrder(&buyBook, buyOrder);
return noMatches;
}
//returns number of matches
int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches) {
int noMatches = numbOfMatches;
int size;
if (*buyOrderBook == NULL) {
addSellOrder(&sellBook, sellOrder);
return noMatches;
}
//
if (sellOrder.price <= (*buyOrderBook)->order->price) {
size = sellOrder.actualSize - (*buyOrderBook)->order->actualSize;
++noMatches;
if (size == 0) {
// sendReport(createTransactionReport());
deleteOrder(buyOrderBook);
}
else if(size > 0) {
// sendReport(createTransactionReport());
sellOrder.filledSize = sellOrder.actualSize - size;
sellOrder.actualSize = size;
deleteOrder(buyOrderBook);
matchSellOrder(buyOrderBook, sellOrder, noMatches);
}
else {
// sendReport(createTransactionReport());
(*buyOrderBook)->order->filledSize += sellOrder.actualSize;
(*buyOrderBook)->order->actualSize = -size;
}
}
else {
printf("here?\n");
addSellOrder(&sellBook, sellOrder);
}
return noMatches;
}
matchingEngine.h
-----------------
#include <stdio.h>
#include <stdlib.h>
struct order {
char dir;
float price;
int actualSize;
int filledSize;
char instr[5];
};
struct bookOrder {
struct bookOrder *next;
struct order *order;
};
struct bookOrder *sellBook;
struct bookOrder *buyBook;
void printBook(char *message);
void addBuyOrder(struct bookOrder **book, struct order buyOrder);
void addSellOrder(struct bookOrder **book, struct order sellOrder);
void deleteOrder(struct bookOrder **orderBook);
//returns number of matches
int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches);
//returns number of matches
int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches);
testMatchingEngine.c
--------------------
#include <stdio.h>
#include <stdlib.h>
#include "matchingEngine.h"
int main(void) {
//insert order and print
struct order inpOrder;
inpOrder.price = 29.88888;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
printBook("Initial");
inpOrder.price = 30;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
inpOrder.price = 100;
inpOrder.actualSize = 600;
addSellOrder(&sellBook, inpOrder);
printBook("Initial");
inpOrder.price = 300;
inpOrder.actualSize = 600;
addBuyOrder(&buyBook, inpOrder);
printBook("Initial");
inpOrder.price = 300;
inpOrder.actualSize = 600;
addBuyOrder(&buyBook, inpOrder);
//insert order and print
inpOrder.price = 67;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 57;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 20;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 67;
inpOrder.actualSize = 380;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 59;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//insert order and print
inpOrder.price = 10;
inpOrder.actualSize = 340;
addSellOrder(&sellBook, inpOrder);
//buyorders
inpOrder.price = 10;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 90;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 45.9;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 100.8;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 8.0331;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 600;
inpOrder.actualSize = 340;
addBuyOrder(&buyBook, inpOrder);
inpOrder.price = 90;
inpOrder.actualSize = 100;
addBuyOrder(&buyBook, inpOrder);
printBook("Initial");
//match order and print
getchar();
inpOrder.price = 58;
inpOrder.actualSize = 200;
matchBuyOrder(&sellBook, inpOrder, 0);
printBook("match buy 200@58");
//match order and print
getchar();
inpOrder.price = 69;
inpOrder.actualSize = 100000;
matchBuyOrder(&sellBook, inpOrder, 0);
printBook("match buy 100000@69");
//match order and print
getchar();
inpOrder.price = 100;
inpOrder.actualSize = 440;
matchSellOrder(&buyBook, inpOrder, 0);
printBook("match sell 440@100");
//match order and print
getchar();
inpOrder.price = 8;
inpOrder.actualSize = 100000;
matchSellOrder(&buyBook, inpOrder, 0);
printBook("match sell 100000@8");
return 0;
}
COMPILER COMMANDS MODIFIED PROGRAM
gcc -c -fpic ..\source\matchingEngine.c
gcc -shared -o matchingEngine.so matchingEngine.o
gcc -I..\source -L..\bin -o testMatchingEngine ..\source\testMatchingEngine.c matchingEngine.so
OUTPUT MODIFIED PROGRAM
Initial
--------BUY---------|---------SELL---------
------------------------------------
Initial
--------BUY---------|---------SELL---------
------------------------------------
Initial
--------BUY---------|---------SELL---------
------------------------------------
Initial
--------BUY---------|---------SELL---------
------------------------------------
match buy 200@58
--------BUY---------|---------SELL---------
------------------------------------
match buy 100000@69
--------BUY---------|---------SELL---------
96920 69.000
------------------------------------
match sell 440@100
--------BUY---------|---------SELL---------
96920 69.000
------------------------------------
match sell 100000@8
--------BUY---------|---------SELL---------
96920 69.000 8.000 97100
------------------------------------