From 13773d502c447d0bcefd52fc53a7b7bbca72947a Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Sun, 17 Nov 2024 15:52:23 +0100 Subject: [PATCH] orders tests refactoring --- .../subscription-registry.test.ts | 2 +- .../api/order/placeConditionalOrder.test.ts | 584 +++++++----------- src/tests/unit/api/order/placeOrder.test.ts | 260 ++++---- src/tests/unit/sample-data/orders.ts | 12 + 4 files changed, 351 insertions(+), 507 deletions(-) create mode 100644 src/tests/unit/sample-data/orders.ts diff --git a/src/tests/unit/api-next-live/subscription-registry.test.ts b/src/tests/unit/api-next-live/subscription-registry.test.ts index b60e3c65..0898796d 100644 --- a/src/tests/unit/api-next-live/subscription-registry.test.ts +++ b/src/tests/unit/api-next-live/subscription-registry.test.ts @@ -2,7 +2,7 @@ import { Subscription } from "rxjs"; import { IBApiNext, IBApiNextError } from "../../.."; describe("Subscription registry Tests", () => { - jest.setTimeout(20000); + jest.setTimeout(2_000); const clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client diff --git a/src/tests/unit/api/order/placeConditionalOrder.test.ts b/src/tests/unit/api/order/placeConditionalOrder.test.ts index 3d41eec6..fb3a8337 100644 --- a/src/tests/unit/api/order/placeConditionalOrder.test.ts +++ b/src/tests/unit/api/order/placeConditionalOrder.test.ts @@ -10,19 +10,20 @@ import { IBApi, MarginCondition, Order, - OrderAction, OrderCondition, - OrderType, PercentChangeCondition, PriceCondition, TimeCondition, - TimeInForce, TriggerMethod, VolumeCondition, } from "../../../.."; import configuration from "../../../../common/configuration"; import logger from "../../../../common/logger"; import { aapl_contract, sample_stock } from "../../sample-data/contracts"; +import { sample_order } from "../../sample-data/orders"; + +const refContract: Contract = sample_stock; +const refOrder: Order = sample_order; const sample_price_condition: OrderCondition = new PriceCondition( 29, @@ -87,450 +88,315 @@ describe("Place Conditional Orders", () => { test("placeOrder with PriceCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_price_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_price_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("placeOrder with ExecutionCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_execution_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_execution_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("placeOrder with MarginCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_margin_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_margin_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("placeOrder with PercentChangeCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_percent_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_percent_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("placeOrder with TimeCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_time_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_time_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { if (orderId == refId) { - isDone = true; expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); } }) - .on(EventName.openOrderEnd, () => { - if (isDone) done(); - }) - .on( - EventName.orderStatus, - ( - orderId, - status, - filled, - remaining, - _avgFillPrice, - _permId, - _parentId, - _lastFillPrice, - _clientId, - _whyHeld, - _mktCapPrice, - ) => { - if (!isDone && orderId == refId) { - isDone = true; - expect(status).toMatch(/Pending/); - expect(filled).toEqual(0); - expect(remaining).toEqual(refOrder.totalQuantity); - done(); - } - }, - ) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect() - .on(EventName.error, (error, code, reqId) => { - if (reqId > 0) { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); } else { - console.error("ERROR", error.message, code, reqId); + ib.disconnect(); + done(msg); } - }) - .on(EventName.info, (msg, code) => console.info("INFO", code, msg)) - .on(EventName.disconnected, () => done()); + } + }); }); test("placeOrder with VolumeCondition", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [sample_volume_condition], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [sample_volume_condition]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("placeOrder with all conditions", (done) => { let refId: number; - const refContract: Contract = sample_stock; - const refOrder: Order = { - orderType: OrderType.LMT, - action: OrderAction.BUY, - lmtPrice: 0.01, - totalQuantity: 1, - conditionsIgnoreRth: true, - conditionsCancelOrder: false, - conditions: [ - sample_price_condition, - sample_execution_condition, - sample_margin_condition, - sample_percent_condition, - sample_time_condition, - sample_volume_condition, - ], - tif: TimeInForce.DAY, - transmit: true, - }; - - let isDone = false; + refOrder.conditions = [ + sample_price_condition, + sample_execution_condition, + sample_margin_condition, + sample_percent_condition, + sample_time_condition, + sample_volume_condition, + ]; + + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); }); diff --git a/src/tests/unit/api/order/placeOrder.test.ts b/src/tests/unit/api/order/placeOrder.test.ts index 3b8e82fb..9df69d71 100644 --- a/src/tests/unit/api/order/placeOrder.test.ts +++ b/src/tests/unit/api/order/placeOrder.test.ts @@ -55,49 +55,43 @@ describe("Place Orders", () => { transmit: true, }; - let isDone = false; + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { - // Ignore this error for tests - logger.warn(msg); - done(); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect().reqOpenOrders(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("What if Order", (done) => { @@ -115,52 +109,36 @@ describe("Place Orders", () => { whatIf: true, }; - let isDone = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder); - }) - .on(EventName.openOrder, (orderId, contract, order, orderState) => { - if (orderId == refId && !isDone) { - expect(contract.symbol).toEqual(refContract.symbol); - expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - if (orderState.minCommission || orderState.maxCommission) { - expect(orderState.commissionCurrency).toEqual(refContract.currency); - isDone = true; - done(); - } + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); + }).on(EventName.openOrder, (orderId, contract, order, orderState) => { + if (orderId == refId) { + expect(contract.symbol).toEqual(refContract.symbol); + expect(order.totalQuantity).toEqual(refOrder.totalQuantity); + if (orderState.minCommission || orderState.maxCommission) { + expect(orderState.commissionCurrency).toEqual(refContract.currency); + done(); } - }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { - // Ignore this error for tests - logger.warn(msg); - done(); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); + } + }); - ib.connect().reqOpenOrders(); + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("Crypto placeOrder", (done) => { @@ -177,49 +155,43 @@ describe("Place Orders", () => { transmit: true, }; - let isDone = false; + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { - // Ignore this error for tests - logger.warn(msg); - done(); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect().reqOpenOrders(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); test("Option placeOrder", (done) => { @@ -236,48 +208,42 @@ describe("Place Orders", () => { transmit: true, }; - let isDone = false; + let isSuccess = false; ib.once(EventName.nextValidId, (orderId: number) => { refId = orderId; - ib.placeOrder(refId, refContract, refOrder); + ib.reqOpenOrders().placeOrder(refId, refContract, refOrder); }) .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; + if (orderId == refId) { expect(contract.symbol).toEqual(refContract.symbol); expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); } }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { - // Ignore this error for tests - logger.warn(msg); - done(); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect().reqOpenOrders(); + .on(EventName.orderStatus, (orderId, _status, filled, remaining) => { + if (!isSuccess && orderId == refId) { + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + isSuccess = true; + ib.cancelOrder(orderId); + done(); + } + }); + + ib.connect().on(EventName.error, (error, code, reqId) => { + if (reqId === ErrorCode.NO_VALID_ID) { + done(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else { + ib.disconnect(); + done(msg); + } + } + }); }); }); diff --git a/src/tests/unit/sample-data/orders.ts b/src/tests/unit/sample-data/orders.ts new file mode 100644 index 00000000..4a805881 --- /dev/null +++ b/src/tests/unit/sample-data/orders.ts @@ -0,0 +1,12 @@ +import { Order, OrderAction, OrderType, TimeInForce } from "../../../.."; + +export const sample_order: Order = { + orderType: OrderType.LMT, + action: OrderAction.BUY, + lmtPrice: 0.01, + totalQuantity: 1, + conditionsIgnoreRth: true, + conditionsCancelOrder: false, + tif: TimeInForce.DAY, + transmit: true, +};