#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include "engine.h"
#define UNROLL_STRCPY
#define MAX_NUM_ORDERS 1010000
#ifdef DEBUG
#define ASSERT(c) do {\
if (!(c)) {
fprintf(stderr, "ASSERT failure at line %d\n", __LINE__);\
exit(1);
}
} while (0)
#else
#define ASSERT(c)
#endif
#ifdef UNROLL_STRCPY
#define COPY_STRING(dst, src) do {\
dst[0] = src[0]; \
dst[1] = src[1]; \
dst[2] = src[2]; \
dst[3] = src[3]; \
} while (0)
#else
#include <string.h>
#define COPY_STRING(dst, src) strcpy(dst, src)
#endif
typedef struct orderBookEntry {
t_size size;
struct orderBookEntry * next;
char trader[4];
}
orderBookEntry_t;
typedef struct pricePoint {
orderBookEntry_t * listHead;
orderBookEntry_t * listTail;
}
pricePoint_t;
static pricePoint_t pricePoints[MAX_PRICE + 1];
static t_orderid curOrderID;
static unsigned int askMin;
static unsigned int bidMax;
static orderBookEntry_t arenaBookEntries[MAX_NUM_ORDERS];
static orderBookEntry_t * arenaPtr;
#define ALLOC_BOOK_ENTRY(id)
void init() {
bzero(pricePoints, (MAX_PRICE + 1) * sizeof(pricePoint_t));
bzero(arenaBookEntries, MAX_NUM_ORDERS * sizeof(orderBookEntry_t));
arenaPtr = arenaBookEntries;
curOrderID = 0;
askMin = MAX_PRICE + 1;
bidMax = MIN_PRICE - 1;
}
void destroy() {}
void ppInsertOrder(pricePoint_t * ppEntry, orderBookEntry_t * entry) {
if (ppEntry->listHead != NULL)
ppEntry->listTail->next = entry;
else
ppEntry->listHead = entry;
ppEntry->listTail = entry;
}
void EXECUTE_TRADE(const char * symbol,
const char * buyTrader,
const char * sellTrader, t_price tradePrice,
t_size tradeSize) {
t_execution exec;
if (tradeSize == 0)
return;
COPY_STRING(exec.symbol, symbol);
exec.price = tradePrice;
exec.size = tradeSize;
exec.side = 0;
COPY_STRING(exec.trader, buyTrader);
exec.trader[4] = '\0';
execution(exec);
exec.side = 1;
COPY_STRING(exec.trader, sellTrader);
exec.trader[4] = '\0';
execution(exec);
}
t_orderid limit(t_order order) {
orderBookEntry_t * bookEntry;
orderBookEntry_t * entry;
pricePoint_t * ppEntry;
t_price price = order.price;
t_size orderSize = order.size;
if (order.side == 0) {
if (price >= askMin) {
ppEntry = pricePoints + askMin;
do {
bookEntry = ppEntry->listHead;
while (bookEntry != NULL) {
if (bookEntry->size < orderSize) {
EXECUTE_TRADE(order.symbol, order.trader,
bookEntry->trader, price, bookEntry->size);
orderSize -= bookEntry->size;
bookEntry = bookEntry->next;
} else {
EXECUTE_TRADE(order.symbol, order.trader,
bookEntry->trader, price, orderSize);
if (bookEntry->size > orderSize)
bookEntry->size -= orderSize;
else
bookEntry = bookEntry->next;
ppEntry->listHead = bookEntry;
return ++curOrderID;
}
}
ppEntry->listHead = NULL;
ppEntry++;
askMin++;
} while (price >= askMin);
}
entry = arenaBookEntries + (++curOrderID);
entry->size = orderSize;
COPY_STRING(entry->trader, order.trader);
ppInsertOrder( & pricePoints[price], entry);
if (bidMax < price)
bidMax = price;
return curOrderID;
} else {
if (price <= bidMax) {
ppEntry = pricePoints + bidMax;
do {
bookEntry = ppEntry->listHead;
while (bookEntry != NULL) {
if (bookEntry->size < orderSize) {
EXECUTE_TRADE(order.symbol, bookEntry->trader,
order.trader, price, bookEntry->size);
orderSize -= bookEntry->size;
bookEntry = bookEntry->next;
} else {
EXECUTE_TRADE(order.symbol, bookEntry->trader,
order.trader, price, orderSize);
if (bookEntry->size > orderSize)
bookEntry->size -= orderSize;
else
bookEntry = bookEntry->next;
ppEntry->listHead = bookEntry;
return ++curOrderID;
}
}
ppEntry->listHead = NULL;
ppEntry--;
bidMax--;
} while (price <= bidMax);
}
entry = arenaBookEntries + (++curOrderID);
entry->size = orderSize;
COPY_STRING(entry->trader, order.trader);
ppInsertOrder( & pricePoints[price], entry);
if (askMin > price)
askMin = price;
return curOrderID;
}
}
void cancel(t_orderid orderid) {
arenaBookEntries[orderid].size = 0;
}