diff --git a/orderBook.js b/orderBook.js new file mode 100644 index 0000000..2ddd338 --- /dev/null +++ b/orderBook.js @@ -0,0 +1,48 @@ + +function reconcileOrder(existingBook, incomingOrder) { + // default switch case key + let key = 'a' + // matching order index variable + let i = -1 + // callback function for findIndex method which sets conditions for matching orders in existing book + + const buyEqualOrder = order => order.type === 'buy' && order.price >= incomingOrder.price + + // Finds matching order index in existing book + + if (existingBook.length) { i = existingBook.findIndex(buyEqualOrder) } + + // switches handling of orders in special scenarios + + if (i >= 0 && incomingOrder.quantity <= existingBook[i].quantity) { key = 'b' } + if (i >= 0 && incomingOrder.quantity > existingBook[i].quantity) { key = 'c' } + + switch (key) { + // adds an order to the book when the book is empty, or no matching order + case 'a': + existingBook.push(incomingOrder) + + return existingBook + // fulfills an order and removes matching order with same quantity, or reduces when larger quantity + case 'b': + existingBook[i].quantity -= incomingOrder.quantity + if (existingBook[i].quantity > 0) { existingBook.push(existingBook.splice((i), 1)[0]) } + existingBook = existingBook.filter(orders => orders.quantity > 0) + + return existingBook + // all the rest of the special cases (uses recursion to fullfill order with to existing orders) + case 'c': + incomingOrder.quantity -= existingBook[i].quantity + existingBook[i].quantity = 0 + existingBook = existingBook.filter(orders => orders.quantity > 0) + if (existingBook.findIndex(buyEqualOrder) >= 0) { + existingBook = reconcileOrder(existingBook, incomingOrder) + } + else { + existingBook.push(incomingOrder) + } + + return existingBook + } +} +module.exports = reconcileOrder diff --git a/package-lock.json b/package-lock.json index 74a2b24..e937acb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -911,9 +911,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "log-symbols": { diff --git a/tests.js b/tests.js index 4926c8a..d7432a4 100644 --- a/tests.js +++ b/tests.js @@ -91,7 +91,7 @@ describe('Order Book', () => { expect(updatedBook).to.deep.equal([{ type: 'sell', quantity: 12, price: 6950 }, { type: 'sell', quantity: 5, price: 6150 }]) }) - it.skip('Extra Credit: it fulfills a mismatched order when both parties benefit', () => { + it('Extra Credit: it fulfills a mismatched order when both parties benefit', () => { const existingBook = [{ type: 'buy', quantity: 15, price: 6000 }, { type: 'sell', quantity: 12, price: 6950 }] const incomingOrder = { type: 'sell', quantity: 15, price: 5900 } @@ -100,7 +100,7 @@ describe('Order Book', () => { expect(updatedBook).to.deep.equal([{ type: 'sell', quantity: 12, price: 6950 }]) }) - it.skip('Extra Credit: it does not fulfill a mismatched order when it does not benefit both parties', () => { + it('Extra Credit: it does not fulfill a mismatched order when it does not benefit both parties', () => { const existingBook = [{ type: 'buy', quantity: 15, price: 5900 }, { type: 'sell', quantity: 12, price: 6950 }] const incomingOrder = { type: 'sell', quantity: 15, price: 6000 }