UNPKG

ib-client

Version:

Interactive Brokers API client library for Node.js

1,260 lines (1,113 loc) 92.3 kB
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports["default"] = void 0;var _lodash = require("lodash"); var _constants = require("./constants"); var _errors = require("./errors");function _toConsumableArray(arr) {return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();}function _nonIterableSpread() {throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}function _unsupportedIterableToArray(o, minLen) {if (!o) return;if (typeof o === "string") return _arrayLikeToArray(o, minLen);var n = Object.prototype.toString.call(o).slice(8, -1);if (n === "Object" && o.constructor) n = o.constructor.name;if (n === "Map" || n === "Set") return Array.from(o);if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);}function _iterableToArray(iter) {if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);}function _arrayWithoutHoles(arr) {if (Array.isArray(arr)) return _arrayLikeToArray(arr);}function _arrayLikeToArray(arr, len) {if (len == null || len > arr.length) len = arr.length;for (var i = 0, arr2 = new Array(len); i < len; i++) {arr2[i] = arr[i];}return arr2;}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}function _createClass(Constructor, protoProps, staticProps) {if (protoProps) _defineProperties(Constructor.prototype, protoProps);if (staticProps) _defineProperties(Constructor, staticProps);return Constructor;}var MessageEncoder = /*#__PURE__*/function () { function MessageEncoder() {_classCallCheck(this, MessageEncoder); this._serverVersion = _constants.SERVER_VERSION; }_createClass(MessageEncoder, [{ key: "_error", value: function _error( id, error, message) { if (typeof error === 'string') { throw new _errors.BrokerError({ id: id, code: null, message: error + ' ' + message }); } else { throw new _errors.BrokerError({ id: id, code: error.code, message: error.message + ' ' + message }); } } }, { key: "_encodeLengthHeader", value: function _encodeLengthHeader( value) { var arr = []; var mask = 0xff; arr.push(mask & value >> 24); arr.push(mask & value >> 16); arr.push(mask & value >> 8); arr.push(mask & value); return arr; } }, { key: "_encodeString", value: function _encodeString( value) { if (value != null) { return Array.from(value.concat(_constants.EOL), function (c) {return c.charCodeAt();}); } else { return 0; } } }, { key: "_encodeBool", value: function _encodeBool( value) { return this._encodeString((value ? 1 : 0).toString()); } }, { key: "_encodeMax", value: function _encodeMax( value) { return value === 0xffffffff || value === Number.MAX_VALUE ? this._encode('') : this._encode(value); } }, { key: "_encode", value: function _encode( value) { if (typeof value === 'boolean') return this._encodeBool(value); return this._encodeString(value === undefined || value === null ? null : value.toString()); } }, { key: "encodeMessage", value: function encodeMessage( data) { var error = data[0]; var func = data[1]; var args = data.slice(2); if (typeof this[func] !== 'function') throw new Error('Unknown broker API request - ' + func); var tokens = (0, _lodash.flattenDeep)(this[func].apply(this, _toConsumableArray(args))); return { error: error, func: func, args: args, message: this._prependV100LengthHeader(tokens) }; } }, { key: "setServerVersion", value: function setServerVersion( version) { this._serverVersion = version; } }, { key: "_prependV100LengthHeader", value: function _prependV100LengthHeader( message) { var header = this._getV100LengthHeader(message.length); return header.concat(message); } }, { key: "_getV100LengthHeader", value: function _getV100LengthHeader( length) { return this._encodeLengthHeader(length); } }, { key: "sendV100APIHeader", value: function sendV100APIHeader() { var prefix = this._encode('API'); var version = this._encode( 'v' + (_constants.MIN_VERSION < _constants.MAX_VERSION ? _constants.MIN_VERSION + '..' + _constants.MAX_VERSION : _constants.MIN_VERSION)); version.splice(-1); return [prefix, this._getV100LengthHeader(version.length), version]; } }, { key: "startAPI", value: function startAPI( clientId, optionalCapabilities) { var version = 2; var buffer = [this._encode(_constants.OUTGOING.START_API), this._encode(version), this._encode(clientId)]; if (this._serverVersion >= _constants.MIN_SERVER_VER.OPTIONAL_CAPABILITIES) { buffer.push(this._encode(optionalCapabilities)); } return buffer; } }, { key: "cancelScannerSubscription", value: function cancelScannerSubscription( tickerId) { if (this._serverVersion < 24) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support API scanner subscription.'); } var version = 1; var buffer = [ this._encode(_constants.OUTGOING.CANCEL_SCANNER_SUBSCRIPTION), this._encode(version), this._encode(tickerId)]; return buffer; } }, { key: "reqScannerParameters", value: function reqScannerParameters() { if (this._serverVersion < 24) { return this._error( _errors.BROKER_ERRORS.NO_VALID_ID, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support API scanner subscription.'); } var version = 1; return [this._encode(_constants.OUTGOING.REQ_SCANNER_PARAMETERS), this._encode(version)]; } }, { key: "reqScannerSubscription", value: function reqScannerSubscription( tickerId, subscription, scannerSubscriptionOptions, scannerSubscriptionFilterOptions) { if (this._serverVersion < 24) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support API scanner subscription.'); } if ( this._serverVersion < _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS && scannerSubscriptionFilterOptions != null) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support API scanner subscription generic filter options'); } var version = 4; var buffer = [this._encode(_constants.OUTGOING.REQ_SCANNER_SUBSCRIPTION)]; if (this._serverVersion < _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS) { buffer.push(this._encode(version)); } buffer.push(this._encode(tickerId)); buffer.push(this._encodeMax(subscription.numberOfRows)); buffer.push(this._encode(subscription.instrument)); buffer.push(this._encode(subscription.locationCode)); buffer.push(this._encode(subscription.scanCode)); buffer.push(this._encodeMax(subscription.abovePrice)); buffer.push(this._encodeMax(subscription.belowPrice)); buffer.push(this._encodeMax(subscription.aboveVolume)); buffer.push(this._encodeMax(subscription.marketCapAbove)); buffer.push(this._encodeMax(subscription.marketCapBelow)); buffer.push(this._encode(subscription.moodyRatingAbove)); buffer.push(this._encode(subscription.moodyRatingBelow)); buffer.push(this._encode(subscription.spRatingAbove)); buffer.push(this._encode(subscription.spRatingBelow)); buffer.push(this._encode(subscription.maturityDateAbove)); buffer.push(this._encode(subscription.maturityDateBelow)); buffer.push(this._encodeMax(subscription.couponRateAbove)); buffer.push(this._encodeMax(subscription.couponRateBelow)); buffer.push(this._encode(subscription.excludeConvertible)); if (this._serverVersion >= 25) { buffer.push(this._encodeMax(subscription.averageOptionVolumeAbove)); buffer.push(this._encode(subscription.scannerSettingPairs)); } if (this._serverVersion >= 27) { buffer.push(this._encode(subscription.stockTypeFilter)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS) { buffer.push(this._encode(scannerSubscriptionFilterOptions)); } // send scannerSubscriptionOptions parameter if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { buffer.push(this._encode(scannerSubscriptionOptions)); } return buffer; } }, { key: "reqMktData", value: function reqMktData( tickerId, contract, genericTickList, snapshot, regulatorySnapshot, mktDataOptions) {var _this = this; if (this._serverVersion < _constants.MIN_SERVER_VER.SNAPSHOT_MKT_DATA && snapshot) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support snapshot market data requests.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support delta-neutral orders.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.REQ_MKT_DATA_CONID) { return this._error(tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId parameter.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass)) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support tradingClass parameter in reqMarketData.'); } } var version = 11; var buffer = [ this._encode(_constants.OUTGOING.REQ_MKT_DATA), this._encode(version), this._encode(tickerId)]; // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.REQ_MKT_DATA_CONID) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); if (this._serverVersion >= 15) { buffer.push(this._encode(contract.multiplier)); } buffer.push(this._encode(contract.exchange)); if (this._serverVersion >= 14) { buffer.push(this._encode(contract.primaryExch)); } buffer.push(this._encode(contract.currency)); if (this._serverVersion >= 2) { buffer.push(this._encode(contract.localSymbol)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } if ( this._serverVersion >= 8 && typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { if (!Array.isArray(contract.comboLegs)) { buffer.push(this._encode(0)); } else { buffer.push(this._encode(contract.comboLegs.length)); contract.comboLegs.forEach(function (comboLeg) { buffer.push(_this._encode(comboLeg.conId)); buffer.push(_this._encode(comboLeg.ratio)); buffer.push(_this._encode(comboLeg.action)); buffer.push(_this._encode(comboLeg.exchange)); }); } } if (this._serverVersion >= _constants.MIN_SERVER_VER.DELTA_NEUTRAL) { if ((0, _lodash.isPlainObject)(contract.deltaNeutralContract)) { buffer.push(this._encode(true)); buffer.push(this._encode(contract.deltaNeutralContract.conId)); buffer.push(this._encode(contract.deltaNeutralContract.delta)); buffer.push(this._encode(contract.deltaNeutralContract.price)); } else { buffer.push(this._encode(false)); } } if (this._serverVersion >= 31) { /* * Note: Even though SHORTABLE tick type supported only * starting server version 33 it would be relatively * expensive to expose this restriction here. * * Therefore we are relying on TWS doing validation. */ buffer.push(this._encode(genericTickList)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SNAPSHOT_MKT_DATA) { buffer.push(this._encode(snapshot)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.REQ_SMART_COMPONENTS) { buffer.push(this._encode(regulatorySnapshot)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { buffer.push(this._encode(mktDataOptions)); } return buffer; } }, { key: "cancelHistoricalData", value: function cancelHistoricalData( tickerId) { if (this._serverVersion < 24) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support historical data query cancellation.'); } var version = 1; var buffer = [ this._encode(_constants.OUTGOING.CANCEL_HISTORICAL_DATA), this._encode(version), this._encode(tickerId)]; return buffer; } }, { key: "cancelRealTimeBars", value: function cancelRealTimeBars( tickerId) { if (this._serverVersion < _constants.MIN_SERVER_VER.REAL_TIME_BARS) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support realtime bar data query cancellation.'); } var version = 1; var buffer = [ this._encode(_constants.OUTGOING.CANCEL_REAL_TIME_BARS), this._encode(version), this._encode(tickerId)]; return buffer; } }, { key: "reqHistoricalData", value: function reqHistoricalData( tickerId, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate, keepUpToDate, chartOptions) {var _this2 = this; var version = 6; if (this._serverVersion < 16) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support historical data backfill.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId and tradingClass parameters in reqHistroricalData.'); } } var buffer = [this._encode(_constants.OUTGOING.REQ_HISTORICAL_DATA)]; if (this._serverVersion < _constants.MIN_SERVER_VER.SYNT_REALTIME_BARS) { buffer.push(this._encode(version)); } buffer.push(this._encode(tickerId)); // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); buffer.push(this._encode(contract.multiplier)); buffer.push(this._encode(contract.exchange)); buffer.push(this._encode(contract.primaryExch)); buffer.push(this._encode(contract.currency)); buffer.push(this._encode(contract.localSymbol)); if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } if (this._serverVersion >= 31) { buffer.push(this._encode(contract.includeExpired ? 1 : 0)); } if (this._serverVersion >= 20) { buffer.push(this._encode(endDateTime)); buffer.push(this._encode(barSizeSetting)); } buffer.push(this._encode(durationStr)); buffer.push(this._encode(useRTH)); buffer.push(this._encode(whatToShow)); if (this._serverVersion > 16) { buffer.push(this._encode(formatDate)); } if ( typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { if (!Array.isArray(contract.comboLegs)) { buffer.push(this._encode(0)); } else { buffer.push(this._encode(contract.comboLegs.length)); contract.comboLegs.forEach(function (comboLeg) { buffer.push(_this2._encode(comboLeg.conId)); buffer.push(_this2._encode(comboLeg.ratio)); buffer.push(_this2._encode(comboLeg.action)); buffer.push(_this2._encode(comboLeg.exchange)); }); } } if (this._serverVersion >= _constants.MIN_SERVER_VER.SYNT_REALTIME_BARS) { buffer.push(this._encode(keepUpToDate)); } // send chartOptions parameter if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { buffer.push(this._encode(chartOptions)); } return buffer; } }, { key: "reqHeadTimestamp", value: function reqHeadTimestamp( reqId, contract, whatToShow, useRTH, formatDate) { if (this._serverVersion < _constants.MIN_SERVER_VER.REQ_HEAD_TIMESTAMP) { return this._error(reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support reqHeadTimeStamp'); } return [ this._encode(_constants.OUTGOING.REQ_HEAD_TIMESTAMP), this._encode(reqId), this._encode(contract.conId), this._encode(contract.symbol), this._encode(contract.secType), this._encode(contract.expiry), this._encode(contract.strike), this._encode(contract.right), this._encode(contract.multiplier), this._encode(contract.exchange), this._encode(contract.primaryExchange), this._encode(contract.currency), this._encode(contract.localSymbol), this._encode(contract.tradingClass), this._encode(contract.includeExpired), this._encode(useRTH), this._encode(whatToShow), this._encode(formatDate)]; } }, { key: "cancelHeadTimestamp", value: function cancelHeadTimestamp( reqId) { if (this._serverVersion < _constants.MIN_SERVER_VER.CANCEL_HEADTIMESTAMP) { return this._error( reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support head time stamp requests canceling.'); } return [this._encode(_constants.OUTGOING.CANCEL_HEAD_TIMESTAMP), this._encode(reqId)]; } }, { key: "reqRealTimeBars", value: function reqRealTimeBars( tickerId, contract, barSize, whatToShow, useRTH, realTimeBarsOptions) { if (this._serverVersion < _constants.MIN_SERVER_VER.REAL_TIME_BARS) { return this._error(tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support real time bars.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId and tradingClass parameters in reqRealTimeBars.'); } } var version = 3; // send req mkt data msg var buffer = [ this._encode(_constants.OUTGOING.REQ_REAL_TIME_BARS), this._encode(version), this._encode(tickerId)]; // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); buffer.push(this._encode(contract.multiplier)); buffer.push(this._encode(contract.exchange)); buffer.push(this._encode(contract.primaryExch)); buffer.push(this._encode(contract.currency)); buffer.push(this._encode(contract.localSymbol)); if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } buffer.push(this._encode(barSize)); // this parameter is not currently used buffer.push(this._encode(whatToShow)); buffer.push(this._encode(useRTH)); // send realTimeBarsOptions parameter if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { buffer.push(this._encode(realTimeBarsOptions)); } return buffer; } }, { key: "reqContractDetails", value: function reqContractDetails( reqId, contract) { if (this._serverVersion < 4) { return this._error( reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'This feature is only available for versions of TWS >=4'); } if (this._serverVersion < _constants.MIN_SERVER_VER.SEC_ID_TYPE) { if (!(0, _lodash.isEmpty)(contract.secIdType) || !(0, _lodash.isEmpty)(contract.secId)) { return this._error( reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support secIdType and secId parameters.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass)) { return this._error( reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support tradingClass parameter in reqContractDetails.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.LINKING) { if (!(0, _lodash.isEmpty)(contract.primaryExch)) { return this._error( reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support primaryExchange parameter in reqContractDetails.'); } } var version = 8; // send req mkt data msg var buffer = [this._encode(_constants.OUTGOING.REQ_CONTRACT_DATA), this._encode(version)]; if (this._serverVersion >= _constants.MIN_SERVER_VER.CONTRACT_DATA_CHAIN) { buffer.push(this._encode(reqId)); } // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.CONTRACT_CONID) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); if (this._serverVersion >= 15) { buffer.push(this._encode(contract.multiplier)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.PRIMARYEXCH) { buffer.push(this._encode(contract.exchange)); buffer.push(this._encode(contract.primaryExch)); } else if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { if ( !(0, _lodash.isEmpty)(contract.primaryExch) && ( 'BEST' === contract.exchange || 'SMART' === contract.exchange)) { buffer.push(this._encode(contract.exchange + ':' + contract.primaryExch)); } else { buffer.push(this._encode(contract.exchange)); } } buffer.push(this._encode(contract.currency)); buffer.push(this._encode(contract.localSymbol)); if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } if (this._serverVersion >= 31) { buffer.push(this._encode(contract.includeExpired)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SEC_ID_TYPE) { buffer.push(this._encode(contract.secIdType)); buffer.push(this._encode(contract.secId)); } return buffer; } }, { key: "reqMktDepth", value: function reqMktDepth( tickerId, contract, numRows, isSmartDepth, mktDepthOptions) { if (this._serverVersion < 6) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'This feature is only available for versions of TWS >=6'); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId and tradingClass parameters in reqMktDepth.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SMART_DEPTH && isSmartDepth) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support SMART depth request.'); } var version = 5; // send req mkt data msg var buffer = [ this._encode(_constants.OUTGOING.REQ_MKT_DEPTH), this._encode(version), this._encode(tickerId)]; // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); if (this._serverVersion >= 15) { buffer.push(this._encode(contract.multiplier)); } buffer.push(this._encode(contract.exchange)); buffer.push(this._encode(contract.currency)); buffer.push(this._encode(contract.localSymbol)); if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } if (this._serverVersion >= 19) { buffer.push(this._encode(numRows)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH) { buffer.push(this._encode(isSmartDepth)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) { buffer.push(this._encode(mktDepthOptions)); } return buffer; } }, { key: "cancelMktData", value: function cancelMktData( tickerId) { var version = 1; var buffer = [ this._encode(_constants.OUTGOING.CANCEL_MKT_DATA), this._encode(version), this._encode(tickerId)]; return buffer; } }, { key: "cancelMktDepth", value: function cancelMktDepth( tickerId, isSmartDepth) { if (this._serverVersion < 6) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'This feature is only available for versions of TWS >=6.'); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH && isSmartDepth) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support SMART depth cancel.'); } var version = 1; var buffer = [ this._encode(_constants.OUTGOING.CANCEL_MKT_DEPTH), this._encode(version), this._encode(tickerId)]; if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH) { buffer.push(this._encode(isSmartDepth)); } return buffer; } }, { key: "exerciseOptions", value: function exerciseOptions( tickerId, contract, exerciseAction, exerciseQuantity, account, override) { var version = 2; if (this._serverVersion < 21) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support options exercise from the API.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) { return this._error( tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId and tradingClass parameters in exerciseOptions.'); } } var buffer = [ this._encode(_constants.OUTGOING.EXERCISE_OPTIONS), this._encode(version), this._encode(tickerId)]; // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); buffer.push(this._encode(contract.multiplier)); buffer.push(this._encode(contract.exchange)); buffer.push(this._encode(contract.currency)); buffer.push(this._encode(contract.localSymbol)); if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } buffer.push(this._encode(exerciseAction)); buffer.push(this._encode(exerciseQuantity)); buffer.push(this._encode(account)); buffer.push(this._encode(override)); return buffer; } }, { key: "placeOrder", value: function placeOrder( id, contract, order) {var _this3 = this; if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS) { if ( order.scaleInitLevelSize !== Number.MAX_VALUE || order.scalePriceIncrement !== Number.MAX_VALUE) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support Scale orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORT_COMBO_LEGS) { if (Array.isArray(contract.comboLegs)) { contract.comboLegs.forEach( function (comboLeg) { if (!(0, _lodash.isEmpty)(comboLeg.shortSaleSlot) || !(0, _lodash.isEmpty)(comboLeg.designatedLocation)) { return this._emitError( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support SSHORT flag for combo legs.'); } }.bind(this)); } } if (this._serverVersion < _constants.MIN_SERVER_VER.WHAT_IF_ORDERS) { if (order.whatIf) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support what-if orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL) { if (contract.deltaNeutralContract) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support delta-neutral orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS2) { if (order.scaleSubsLevelSize && order.scaleSubsLevelSize !== Number.MAX_VALUE) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support Subsequent Level Size for Scale orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.ALGO_ORDERS) { if (!(0, _lodash.isEmpty)(order.algoStrategy)) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support algo orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.NOT_HELD) { if (order.notHeld) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support notHeld parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SEC_ID_TYPE) { if (!(0, _lodash.isEmpty)(contract.secIdType) || !(0, _lodash.isEmpty)(contract.secId)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support secIdType and secId parameters.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.PLACE_ORDER_CONID) { if (contract.conId > 0) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORTX) { if (order.exemptCode && order.exemptCode !== -1) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support exemptCode parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORTX) { if (Array.isArray(contract.comboLegs)) { contract.comboLegs.forEach( function (comboLeg) {return ( comboLeg.exemptCode !== -1 && _this3._error('It does not support exemptCode parameter.'));}); } } if (this._serverVersion < _constants.MIN_SERVER_VER.HEDGE_ORDERS) { if (!(0, _lodash.isEmpty)(order.hedgeType)) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support hedge orders.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.OPT_OUT_SMART_ROUTING) { if (order.optOutSmartRouting) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support optOutSmartRouting parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL_CONID) { if ( order.deltaNeutralConId > 0 || !(0, _lodash.isEmpty)(order.deltaNeutralSettlingFirm) || !(0, _lodash.isEmpty)(order.deltaNeutralClearingAccount) || !(0, _lodash.isEmpty)(order.deltaNeutralClearingIntent)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL_OPEN_CLOSE) { if ( !(0, _lodash.isEmpty)(order.deltaNeutralOpenClose) || order.deltaNeutralShortSale || order.deltaNeutralShortSaleSlot > 0 || !(0, _lodash.isEmpty)(order.deltaNeutralDesignatedLocation)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support deltaNeutral parameters: OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS3) { if (order.scalePriceIncrement > 0 && order.scalePriceIncrement !== Number.MAX_VALUE) { if ( order.scalePriceAdjustValue !== Number.MAX_VALUE || order.scalePriceAdjustInterval !== Number.MAX_VALUE || order.scaleProfitOffset !== Number.MAX_VALUE || order.scaleAutoReset || order.scaleInitPosition !== Number.MAX_VALUE || order.scaleInitFillQty !== Number.MAX_VALUE || order.scaleRandomPercent) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent'); } } } if ( this._serverVersion < _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE && typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { if (Array.isArray(order.orderComboLegs)) { order.orderComboLegs.forEach( function (orderComboLeg) {return ( orderComboLeg.price !== Number.MAX_VALUE && _this3._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support per-leg prices for order combo legs.'));}); } } if (this._serverVersion < _constants.MIN_SERVER_VER.TRAILING_PERCENT) { if (order.trailingPercent && order.trailingPercent !== Number.MAX_VALUE) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support trailing percent parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) { if (!(0, _lodash.isEmpty)(contract.tradingClass)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support tradingClass parameters in placeOrder.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.ALGO_ID && !(0, _lodash.isEmpty)(order.algoId)) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support algoId parameter.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_TABLE) { if ( !(0, _lodash.isEmpty)(order.scaleTable) || !(0, _lodash.isEmpty)(order.activeStartTime) || !(0, _lodash.isEmpty)(order.activeStopTime)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support scaleTable, activeStartTime and activeStopTime parameters.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_SOLICITED) { if (order.solicited) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support order solicited parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.MODELS_SUPPORT) { if (!(0, _lodash.isEmpty)(order.modelCode)) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support model code parameter.'); } } if (this._serverVersion < _constants.MIN_SERVER_VER.EXT_OPERATOR && !(0, _lodash.isEmpty)(order.extOperator)) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support ext operator'); } if ( this._serverVersion < _constants.MIN_SERVER_VER.SOFT_DOLLAR_TIER && order.softDollarTier && ( !(0, _lodash.isEmpty)(order.softDollarTier.name) || !(0, _lodash.isEmpty)(order.softDollarTier.value))) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support soft dollar tier.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.CASH_QTY) { if (order.cashQty && order.cashQty != Number.MAX_VALUE) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support cash quantity parameter.'); } } if ( this._serverVersion < _constants.MIN_SERVER_VER.DECISION_MAKER && ( !(0, _lodash.isEmpty)(order.mifid2DecisionMaker) || !(0, _lodash.isEmpty)(order.mifid2DecisionAlgo))) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support MIFID II decision maker parameters.'); } if ( this._serverVersion < _constants.MIN_SERVER_VER.MIFID_EXECUTION && ( !(0, _lodash.isEmpty)(order.mifid2ExecutionTrader) || !(0, _lodash.isEmpty)(order.mifid2ExecutionAlgo))) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, ' It does not support MIFID II execution parameters'); } if ( this._serverVersion < _constants.MIN_SERVER_VER.AUTO_PRICE_FOR_HEDGE && order.dontUseAutoPriceForHedge) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, "It does not support don't use auto price for hedge parameter."); } if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_CONTAINER && order.isOmsContainer) { return this._error( id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support oms container parameter.'); } if (this._serverVersion < _constants.MIN_SERVER_VER.D_PEG_ORDERS && order.discretionaryUpToLimitPrice) { return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support D-Peg orders.'); } var version = this._serverVersion < _constants.MIN_SERVER_VER.NOT_HELD ? 27 : 45; // send place order msg var buffer = [this._encode(_constants.OUTGOING.PLACE_ORDER)]; if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_CONTAINER) { buffer.push(this._encode(version)); } buffer.push(this._encode(id)); // send contract fields if (this._serverVersion >= _constants.MIN_SERVER_VER.PLACE_ORDER_CONID) { buffer.push(this._encode(contract.conId)); } buffer.push(this._encode(contract.symbol)); buffer.push(this._encode(contract.secType)); buffer.push(this._encode(contract.expiry)); buffer.push(this._encode(contract.strike)); buffer.push(this._encode(contract.right)); if (this._serverVersion >= 15) { buffer.push(this._encode(contract.multiplier)); } buffer.push(this._encode(contract.exchange)); if (this._serverVersion >= 14) { buffer.push(this._encode(contract.primaryExch)); } buffer.push(this._encode(contract.currency)); if (this._serverVersion >= 2) { buffer.push(this._encode(contract.localSymbol)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) { buffer.push(this._encode(contract.tradingClass)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.SEC_ID_TYPE) { buffer.push(this._encode(contract.secIdType)); buffer.push(this._encode(contract.secId)); } // send main order fields buffer.push(this._encode(order.action)); if (this._serverVersion >= _constants.MIN_SERVER_VER.FRACTIONAL_POSITIONS) buffer.push(this._encode(order.totalQuantity));else buffer.push(this._encode(parseInt(order.totalQuantity, 10))); buffer.push(this._encode(order.orderType)); if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE) { buffer.push(this._encode(order.lmtPrice === Number.MAX_VALUE ? 0 : order.lmtPrice)); } else { buffer.push(this._encodeMax(order.lmtPrice)); } if (this._serverVersion < _constants.MIN_SERVER_VER.TRAILING_PERCENT) { buffer.push(this._encode(order.auxPrice === Number.MAX_VALUE ? 0 : order.auxPrice)); } else { buffer.push(this._encodeMax(order.auxPrice)); } // send extended order fields buffer.push(this._encode(order.tif)); buffer.push(this._encode(order.ocaGroup)); buffer.push(this._encode(order.account)); buffer.push(this._encode(order.openClose)); buffer.push(this._encode(order.origin)); buffer.push(this._encode(order.orderRef)); buffer.push(this._encode(order.transmit)); if (this._serverVersion >= 4) { buffer.push(this._encode(order.parentId)); } if (this._serverVersion >= 5) { buffer.push(this._encode(order.blockOrder)); buffer.push(this._encode(order.sweepToFill)); buffer.push(this._encode(order.displaySize)); buffer.push(this._encode(order.triggerMethod)); if (this._serverVersion < 38) { // will never happen buffer.push(this._encode( /* order.ignoreRth */false)); } else { buffer.push(this._encode(order.outsideRth)); } } if (this._serverVersion >= 7) { buffer.push(this._encode(order.hidden)); } // Send combo legs for BAG requests if ( this._serverVersion >= 8 && typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { if (!Array.isArray(contract.comboLegs)) { buffer.push(this._encode(0)); } else { buffer.push(this._encode(contract.comboLegs.length)); contract.comboLegs.forEach(function (comboLeg) { buffer.push(_this3._encode(comboLeg.conId)); buffer.push(_this3._encode(comboLeg.ratio)); buffer.push(_this3._encode(comboLeg.action)); buffer.push(_this3._encode(comboLeg.exchange)); buffer.push(_this3._encode(comboLeg.openClose)); if (_this3._serverVersion >= _constants.MIN_SERVER_VER.SSHORT_COMBO_LEGS) { buffer.push(_this3._encode(comboLeg.shortSaleSlot)); buffer.push(_this3._encode(comboLeg.designatedLocation)); } if (_this3._serverVersion >= _constants.MIN_SERVER_VER.SSHORTX_OLD) { buffer.push(_this3._encode(comboLeg.exemptCode)); } }); } } // Send order combo legs for BAG requests if ( this._serverVersion >= _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE && typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { if (!Array.isArray(order.orderComboLegs)) { buffer.push(this._encode(0)); } else { buffer.push(this._encode(order.orderComboLegs.length)); order.orderComboLegs.forEach(function (orderComboLeg) {return ( buffer.push(_this3._encodeMax(orderComboLeg.price)));}); } } var smartComboRoutingParamsCount; if ( this._serverVersion >= _constants.MIN_SERVER_VER.SMART_COMBO_ROUTING_PARAMS && typeof contract.secType === 'string' && _constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase()) { smartComboRoutingParamsCount = !Array.isArray(order.smartComboRoutingParams) ? 0 : order.smartComboRoutingParams.length; buffer.push(this._encode(smartComboRoutingParamsCount)); if (smartComboRoutingParamsCount > 0) { order.smartComboRoutingParams.forEach(function (tagValue) { buffer.push(_this3._encode(tagValue.tag)); buffer.push(_this3._encode(tagValue.value)); }); } } if (this._serverVersion >= 9) { // send deprecated sharesAllocation field buffer.push(this._encode('')); } if (this._serverVersion >= 10) { buffer.push(this._encode(order.discretionaryAmt)); } if (this._serverVersion >= 11) { buffer.push(this._encode(order.goodAfterTime)); } if (this._serverVersion >= 12) { buffer.push(this._encode(order.goodTillDate)); } if (this._serverVersion >= 13) { buffer.push(this._encode(order.faGroup)); buffer.push(this._encode(order.faMethod)); buffer.push(this._encode(order.faPercentage)); buffer.push(this._encode(order.faProfile)); } if (this._serverVersion >= _constants.MIN_SERVER_VER.MODELS_SUPPORT) { buffer.push(this._encode(order.modelCode)); } if (this._serverVersion >= 18) { // institutional short sale slot fields. buffer.push(this._encode(order.shortSaleSlot)); // 0 only for retail, 1 or 2 only for institution. buffer.push(this._encode(order.designatedLocation)); // only populate when order.shortSaleSlot = 2. } if (this._serverVersion >= _constants.MIN_SERVER_VER.SSHORTX_OLD) { buffer.push(this._encode(order.exemptCode)); } var lower; var upper; if (this._serverVersion >= 19) { buffer.push(this._encode(order.ocaType)); if (this._serverVersion < 38) { // will never happen buffer.push(this._encode( /* order.rthOnly */false)); } buffer.push(this._encode(order.rule80A)); buffer.push(this._encode(order.settlingFirm)); buffer.push(this._encode(order.allOrNone)); buffer.push(this._encodeMax(order.minQty)); buffer.push(this._encodeMax(order.percentOffset)); buffer.push(this._encode(order.eTradeOnly)); buffer.push(this._encode(order.firmQuoteOnly)); buffer.push(this._encodeMax(order.nbboPriceCap)); buffer.push(this._encodeMax(order.auctionStrategy)); buffer.push(this._encodeMax(order.startingPrice)); buffer.push(this._encodeMax(order.stockRefPrice)); buffer.push(this._encodeMax(order.delta)); // Volatility orders had specific watermark price attribs in server version 26 lower = this._serverVersion === 26 && order.orderType === 'VOL' ? Number.MAX_VALUE : order.stockRangeLower; upper = this._serverVersion === 26 && order.orderType === 'VOL' ? Number.MAX_VALUE : order.stockRangeUpper; buffer.push(this._encodeMax(lower)); buffer.push(this._encodeMax(upper)); } if (this._serverVersion >= 22) { buffer.push(this._encode(order.overridePercentageConstraints)); } if (this._serverVersion >= 26) { // Volatility orders buffer.push(this._encodeMax(order.volatility)); buffer.push(this._encodeMax(order.volatilityType)); if (this._serverVersion < 28) { buffer.push(this._encode(order.deltaNeutralOrderType.toUpperCase()) === 'MKT');